实现类似launcher的滑动桌面

来源:互联网 发布:三星电视无法连接网络 编辑:程序博客网 时间:2024/05/12 20:10

这个例子中涉及到了以下几个知识点:

  • 1) attrs.xml文件的使用
  • 2) GestureDetector.OnGestureListener监听手势
  • 3) onLayout()、onMeasure()、onTouchEvent()的使用

接下来说一下我实现的思路
  • 1) 每个桌面就是一个大组件,水平的排列在线性布局文件中,每个桌面适合屏幕一样大小,所以要拓展LinearLayout,重写其中的onMeasure()、onLayout()方法
  • 2) 由于要实现随手势滑动,所以只要实现GestureDetector.OnGestureListener接口中的onDown()、onScroll()方法就可以
  • 3) 由于要接收触屏事件,所以要实现onTouchEvent()
接下来我们来看一下代码吧:
public class ScrollLayout extends LinearLayout implements GestureDetector.OnGestureListener{    private int offset;  //相对距离    private GestureDetector gestureDetector;  //手势事件    private int childWidth; //子View的宽度    private int childCount; //子视图的数量    private int defaultWindow; //默认窗口    private boolean setShareWindowFlag=false;    // 保证默认窗口的设置只执行一次    public ScrollLayout(Context context) {        super(context);        init();    }    public ScrollLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();        //获取定义的defaultWindow的值        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyScrollWindow);        defaultWindow = typedArray.getInteger(R.styleable.MyScrollWindow_defaultWindow,0);    }    private void init(){        gestureDetector = new GestureDetector(this.getContext(),this);    }    //返回值为true 才能触发 手势事件    public boolean onDown(MotionEvent e) {        return true;    }    public void onShowPress(MotionEvent e) { }    public boolean onSingleTapUp(MotionEvent e) {        return false;      }    //顺手势滑动    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        //获取滑动的距离        offset = (int) (offset - distanceX);        //防止滑出边界        if(offset>0){            offset=0;        }else if(offset < -1*childWidth*(childCount-1)){            offset= -1*childWidth*(childCount-1);        }        //重绘布局        requestLayout();        return true;    }    public void onLongPress(MotionEvent e) {            }    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        return false;      }    //设置布局文件的宽高和每个桌面的宽高    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec,heightMeasureSpec);        //给每个桌面设置和屏幕相同的宽度和高度        int childCount = getChildCount();        for(int i=0;i<childCount;i++){            getChildAt(i).measure(widthMeasureSpec,heightMeasureSpec);        }    }    //设置布局    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        childCount = getChildCount();   //获取子视图数        childWidth = childCount > 0? getChildAt(0).getMeasuredWidth():0; //获取字节点的宽度        if(!setShareWindowFlag&&defaultWindow>=0&&defaultWindow<=childCount-1){            //设置默认窗口的左端距离            offset = -1*defaultWindow*childWidth;            setShareWindowFlag=true;        }        //设置距离(0,0)点X轴方向的初始距离        int left = 0+offset;        for (int i = 0; i < childCount ;  i ++){            //设置每个子视图在布局中的位置            View child = getChildAt(i);            if(child.getVisibility()!=View.GONE){                child.layout(left,0,childWidth+left,child.getMeasuredHeight());                left = left + childWidth;            }        }    }    //触屏事件    @Override    public boolean onTouchEvent(MotionEvent event) {       boolean result = gestureDetector.onTouchEvent(event);       if(event.getAction()==MotionEvent.ACTION_UP){           //当手指抬起来时 判断滑动距离显示整个子视图           showOneDesktop();       }       return result;    }    //判断当手指抬起时显示那个桌面    private void showOneDesktop(){       int index = Math.abs(offset)/childWidth;       if(Math.abs(offset)-index*childWidth>childWidth/2){           index++;       }       offset = offset > 0 ? index*childWidth : -1*index*childWidth;        requestLayout();    }}

在这段代码中使用到的attrs.xml文件:
<resources>        <declare-styleable name="MyScrollWindow">            <attr name="defaultWindow" format="integer"/>        </declare-styleable></resources>

使用:
<?xml version="1.0" encoding="utf-8"?><com.wxg.scroll_window.view.ScrollLayout        xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:demo="http://schemas.android.com/apk/res/com.wxg.scroll_window"        android:id="@+id/testLayout"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        demo:defaultWindow="1"        >        <FrameLayout            android:layout_height="fill_parent"            android:layout_width="fill_parent"            android:background="#cccccc">            <Button                    android:layout_height="wrap_content"                    android:layout_width="wrap_content"                    android:text="1"/>            </FrameLayout>        <FrameLayout            android:layout_height="fill_parent"            android:layout_width="fill_parent"            android:background="#ffffff">            <Button                    android:layout_height="wrap_content"                    android:layout_width="wrap_content"                    android:text="2"/>            </FrameLayout>        <FrameLayout            android:layout_height="fill_parent"            android:layout_width="fill_parent"            android:background="#bcbcbc">            <Button                    android:layout_height="wrap_content"                    android:layout_width="wrap_content"                    android:text="3"/>            </FrameLayout>        </com.wxg.scroll_window.view.ScrollLayout>