博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 开发第三弹:自定义左右菜单(滑动动画+蒙版效果)
阅读量:7175 次
发布时间:2019-06-29

本文共 8185 字,大约阅读时间需要 27 分钟。

下面的截图……哎,因为1080P在Windows 10上虽然适配了,但大部分软件并没有跟上,比如某个录制GIF的软件,所以这里有一定的偏移导致画面不完整,但效果大概就是这么一个效果了。

这里写图片描述

MainUI.java

首先需要这么一个类,在这里一些UI的滑动呀之类的都会定义。首先吧,定义好这些变量,当然了,实际开发过程中肯定需要哪一个就添加上哪一个的。

private Context context;  // 上下文    private FrameLayout leftMenu;    // 左边部分    private FrameLayout middleMenu;  // 中间部分    private FrameLayout rightMenu;   // 右边部分    private FrameLayout middleMask;  // 蒙版效果    private Scroller mScroller;    // 滑动动画    public static final int ID = 0;    // ID    public static final int LEFT_ID = ID+0xaabbcc;    public static final int MIDDLE_ID = ID+0xaaccbb;    public static final int RIGHT_ID = ID+0xccbbaa;

构造函数也是不能少的。

public MainUI(Context context) {        super(context);        initView(context);    }    public MainUI(Context context, AttributeSet attrs) {        super(context, attrs);        initView(context);    }

initView就是用来初始化视图的,相应的功能我都写在注释上了,就不多废话了。

// 初始化视图    private void initView(Context context){        this.context=context;        mScroller = new Scroller(context,new DecelerateInterpolator());        leftMenu=new FrameLayout(context);        middleMenu = new FrameLayout(context);        rightMenu = new FrameLayout(context);        middleMask = new FrameLayout(context);        leftMenu.setBackgroundColor(Color.RED);  // 设置背景颜色        middleMenu.setBackgroundColor(Color.GREEN);        rightMenu.setBackgroundColor(Color.RED);        middleMask.setBackgroundColor(0x88000000);        leftMenu.setId(LEFT_ID);        middleMenu.setId(MIDDLE_ID);        rightMenu.setId(RIGHT_ID);        addView(leftMenu);   // 添加至View        addView(middleMenu);        addView(rightMenu);        addView(middleMask);        middleMask.setAlpha(0);  // 设置middleMask的透明度    }

然后就是它们的一些布局呀,balabala……

