存一个自定义滑动菜单:
记一些关键的函数作用:
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;
}
}
}