zoukankan      html  css  js  c++  java
  • Android之自定义侧滑菜单

    先来上图:

    我们把主界面从左向右拉动,可以看到地下有一层菜单页,从透明渐渐变得不透明,从小渐渐变大,感觉上觉得菜单页是从屏幕外面被拉到屏幕中的。下面的代码实现这个DEMO:

    首先是自定义控件SlidingMenu控件的代码

      1 public class SlidingMenu extends HorizontalScrollView {
      2     // 自定义View的步骤:
      3     // 1、onMeasure():决定子View的宽和高和自己的宽和高
      4     // 2、onLayout():决定子View放置的位置
      5     // 3、onTouchEvent:判断用户手指的滑动状态
      6     // 自定义属性的步骤:
      7     // 1、书写XML文件(values/attrs.xml)
      8     // 2、在布局文件中进行使用,注意xmlns命名空间
      9     // 3、在三个参数的构造方法中获得我们设置的值
     10 
     11     private LinearLayout wrapper; // 总容器
     12     private ViewGroup menu, content; // 菜单页,内容页
     13     private int screenWidth; // 屏幕的宽度
     14     private int menuWidth; // menu的宽度
     15     private int menuRightPadding = 50; // menu菜单距离屏幕右侧的距离(单位是DIP)
     16     private boolean once; // onMeasure()方法是不是第一次调用
     17     private boolean isOpen; // 侧滑菜单是否是开启状态
     18 
     19     // 在界面上通过上下文直接生成控件时,调用这个构造方法
     20     public SlidingMenu(Context context) {
     21         this(context, null);
     22     }
     23 
     24     // 当没有使用自定义属性时,调用这个构造方法
     25     public SlidingMenu(Context context, AttributeSet attrs) {
     26         this(context, attrs, 0);
     27     }
     28 
     29     // 当使用了自定义属性(values/attrs.xml)时,调用这个构造方法
     30     public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {
     31         super(context, attrs, defStyleAttr);
     32         // 获取我们自定义的属性
     33         TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenu, defStyleAttr, 0);
     34         for (int i = 0; i < a.getIndexCount(); i++) {
     35             int attr = a.getIndex(i);
     36             switch (attr) {
     37             case R.styleable.SlidingMenu_rightPadding:
     38                 // getDimensionPixelSize:为attr下标的属性设置默认值(第二个参数)
     39                 menuRightPadding = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
     40                         50, context.getResources().getDisplayMetrics()));
     41                 break;
     42             }
     43         }
     44         a.recycle();
     45 
     46         // 获取屏幕的宽度
     47         WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
     48         DisplayMetrics metrics = new DisplayMetrics();
     49         manager.getDefaultDisplay().getMetrics(metrics);
     50         screenWidth = metrics.widthPixels;
     51     }
     52 
     53     @Override
     54     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     55         if (!once) {
     56             wrapper = (LinearLayout) getChildAt(0);
     57             menu = (ViewGroup) wrapper.getChildAt(0);
     58             content = (ViewGroup) wrapper.getChildAt(1);
     59             // 设置菜单和主页的宽度
     60             menuWidth = menu.getLayoutParams().width = screenWidth - menuRightPadding;
     61             content.getLayoutParams().width = screenWidth;
     62             
     63             once = true;
     64         }
     65         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     66     }
     67 
     68     // 通过设置偏移量,将Menu隐藏
     69     @Override
     70     protected void onLayout(boolean changed, int l, int t, int r, int b) {
     71         super.onLayout(changed, l, t, r, b);
     72         if (changed) {
     73             this.scrollTo(menuWidth, 0);
     74         }
     75     }
     76 
     77     @Override
     78     public boolean onTouchEvent(MotionEvent ev) {
     79         int action = ev.getAction();
     80         switch (action) {
     81         case MotionEvent.ACTION_UP:
     82             int scrollX = getScrollX(); // 隐藏在左边的宽度
     83             if (scrollX >= menuWidth / 2) {
     84                 this.smoothScrollTo(menuWidth, 0);
     85                 isOpen = false;
     86             } else {
     87                 this.smoothScrollTo(0, 0);
     88                 isOpen = true;
     89             }
     90             return true;
     91         }
     92         return super.onTouchEvent(ev);
     93     }
     94 
     95     // 打开菜单
     96     public void openMenu() {
     97         if (isOpen)
     98             return;
     99         this.smoothScrollTo(0, 0);
    100         isOpen = false;
    101     }
    102 
    103     // 关闭菜单
    104     public void closeMenu() {
    105         if (!isOpen)
    106             return;
    107         this.smoothScrollTo(menuWidth, 0);
    108         isOpen = true;
    109     }
    110 
    111     // 管理菜单的状态和动作(如果菜单是关闭的就打开它,如果是打开的就关闭它)
    112     public void toggle() {
    113         if (isOpen) {
    114             closeMenu();
    115         } else {
    116             openMenu();
    117         }
    118     }
    119 
    120     // 抽屉式侧滑(这个方法监听滚动的全过程)
    121     @Override
    122     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    123         super.onScrollChanged(l, t, oldl, oldt);
    124         float scale = l * 1.0f / menuWidth;
    125         // 实现仿QQ5.0的侧滑界面:在滑动时,滑动朝向的ViewGroup不断缩小,另一个ViewGroup不断放大
    126         float rightScrollScale = 0.85f + 0.15f * scale; // 主界面的滑动缩放比例
    127         float leftScrollScale = 1.0f - 0.4f * scale; // 菜单的滑动缩放比例
    128         float leftAlphaScale = 0.6f + 0.4f * (1 - scale); // 菜单透明度的变化比例
    129         // 调用属性动画(Android3.0时引入),设置TranslationX(这里需要引入nineoldandroids.jar包)
    130         ViewHelper.setTranslationX(menu, menuWidth * scale * 0.75f);
    131         // 设置Menu的缩放和透明度
    132         ViewHelper.setScaleX(menu, leftScrollScale);
    133         ViewHelper.setScaleY(menu, leftScrollScale);
    134         ViewHelper.setAlpha(menu, leftAlphaScale);
    135         // 设置Content的缩放
    136         ViewHelper.setPivotX(content, 0);
    137         ViewHelper.setPivotY(content, content.getHeight() / 2);
    138         ViewHelper.setScaleX(content, rightScrollScale);
    139         ViewHelper.setScaleY(content, rightScrollScale);
    140     }
    141 }

    下面是主界面布局的代码

     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     xmlns:xgz="http://schemas.android.com/apk/res/com.activity"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     android:background="@drawable/menu_bg" >
     7 
     8     <com.view.SlidingMenu
     9         android:id="@+id/main_slidingmenu"
    10         android:layout_width="match_parent"
    11         android:layout_height="match_parent"
    12         xgz:rightPadding="75.0dip" >
    13 
    14         <LinearLayout
    15             android:layout_width="wrap_content"
    16             android:layout_height="match_parent"
    17             android:orientation="horizontal" >
    18 
    19             <include layout="@layout/sideworks_menu" />
    20 
    21             <LinearLayout
    22                 android:layout_width="match_parent"
    23                 android:layout_height="match_parent"
    24                 android:background="@drawable/main_bg" >
    25 
    26                 <Button
    27                     android:id="@+id/main_togglebtn"
    28                     android:layout_width="wrap_content"
    29                     android:layout_height="30.0dip"
    30                     android:layout_marginLeft="10.0dip"
    31                     android:layout_marginTop="10.0dip"
    32                     android:background="#00000000"
    33                     android:text="@string/main_toggle_btn"
    34                     android:textColor="#ffffff"
    35                     android:textSize="16.0sp" />
    36             </LinearLayout>
    37         </LinearLayout>
    38     </com.view.SlidingMenu>
    39 
    40 </RelativeLayout>

    下面是主界面中引用的菜单页的布局代码

      1 <?xml version="1.0" encoding="utf-8"?>
      2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      3     android:layout_width="match_parent"
      4     android:layout_height="match_parent"
      5     android:background="#00000000"
      6     android:gravity="center_vertical"
      7     android:orientation="vertical" >
      8 
      9     <RelativeLayout
     10         android:layout_width="match_parent"
     11         android:layout_height="wrap_content" >
     12 
     13         <ImageView
     14             android:id="@+id/menu_icon1"
     15             android:layout_width="40.0dip"
     16             android:layout_height="40.0dip"
     17             android:layout_marginLeft="10.0dip"
     18             android:contentDescription="@string/app_name"
     19             android:src="@drawable/img_1" />
     20 
     21         <TextView
     22             android:layout_width="wrap_content"
     23             android:layout_height="wrap_content"
     24             android:layout_centerVertical="true"
     25             android:layout_marginLeft="10.0dip"
     26             android:layout_toRightOf="@id/menu_icon1"
     27             android:text="@string/menu_icon1_text"
     28             android:textColor="#ffffff"
     29             android:textSize="15.0sp" />
     30     </RelativeLayout>
     31 
     32     <RelativeLayout
     33         android:layout_width="match_parent"
     34         android:layout_height="wrap_content"
     35         android:layout_marginTop="15.0dip" >
     36 
     37         <ImageView
     38             android:id="@+id/menu_icon2"
     39             android:layout_width="40.0dip"
     40             android:layout_height="40.0dip"
     41             android:layout_marginLeft="10.0dip"
     42             android:contentDescription="@string/app_name"
     43             android:src="@drawable/img_2" />
     44 
     45         <TextView
     46             android:layout_width="wrap_content"
     47             android:layout_height="wrap_content"
     48             android:layout_centerVertical="true"
     49             android:layout_marginLeft="10.0dip"
     50             android:layout_toRightOf="@id/menu_icon2"
     51             android:text="@string/menu_icon2_text"
     52             android:textColor="#ffffff"
     53             android:textSize="15.0sp" />
     54     </RelativeLayout>
     55 
     56     <RelativeLayout
     57         android:layout_width="match_parent"
     58         android:layout_height="wrap_content"
     59         android:layout_marginTop="15.0dip" >
     60 
     61         <ImageView
     62             android:id="@+id/menu_icon3"
     63             android:layout_width="40.0dip"
     64             android:layout_height="40.0dip"
     65             android:layout_marginLeft="10.0dip"
     66             android:contentDescription="@string/app_name"
     67             android:src="@drawable/img_3" />
     68 
     69         <TextView
     70             android:layout_width="wrap_content"
     71             android:layout_height="wrap_content"
     72             android:layout_centerVertical="true"
     73             android:layout_marginLeft="10.0dip"
     74             android:layout_toRightOf="@id/menu_icon3"
     75             android:text="@string/menu_icon3_text"
     76             android:textColor="#ffffff"
     77             android:textSize="15.0sp" />
     78     </RelativeLayout>
     79 
     80     <RelativeLayout
     81         android:layout_width="match_parent"
     82         android:layout_height="wrap_content"
     83         android:layout_marginTop="15.0dip" >
     84 
     85         <ImageView
     86             android:id="@+id/menu_icon4"
     87             android:layout_width="40.0dip"
     88             android:layout_height="40.0dip"
     89             android:layout_marginLeft="10.0dip"
     90             android:contentDescription="@string/app_name"
     91             android:src="@drawable/img_4" />
     92 
     93         <TextView
     94             android:layout_width="wrap_content"
     95             android:layout_height="wrap_content"
     96             android:layout_centerVertical="true"
     97             android:layout_marginLeft="10.0dip"
     98             android:layout_toRightOf="@id/menu_icon4"
     99             android:text="@string/menu_icon4_text"
    100             android:textColor="#ffffff"
    101             android:textSize="15.0sp" />
    102     </RelativeLayout>
    103 
    104     <RelativeLayout
    105         android:layout_width="match_parent"
    106         android:layout_height="wrap_content"
    107         android:layout_marginTop="15.0dip" >
    108 
    109         <ImageView
    110             android:id="@+id/menu_icon5"
    111             android:layout_width="40.0dip"
    112             android:layout_height="40.0dip"
    113             android:layout_marginLeft="10.0dip"
    114             android:contentDescription="@string/app_name"
    115             android:src="@drawable/img_5" />
    116 
    117         <TextView
    118             android:layout_width="wrap_content"
    119             android:layout_height="wrap_content"
    120             android:layout_centerVertical="true"
    121             android:layout_marginLeft="10.0dip"
    122             android:layout_toRightOf="@id/menu_icon5"
    123             android:text="@string/menu_icon5_text"
    124             android:textColor="#ffffff"
    125             android:textSize="15.0sp" />
    126     </RelativeLayout>
    127 
    128 </LinearLayout>

    下面是自定义属性attrs.xml文件中的代码

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <resources>
     3 
     4     <!-- 自定义属性:菜单离屏幕右侧的间距 -->
     5     <attr name="rightPadding" format="dimension"></attr>
     6 
     7     <declare-styleable name="SlidingMenu">
     8         <attr name="rightPadding"></attr>
     9     </declare-styleable>
    10 
    11 </resources>


    下面是主界面MainActivity.java中的代码

     1 public class MainActivity extends Activity {
     2     private SlidingMenu slidingMenu;
     3     private Button toggleBtn;
     4 
     5     @Override
     6     protected void onCreate(Bundle savedInstanceState) {
     7         super.onCreate(savedInstanceState);
     8         setContentView(R.layout.activity_main);
     9         slidingMenu = (SlidingMenu) findViewById(R.id.main_slidingmenu);
    10         toggleBtn = (Button) findViewById(R.id.main_togglebtn);
    11 
    12         toggleBtn.setOnClickListener(new OnClickListener() {
    13             @Override
    14             public void onClick(View v) {
    15                 slidingMenu.toggle();
    16             }
    17         });
    18     }
    19 }
  • 相关阅读:
    Spark Executor内存管理
    Spring中Bean的生命周期及其扩展点
    NIO非阻塞IO
    TCP,UDP和socket,Http之间联系和区别
    md5加密,md5加盐加密和解密
    线程监测方法多久没被调用
    项目部署后,替换.class文件不生效
    mysql存储过程导入表
    java生成二维码
    Map中keySet和entrySet的区别
  • 原文地址:https://www.cnblogs.com/blog-wzy/p/5268735.html
Copyright © 2011-2022 走看看