• 仿网易菜单 实现侧滑 SlidingMenu


      不知不觉已经工作一个月了,时间过的真快,提早一年步入社会,心里感触还是挺大了,所有的一切都没有了在学校的那种感觉  .....

      废话不多说,在公司做android的时候用到这个侧滑,公司里用的是开源框架,SlidingMenu,自己也尝试着去引用,感觉自己基础不好,实现起来十分费劲。

    无意之中,发现黑马老师的视频里有这个就听了下,基本照写了一遍,代码就放在这里,方便自己查看,复习,也方便像我这样的android小白,来研究学习。

    主界面:

    package com.tai.dandelion;
    
    import com.tai.dandelion.view.SlideMenu;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.KeyEvent;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.view.Window;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity implements OnClickListener
    {
        private SlideMenu viewGroup;//这就是下面自定义ViewGroup
        private ImageView slidingmenu;
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            //去除标题 一定要在setContentView之前
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            viewGroup = (SlideMenu) findViewById(R.id.slidmenu);
            slidingmenu = (ImageView) findViewById(R.id.iv_slidmenu_back);
            slidingmenu.setOnClickListener(this);
        }
        @Override
        public void onClick(View v)
        {
            switch (v.getId())
            {
            case R.id.iv_slidmenu_back:
                if(viewGroup.isShow())
                {
                    viewGroup.showMenu();
                }
                else
                {
                    viewGroup.hideMenu();
                }
                break;
            default:
                break;
            }
        }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        
        if (keyCode == KeyEvent.KEYCODE_MENU)
        {
            if(viewGroup.isShow())
            {
                viewGroup.showMenu();
            }
            else
            {
                viewGroup.hideMenu();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    //菜单的点击事件,在与布局文件中对应,这里的方法名与xml中的方法名对应。
    public void click(View v)
    {
        TextView tv = (TextView) v;
        Toast.makeText(this, tv.getText(), Toast.LENGTH_SHORT).show();
    }
    
    
    }

    侧滑菜单:ViewGroup

      1 package com.tai.dandelion.view;
      2 
      3 import android.content.Context;
      4 import android.util.AttributeSet;
      5 import android.view.MotionEvent;
      6 import android.view.View;
      7 import android.view.ViewConfiguration;
      8 import android.view.ViewGroup;
      9 import android.widget.Scroller;
     10 
     11 public class SlideMenu extends ViewGroup
     12 {
     13     private int touchSlop;
     14     public SlideMenu(Context context, AttributeSet attrs)
     15     {
     16         super(context, attrs);
     17         mScroller = new Scroller(context);
     18         //startX, startY, dx, dy,duration
     19         //滑动间距的距离 默认为8
     20         touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     21     }
     22     
     23     //测量出所有子布局的宽和高
     24         @Override
     25         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
     26         {
     27             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     28             //这个super必须要重写的
     29             measureView(widthMeasureSpec,heightMeasureSpec);
     30         }
     31     /**
     32      * int widthMeasureSpec, int heightMeasureSpec
     33      * @param widthMeasureSpec 父布局的测量
     34      * @param heightMeasureSpec
     35      */
     36     private void measureView(int widthMeasureSpec, int heightMeasureSpec)
     37     {
     38         //测量菜单布局
     39         View menuView = getChildAt(0);
     40         menuView.measure(menuView.getLayoutParams().width, heightMeasureSpec);
     41         //测量主界面的布局
     42         View mainView  = getChildAt(1);
     43         mainView.measure(widthMeasureSpec, heightMeasureSpec);
     44                 
     45     }
     46     //设置菜单和主界面的布局
     47     @Override
     48     protected void onLayout(boolean chenged, int l, int t, int r, int b)
     49     {
     50         //布置菜单的位置
     51         View menuView = getChildAt(0);
     52         //得到测量之后的边长
     53         menuView.layout(-menuView.getMeasuredWidth(), 0, 0, b);
     54         //布置主界面的位置
     55         View mainView =getChildAt(1);
     56         
     57         mainView.layout(0, 0, r, b);
     58         
     59     }
     60     private int mMostRecentX;//最后一次的X轴偏移量
     61     private int MenuScreen = 0;//菜单页面
     62     private int MainScreen = 1;//主界面
     63     private int mCurrentScreen = MainScreen;//当前屏幕的主界面
     64     //定义数据模拟器 来动态模拟数据的增量
     65     private Scroller mScroller;
     66     
     67     @Override
     68     public boolean onTouchEvent(MotionEvent event)
     69     {
     70         switch (event.getAction())
     71         {
     72         case MotionEvent.ACTION_DOWN:
     73             mMostRecentX = (int) event.getX();
     74             break;
     75         case MotionEvent.ACTION_MOVE:
     76             //最新的X轴偏移量
     77             int moveX = (int) event.getX();
     78             //增量值
     79             int detaX  = mMostRecentX - moveX;
     80             //把最新的X轴偏移量赋值给最后一次的X轴偏移量
     81             mMostRecentX = moveX;
     82             
     83             //得到X轴移动后的偏移量
     84             int newScrolLX = (int) (getScrollX() + detaX);
     85             //当前X轴的偏移量超过了菜单的边界
     86             if(newScrolLX<-getChildAt(0).getWidth())
     87             {
     88                 //回到菜单的左边界
     89                 scrollTo(-getChildAt(0).getWidth(), 0);
     90             }
     91             else if(newScrolLX>0)
     92             {
     93                 //回到主界面的左边界
     94                 scrollTo(0, 0);
     95             }
     96             else
     97             {
     98                 scrollBy(detaX, 0);
     99             }
    100             break;
    101         case MotionEvent.ACTION_UP :
    102             //最新的X轴偏移量
    103             int scrollX = (int) getScrollX();
    104             //菜单的中心X轴
    105             int menuXCenter = -getChildAt(0).getWidth()/2;
    106             if(scrollX>menuXCenter)
    107             {//切换到主界面
    108                 mCurrentScreen = MainScreen;
    109             }
    110             else
    111             {//切换到菜单界面
    112                 mCurrentScreen = MenuScreen;
    113             }
    114             switchScreen();
    115             break;
    116         default:
    117             break;
    118         }
    119         
    120         return true;
    121     }
    122     
    123     private void switchScreen()
    124     {
    125         int scrollX = getScrollX();
    126         int dx = 0;
    127         if(mCurrentScreen == MainScreen)
    128         {//切换到主界面
    129 //            scrollTo(0, 0);
    130             dx = 0-scrollX;
    131         }
    132         else if(mCurrentScreen == MenuScreen)
    133         {//切换到菜单界面
    134 //            scrollTo(-getChildAt(0).getWidth(), 0);
    135             dx = -getChildAt(0).getWidth()-scrollX;
    136         }
    137         mScroller.startScroll(scrollX, 0, dx, 0, Math.abs(dx)*3);
    138         
    139         invalidate();//invalidate --> drawChild -->chlid.draw -->computerScroll
    140     }
    141     @Override
    142     public void computeScroll()
    143     {
    144         //invaliadate调用此方法,更新X轴的偏移量
    145         if(mScroller.computeScrollOffset()) //判断是否正在模拟数据中,true 正在进行
    146         {
    147             scrollTo(mScroller.getCurrX(), 0);
    148             
    149             invalidate();//引起computeScroll的调用
    150         }
    151     }
    152     //时候显示菜单
    153     public boolean isShow()
    154     {
    155         return mCurrentScreen == MainScreen;
    156     }
    157     
    158     public void hideMenu()
    159     {
    160         mCurrentScreen = MainScreen;
    161         switchScreen();
    162     }
    163     
    164     public void showMenu()
    165     {
    166         mCurrentScreen = MenuScreen;
    167         switchScreen();
    168     }
    169     /**
    170      * 拦截事件的方法
    171      */
    172     @Override
    173     public boolean onInterceptTouchEvent(MotionEvent ev)
    174     {
    175         switch (ev.getAction())
    176         {
    177         case MotionEvent.ACTION_DOWN:
    178             mMostRecentX = (int) ev.getX();
    179             break;
    180         case MotionEvent.ACTION_MOVE:
    181             int diffX = (int) (ev.getX() - mMostRecentX);
    182             if(Math.abs(diffX)>touchSlop)
    183             {
    184                 return true;
    185             }
    186             break;
    187         default:
    188             break;
    189         }
    190         return super.onInterceptTouchEvent(ev);
    191     }
    192 }

    主要的核心方法:Scrollto、ScrollBy  

    invalidate();//invalidate --> drawChild -->chlid.draw -->computerScroll 这里比较复杂,大家可以查阅一下有关资料

    布局文件:
     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     tools:context=".MainActivity" >
     6 
     7     <com.tai.dandelion.view.SlideMenu
     8         android:id="@+id/slidmenu"
     9         android:layout_width="fill_parent"
    10         android:layout_height="fill_parent">
    11        <include layout="@layout/slidemenu_menu"/>
    12        <include layout="@layout/mian"/> 
    13     </com.tai.dandelion.view.SlideMenu>
    14         
    15 
    16 </RelativeLayout>

    非android原生控件定义的时候要写上自定义类的全名  

     com.tai.dandelion.view.SlideMenu
     侧滑主界面
     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:orientation="vertical" >
     6     <LinearLayout 
     7         android:layout_width="fill_parent"
     8         android:layout_height="wrap_content"
     9         android:orientation="horizontal"
    10         android:background="@drawable/top_bar_bg">
    11         <ImageView 
    12             android:id="@+id/iv_slidmenu_back"
    13             android:layout_width="wrap_content"
    14             android:layout_height="wrap_content"
    15             android:background="@drawable/main_back"
    16             />
    17         <View android:layout_width="1dip"
    18             android:layout_height="fill_parent"
    19             android:background="@drawable/top_bar_divider"
    20             android:layout_margin="5dip"/>
    21         <TextView 
    22             android:layout_width="wrap_content"
    23             android:layout_height="wrap_content"
    24             android:layout_gravity="center_vertical"
    25             android:layout_marginLeft="55dip"
    26             android:text="title"
    27             android:textSize="26sp"
    28             android:textColor="@android:color/white"/>
    29     </LinearLayout>
    30 
    31     
    32     
    33     <TextView 
    34         android:layout_width="fill_parent"
    35         android:layout_height="fill_parent"
    36         android:text="内容"
    37         android:gravity="center"
    38         android:textColor="#ff0000"
    39         android:textSize="26sp"/>
    40     
    41     
    42     
    43     
    44 </LinearLayout>

    侧滑隐藏菜单

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="240dip"
     4     android:layout_height="match_parent" >
     5 <!-- ScrollView只允许有一个子控件 -->
     6     <LinearLayout
     7         android:layout_width="240dip"
     8         android:background="@drawable/menu_bg"
     9         android:layout_height="wrap_content"
    10         android:orientation="vertical" >
    11         <TextView 
    12             style="@style/menu_style"
    13             android:text="新闻"
    14             android:drawableLeft="@drawable/tab_news"
    15             />
    16          <TextView 
    17             style="@style/menu_style"
    18             android:text="订阅"
    19             android:drawableLeft="@drawable/tab_read"
    20             />
    21          <TextView 
    22             style="@style/menu_style"
    23             android:text="菜单"
    24             android:drawableLeft="@drawable/tab_pics"
    25             />
    26          <TextView 
    27             style="@style/menu_style"
    28             android:text="本地"
    29             android:drawableLeft="@drawable/tab_local"
    30             />
    31          <TextView 
    32             style="@style/menu_style"
    33             android:text="跟帖"
    34             android:drawableLeft="@drawable/tab_ties"
    35             />
    36          <TextView 
    37             style="@style/menu_style"
    38             android:text="投票"
    39             android:drawableLeft="@drawable/tab_vote"
    40             />
    41          <TextView 
    42             style="@style/menu_style"
    43             android:text="聚合阅读"
    44             android:drawableLeft="@drawable/tab_focus"
    45             />
    46     </LinearLayout>
    47     
    48 
    49 </ScrollView>

    style中的菜单的样式:

     1  <style name="menu_style">
     2         <item name="android:layout_width">fill_parent</item>
     3         <item name="android:layout_height">wrap_content</item>
     4         <item name="android:paddingTop">10dip</item>
     5         <item name="android:paddingBottom">10dip</item>
     6         <item name="android:textColor">@android:color/white</item>
     7         <item name="android:background">@drawable/text_bg</item>
     8         <item name="android:textSize">23sp</item>
     9         <item name="android:gravity">center_vertical</item>
    10         <item name="android:paddingLeft">15dip</item>
    11         <item name="android:drawablePadding">30dip</item>
    12         <item name="android:clickable">true</item>
    13         <item name="android:onClick">click</item>
    14     </style>

    菜单项的选择器

    1 <?xml version="1.0" encoding="utf-8"?>
    2 <selector xmlns:android="http://schemas.android.com/apk/res/android" >
    3     <item android:state_pressed="true" android:drawable="@color/press"></item>
    4     <item android:state_pressed="false" android:drawable="@color/pressed"></item>
    5 </selector>

    Manifast中Activity的声明就这里就不贴了。别的基本没什么。代码就在这里,有用的到的朋友可以研究一下。

                                                    整理By      android小白。

    最终效果:

  • 相关阅读:
    LeetCode刷题191120
    LeetCode刷题191119
    LeetCode刷题191118
    LeetCode刷题191117
    Http相关小知识点笔记咯~
    Java开发之JSP指令
    Java开发之Servlet之间的跳转
    Java开发之Servlet生命周期
    Java开发之文件上传
    微信公众号开发之数据库
  • 原文地址:https://www.cnblogs.com/mauiie/p/Ma.html
Copyright © 2020-2023  润新知