android 自己实现qqminihd 左右滑动菜单效果
16lz
2021-01-23
观察qqminihd界面,发现其界面能够左右滑动来实现两侧菜单效果。
自定义Layout:ScrollLayout.java
直接贴出代码:
View Code1 package grimbo.android.demo.slidingmenu; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.view.GestureDetector; 7 import android.view.GestureDetector.OnGestureListener; 8 import android.view.MotionEvent; 9 import android.view.View; 10 import android.view.ViewConfiguration; 11 import android.view.animation.AnimationUtils; 12 import android.widget.LinearLayout; 13 import android.widget.Scroller; 14 15 public class ScrollLayout extends LinearLayout { 16 17 // private static final String TAG = "scroller"; 18 19 private Scroller scroller; 20 21 private int currentScreenIndex; 22 23 private GestureDetector gestureDetector; 24 25 // 设置一个标志位,防止底层的onTouch事件重复处理UP事件 26 private boolean fling; 27 28 /** 29 * 菜单栏的宽度 30 */ 31 int menuWidth=80; 32 33 /** 34 * 显示左边菜单 35 * 否则显示右边菜单 36 */ 37 private boolean showLeft=true; 38 39 /** 40 * 滚出边界监听器 41 */ 42 private OnScrollSideChangedListener scrollSideChangedListener; 43 44 public Scroller getScroller() { 45 return scroller; 46 } 47 48 public OnScrollSideChangedListener getScrollSideChangedListener() { 49 return scrollSideChangedListener; 50 } 51 52 public void setScrollSideChangedListener( 53 OnScrollSideChangedListener scrollSideChangedListener) { 54 this.scrollSideChangedListener = scrollSideChangedListener; 55 } 56 57 public ScrollLayout(Context context, AttributeSet attrs) { 58 super(context, attrs); 59 initView(context); 60 } 61 62 public ScrollLayout(Context context) { 63 super(context); 64 initView(context); 65 } 66 67 private void initView(final Context context) { 68 this.scroller = new Scroller(context,AnimationUtils.loadInterpolator(context, 69 android.R.anim.overshoot_interpolator)); 70 71 this.gestureDetector = new GestureDetector(new OnGestureListener() { 72 73 @Override 74 public boolean onSingleTapUp(MotionEvent e) { 75 return false; 76 } 77 78 @Override 79 public void onShowPress(MotionEvent e) { 80 } 81 82 @Override 83 public boolean onScroll(MotionEvent e1, MotionEvent e2, 84 float distanceX, float distanceY) { 85 86 {// 防止向第一页之前移动 87 if(1==currentScreenIndex) 88 { 89 int screenLeft=getWidth()-menuWidth; 90 if(showLeft && getScrollX()>screenLeft) 91 { 92 showLeft=false; 93 // Log.e("TAG","显示右边菜单栏"); 94 if(null!=scrollSideChangedListener) 95 scrollSideChangedListener.onScrollSideChanged(ScrollLayout.this, showLeft); 96 } 97 else if(!showLeft && getScrollX()<screenLeft) 98 { 99 showLeft=true;100 // Log.e("TAG","显示左边菜单栏");101 if(null!=scrollSideChangedListener)102 scrollSideChangedListener.onScrollSideChanged(ScrollLayout.this, showLeft);103 }104 }105 106 fling = true;107 scrollBy((int) distanceX, 0);108 // Log.d("TAG", "on scroll>>>>>>>>>>>>>>>>>移动<<<<<<<<<<<<<<>>>");109 }110 return true;111 }112 113 @Override114 public void onLongPress(MotionEvent e) {115 }116 117 @Override118 public boolean onFling(MotionEvent e1, MotionEvent e2,119 float velocityX, float velocityY) {120 121 if (Math.abs(velocityX) > ViewConfiguration.get(context)122 .getScaledMinimumFlingVelocity()) 123 {// 判断是否达到最小轻松速度,取绝对值的124 fling = true;125 snapToDestination();126 // Log.d(TAG, "on scroll>>>>>>>>>>>>>>>>>滑动<<<<<<<<<<<<<<>>>");127 }128 129 return true;130 }131 132 @Override133 public boolean onDown(MotionEvent e) {134 return false;135 }136 });137 138 }139 //每一个屏的边界值140 //0----[getWidth()-20]----[2*getWidth()-20]-----[3*getWidth()-40]141 142 143 @Override144 protected void onLayout(boolean changed, int left, int top, int right,145 int bottom) {146 /**147 * 设置布局,将子视图顺序横屏排列148 */149 super.onLayout(changed, left, top, right, bottom);150 int move=getWidth()-menuWidth;151 for (int i = 0; i < getChildCount(); i++) 152 {153 View child = getChildAt(i);154 // child.setVisibility(View.VISIBLE);155 //移动一定的距离156 child.layout(child.getLeft()+move,child.getTop(),child.getRight()+move,child.getBottom());157 }158 }159 160 @Override161 public void computeScroll() {162 if (scroller.computeScrollOffset()) {163 // Log.d(TAG, ">>>>>>>>>>computeScroll>>>>>"+scroller.getCurrX());164 scrollTo(scroller.getCurrX(), 0);165 postInvalidate();166 }167 }168 169 @Override170 public boolean onTouchEvent(MotionEvent event) {171 172 float x2s=getScrollX()+event.getX();173 174 if(x2s<getWidth()-menuWidth || x2s>2*getWidth()-menuWidth)175 {//动作在区域外面176 if(!fling)//没有在滑动177 {178 // Log.d(TAG, "on scroll>>>>>>>>>>>>>>>>>动作在区域外面 没有在滑动<<<<<<<<<<<<<<>>>");179 return false;180 }181 else if(MotionEvent.ACTION_UP!=event.getAction())182 {//否则如果也不是抬起手势,则强制模拟抬起183 snapToDestination();184 fling = false;185 // Log.d(TAG, "on scroll>>>>>>>>>>>>>>>>>动作在区域外面 在滑动 也不是抬起手势<<<<<<<<<<<<<<>>>");186 return false;187 }188 // Log.e(TAG, "on scroll>>>>>>>>>>>>>>>>>动作在区域外面 在滑动 是抬起手势<<<<<<<<<<<<<<>>>");189 }190 191 gestureDetector.onTouchEvent(event);192 193 switch (event.getAction()) {194 case MotionEvent.ACTION_DOWN:195 break;196 case MotionEvent.ACTION_MOVE:197 break;198 case MotionEvent.ACTION_UP:199 // Log.d(TAG, ">>ACTION_UP:>>>>>>>> MotionEvent.ACTION_UP>>>>>");200 // if (!fling) 201 {202 snapToDestination();203 }204 fling = false;205 break;206 default:207 break;208 }209 return true;210 }211 212 /**213 * 切换到指定屏214 * 215 * @param whichScreen216 */217 public void scrollToScreen(int whichScreen) {218 if (getFocusedChild() != null && whichScreen != currentScreenIndex219 && getFocusedChild() == getChildAt(currentScreenIndex)) {220 getFocusedChild().clearFocus();221 }222 int delta = 0;223 224 if(whichScreen==0)225 delta= - getScrollX();226 else if(whichScreen==1)227 delta= getWidth()-menuWidth- getScrollX();228 else if(whichScreen==2)229 delta= 2*(getWidth()-menuWidth)- getScrollX();230 else231 return;232 // delta = whichScreen * getWidth() - getScrollX();233 234 scroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);235 invalidate();236 237 currentScreenIndex = whichScreen;238 }239 240 /**241 * 根据当前x坐标位置确定切换到第几屏242 */243 private void snapToDestination() {244 245 if(getScrollX()<(getWidth()-menuWidth)/2)246 scrollToScreen(0);247 else if(getScrollX()<(getWidth()-menuWidth+getWidth()/2))248 scrollToScreen(1);249 else250 scrollToScreen(2);251 }252 253 public interface OnScrollSideChangedListener254 {255 public void onScrollSideChanged(View v,boolean leftSide);256 }257 }
接下来,在定义activity里面的布局my_layout.xml:
View Code1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res/grimbo.android.demo.slidingmenu" 4 android:id="@+id/FrameLayout1" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" > 7 <LinearLayout 8 android:layout_width="match_parent" 9 android:layout_height="match_parent"10 android:id="@+id/left_menu"11 android:background="#333"12 android:orientation="vertical" >13 14 <Button15 android:layout_width="200dp"16 android:layout_height="wrap_content"17 android:text="左菜单一" />18 <Button19 android:layout_width="200dp"20 android:layout_height="wrap_content"21 android:text="左菜单二" />22 </LinearLayout>23 24 <LinearLayout25 android:id="@+id/right_menu"26 android:layout_width="match_parent"27 android:layout_height="match_parent"28 android:background="#666"29 android:orientation="horizontal" >30 <LinearLayout31 android:layout_width="wrap_content"32 android:layout_height="wrap_content"33 android:layout_weight="1"34 android:orientation="vertical" >35 </LinearLayout>36 <LinearLayout37 android:layout_width="200dp"38 android:layout_height="wrap_content"39 android:orientation="vertical" >40 <Button41 android:layout_width="match_parent"42 android:layout_height="wrap_content"43 android:text="右菜单一" />44 <Button45 android:layout_width="match_parent"46 android:layout_height="wrap_content"47 android:text="右菜单二" />48 49 </LinearLayout>50 51 </LinearLayout>52 <grimbo.android.demo.slidingmenu.ScrollLayout53 android:layout_width="match_parent"54 android:orientation="vertical"55 android:id="@+id/my_scrollLayout"56 android:layout_height="match_parent">57 <LinearLayout58 android:layout_width="match_parent"59 android:layout_height="match_parent"60 android:background="#aaa"61 android:orientation="vertical" >62 63 64 <Button65 android:id="@+id/button1"66 android:layout_width="match_parent"67 android:layout_height="wrap_content"68 android:text="Button Button" />69 70 <Spinner71 android:id="@+id/spinner1"72 android:layout_width="match_parent"73 android:layout_height="wrap_content" />74 75 <SeekBar76 android:id="@+id/seekBar1"77 android:layout_width="match_parent"78 android:layout_height="wrap_content" />79 80 </LinearLayout>81 82 </grimbo.android.demo.slidingmenu.ScrollLayout>83 84 </FrameLayout>
最后,在activity里面的onCreate函数里加上:
View Code1 setContentView(R.layout.my_layout); 2 3 final LinearLayout left=(LinearLayout)findViewById(R.id.left_menu); 4 final LinearLayout right=(LinearLayout)findViewById(R.id.right_menu); 5 right.setVisibility(View.GONE); 6 left.setVisibility(View.VISIBLE); 7 8 ScrollLayout mScrollLayout=(ScrollLayout)findViewById(R.id.my_scrollLayout); 9 mScrollLayout.setScrollSideChangedListener(new OnScrollSideChangedListener() {10 @Override11 public void onScrollSideChanged(View v, boolean leftSide) {12 if(leftSide)13 {14 right.setVisibility(View.GONE);15 left.setVisibility(View.VISIBLE);16 }else17 {18 right.setVisibility(View.VISIBLE);19 left.setVisibility(View.GONE);20 }21 }22 });
大功告成!左右滑动是弹性效果也一并实现~
原创文章欢迎转载,转载请注明出处:http://www.cnblogs.com/zhouchanwen
更多相关文章
- 史上最全!最经典!最无私的Android资料(书籍+代码)分享-不要积分(求置
- Android 5中不同效果的Toast
- Android实现textview文字滚动显示(跑马灯效果)
- GreenDao自动生成Android数据库操作代码
- Android源代码下载与编译
- android实现节点进度条效果
- android启动时应用程序渐变效果
- 【Android】自定义环形菜单View
- Android应用libGDX引擎系列(一)-Android FrameWork 基于libGDX实