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

本文继续探讨自定义Adapter组件的实现,重点在于如何集成GestureDetector,实现图片随手势滑动的功能。通过实现OnGestureListener接口的几个关键方法,包括onDown、onShowPress、onSingleTapUp、onScroll、onLongPress和onFling,让组件具备流畅的手势交互体验。
摘要由CSDN通过智能技术生成

上篇只实现了效果但是图片不能随手势滑动,要想实现这个效果,需要实现接口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();

    }



}


  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值