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

来源:互联网 发布:大数据项目视频 编辑:程序博客网 时间:2024/05/05 19:38

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

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

  • onDown   
  • onShowPress
  • onSingleTapUp
  • onScroll
  • onLongPress
  • onFling
在这个组件中,我们只需要实现onDown、onScroll就可以了,onDown返回true时才会响应触屏手势事件。onScroll中实现图片的滑动。
接下来,我们说下图片随手势滑动的原理其实,不是图片滑动,是组件在滑动,屏幕沿X轴运动,看起来就像图片在随着手势滑动。
接下来,我们看下代码:
public class ImageWallView extends AdapterView<ListAdapter> implements GestureDetector.OnGestureListener{    private ListAdapter mAdapter;    private GestureDetector gestureDetector;         //监听屏幕事件    private float offset=0;                     // 相对于(0,0)点水平方向滑动的距离    private int unitWidth;                      //每个单元的宽    private int numColumns;                //屏幕展示的孩子的数目    /**     * 构造方法     */    public ImageWallView(Context context) {        super(context);        init();    }    public ImageWallView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public ImageWallView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init();    }    private void init(){        gestureDetector = new GestureDetector(this.getContext(),this);        gestureDetector.setIsLongpressEnabled(true);  //监听长按事件    }    /**     * 继承AdapterView需要实现以下四个方法     *  getAdapter()     *  setAdapter(ListAdapter adapter)     *  getSelectedView()     *  setSelection(int position)     */    @Override    public ListAdapter getAdapter() {        return mAdapter;    }    @Override    public void setAdapter(ListAdapter adapter) {        this.mAdapter = adapter;        //把所有的child添加到布局中        for(int i=0;i<mAdapter.getCount();i++){            View child = mAdapter.getView(i,null,this);            addViewInLayout(child,i,child.getLayoutParams());        }    }    @Override    public View getSelectedView() {        return null;    }    @Override    public void setSelection(int position) { }    /**     * 实现GestureDetector.OnGestureListener接口需要实现以下方法     *   onDown    //响应触屏事件 这个必须返回true     *   onShowPress     *   onSingleTapUp     *   onScroll     *   onLongPress     *   onFling     */    public boolean onDown(MotionEvent e) {        return true;    }    public void onShowPress(MotionEvent e) {    }    /**     * 单击松开时响应     */    public boolean onSingleTapUp(MotionEvent e) {        return false;    }    /**     * 图片顺手势滑动     * @param distanceX      往右滑动是负值 往左滑动是正值     */    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        offset = offset- distanceX;        //确保不滑出界        if(offset>0){            offset=0;        }       else if(offset < (getChildCount()-numColumns)*unitWidth*-1) {            offset = (getChildCount()-numColumns)*unitWidth*-1;        }        //重绘布局        requestLayout();        return true;    }    public void onLongPress(MotionEvent e) {            }    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {;        return true;    }    /**     * 设置布局     */    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        int childCount = getChildCount();        int pLeft = 0;        int pTop = 0;        int childWidth=0;        int childHeight=0;        if(childCount>0){            View child = getChildAt(0);            LayoutParams p = child.getLayoutParams();            childWidth = p.width + child.getPaddingLeft() + child.getPaddingRight() ;                 // child 的宽            childHeight = p.height + child.getPaddingTop() + child.getPaddingBottom();            // child 的高            numColumns = (getMeasuredWidth() - getPaddingLeft() - getPaddingRight())/childWidth;  //计算屏幕中可以放置几个child            int spacing = (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - numColumns * childWidth)/numColumns;  //计算child之间的平均空隙            int spacingLR = (getPaddingLeft() + getPaddingRight() )/2;//组件左右边的平均空隙            if(spacing > spacingLR){                  int outSpacing = spacing - spacingLR;                  setPadding(spacingLR+outSpacing,getPaddingTop(),spacingLR+outSpacing,getPaddingBottom());             }            unitWidth = childWidth + spacing ;        }        for(int i=0;i<childCount;i++){             View child = getChildAt(i);            pLeft = getPaddingLeft() + i * unitWidth+(int)offset;                 //child距离左端的距离            pTop = getPaddingTop();                                         //child距离顶端的距离            child.layout(pLeft,pTop,pLeft + childWidth,pTop + childHeight);                    }    }    /**     * 设置大小     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        //设置宽度和高度        setMeasuredDimension(                getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),                getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec)        );    }    /**     * 响应触屏事件     */    @Override    public boolean onTouchEvent(MotionEvent event) {        if(mAdapter == null){            return true;        }        boolean touchValue = gestureDetector.onTouchEvent(event);        if(event.getAction() == MotionEvent.ACTION_UP ){ //在手指抬起时调用onUp方法            onUp();        }        return touchValue;    }    /**     * 实现屏幕只显示整章的商品图片     */    private void onUp(){        int index = (int) (Math.abs(offset) / unitWidth);        index += (Math.abs(offset) - index*unitWidth) > unitWidth/2 ? 1:0;        offset = offset>0? index*unitWidth : -1*index*unitWidth;        requestLayout();    }}


原创粉丝点击