5.0侧滑菜单(仿QQ)

效果图:这个效果是类似QQ客户端滑动那样的效果, 应该说差不多一样把.

实现原理: 自定义一个 view 继承 HorizontalScrollView(因为它可左右滑动).    view 里面包含 两个布局, 一个在左边(菜单layout),另一个右边(主layout), 通过重写父类方法 来实现 侧滑功能


下面贴布局文件: 

[html]  view plain copy
  1. <pre name="code" class="html"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:it="http://schemas.android.com/apk/res/com.it.sideslipmenu"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:background="@drawable/background"  
  7.     tools:context="com.it.sideslipmenu.MainActivity" >  
  8.   
  9.     <com.it.sideslipmenuview.MyView  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="match_parent"  
  12.         android:clickable="false"  
  13.         android:scrollbars="none"  
  14.         it:rightPadding="100dp" >  
  15.   
  16.         <LinearLayout  
  17.             android:layout_width="wrap_content"  
  18.             android:layout_height="match_parent"  
  19.             android:background="@drawable/ic_launcher"  
  20.             android:orientation="horizontal" >  
  21.   
  22.             <include layout="@layout/menu" />  
  23.   
  24.             <LinearLayout  
  25.                 android:layout_width="match_parent"  
  26.                 android:layout_height="match_parent"  
  27.                 android:orientation="vertical" >  
  28.   
  29.                 <include  
  30.                     android:id="@+id/aa"  
  31.                     layout="@layout/messagetop" />  
  32.   
  33.                 <com.it.sideslipmenuview.mViewPager  
  34.                     android:id="@+id/vp1"  
  35.                     android:layout_width="match_parent"  
  36.                     android:layout_height="0dp"  
  37.                     android:layout_weight="1"  
  38.                     android:background="#FFFFFF" >  
  39.                 </com.it.sideslipmenuview.mViewPager>  
  40.   
  41.                 <include layout="@layout/bottom" />  
  42.             </LinearLayout>  
  43.         </LinearLayout>  
  44.     </com.it.sideslipmenuview.MyView>  
  45. <p></RelativeLayout></p><p>  
  46. </p>  
 

最外层是一个RelativeLayout, 它里面只有一个 继承了 horizontalScroll 的 custom view.       因为 horizontalScroll  内 只能有一个子view, 所以我们写一个 linearlayout, 里面包含了 一个左menu,  右边是一个linearlayout 里面 组成的一个 主页面.

自定义属性it:rightPadding: 作用是滑动过后, 让内容区域显示多少的值!

左右布局在这里就不贴了, 左侧就是一些 linearlayout + relativelaout 写出来的., 而右侧 是  头部 +自定义viewpager +底部 组成 也没什么说的

下面来说说程序的核心, 我们的custom view 

