自定义ViewGroup 实现拖动跟快速滚动的效果


效果: 1:子控件跟着手指移动  2:快速拨动一下,根据拨动的速度 滑动过去  3:拖过头,放手后弹回去 
   但是用listView或者GridView又不好实现项目要求的其他效果..于是继承viewGroup实现以上效果。 
   既然要获取拨动速度,并以此滑动。首先想到了OnGestureListener 这个接口,实现这个接口并实现其onFling方法. 
  还要控制拖动。重写onTouchEvent方法,并在其中控制内容控件的拖动,反弹等效果 
这时候基本已经完成了。。。。测试了一下了,发现了一个问题,当手指点在viewGroup上 
进行 拖动是没问题的,但是在子控件上就不行了,这是事件响应的问题 那么还要做如面的处 

理:实现onInterceptTouchEvent方法,判断是拖动事件时 ,将事件传递下去。 

 

 

  1. import java.util.List;    
  2. import android.content.Context;    
  3. import android.graphics.Color;    
  4. import android.util.Log;    
  5. import android.view.GestureDetector;    
  6. import android.view.MotionEvent;    
  7. import android.view.View;    
  8. import android.view.ViewConfiguration;    
  9. import android.view.ViewGroup;    
  10. import android.view.GestureDetector.OnGestureListener;    
  11. import android.widget.Button;    
  12. import android.widget.ImageView;    
  13. import android.widget.Scroller;    
  14. import android.widget.Toast;    
  15. import android.widget.ImageView.ScaleType;    
  16.     
  17. public class MyViewGroup extends ViewGroup implements OnGestureListener {    
  18.     
  19.     private float mLastMotionY;// 最后点击的点    
  20.     private GestureDetector detector;    
  21.     int move = 0;// 移动距离    
  22.     int MAXMOVE = 850;// 最大允许的移动距离    
  23.     private Scroller mScroller;    
  24.     int up_excess_move = 0;// 往上多移的距离    
  25.     int down_excess_move = 0;// 往下多移的距离    
  26.     private final static int TOUCH_STATE_REST = 0;    
  27.     private final static int TOUCH_STATE_SCROLLING = 1;    
  28.     private int mTouchSlop;    
  29.     private int mTouchState = TOUCH_STATE_REST;    
  30.     Context mContext;    
  31.         
  32.     
  33.     public MyViewGroup(Context context) {    
  34.         super(context);    
  35.         mContext = context;    
  36.         // TODO Auto-generated constructor stub    
  37.         setBackgroundResource(R.drawable.pic);    
  38.         mScroller = new Scroller(context);    
  39.         detector = new GestureDetector(this);    
  40.     
  41.         final ViewConfiguration configuration = ViewConfiguration.get(context);    
  42.         // 获得可以认为是滚动的距离    
  43.         mTouchSlop = configuration.getScaledTouchSlop();    
  44.     
  45.         // 添加子View    
  46.         for (int i = 0; i < 48; i++) {    
  47.             final Button    MButton = new Button(context);    
  48.             MButton.setText("" + (i + 1));    
  49.             MButton.setOnClickListener(new OnClickListener() {    
  50.                     
  51.                 public void onClick(View v) {    
  52.                     // TODO Auto-generated method stub    
  53.                     Toast.makeText(mContext, MButton.getText(), Toast.LENGTH_SHORT).show();     
  54.                 }    
  55.             });    
  56.             addView(MButton);    
  57.         }    
  58.     }    
  59.     
  60.     @Override    
  61.     public void computeScroll() {    
  62.         if (mScroller.computeScrollOffset()) {    
  63.             // 返回当前滚动X方向的偏移    
  64.             scrollTo(0, mScroller.getCurrY());    
  65.             postInvalidate();    
  66.         }    
  67.     }    
  68.     
  69.     @Override    
  70.     public boolean onInterceptTouchEvent(MotionEvent ev) {    
  71.         final int action = ev.getAction();    
  72.     
  73.         final float y = ev.getY();    
  74.         switch (ev.getAction())    
  75.         {    
  76.         case MotionEvent.ACTION_DOWN:    
  77.     
  78.             mLastMotionY = y;    
  79.             mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST    
  80.                     : TOUCH_STATE_SCROLLING;    
  81.             break;    
  82.         case MotionEvent.ACTION_MOVE:    
  83.             final int yDiff = (int) Math.abs(y - mLastMotionY);    
  84.             boolean yMoved = yDiff > mTouchSlop;    
  85.             // 判断是否是移动    
  86.             if (yMoved) {    
  87.                 mTouchState = TOUCH_STATE_SCROLLING;    
  88.             }    
  89.             break;    
  90.         case MotionEvent.ACTION_UP:    
  91.             mTouchState = TOUCH_STATE_REST;    
  92.             break;    
  93.         }    
  94.         return mTouchState != TOUCH_STATE_REST;    
  95.     }    
  96.     
  97.     @Override    
  98.     public boolean onTouchEvent(MotionEvent ev) {    
  99.     
  100.         // final int action = ev.getAction();    
  101.     
  102.         final float y = ev.getY();    
  103.         switch (ev.getAction())    
  104.         {    
  105.         case MotionEvent.ACTION_DOWN:    
  106.             if (!mScroller.isFinished()) {    
  107.                 mScroller.forceFinished(true);    
  108.                 move = mScroller.getFinalY();    
  109.             }    
  110.             mLastMotionY = y;    
  111.             break;    
  112.         case MotionEvent.ACTION_MOVE:    
  113.             if (ev.getPointerCount() == 1) {    
  114.                     
  115.                 // 随手指 拖动的代码    
  116.                 int deltaY = 0;    
  117.                 deltaY = (int) (mLastMotionY - y);    
  118.                 mLastMotionY = y;    
  119.                 Log.d("move", "" + move);    
  120.                 if (deltaY < 0) {    
  121.                     // 下移    
  122.                     // 判断上移 是否滑过头    
  123.                     if (up_excess_move == 0) {    
  124.                         if (move > 0) {    
  125.                             int move_this = Math.max(-move, deltaY);    
  126.                             move = move + move_this;    
  127.                             scrollBy(0, move_this);    
  128.                         } else if (move == 0) {// 如果已经是最顶端 继续往下拉    
  129.                             Log.d("down_excess_move", "" + down_excess_move);    
  130.                             down_excess_move = down_excess_move - deltaY / 2;// 记录下多往下拉的值    
  131.                             scrollBy(0, deltaY / 2);    
  132.                         }    
  133.                     } else if (up_excess_move > 0)// 之前有上移过头    
  134.                     {                       
  135.                         if (up_excess_move >= (-deltaY)) {    
  136.                             up_excess_move = up_excess_move + deltaY;    
  137.                             scrollBy(0, deltaY);    
  138.                         } else {                            
  139.                             up_excess_move = 0;    
  140.                             scrollBy(0, -up_excess_move);                   
  141.                         }    
  142.                     }    
  143.                 } else if (deltaY > 0) {    
  144.                     // 上移    
  145.                     if (down_excess_move == 0) {    
  146.                         if (MAXMOVE - move > 0) {    
  147.                             int move_this = Math.min(MAXMOVE - move, deltaY);    
  148.                             move = move + move_this;    
  149.                             scrollBy(0, move_this);    
  150.                         } else if (MAXMOVE - move == 0) {    
  151.                             if (up_excess_move <= 100) {    
  152.                                 up_excess_move = up_excess_move + deltaY / 2;    
  153.                                 scrollBy(0, deltaY / 2);    
  154.                             }    
  155.                         }    
  156.                     } else if (down_excess_move > 0) {    
  157.                         if (down_excess_move >= deltaY) {    
  158.                             down_excess_move = down_excess_move - deltaY;    
  159.                             scrollBy(0, deltaY);    
  160.                         } else {    
  161.                             down_excess_move = 0;    
  162.                             scrollBy(0, down_excess_move);    
  163.                         }    
  164.                     }    
  165.                 }           
  166.             }     
  167.             break;    
  168.         case MotionEvent.ACTION_UP:             
  169.             // 多滚是负数 记录到move里    
  170.             if (up_excess_move > 0) {    
  171.                 // 多滚了 要弹回去    
  172.                 scrollBy(0, -up_excess_move);    
  173.                 invalidate();    
  174.                 up_excess_move = 0;    
  175.             }    
  176.             if (down_excess_move > 0) {    
  177.                 // 多滚了 要弹回去    
  178.                 scrollBy(0, down_excess_move);    
  179.                 invalidate();    
  180.                 down_excess_move = 0;    
  181.             }    
  182.             mTouchState = TOUCH_STATE_REST;    
  183.             break;    
  184.         }    
  185.         return this.detector.onTouchEvent(ev);    
  186.     }    
  187.     
  188.     int Fling_move = 0;    
  189.     
  190.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    
  191.             float velocityY) {    
  192.          //随手指 快速拨动的代码    
  193.         Log.d("onFling", "onFling");    
  194.         if (up_excess_move == 0 && down_excess_move == 0) {    
  195.     
  196.             int slow = -(int) velocityY * 3 / 4;    
  197.             mScroller.fling(0, move, 0, slow, 0, 0, 0, MAXMOVE);    
  198.             move = mScroller.getFinalY();    
  199.             computeScroll();    
  200.         }    
  201.         return false;    
  202.     }    
  203.     
  204.     public boolean onDown(MotionEvent e) {    
  205.         // TODO Auto-generated method stub    
  206.         return true;    
  207.     }    
  208.     
  209.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,    
  210.             float distanceY) {    
  211.         return false;    
  212.     }    
  213.     
  214.     public void onShowPress(MotionEvent e) {    
  215.         // // TODO Auto-generated method stub    
  216.     }    
  217.     
  218.     public boolean onSingleTapUp(MotionEvent e) {    
  219.         // TODO Auto-generated method stub    
  220.         return false;    
  221.     }    
  222.     
  223.     public void onLongPress(MotionEvent e) {    
  224.         // TODO Auto-generated method stub    
  225.     }    
  226.     
  227.     @Override    
  228.     protected void onLayout(boolean changed, int l, int t, int r, int b) {    
  229.         // TODO Auto-generated method stub    
  230.         int childTop = 0;    
  231.         int childLeft = 0;    
  232.         final int count = getChildCount();    
  233.         for (int i = 0; i < count; i++) {    
  234.             final View child = getChildAt(i);    
  235.             if (child.getVisibility() != View.GONE) {    
  236.                 child.setVisibility(View.VISIBLE);    
  237.                 child.measure(r - l, b - t);    
  238.                 child    
  239.                         .layout(childLeft, childTop, childLeft + 80,    
  240.                                 childTop + 80);    
  241.                 if (childLeft < 160) {    
  242.                     childLeft += 80;    
  243.                 } else {    
  244.                     childLeft = 0;    
  245.                     childTop += 80;    
  246.                 }    
  247.             }    
  248.         }    
  249.     }    
  250.     
  251. }    
 
  1. import android.content.Context;    
  2. import android.view.View;    
  3. import android.view.ViewGroup;    
  4.     
  5. public class Workspace extends ViewGroup {    
  6.     
  7.     public Workspace(Context context) {    
  8.         super(context);    
  9.         // TODO Auto-generated constructor stub    
  10.         addView(new MyViewGroup(context));    
  11.     }    
  12.     
  13.     @Override    
  14.     protected void onLayout(boolean changed, int l, int t, int r, int b) {    
  15.         // TODO Auto-generated method stub    
  16.         final int count = getChildCount();    
  17.         for (int i = 0; i < count; i++) {    
  18.             final View child = getChildAt(i);    
  19.             child.measure(r - l, b - t);    
  20.             child.layout(0, 0, 320, 480);    
  21.         }    
  22.     }    
  23.     
  24. }    
 
  1. import android.app.Activity;    
  2. import android.os.Bundle;    
  3.     
  4. public class MoveViewGroup extends Activity {    
  5.     /** Called when the activity is first created. */    
  6.     @Override    
  7.     public void onCreate(Bundle savedInstanceState) {    
  8.         super.onCreate(savedInstanceState);    
  9.         setContentView(new Workspace(this));    
  10.     
  11.     }    
  12. }    


http://blog.csdn.net/ztp800201/article/details/14057695

转载于:https://www.cnblogs.com/MMLoveMeMM/articles/4102747.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值