自定义View-22.酷狗侧滑菜单效果

2018-07-08  本文已影响41人  zsj1225

效果如下

TIM图片20180708173517.gif

1.1继承自定义 HorizontalScrollView , 写个好两个布局(menu , content).

public class SlidingMenu extends HorizontalScrollView {
}
<?xml version="1.0" encoding="utf-8"?>
<com.zsj.slidingmenu.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/home_menu_bg"
    tools:context="com.zsj.slidingmenu.MainActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <include layout="@layout/layout_home_menu" />


        <include layout="@layout/layout_home_content" />

    </LinearLayout>


</com.zsj.slidingmenu.SlidingMenu>

运行起来界面异常,宽度显示不对.

1.2 重新指定宽度.

  //宽度不对,全乱了.指定宽度
    @Override
    protected void onFinishInflate() {
        //这个方法是xml解析完毕调用
        super.onFinishInflate();

        //获取LinearLayout
        ViewGroup container = (ViewGroup) getChildAt(0);

        int childCount = container.getChildCount();
        if (childCount > 2) {
            new IllegalAccessException("不能超过2个子View");
        }
        //获取menu
        mMenuView = container.getChildAt(0);
        //获取内容
        mContentView = container.getChildAt(1);

        //指定内容也的宽度
        ViewGroup.LayoutParams contentLayoutParams = mContentView.getLayoutParams();
        //内容的宽度 = 屏幕的宽度
        contentLayoutParams.width = DimenUtils.getScreenWidth(getContext());
        mContentView.setLayoutParams(contentLayoutParams);

        //指定menu的宽度
        ViewGroup.LayoutParams menuLayoutParams = mMenuView.getLayoutParams();
        //menu的宽度 = 屏幕的宽度 - mMenuRightMargin
        mMenuWidth = DimenUtils.getScreenWidth(getContext()) - mMenuRightMargin;
        menuLayoutParams.width = mMenuWidth;
        mMenuView.setLayoutParams(menuLayoutParams);

        //发现,初始化关闭没有作用
//        scrollTo(mMenuWidth, 0);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        //初始化关闭menu
        scrollTo(mMenuWidth, 0);
    }

处理触摸事件

    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            //只管手指抬起了的事件
            //根据当前滑动的位置处理关闭还是打开
            int currentScrollX = getScrollX();
            if (currentScrollX > mMenuWidth / 2) {
                //关闭
                closeMenu();
            } else {
                //打开
                openMenu();
            }
            //确保不会调用super,因为super.里面也有滑动的方法
            return true;
        }
        return super.onTouchEvent(ev);
    }

    private void closeMenu() {
        scrollTo(mMenuWidth, 0);
        mCurrentMenuState = false;
    }

    private void openMenu() {
        scrollTo(0, 0);
        mCurrentMenuState = true;
    }

1.4 处理滑动的缩放

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        // 打开 Menu l == mMenuWidth --> 0
        // 所以 scale == 0 --> 1.0
        double scale = 1 - l * 1.0 / mMenuWidth;

        //右边的contentView 从 1 --> 0.7 缩放
        // 1 --> 0.7
        float rightScale = (float) (1.0 - 0.3 * scale);
        ViewCompat.setScaleX(mContentView, rightScale);
        ViewCompat.setScaleY(mContentView, rightScale);
        //设置锚点
        ViewCompat.setPivotX(mContentView, 0);
        ViewCompat.setPivotY(mContentView, mContentView.getMeasuredHeight() / 2);
    }

1.5 处理快速滑动

    public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //处理快速滑动
        mGestureDetector = new GestureDetector(context, mOnGestureListener);
    }

    private GestureDetector.OnGestureListener mOnGestureListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            //Log.e(TAG, "onFling velocityX -->"+velocityX);
            //往右快速滑动为正数,往左快速滑动为负数

            if (mCurrentMenuState) {
                //当menu打开的时候,往左快速滑动关闭menu
                if (velocityX < 0) {
                    closeMenu();
                    return true;
                }
            } else {
                //当menu关闭的时候,往右快速滑动打开menu
                if (velocityX> 0){
                    openMenu();
                    return true;
                }
            }
            return super.onFling(e1, e2, velocityX, velocityY);
        }
    };

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //快速滑动处理
        if (mGestureDetector.onTouchEvent(ev)) {
            //当处理了快速滑动就不需要执行下面的逻辑
            return true;
        }
}

1.6 menu打开的时候点击,内容页关闭menu,并不能响应内容页的Touch事件

事件拦截

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        mIntercept = false;
        //menu打开的时候的点击内容,关闭menu,同时不会响应内容页的事件 事件拦截.
        if (mCurrentMenuState){
            //获取点击是位置
            float currentX = ev.getX();
            if (currentX > mMenuWidth){
                //点击的位置在内容页
                //关闭menu
                closeMenu();

                mIntercept = true;
                //不响应内容的事件
                return true;
            }
        }
        return super.onInterceptTouchEvent(ev);
    }

完整代码:slidingmenu

上一篇下一篇

猜你喜欢

热点阅读