adapterView实现GestureDetector.OnGestureListener来左右滑动!!!!

来源:互联网 发布:jsw windows x86 64 编辑:程序博客网 时间:2024/06/16 09:55

自定义使用Adapter的组件(一)


这次,我要实现个类似京东商城android客户端上商品图片展示的组件,如下图展示爱疯4的组件,注意,不包含小箭头偷笑。【由于不方便上传图片,就只能使用网上图片了】

首先,我先实现上图的效果,要实现这种组件就必须继承AdapterView<ListAdapter>,实现构造方法、onMeasure()、onLayout()、setAdapter()方法。看代码:

[java] view plaincopyprint?
  1. public class ImageWallView extends AdapterView<ListAdapter>{  
  2.   
  3.     private ListAdapter mAdapter;  
  4.     private int unitWidth;                      //每个child的宽  
  5.     private int numColumns;                //屏幕展示的孩子的数目  
  6.   
  7.     /** 
  8.      * 构造方法 
  9.      */  
  10.   
  11.     public ImageWallView(Context context) {  
  12.         super(context);  
  13.     }  
  14.   
  15.     public ImageWallView(Context context, AttributeSet attrs) {  
  16.         super(context, attrs);  
  17.   
  18.     }  
  19.   
  20.     public ImageWallView(Context context, AttributeSet attrs, int defStyle) {  
  21.         super(context, attrs, defStyle);  
  22.     }  
  23.   
  24.     /** 
  25.      * 继承AdapterView需要实现以下四个方法 
  26.      *  getAdapter() 
  27.      *  setAdapter(ListAdapter adapter) 
  28.      *  getSelectedView() 
  29.      *  setSelection(int position) 
  30.      */  
  31.     @Override  
  32.     public ListAdapter getAdapter() {  
  33.         return mAdapter;  
  34.     }  
  35.   
  36.     @Override  
  37.     public void setAdapter(ListAdapter adapter) {  
  38.         this.mAdapter = adapter;  
  39.         //把所有的child添加到布局中  
  40.         for(int i=0;i<mAdapter.getCount();i++){  
  41.             View child = mAdapter.getView(i,null,this);  
  42.             addViewInLayout(child,i,child.getLayoutParams());  
  43.         }  
  44.     }  
  45.   
  46.     @Override  
  47.     public View getSelectedView() {  
  48.         return null;  
  49.     }  
  50.   
  51.     @Override  
  52.     public void setSelection(int position) { }  
  53.   
  54.     /** 
  55.      * 设置布局 
  56.      */  
  57.     @Override  
  58.     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
  59.         int childCount = getChildCount();  
  60.         int pLeft = 0;  
  61.         int pTop = 0;  
  62.         int childWidth=0;  
  63.         int childHeight=0;  
  64.   
  65.         if(childCount>0){  
  66.             View child = getChildAt(0);  
  67.             LayoutParams p = child.getLayoutParams();  
  68.             childWidth = p.width + child.getPaddingLeft() + child.getPaddingRight() ;  //组件的宽度  
  69.             childHeight = p.height + child.getPaddingTop() + child.getPaddingBottom(); //组件的高度  
  70.   
  71.             numColumns = (getMeasuredWidth() - getPaddingLeft() - getPaddingRight())/childWidth;  //计算屏幕中可以放置几个child  
  72.             int spacing = (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - numColumns * childWidth)/numColumns;  //计算child之间的平均空隙  
  73.   
  74.             int spacingLR = (getPaddingLeft() + getPaddingRight() )/2;//组件左右边的平均空隙  
  75.   
  76.             if(spacing > spacingLR){  // 当组件间的均距离大于两边的组件左右的空隙的平均值时,调整一下,这个只是为了样式,可越过  
  77.                   int outSpacing = spacing - spacingLR;  
  78.                   setPadding(spacingLR+outSpacing,getPaddingTop(),spacingLR+outSpacing,getPaddingBottom());  
  79.              }  
  80.             unitWidth = childWidth + spacing ;  
  81.         }  
  82.   
  83.         for(int i=0;i<childCount;i++){  
  84.              View child = getChildAt(i);  
  85.   
  86.             pLeft = getPaddingLeft() + i * unitWidth+(int)offset;                 //child距离左端的距离  
  87.   
  88.   
  89.             pTop = getPaddingTop();                                         //child距离顶端的距离  
  90.             child.layout(pLeft,pTop,pLeft + childWidth,pTop + childHeight);  
  91.               
  92.         }  
  93.   
  94.     }  
  95.   
  96.     /** 
  97.      * 设置大小 
  98.      */  
  99.     @Override  
  100.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  101.         //设置宽度和高度  
  102.         setMeasuredDimension(  
  103.                 getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),  //getDefaultSize() 获取参数两个值中较大的那个  
  104.                 getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec)  
  105.         );  
  106.     }  
  107.   
  108. }  

