仿网易菜单 实现侧滑 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小白。

最终效果:

原文地址:https://www.cnblogs.com/mauiie/p/Ma.html