Android實現類似launcher的滑動桌面

openkk 12年前發布 | 37K 次閱讀 Android Android開發 移動開發

這個例子中涉及到了以下幾個知識點:

  • 1) attrs.xml文件的使用
  • 2) GestureDetector.OnGestureListener監聽手勢
  • 3) onLayout()、onMeasure()、onTouchEvent()的使用
  • </ul>

    接下來說一下我實現的思路
    • 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>  
 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!