[java]  view plain copy
  1. /** 
  2.  * 5.0新特性 侧滑菜单 
  3.  *  
  4.  * @author accer 
  5.  *  
  6.  */  
  7. public class MyView extends HorizontalScrollView {  
  8.     private LinearLayout mWapper;  
  9.     private ViewGroup menu; // menu layout  
  10.     private ViewGroup content; // content layout  
  11.   
  12.     private int mMenuPaddingRight;  
  13.     private int screenWidth;  
  14.     private boolean once; //是否分配过大小  
  15.     private int menuWidth;  
  16.   
  17.     /** 
  18.      * 当使用自定义属性的时候 
  19.      *  
  20.      * @param context 
  21.      * @param attrs 
  22.      */  
  23.     public MyView(Context context, AttributeSet attrs) {  
  24.         super(context, attrs);  
  25.         DisplayMetrics outMetrics = new DisplayMetrics();  
  26.         WindowManager wm = (WindowManager) context  
  27.                 .getSystemService(context.WINDOW_SERVICE);  
  28.         wm.getDefaultDisplay().getMetrics(outMetrics);  
  29.         screenWidth = outMetrics.widthPixels;  
  30.   
  31.         // 获取自定义的属性  
  32.         TypedArray array = context.getTheme().obtainStyledAttributes(attrs,  
  33.                 R.styleable.MyView, 00);  
  34.         // 查看有多少个属性  
  35.         int attributeNumber = array.getIndexCount();  
  36.         // 遍历每个属性  
  37.         for (int i = 0; i < attributeNumber; i++) {  
  38.             int attribute = array.getIndex(i);  
  39.             // 判断属性值  
  40.             switch (attribute) {  
  41.             case R.styleable.MyView_rightPadding:  
  42.                 mMenuPaddingRight = array.getDimensionPixelSize(attribute,  
  43.                         (int) TypedValue.applyDimension(  
  44.                                 TypedValue.COMPLEX_UNIT_DIP, 50, context  
  45.                                         .getResources().getDisplayMetrics()));  
  46.                 break;  
  47.             }  
  48.         }  
  49.         array.recycle();  
  50.     }  
  51.   
  52.     @Override  
  53.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  54.   
  55.         if (!once) {   
  56.             mWapper = (LinearLayout) getChildAt(0); // horizontal 下的 linearlayout  
  57.   
  58.             menu = (ViewGroup) mWapper.getChildAt(0);// linearlayout 下的 left menu  
  59.   
  60.             content = (ViewGroup) mWapper.getChildAt(1);// linearlayout home page  
  61.   
  62.             menuWidth = menu.getLayoutParams().width = screenWidth  
  63.                     - mMenuPaddingRight;  
  64.             content.getLayoutParams().width = screenWidth;  
  65.   
  66.             once = true;  
  67.         }  
  68.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  69.   
  70.     }  
  71.   
  72.     @Override  
  73.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  74.         super.onLayout(changed, l, t, r, b);  
  75.         if (changed) {  
  76.             this.scrollTo(menuWidth, 0);  
  77.         }  
  78.     }  
  79.   
  80.     /** 
  81.      * 实现抽屉式菜单. 第一个参数 l 就相当于 getScrollX 当滚动条改变的时候 不停的计算偏移量 
  82.      */  
  83.     @Override  
  84.     protected void onScrollChanged(int l, int t, int oldl, int oldt) {  
  85.         super.onScrollChanged(l, t, oldl, oldt);  
  86.   
  87.         float scale = l * 1.0f / menuWidth; // 1 ~ 0 变化  
  88.         ViewHelper.setTranslationX(menu, menuWidth * scale * 0.7f);  
  89.         /** 
  90.          *  
  91.          * QQ侧滑菜单与抽屉式侧滑区别.. 
  92.          *  
  93.          * 1, 内容区域 1.0 ~ 0.7的缩放效果 
  94.          *  
  95.          * scale : 1.0~0.0 0.7 + 0.3 * scale 
  96.          *  
  97.          * 2, 菜单的偏移量需要修改 
  98.          *  
  99.          * 3, 菜单显示的时候有缩放以及透明度变化 缩放: 0.7~ 1.0 1.0 - scale * 0.3 透明度 0.6 ~ 1.0 0.6 
  100.          * + 0.4 * (1 -scale) ; 
  101.          **/  
  102.         float rightScale = 0.7f + 0.3f * scale;  
  103.         float leftScale = 1.0f - scale * 0.3f;  
  104.         float alpha = 0.6f + 0.4f * (1f - scale);  
  105.         ViewHelper.setPivotX(content, 0);  
  106.         ViewHelper.setPivotY(content, content.getHeight() / 2);  
  107.         ViewHelper.setScaleX(content, rightScale);  
  108.         ViewHelper.setScaleY(content, rightScale);  
  109.         ViewHelper.setScaleX(menu, leftScale);  
  110.         ViewHelper.setScaleY(menu, leftScale);  
  111.         ViewHelper.setAlpha(menu, alpha);  
  112.     }  
  113.   
  114.     @Override  
  115.     public boolean onTouchEvent(MotionEvent ev) {  
  116.   
  117.         int action = ev.getAction();  
  118.         switch (action) {  
  119.         case MotionEvent.ACTION_UP:  
  120.             int scrollX = getScrollX();  
  121.   
  122.             if (scrollX >= menuWidth / 2) {  
  123.                 this.smoothScrollTo(menuWidth, 0);  
  124.             } else {  
  125.                 this.smoothScrollTo(00);  
  126.             }  
  127.             return true;  
  128.         }  
  129.   
  130.         return super.onTouchEvent(ev);  
  131.     }  
  132. }  

下面来说每个方法的作用 . 

onMeasure 中 需要计算子View 的宽和高, 以及设置自己的宽和高.
onLayout 中 计算 子 view 的位置

onTouchEvent 触摸时间,根据 offset 判断是否 切换

onScrollChanged  监听滑动状态, 方法内用到ViewHelper  是一个动画切换的jar包 (nineOldAndroids)


写的不好 忘见谅.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值