• Android 打造完美的侧滑菜单/侧滑View控件


    概述

    Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便.

    详细

    一.概述

    在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上

    咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点:

    1.对Android中Window类中的DecorView有所了解

    2.对Scroller类实现平滑移动效果

    3.自定义ViewGroup的实现

    下面现在就来说说这里咱们实现侧滑View的基本思路吧,这里我采用的是自定义一个继承于RelativeLayout的控件叫做XCSlideView类吧。

    首先从布局文件中inflater出来一个menuView,然后通过addView的方法,将该侧滑View添加到自定义的控件View中

    怎么让XCSlideView 这个侧滑View 隐藏到屏幕之外呢?很简单通过ScrollTo方法,移动一个屏幕宽度的距离即可,这里以

    左侧滑出为例吧,只需要这样 XCSlideView.this.scrollTo(mScreenWidth, 0);mScreenWidth是屏幕宽度。下面还要处理的就是底下的

    半透明黑色的蒙层效果,这个其实就是一个View,然后设置半透明效果。这个当然简单了,关键是咱们让他显示在咱们的自定义侧滑View的下面呢,

    这里咱们先给出DecorView的简单分析,方便下面介绍添加半透明View蒙层下:

    4.png

    二.演示效果图

    00.gif 02.png 01.png

    三.代码实现过程解析

    根据上面的概述,大家应该知道大概的思路了,下面我就给出自定义侧滑View类的核心代码:

    1、自定义侧滑View用到的变量:

    //侧滑方向-从哪侧滑出
        public static enum Positon {
            LEFT, RIGHT
        }
        private Context mContext;
        private Activity mActivity;
        private Scroller mScroller = null;
        //侧滑菜单布局View
        private View mMenuView;
        //底部蒙层View
        private View mMaskView;
        private int mMenuWidth = 0;
        //屏幕宽度
        private int mScreenWidth = 0;
        //是否在滑动中
        private boolean mIsMoving = false;
        //显示登录界面与否
        private boolean mShow = false;
        //滑动动画时间
        private int mDuration = 600;
        //缺省侧滑方向为左
        private Positon mPositon = Positon.LEFT;

    2、初始化创建自定义侧滑View:

    **
         * 创建侧滑菜单View
         */
        public static XCSlideView create(Activity activity) {
            XCSlideView view = new XCSlideView(activity);
            return view;
        }
        /**
         * 创建侧滑菜单View
         */
        public static XCSlideView create(Activity activity, Positon positon) {
            XCSlideView view = new XCSlideView(activity);
            view.mPositon = positon;
            return view;
        }

    3、创建半透明蒙层View,并添加到contentView中去

    /**
         * 创建 蒙层View并添加到contentView中
         */
        private void attachToContentView(Activity activity, Positon positon) {
            mPositon = positon;
            ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
            ViewGroup contentView = ((ViewGroup) contentFrameLayout.getChildAt(0));
            mMaskView = new View(activity);
            mMaskView.setBackgroundColor(mContext.getResources().getColor(R.color.mask_color));
            contentView.addView(mMaskView, contentView.getLayoutParams());
            mMaskView.setVisibility(View.GONE);
            mMaskView.setClickable(true);
            mMaskView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (isShow()) {
                        dismiss();
                    }
                }
            });
        }

    4、设置侧滑菜单View,并添加到DectorView->LinearLayout->内容显示区域View(FrameLayout)中

    /**
         * 设置侧滑菜单View,并添加到DectorView->LinearLayout->内容显示区域View中
         */
        public void setMenuView(Activity activity, View view) {
            mActivity = activity;
            mMenuView = view;
            LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            addView(mMenuView, params);
            mMenuView.post(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    mMenuWidth = mMenuView.getWidth();
                    switch (mPositon) {
                        case LEFT:
                            XCSlideView.this.scrollTo(mScreenWidth, 0);
                            break;
                        case RIGHT:
                            XCSlideView.this.scrollTo(-mScreenWidth, 0);
                            break;
                    }
    
                }
            });
            ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
            ViewGroup contentView = contentFrameLayout;
            contentView.addView(this);
            FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) this.getLayoutParams();
            switch (mPositon) {
                case LEFT:
                    layoutParams.gravity = Gravity.LEFT;
                    layoutParams.leftMargin = 0;
                    break;
                case RIGHT:
                    layoutParams.gravity = Gravity.RIGHT;
                    layoutParams.rightMargin = 0;
                    break;
            }
            TextView titleFrameLayout = (TextView) activity.findViewById(android.R.id.title);
            if( titleFrameLayout != null){
                layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext);
            }
            int flags =  mActivity.getWindow().getAttributes().flags;
            int flag = (flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            if(flag == WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS){
                //说明状态栏使用沉浸式
                layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext);
            }
            this.setLayoutParams(layoutParams);
        }

    5、处理自定义侧滑View的侧滑滑动和隐藏效果:

    /**
         * 显示侧滑菜单View
         */
        public void show(){
            if(isShow() && !mIsMoving)
                return;
            switch (mPositon) {
                case LEFT:
                    startScroll(mMenuWidth, -mMenuWidth, mDuration);
                    break;
                case RIGHT:
                    startScroll(-mMenuWidth, mMenuWidth, mDuration);
                    break;
            }
            switchMaskView(true);
            mShow = true;
        }
        /**
         * 蒙层显示开关
         */
        private void switchMaskView(boolean bShow){
            if(bShow){
                mMaskView.setVisibility(View.VISIBLE);
                Animation animation = new AlphaAnimation(0.0f, 1.0f);
                animation.setDuration(mDuration);
                mMaskView.startAnimation(animation);
            }else{
                mMaskView.setVisibility(View.GONE);
            }
        }
        /**
         * 关闭侧滑菜单View
         */
        public void dismiss() {
            // TODO Auto-generated method stub
            if(!isShow() && !mIsMoving)
                return;
            switch (mPositon) {
                case LEFT:
                    startScroll(XCSlideView.this.getScrollX(), mMenuWidth, mDuration);
                    break;
                case RIGHT:
                    startScroll(XCSlideView.this.getScrollX(), -mMenuWidth, mDuration);
                    break;
            }
            switchMaskView(false);
            mShow = false;
        }
        public boolean isShow(){
            return mShow;
        }
        @Override
        public void computeScroll() {
            // TODO Auto-generated method stub
            if (mScroller.computeScrollOffset()) {
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                // 更新界面
                postInvalidate();
                mIsMoving = true; 
            } else {
                mIsMoving = false;
            }
            super.computeScroll();
        }
        /**
         * 拖动移动
         */
        public void startScroll(int startX, int dx,int duration){
            mIsMoving = true;
            mScroller.startScroll(startX,0,dx,0,duration);
            invalidate();
        }

    四.如何使用该自定义侧滑View控件

    使用起来,比较简单,通过create方法创建一个侧滑VIew,然后通过setMenuView方法设置一个侧滑View进去,有需要设置

    宽度的话, 通过setMenuWidth方法来设置即可,最后用show()方法滑出来就可以啦,使用起来是不是很方便?

    private XCSlideView mSlideViewLeft;
    //屏幕宽度
    private int mScreenWidth = 0;
    View menuViewLeft = LayoutInflater.from(mContext).inflate(R.layout.layout_slideview,null);
    mSlideViewLeft = XCSlideView.create(this, XCSlideView.Positon.LEFT);
    mSlideViewLeft.setMenuView(MainActivity.this, menuViewLeft);
    mSlideViewLeft.setMenuWidth(mScreenWidth * 7 / 9);
    Button left = (Button)findViewById(R.id.btn_left);
            left.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    if (!mSlideViewLeft.isShow())
                        mSlideViewLeft.show();
                }
            });

    五.项目代码结构图

    slide.png

    注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

  • 相关阅读:
    vfork与fork的区别
    常见的六种设计模式以及应用场景
    Java中常见的集合类比较
    排序——总结
    排序——交换排序
    排序——选择排序
    排序——归并排序
    排序——基数排序
    排序——插入排序
    设计模式
  • 原文地址:https://www.cnblogs.com/demodashi/p/8491148.html
Copyright © 2020-2023  润新知