• android 自己实现qqminihd 左右滑动菜单效果


    观察qqminihd界面,发现其界面能够左右滑动来实现两侧菜单效果。

    自定义Layout:ScrollLayout.java

    直接贴出代码:

    View Code
      1 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                     @Override
    114                     public void onLongPress(MotionEvent e) {
    115                     }
    116 
    117                     @Override
    118                     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                     @Override
    133                     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     @Override
    144     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     @Override
    161     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     @Override
    170     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 whichScreen
    216      */
    217     public void scrollToScreen(int whichScreen) {
    218             if (getFocusedChild() != null && whichScreen != currentScreenIndex
    219                             && 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             else
    231                 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         else
    250             scrollToScreen(2);
    251     }
    252 
    253     public interface OnScrollSideChangedListener
    254     {
    255         public void onScrollSideChanged(View v,boolean leftSide);
    256     }
    257 }

    接下来,在定义activity里面的布局my_layout.xml:

    View Code
     1 <?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         <Button
    15             android:layout_width="200dp"
    16             android:layout_height="wrap_content"
    17             android:text="左菜单一" />
    18         <Button
    19             android:layout_width="200dp"
    20             android:layout_height="wrap_content"
    21             android:text="左菜单二" />
    22     </LinearLayout>
    23 
    24     <LinearLayout
    25         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         <LinearLayout
    31             android:layout_width="wrap_content"
    32             android:layout_height="wrap_content"
    33             android:layout_weight="1"
    34             android:orientation="vertical" >
    35         </LinearLayout>
    36         <LinearLayout
    37             android:layout_width="200dp"
    38             android:layout_height="wrap_content"
    39             android:orientation="vertical" >
    40             <Button
    41                 android:layout_width="match_parent"
    42                 android:layout_height="wrap_content"
    43                 android:text="右菜单一" />
    44             <Button
    45                 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.ScrollLayout
    53         android:layout_width="match_parent"
    54         android:orientation="vertical"
    55         android:id="@+id/my_scrollLayout"
    56         android:layout_height="match_parent">
    57         <LinearLayout
    58             android:layout_width="match_parent"
    59             android:layout_height="match_parent"
    60             android:background="#aaa"
    61             android:orientation="vertical" >
    62 
    63 
    64             <Button
    65                 android:id="@+id/button1"
    66                 android:layout_width="match_parent"
    67                 android:layout_height="wrap_content"
    68                 android:text="Button Button" />
    69 
    70             <Spinner
    71                 android:id="@+id/spinner1"
    72                 android:layout_width="match_parent"
    73                 android:layout_height="wrap_content" />
    74 
    75             <SeekBar
    76                 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 Code
     1 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             @Override
    11             public void onScrollSideChanged(View v, boolean leftSide) {
    12                 if(leftSide)
    13                 {
    14                     right.setVisibility(View.GONE);
    15                     left.setVisibility(View.VISIBLE);
    16                 }else
    17                 {
    18                     right.setVisibility(View.VISIBLE);
    19                     left.setVisibility(View.GONE);
    20                 }
    21             }
    22         });

    大功告成!左右滑动是弹性效果也一并实现~

  • 相关阅读:
    Mvc分页:为IQueryable定义一个扩展方法,直接反回PagedList<T>结果集
    从零开始一起学习SLAM | 相机成像模型
    从零开始一起学习SLAM | 为啥需要李群与李代数?
    从零开始一起学习SLAM | 三维空间刚体的旋转
    从零开始一起学习SLAM | 为什么要用齐次坐标?
    从零开始一起学习SLAM | C++新特性要不要学?
    从零开始一起学习SLAM | SLAM有什么用?
    从零开始一起学习SLAM | 学习SLAM到底需要学什么?
    2019年度【计算机视觉&机器学习&人工智能】国际重要会议汇总
    从零开始一起学习SLAM | 为什么要学SLAM?
  • 原文地址:https://www.cnblogs.com/zhouchanwen/p/2726984.html
Copyright © 2020-2023  润新知