仿QQ5.0菜单的实现及分析

在慕课网上看了鸿洋扣扣5.0菜单的视频,在这里写下新的也顺便梳理一下里面涉及到的知识点。不得不佩服大神的深度,讲的非常好。

一、普通侧滑菜单的实

定义出menu的布局文件。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:orientation="vertical">
        <-- 里面随意放一些组件来显示一下 -->
    </LinearLayout>
</RelativeLayout>
主布局代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:costunattr="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/img_frame_background"
    tools:context="com.herodemo.sheadon.qq50_slide_menu.MainActivity">

    <!--HorizontalScrollView内部只能有一个控件-->
    <com.herodemo.sheadon.qq50_slide_menu.view.SlidingMenu
        android:id="@+id/sliding_menu"
        costunattr:rightPadding="80dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal">
            <-- 上面定义的menu菜单-->
            <include layout="@layout/left_menu"/

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:background="@drawable/qq"
            </LinearLayout>
        </LinearLayout>   </com.herodemo.sheadon.qq50_slide_menu.view.SlidingMenu>
</RelativeLayout>

自定义一个SlidingMenu,让它继承HorizontalScrollView,因为HorizontalScrollView可以自动处理水平的滑动事件,这样我们就不必人工处理ACTION_MOVE事件了。

public class SlidingMenu extends HorizontalScrollView

覆盖两个参数的构造方法该构造方法会在加载布局文件时调用,前提是没有自定义布局属性。

public SlidingMenu(Context context, AttributeSet attrs){
    //得到系统的宽度像素
    WindowManager wm = (WindowManager) context.
    getSystemService(Context.WINDOW_SERVICE);
   DisplayMetrics metrics = new DisplayMetrics();
   wm.getDefaultDisplay().getMetrics(metrics);
   this.mSreenWidth = metrics.widthPixels;//得到宽度像素值
}

重写onMeasure()方法确定view的宽高

/**
     * 设置子view的宽和高
     * 设置自己的宽和高
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if(once == false){
            mWapper = (LinearLayout) getChildAt(0);
            mMenu = (ViewGroup) mWapper.getChildAt(0);
            mContent = (ViewGroup) mWapper.getChildAt(1);

            mMenuWidth = mMenu.getLayoutParams().width = mSreenWidth - mMenuRightPadding;
            mContent.getLayoutParams().width = mSreenWidth;
            //menu和content都设置好之后mWraper会自己设置宽度
            once = true;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

这里有一个非常重要的东西需要理解:

在我刚开始实现的时候遇到一个问题,就是运行该布局后menu和content内容都在一个屏幕上面。而在布局文件中无论怎样修该布局参数都起不到作用。

这里一个关键的问题就是,你要在onMeasure的方法中指定menu和content的长宽,如果不做特别指定,系统会默认在一个屏幕下显示两个布局文件。在上面的方法中,特别指定了menu的宽度为屏幕宽度,mContent的宽度也是屏幕的宽度,这样HorizontalScrollView类的水平滑动效果就会起作用了。

 @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        //判断当前布局改变le
        if(changed){
            //布局文件加载后,立即滑动只让content部分显示在屏幕上
            //所以,必须在super.onLayout()中加载
            this.scrollTo(mMenuWidth, 0);
        }
    }

接下来就是控制滑动事件了,因为继承了水平滑动布局,所以ACTION_MOVE时间就不用我们亲自处理了,省下了很多麻烦。我们只需要处理ACTION_UP事件。

case MotionEvent.ACTION_UP:
                //隐藏在左边的宽度,并不是显示的宽度
                int scrollX = getScrollX();
                if (scrollX <= mMenuWidth/2){
                    //打开菜单
                    smoothScrollTo(0,0);
                    isOpen = true;
                }else{
                    smoothScrollTo(mMenuWidth,0);
                    isOpen = false;
                }
                return true;

完成了这些,一个具有基本功能的滑动菜单试图就完成了。

接下来,要做一些动画的处理,实现缩放,透明度,位移的一些变化
View 类有一个方法叫做 onScrollChanged(int l, int t, int oldl, int oldt),当view在滚动时就会不停的回调该方法,其中参数l就是当前view在屏幕边缘的地方在该view中的left值,放menu被完全遮盖时,left值为menu的宽度,当menu完全显示时,left值为0。
我们就可以利用这一点,将l值转化成一个从1~0的梯度值。

float scale = l* 1.0f/mMenuWidth;

1、实现偏移量的变化:

首先,我们要认识一个变量,translationX,它代表view与父view之间的横坐标偏移值。

看下效果:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值