自定義左右滑動選單
阿新 • • 發佈:2019-02-08
存一個自定義滑動選單:
記一些關鍵的函式作用:
1.定義一個FrameLayout fm,fm.measure(width,height)代表定義這個fm的長和寬。
2.onMeasure()用於測量父Layout裡面的各個layout,onLayout用於佈局父Layout裡面的各個layout。
3.實際操作滑動距離的時候用下面的程式碼:
int scrollX = getScrollX(); int dX = (int) ev.getX() - point.x; int finalX = 0; int exX = scrollX - dX; if(exX > 0){ finalX = Math.max(exX,-leftFrame.getMeasuredWidth()); //最多隻能滑到右邊的邊界 scrollTo(finalX,0); //滑動操作 } else{ finalX = Math.min(exX,rightFrame.getMeasuredWidth()); //最多隻能滑到左邊的邊界 scrollTo(finalX,0); }
4.更新了蒙版效果,在滑倒其他頁面時,主頁面會進行灰度的漸變。
5.添加了事件監聽。
MainActivity.Java
package com.example.a53125.slidingrelativelayouttest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { private MainUI mainUI; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainUI = new MainUI(this); setContentView(mainUI); } }
MainUI.Java
package com.example.a53125.slidingrelativelayouttest; import android.content.Context; import android.graphics.Color; import android.graphics.Point; import android.support.annotation.Px; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.RelativeLayout; import android.widget.Scroller; /** * Created by 53125 on 2017/8/16. */ public class MainUI extends RelativeLayout { @android.support.annotation.IdRes int LEFT_ID = 0xaabbcc; @android.support.annotation.IdRes int MID_ID = 2222; @android.support.annotation.IdRes int RIGHT_ID = 3333; private Context context; private FrameLayout middleFrame; private FrameLayout leftFrame; private FrameLayout rightFrame; private FrameLayout maskFrame; private Scroller scroller; // public static int LEFT_ID = 0xaabbcc; // public final int MID_ID = 2222; // public final int RIGHT_ID = 3333; public MainUI(Context context) { super(context); this.context = context; initView(context); } public MainUI(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public void initView(Context context){ scroller = new Scroller(context,new DecelerateInterpolator()); middleFrame = new FrameLayout(context); leftFrame = new FrameLayout(context); rightFrame = new FrameLayout(context); maskFrame = new FrameLayout(context); middleFrame.setBackgroundColor(Color.GREEN); leftFrame.setBackgroundColor(Color.YELLOW); rightFrame.setBackgroundColor(Color.YELLOW); maskFrame.setBackgroundColor(0x88000000); maskFrame.setAlpha(0); leftFrame.setId(LEFT_ID); middleFrame.setId(MID_ID); rightFrame.setId(RIGHT_ID); addView(leftFrame); addView(middleFrame); addView(rightFrame); addView(maskFrame); } @Override public void scrollTo(@Px int x, @Px int y) { super.scrollTo(x, y); int scr = Math.abs(getScrollX()); float alpha = scr/(float) leftFrame.getMeasuredWidth(); maskFrame.setAlpha(alpha); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); middleFrame.measure(widthMeasureSpec,heightMeasureSpec); maskFrame.measure(widthMeasureSpec,heightMeasureSpec); int Screen_Width = MeasureSpec.getSize(widthMeasureSpec); // System.out.println("widthMeasureSpec:"+widthMeasureSpec); // System.out.println("Screen_Width"+Screen_Width); int Left_Width = MeasureSpec.makeMeasureSpec((int)(Screen_Width*0.8f),MeasureSpec.EXACTLY); leftFrame.measure(Left_Width,heightMeasureSpec); rightFrame.measure(Left_Width,heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); middleFrame.layout(l, t, r, b); maskFrame.layout(l, t, r, b); leftFrame.layout(l-leftFrame.getMeasuredWidth(), t, r, b); rightFrame.layout(l+middleFrame.getMeasuredWidth(), t, r+rightFrame.getMeasuredWidth(), b); } private int state = 0; private boolean stateSlidingLeftRight = false; //是否左右滑動 private boolean stateSlidingUpDown = false; //是否上下滑動 private int TEST_DIS = 20; //滑動判定的最小距離 Point point = new Point(); @Override public boolean dispatchTouchEvent(MotionEvent ev) { // System.out.println("Click successfully!"); // System.out.println("LeftWidth:"+leftFrame.getMeasuredWidth()); // System.out.println("MidWidth:"+middleFrame.getMeasuredWidth()); if(!(state == 1)){ getState(ev); // System.out.println("stateSlidingLeftRight:"+stateSlidingLeftRight); return true; //一定要返回true,否則的話不會進行滑動操作 } if(stateSlidingUpDown){ //用於初始化橫向滑動的狀態,便於接著上次再次滑動 stateSlidingLeftRight = false; state = 0; } if(stateSlidingLeftRight){ System.out.println("Sliding successfully!"); switch (ev.getActionMasked()){ case MotionEvent.ACTION_MOVE: int scrollX = getScrollX(); int dX = (int) ev.getX() - point.x; int finalX = 0; int exX = scrollX - dX; if(exX > 0){ finalX = Math.max(exX,-leftFrame.getMeasuredWidth()); //最多隻能滑到右邊的邊界 scrollTo(finalX,0); //滑動操作 } else{ finalX = Math.min(exX,rightFrame.getMeasuredWidth()); //最多隻能滑到左邊的邊界 scrollTo(finalX,0); } point.x = (int) ev.getX(); //儲存點,用於下一次滑動 point.y = (int) ev.getY(); break; case MotionEvent.ACTION_UP: //用於初始化橫向滑動的狀態,便於接著上次再次滑動 case MotionEvent.ACTION_CANCEL: //用於初始化橫向滑動的狀態,便於接著上次再次滑動 int scroll = getScrollX(); if(Math.abs(scroll) > leftFrame.getMeasuredWidth() >>1){ if(scroll < 0){ scroller.startScroll(scroll,0,-leftFrame.getMeasuredWidth()-scroll,0); } else{ scroller.startScroll(scroll,0,leftFrame.getMeasuredWidth()-scroll,0); } } else{ scroller.startScroll(scroll,0,-scroll,0); } invalidate(); stateSlidingLeftRight = false; state = 0; break; default:break; } } return super.dispatchTouchEvent(ev); } @Override public void computeScroll() { super.computeScroll(); if(!scroller.computeScrollOffset()){ return; } int tempX = scroller.getCurrX(); scrollTo(tempX,0); } private void getState(MotionEvent ev) { switch (ev.getActionMasked()){ case MotionEvent.ACTION_UP: //手指擡起後觸發 state = 0; stateSlidingLeftRight = false; stateSlidingUpDown = false; super.dispatchTouchEvent(ev); break; case MotionEvent.ACTION_DOWN: //手指按下的一瞬間觸發 point.x = (int) ev.getX(); point.y = (int) ev.getY(); super.dispatchTouchEvent(ev); break; case MotionEvent.ACTION_CANCEL: //手指滑到邊界觸發 stateSlidingLeftRight = false; state = 0; dispatchTouchEvent(ev); break; case MotionEvent.ACTION_MOVE: //手指滑動觸發 int dX = Math.abs((int)ev.getX() - point.x); int dY = Math.abs((int)ev.getY() - point.y); if(dX > dY && dX > TEST_DIS){ //滑動舉例大於TEST_DIS才算滑動 stateSlidingLeftRight = true; stateSlidingUpDown = false; state = 1; point.x = (int) ev.getX(); point.y = (int) ev.getY(); }else if(dX < dY && dY > TEST_DIS){ stateSlidingUpDown = true; stateSlidingLeftRight = false; state = 1; point.x = (int) ev.getX(); //記錄點用於下次滑動 point.y = (int) ev.getY(); } break; } } }