@Override    protected void onMeasure(int widthMeasureSepc, int heightMeasureSpec){        super.onMeasure(widthMeasureSepc, heightMeasureSpec);        middleMenu.measure(widthMeasureSepc, heightMeasureSpec);        middleMask.measure(widthMeasureSepc,heightMeasureSpec);        int realWidth = MeasureSpec.getSize(widthMeasureSepc);  // 获取实际(屏幕)宽度        int tempWidthMeasure = MeasureSpec.makeMeasureSpec(                (int)(realWidth*0.7f), MeasureSpec.EXACTLY);  // 左右侧的宽度为中间宽度的0.7        leftMenu.measure(tempWidthMeasure, heightMeasureSpec);  // 左右侧的高度和中间的一样        rightMenu.measure(tempWidthMeasure, heightMeasureSpec);    }    @Override    protected void onLayout(boolean changed, int l, int t, int r,int b){  // l,t,r,b分别为中间部分的左、上、右、下边界        super.onLayout(changed, l, t, r, b);  // 设置布局        middleMenu.layout(l, t, r, b);   // 中间部分的四个边界不变        middleMask.layout(l, t, r, b);  // 蒙版的四个边界和中间部分一样        leftMenu.layout(l - leftMenu.getMeasuredWidth(), t, r, b); // 左侧部分的左边边界等于中间部分的左边边界减去左侧部分的宽度        rightMenu.layout(l + middleMenu.getMeasuredWidth(), t,  // 右侧部分的左边边界则等于中间部分的左边边界加上中间部分的宽度                l + middleMenu.getMeasuredWidth() +   // 右侧部分的右边边界等于中间部分的左边边界加上中间部分的宽度加上右侧部分的宽度                        rightMenu.getMeasuredWidth(), b);    }
public float onMiddleMask(){        System.out.println("透明度"+middleMask.getAlpha());        return middleMask.getAlpha();    }    @Override    public void scrollTo(int x, int y){        super.scrollTo(x,y);        onMiddleMask();  // 输出透明度        int curX = Math.abs(getScrollX());        float scale = curX/(float)leftMenu.getMeasuredWidth();  // 设置透明度的渐变        middleMask.setAlpha(scale);    }

再用两个布尔值来确定是否在左右滑动等。

private boolean isTestComete;  // 测试是否完成    private boolean isleftrightevent;  // 判断是否是左右滑动
@Override    public boolean dispatchTouchEvent(MotionEvent ev){        if(!isTestComete){  // 没有完成滑动动作            getEventType(ev);   // 继续调用事件进行判断            return true;        }        if(isleftrightevent){   // 左右滑动            switch (ev.getActionMasked()) {                case MotionEvent.ACTION_MOVE:                    int curScrollX = getScrollX();                    int dis_x = (int) (ev.getX() - point.x);                    int expectX = -dis_x + curScrollX;                    int finalX = 0;                    if (expectX < 0) {                        finalX = Math.max(expectX, -leftMenu.getMeasuredWidth());                    } else {                        finalX = Math.min(expectX, rightMenu.getMeasuredWidth());                    }                    scrollTo(finalX, 0);                    point.x = (int) ev.getX();                    break;                case MotionEvent.ACTION_UP:                case MotionEvent.ACTION_CANCEL:                    curScrollX = getScrollX();                    if (Math.abs(curScrollX) > leftMenu.getMeasuredWidth() >> 1) {                        if (curScrollX < 0) {                            mScroller.startScroll(curScrollX, 0, -leftMenu.getMeasuredWidth() - curScrollX, 0, 200);                        } else {                            mScroller.startScroll(curScrollX, 0, leftMenu.getMeasuredWidth() - curScrollX, 0, 200);                        }                    } else {                        mScroller.startScroll(curScrollX, 0, -curScrollX, 0, 200);                    }                    invalidate();                    isleftrightevent = false;                    isTestComete = false;                    break;            }        }else{            switch (ev.getActionMasked()){                case MotionEvent.ACTION_UP:                    isleftrightevent = false;                    isTestComete = false;                    break;                default:                    break;            }        }        return super.dispatchTouchEvent(ev);    }
@Override    public void computeScroll(){        super.computeScroll();        if(!mScroller.computeScrollOffset()){            return;        }        int tempX = mScroller.getCurrX();        scrollTo(tempX, 0);    }    private Point point = new Point();    private static final int TEST_DIS = 20;
private void getEventType(MotionEvent ev){        switch (ev.getActionMasked()){            case MotionEvent.ACTION_DOWN:                point.x = (int)ev.getX();                point.y = (int) ev.getY();                super.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 >= TEST_DIS && dX>dY ){ // 左右滑动                    isleftrightevent = true;                    isTestComete = true;                    point.x = (int)ev.getX();                    point.y = (int)ev.getY();                }else if(dY>=TEST_DIS && dY>dX ){   // 上下滑动                    isleftrightevent = false;                    isTestComete = true;                    point.x = (int)ev.getX();                    point.y = (int)ev.getY();                }                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                super.dispatchTouchEvent(ev);                isleftrightevent = false;                isTestComete = false;                break;        }    }

LeftMenu.java

下面继续看看如何在左侧的目录中添加一个Button。

你需要创建一个LeftMenu类,并扩展Fragment,因此你需要

import android.support.v4.app.Fragment;

如果你不知道如何添加,请看这里:

在下面这段代码之前你需要再新建一个left.xml布局文件,其中添加一个Button1。

@Override      public View onCreateView(LayoutInflater inflater,                               @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View v = inflater.inflate(R.layout.left, container,false);        v.findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                System.out.println("Hello nomasp");            }        });        return v;    }

MainActivity.java

现在你就需要来create它们了。

private MainUI mainUI;    private LeftMenu leftMenu;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mainUI = new MainUI(this);        setContentView(mainUI);        leftMenu = new LeftMenu();        getSupportFragmentManager().beginTransaction()                .add(MainUI.LEFT_ID, leftMenu).commit();    }

当然了,这里的MainActivity也需要扩展FragmentActivity,也就是要导入androidsupportv4.jar,至于如何导入请看前文的导航链接。

当然了,完整的代码你可以从这里Fork:

你可能感兴趣的文章
AIX系统开启ftp服务
查看>>
linux 上拷贝文件到windows 上 文件出现锁的文件
查看>>
Xamarin iOS教程之编辑界面编写代码
查看>>
Construct Binary Tree from Preorder and Inorder Traversal
查看>>
写得好 git 提交信息
查看>>
Linux下获取线程TID的方法
查看>>
Redis和Memcache的区别分析(转)
查看>>
网络请求 http get post 一
查看>>
《计算机问题求解》总结——2014年CCF计算机课程改革导教班(2014.07.11)
查看>>
Google Chrome Plus——绿色便携多功能谷歌浏览器
查看>>
Instant Run
查看>>
浏览器中 for in 反射 对象成员 的差异
查看>>
关于Linux启动时挂载rootfs的几种方式
查看>>
2018年总结
查看>>
34个漂亮的应用程序后台管理界面
查看>>
java JDK6的可变参数
查看>>
初入职场程序员的五大钻石法则
查看>>
Node.js学习笔记(一)概述
查看>>
split的3种方法
查看>>
忽略PNG透明区域的事件(AS/Flash)
查看>>