Android实现网易新闻客户端侧滑菜单

通过自定义View来实现这种功能。

代码如下:

SlideMenu.java

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

MainActivity.java

[java]  view plain copy
  1. package com.jackie.slidemenu;  
  2.   
  3. import com.jackie.slidemenu.view.SlideMenu;  
  4.   
  5. import android.os.Bundle;  
  6. import android.app.Activity;  
  7. import android.view.Menu;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.view.Window;  
  11. import android.widget.TextView;  
  12. import android.widget.Toast;  
  13.   
  14. public class MainActivity extends Activity implements OnClickListener {  
  15.   
  16.     private SlideMenu mSlideMenu;  
  17.   
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         // 去除标题, 需要在setContentView之前调用  
  22.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  23.         setContentView(R.layout.activity_main);  
  24.           
  25.           
  26.         mSlideMenu = (SlideMenu) findViewById(R.id.slidemenu);  
  27.         findViewById(R.id.iv_slidemenu_main_back).setOnClickListener(this);  
  28.           
  29.           
  30.     }  
  31.   
  32.     @Override  
  33.     public boolean onCreateOptionsMenu(Menu menu) {  
  34.         // Inflate the menu; this adds items to the action bar if it is present.  
  35.         getMenuInflater().inflate(R.menu.main, menu);  
  36.         return true;  
  37.     }  
  38.   
  39.     @Override  
  40.     public void onClick(View v) {  
  41.         if(mSlideMenu.isShowMenu()) {  
  42.             mSlideMenu.hideMenu();  
  43.         } else {  
  44.             mSlideMenu.showMenu();  
  45.         }  
  46.     }  
  47.   
  48.     public void click(View v) {  
  49.         TextView tv = (TextView) v;  
  50.         Toast.makeText(this, tv.getText(), 0).show();  
  51.     }  

你可能感兴趣的:(自定义控件,侧滑)