類似launcher案頭滑動效果

來源:互聯網
上載者:User

這個例子中涉及到了以下幾個知識點:
1) attrs.xml檔案的使用
2) GestureDetector.OnGestureListener監聽手勢
3) onLayout()、onMeasure()、onTouchEvent()的使用
接下來說一下我實現的思路:
1) 每個案頭就是一個大組件,水平的排列線上性布局檔案中,每個案頭適合螢幕一樣大小,所以要拓展LinearLayout,重寫其中的onMeasure()、onLayout()方法
2) 由於要實現隨手勢滑動,所以只要實現GestureDetector.OnGestureListener介面中的onDown()、onScroll()方法就可以
3) 由於要接收觸屏事件,所以要實現onTouchEvent()
接下來我們來看一下代碼吧:

  1. public class ScrollLayout extends LinearLayout implements GestureDetector.OnGestureListener{
  2.     private int offset;  //相對距離
  3.     private GestureDetector gestureDetector;  //手勢事件
  4.     private int childWidth; //子View的寬度
  5.     private int childCount; //子視圖的數量
  6.     private int defaultWindow; //預設視窗
  7.     private boolean setShareWindowFlag=false;    // 保證預設視窗的設定只執行一次
  8.     public ScrollLayout(Context context) {
  9.         super(context);
  10.         init();
  11.     }
  12.     public ScrollLayout(Context context, AttributeSet attrs) {
  13.         super(context, attrs);
  14.         init();
  15.         //擷取定義的defaultWindow的值
  16.         TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyScrollWindow);
  17.         defaultWindow = typedArray.getInteger(R.styleable.MyScrollWindow_defaultWindow,0);
  18.     }
  19.     private void init(){
  20.         gestureDetector = new GestureDetector(this.getContext(),this);
  21.     }
  22.     //傳回值為true 才能觸發 手勢事件
  23.     public boolean onDown(MotionEvent e) {
  24.         return true;
  25.     }
  26.     public void onShowPress(MotionEvent e) { }
  27.     public boolean onSingleTapUp(MotionEvent e) {
  28.         return false;  
  29.     }
  30.     //順手勢滑動
  31.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  32.         //擷取滑動的距離
  33.         offset = (int) (offset - distanceX);
  34.         //防止滑出邊界
  35.         if(offset>0){
  36.             offset=0;
  37.         }else if(offset < -1*childWidth*(childCount-1)){
  38.             offset= -1*childWidth*(childCount-1);
  39.         }
  40.         //重繪布局
  41.         requestLayout();
  42.         return true;
  43.     }
  44.     public void onLongPress(MotionEvent e) {
  45.         
  46.     }
  47.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  48.         return false;  
  49.     }
  50.     //設定布局檔案的寬高和每個案頭的寬高
  51.     @Override
  52.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  53.         super.onMeasure(widthMeasureSpec,heightMeasureSpec);
  54.         //給每個案頭設定和螢幕相同的寬度和高度
  55.         int childCount = getChildCount();
  56.         for(int i=0;i<childCount;i++){
  57.             getChildAt(i).measure(widthMeasureSpec,heightMeasureSpec);
  58.         }
  59.     }
  60.     //設定布局
  61.     @Override
  62.     protected void onLayout(boolean changed, int l, int t, int r, int b) {
  63.         childCount = getChildCount();   //擷取子視圖數
  64.         childWidth = childCount > 0? getChildAt(0).getMeasuredWidth():0; //擷取位元組點的寬度
  65.         if(!setShareWindowFlag&&defaultWindow>=0&&defaultWindow<=childCount-1){
  66.             //設定預設視窗的左端距離
  67.             offset = -1*defaultWindow*childWidth;
  68.             setShareWindowFlag=true;
  69.         }
  70.         //設定距離(0,0)點X軸方向的初始距離
  71.         int left = 0+offset;
  72.         for (int i = 0; i < childCount ;  i ++){
  73.             //設定每個子視圖在布局中的位置
  74.             View child = getChildAt(i);
  75.             if(child.getVisibility()!=View.GONE){
  76.                 child.layout(left,0,childWidth+left,child.getMeasuredHeight());
  77.                 left = left + childWidth;
  78.             }
  79.         }
  80.     }
  81.     //觸屏事件
  82.     @Override
  83.     public boolean onTouchEvent(MotionEvent event) {
  84.        boolean result = gestureDetector.onTouchEvent(event);
  85.        if(event.getAction()==MotionEvent.ACTION_UP){
  86.            //當手指抬起來時 判斷滑動距離顯示整個子視圖
  87.            showOneDesktop();
  88.        }
  89.        return result;
  90.     }
  91.     //判斷當手指抬起時顯示那個案頭
  92.     private void showOneDesktop(){
  93.        int index = Math.abs(offset)/childWidth;
  94.        if(Math.abs(offset)-index*childWidth>childWidth/2){
  95.            index++;
  96.        }
  97.        offset = offset > 0 ? index*childWidth : -1*index*childWidth;
  98.        requestLayout();
  99.     }
  100. }

複製代碼

在這段代碼中使用到的attrs.xml檔案:

  1. <resources>
  2.         <declare-styleable name="MyScrollWindow">
  3.             <attr name="defaultWindow" format="integer"/>
  4.         </declare-styleable>
  5. </resources>

複製代碼

可以和系統內建的布局檔案一樣使用

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <com.wxg.scroll_window.view.ScrollLayout
  3.         xmlns:android="http://schemas.android.com/apk/res/android"
  4.         xmlns:demo="http://schemas.android.com/apk/res/com.wxg.scroll_window"
  5.         android:id="@+id/testLayout"
  6.         android:layout_width="fill_parent"
  7.         android:layout_height="fill_parent"
  8.         demo:defaultWindow="1"
  9.         >
  10.         <FrameLayout
  11.             android:layout_height="fill_parent"
  12.             android:layout_width="fill_parent"
  13.             android:background="#cccccc">
  14.             <Button
  15.                     android:layout_height="wrap_content"
  16.                     android:layout_width="wrap_content"
  17.                     android:text="1"/>
  18.             </FrameLayout>
  19.         <FrameLayout
  20.             android:layout_height="fill_parent"
  21.             android:layout_width="fill_parent"
  22.             android:background="#ffffff">
  23.             <Button
  24.                     android:layout_height="wrap_content"
  25.                     android:layout_width="wrap_content"
  26.                     android:text="2"/>
  27.             </FrameLayout>
  28.         <FrameLayout
  29.             android:layout_height="fill_parent"
  30.             android:layout_width="fill_parent"
  31.             android:background="#bcbcbc">
  32.             <Button
  33.                     android:layout_height="wrap_content"
  34.                     android:layout_width="wrap_content"
  35.                     android:text="3"/>
  36.             </FrameLayout>
  37.         </com.wxg.scroll_window.view.ScrollLayout>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.