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

  之前做到个项目要类似listView或者GridView中的控件移动的效果(主屏上所有程序列表上的效果): 
1:子控件跟着手指移动 
2:快速拨动一下,根据拨动的速度 滑动过去 
3:拖过头,放手后弹回去 

   但是用listView或者GridView又不好实现项目要求的其他效果..于是继承viewGroup实现以上效果。 

   既然要获取拨动速度,并以此滑动。首先想到了OnGestureListener 这个接口,实现这个接口并实现其onFling方法. 

  还要控制拖动。重写onTouchEvent方法,并在其中控制内容控件的拖动,反弹等效果 

这时候基本已经完成了。。。。测试了一下了,发现了一个问题,当手指点在viewGroup上 

进行 拖动是没问题的,但是在子控件上就不行了,这是事件响应的问题 那么还要做如面的处 

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

 

Java代码     收藏代码
  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, 000, 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. }  

Java代码     收藏代码
  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(00320480);  
  21.         }  
  22.     }  
  23.   
  24. }  

Java代码     收藏代码
  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. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值