当前位置:   article > 正文

Android实现网易新闻客户端侧滑菜单(二)_android网易新闻客户端侧滑菜单设计

android网易新闻客户端侧滑菜单设计

前面已经讲过通过三方开源库SlideMenu来实现这种效果,请参考Android实现网易新闻客户端侧滑菜单(一)

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

代码如下:

SlideMenu.java

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

MainActivity.java

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/279504
推荐阅读
相关标签
  

闽ICP备14008679号