onMeasure()  中设置了组件的大小
onLayout() 中设置了传进来的ListAdapter内容怎样在组件中分布
setAdapter() 中把ListAdapter的内容加入组件中

使用:

[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:demo="http://schemas.android.com/apk/res/com.wxg.activity"  
  4.     android:orientation="vertical"  
  5.     android:layout_width="fill_parent"  
  6.     android:layout_height="fill_parent"  
  7.     >  
  8.     <com.wxg.view.ImageWallView  
  9.             android:layout_width="fill_parent"  
  10.             android:layout_height="100dp"  
  11.             android:paddingLeft="10dp"  
  12.             android:paddingTop="5dp"  
  13.             android:paddingRight="10dp"  
  14.             android:id="@+id/imageWallView"  
  15.             android:background="#ffffff"  
  16.             />  
  17.     <TextView  
  18.         android:layout_height="fill_parent"  
  19.         android:layout_width="fill_parent"  
  20.         android:gravity="center"  
  21.         android:text="图片墙组件"  
  22.         android:textColor="#ffffff"  
  23.         android:textSize="25sp"/>  
  24.   
  25. </LinearLayout>  

有个地方需要注意,使用组件时要自定义Adapter,不能使用系统自带的Adapter。

这样,就可以实现想要的样式了,但是现在图片还不能随着手势滑动,在下篇中会实现随手势滑动。


自定义使用Adapter的组件(二)

上篇只实现了效果但是图片不能随手势滑动,要想实现这个效果,需要实现接口GestureDetector.OnGestureListener。

 实现GestureDetector.OnGestureListener接口需要实现以下方法

  • onDown   
  • onShowPress
  • onSingleTapUp
  • onScroll
  • onLongPress
  • onFling
在这个组件中,我们只需要实现onDown、onScroll就可以了,onDown返回true时才会响应触屏手势事件。onScroll中实现图片的滑动。
接下来,我们说下图片随手势滑动的原理其实,不是图片滑动,是组件在滑动,屏幕沿X轴运动,看起来就像图片在随着手势滑动。
接下来,我们看下代码:
[java] view plaincopyprint?
  1. public class ImageWallView extends AdapterView<ListAdapter> implements GestureDetector.OnGestureListener{  
  2.   
  3.     private ListAdapter mAdapter;  
  4.     private GestureDetector gestureDetector;         //监听屏幕事件  
  5.     private float offset=0;                     // 相对于(0,0)点水平方向滑动的距离  
  6.     private int unitWidth;                      //每个单元的宽  
  7.     private int numColumns;                //屏幕展示的孩子的数目  
  8.   
  9.     /** 
  10.      * 构造方法 
  11.      */  
  12.   
  13.     public ImageWallView(Context context) {  
  14.         super(context);  
  15.         init();  
  16.     }  
  17.   
  18.     public ImageWallView(Context context, AttributeSet attrs) {  
  19.         super(context, attrs);  
  20.         init();  
  21.   
  22.     }  
  23.   
  24.     public ImageWallView(Context context, AttributeSet attrs, int defStyle) {  
  25.         super(context, attrs, defStyle);  
  26.         init();  
  27.     }  
  28.   
  29.     private void init(){  
  30.         gestureDetector = new GestureDetector(this.getContext(),this);  
  31.         gestureDetector.setIsLongpressEnabled(true);  //监听长按事件  
  32.     }  
  33.     /** 
  34.      * 继承AdapterView需要实现以下四个方法 
  35.      *  getAdapter() 
  36.      *  setAdapter(ListAdapter adapter) 
  37.      *  getSelectedView() 
  38.      *  setSelection(int position) 
  39.      */  
  40.     @Override  
  41.     public ListAdapter getAdapter() {  
  42.         return mAdapter;  
  43.     }  
  44.   
  45.     @Override  
  46.     public void setAdapter(ListAdapter adapter) {  
  47.         this.mAdapter = adapter;  
  48.         //把所有的child添加到布局中  
  49.         for(int i=0;i<mAdapter.getCount();i++){  
  50.             View child = mAdapter.getView(i,null,this);  
  51.             addViewInLayout(child,i,child.getLayoutParams());  
  52.         }  
  53.     }  
  54.   
  55.     @Override  
  56.     public View getSelectedView() {  
  57.         return null;  
  58.     }  
  59.   
  60.     @Override  
  61.     public void setSelection(int position) { }  
  62.   
  63.   
  64.     /** 
  65.      * 实现GestureDetector.OnGestureListener接口需要实现以下方法 
  66.      *   onDown    //响应触屏事件 这个必须返回true 
  67.      *   onShowPress 
  68.      *   onSingleTapUp 
  69.      *   onScroll 
  70.      *   onLongPress 
  71.      *   onFling 
  72.      */  
  73.     public boolean onDown(MotionEvent e) {  
  74.   
  75.         return true;  
  76.     }  
  77.   
  78.     public void onShowPress(MotionEvent e) {  
  79.   
  80.     }  
  81.   
  82.     /** 
  83.      * 单击松开时响应 
  84.      */  
  85.     public boolean onSingleTapUp(MotionEvent e) {  
  86.   
  87.         return false;  
  88.     }  
  89.   
  90.     /** 
  91.      * 图片顺手势滑动 
  92.      * @param distanceX      往右滑动是负值 往左滑动是正值 
  93.      */  
  94.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {  
  95.   
  96.         offset = offset- distanceX;  
  97.         //确保不滑出界  
  98.         if(offset>0){  
  99.             offset=0;  
  100.         }  
  101.        else if(offset < (getChildCount()-numColumns)*unitWidth*-1) {  
  102.             offset = (getChildCount()-numColumns)*unitWidth*-1;  
  103.         }  
  104.         //重绘布局  
  105.         requestLayout();  
  106.   
  107.         return true;  
  108.     }  
  109.   
  110.     public void onLongPress(MotionEvent e) {  
  111.           
  112.     }  
  113.   
  114.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {;  
  115.         return true;  
  116.     }  
  117.   
  118.   
  119.     /** 
  120.      * 设置布局 
  121.      */  
  122.     @Override  
  123.     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
  124.         int childCount = getChildCount();  
  125.         int pLeft = 0;  
  126.         int pTop = 0;  
  127.         int childWidth=0;  
  128.         int childHeight=0;  
  129.   
  130.         if(childCount>0){  
  131.             View child = getChildAt(0);  
  132.             LayoutParams p = child.getLayoutParams();  
  133.             childWidth = p.width + child.getPaddingLeft() + child.getPaddingRight() ;                 // child 的宽  
  134.             childHeight = p.height + child.getPaddingTop() + child.getPaddingBottom();            // child 的高  
  135.   
  136.             numColumns = (getMeasuredWidth() - getPaddingLeft() - getPaddingRight())/childWidth;  //计算屏幕中可以放置几个child  
  137.             int spacing = (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - numColumns * childWidth)/numColumns;  //计算child之间的平均空隙  
  138.   
  139.             int spacingLR = (getPaddingLeft() + getPaddingRight() )/2;//组件左右边的平均空隙  
  140.   
  141.             if(spacing > spacingLR){  
  142.                   int outSpacing = spacing - spacingLR;  
  143.                   setPadding(spacingLR+outSpacing,getPaddingTop(),spacingLR+outSpacing,getPaddingBottom());  
  144.              }  
  145.             unitWidth = childWidth + spacing ;  
  146.         }  
  147.   
  148.         for(int i=0;i<childCount;i++){  
  149.              View child = getChildAt(i);  
  150.   
  151.             pLeft = getPaddingLeft() + i * unitWidth+(int)offset;                 //child距离左端的距离  
  152.   
  153.   
  154.             pTop = getPaddingTop();                                         //child距离顶端的距离  
  155.             child.layout(pLeft,pTop,pLeft + childWidth,pTop + childHeight);  
  156.               
  157.         }  
  158.   
  159.     }  
  160.   
  161.     /** 
  162.      * 设置大小 
  163.      */  
  164.     @Override  
  165.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  166.         //设置宽度和高度  
  167.         setMeasuredDimension(  
  168.                 getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),  
  169.                 getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec)  
  170.         );  
  171.     }  
  172.   
  173.   
  174.   
  175.   
  176.     /** 
  177.      * 响应触屏事件 
  178.      */  
  179.     @Override  
  180.     public boolean onTouchEvent(MotionEvent event) {  
  181.         if(mAdapter == null){  
  182.             return true;  
  183.         }  
  184.         boolean touchValue = gestureDetector.onTouchEvent(event);  
  185.   
  186.         if(event.getAction() == MotionEvent.ACTION_UP ){ //在手指抬起时调用onUp方法  
  187.             onUp();  
  188.         }  
  189.         return touchValue;  
  190.     }  
  191.   
  192.     /** 
  193.      * 实现屏幕只显示整章的商品图片 
  194.      */  
  195.     private void onUp(){  
  196.   
  197.         int index = (int) (Math.abs(offset) / unitWidth);  
  198.   
  199.         index += (Math.abs(offset) - index*unitWidth) > unitWidth/2 ? 1:0;  
  200.   
  201.         offset = offset>0? index*unitWidth : -1*index*unitWidth;  
  202.   
  203.         requestLayout();  
  204.   
  205.     }  
  206.   
  207.   
  208.