下拉刷新的ScrollView 不影响item点击事件

ScrollView 的item有了点击事件后,按item下拉时ScrollView 已经失去了事件 下面是个人做的处理方式,KiciScrollView 附demo下载

注:支持API11及以上

注:使用时子View不能设置onClick事件 在setChildOnClick(); 里处理, 默认按下小于150毫秒 并且在一定移动距离内视为单击


主类

public class KiciScrollView extends ScrollView {

    public KiciScrollView(Context context) {
        this(context, null);
    }

    public KiciScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public KiciScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private int protoY; //原始位置
    private float downY;// 按下位置
    private long time; // 记录按下时间
    private ValueAnimator mAnimator; //回弹动画
    private boolean isMove = false;
    private boolean isFirst = false;
    private boolean isFirstItem;
    private View mOnClickView;
    private ChildOnClick mChildOnClick; //item 的点击事件
    private OnPullDownRefresh mOnPullDownRefresh;//下拉刷新

    public void setRefreshStateListener(RefreshStateListener refreshStateListener) {
        mRefreshStateListener = refreshStateListener;
    }

    private RefreshStateListener mRefreshStateListener; //下拉刷新监听

    public void setStartRefreshListener(RefreshStartListener refreshStartListener) {
        mRefreshStartListener = refreshStartListener;
    }

    private RefreshStartListener mRefreshStartListener; //下拉刷新 监听开始刷新
    /**
     * 下拉的状态 0默认 1下拉中 2松开刷新 3加载中
     */
    private int type = 0; //
    private float refreshHeight = 60; //刷新的位置高度
    private View mHeadView;//下载刷新头部
    private int topMargin;


    private void init() {
        setOnTouchListener(new OnTouchListener() {
                               @Override
                               public boolean onTouch(View v, MotionEvent event) {

                                   if (protoY <= 10) {
                                       protoY = getMeasuredHeight();
                                   }

                                   switch (event.getAction()) {
                                       case MotionEvent.ACTION_DOWN:
                                           if (mRefreshStateListener != null && type != 3)
                                               mRefreshStateListener.onPulling(0); //初始化
                                           downY = event.getY();
                                           isFirst = true;
                                           if (mAnimator != null) {
                                               mAnimator.cancel();
                                           }
                                           time = System.currentTimeMillis();
                                           break;
                                       case MotionEvent.ACTION_MOVE:
                                           int d = (int) (event.getY() - downY);
                                           if (isFirst && (getScrollY() == 0)) {
                                               isFirst = !isFirst;
                                               if (d < 0) {
                                                   break; //首次进来是上拉 不执行
                                               } else {
                                                   isMove = true;
                                               }
                                           }
                                           if (d != 0 && isMove) {
                                               setParamsTop(d);
                                               if (mHeadView != null && type != 3) {  // 下拉刷新

                                                   float ratio = (event.getY() - downY) / 3 / (dip2px(getContext(), refreshHeight));
                                                   if (ratio < 1) {
                                                       type = 1;
                                                       if (mRefreshStateListener != null)
                                                           mRefreshStateListener.onPulling(ratio); //没到刷新条件
                                                   } else {//松开刷新
                                                       type = 2;
                                                       if (mRefreshStateListener != null)
                                                           mRefreshStateListener.onMoreThanRefresh();//达到刷新条件
                                                   }
                                               }
                                               return true;
                                           }
                                           break;
                                       case MotionEvent.ACTION_UP:
                                           if (isMove) {
                                               if (mHeadView != null && (type == 2 || type == 3)) {//开始刷新
                                                   if (type == 2) {
                                                       if (mRefreshStateListener != null)
                                                           mRefreshStateListener.onRehresh();
                                                       if (mRefreshStartListener != null)
                                                           mRefreshStartListener.onRefreshStart();
                                                       type = 3;
                                                   }

                                                   marginValueAnimator(dip2px(getContext(), refreshHeight));
                                               } else {
                                                   marginValueAnimator(dip2px(getContext(), 0));
                                               }
                                           }
                                           isMove = false;
                                           if (System.currentTimeMillis() - time < 150 && mChildOnClick != null && mOnClickView != null &&
                                                   Math.abs((event.getY() - downY)) < dip2px(getContext(), 10f)) { //视为点击事件
                                               mChildOnClick.onChildClick(mOnClickView);
                                           }
                                           break;

                                   }
                                   return false;
                               }
                           }
        );
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        initListener();
    }

    /**
     * 刷新成功
     */

    public void setRefreshSucceed() {
        type = 0;
        if (mHeadView != null && mRefreshStateListener != null) {
            mRefreshStateListener.onRefreshComplete();//
        }
        marginValueAnimator(0);
    }

    /**
     * 刷新失败
     */

    public void setRefreshFailure() {
        type = 0;
        if (mHeadView != null && mRefreshStateListener != null) {
            mRefreshStateListener.onRefreshFailure();//开始刷新
        }
        marginValueAnimator(0);

    }

    public void initListener() {//设置子View的事件
        try {
            ViewGroup viewGroup = (ViewGroup) getChildAt(0);
            initListener(viewGroup);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void initListener(ViewGroup viewGroup) {
        try {
            int count = viewGroup.getChildCount();
            for (int i = 0; i < count; i++) {
                View v = viewGroup.getChildAt(i);
                if (v != null)
                    v.setOnTouchListener(mOnTouchListener);
                try {
                    initListener((ViewGroup) v);
                } catch (Exception e) {
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void addView(View child, int width, int height) {
        super.addView(child, width, height);
    }

    /**
     * 设置下拉刷新的位置高度  默认高度是60dip
     *
     * @param height 单位dip
     */
    public void setRefreshHeighe(float height) {
        refreshHeight = height;
    }

    /**
     * 使用ValueAnimator改变margin的值
     *
     * @param height 回弹距离
     */
    public void marginValueAnimator(final int height) {
        //1.调用ofInt(int...values)方法创建ValueAnimator对象
        topMargin = height;
        mAnimator = ObjectAnimator.ofFloat(0.0F, 1.0F).setDuration(500);
        //2.为目标对象的属性变化设置监听器
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 3.为目标对象的属性设置计算好的属性值
                float animatorValue = (float) animation.getAnimatedValue();
                MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getLayoutParams();
                if (marginLayoutParams.topMargin > height) {
                    marginLayoutParams.topMargin = (int) (marginLayoutParams.topMargin - marginLayoutParams.topMargin * animatorValue);
                } else {
                    marginLayoutParams.topMargin = (int) (marginLayoutParams.topMargin + (height - marginLayoutParams.topMargin) * animatorValue);
                }
                setLayoutParams(marginLayoutParams);

                if (mHeadView != null) {
                    ViewGroup.LayoutParams params = mHeadView.getLayoutParams();
                    if (params.height > height) {
                        params.height = (int) (params.height - params.height * animatorValue);
                    } else {
                        params.height = (int) (params.height + (height - params.height) * animatorValue);
                    }
                    mHeadView.setLayoutParams(params);
                }
            }
        });
        //4.设置动画的持续时间、是否重复及重复次数等属性
        mAnimator.start();
    }

    /**
     * 下拉了距离 更新UI
     *
     * @param height
     */
    private void setParamsTop(int height) {
        if (height == 0) return;
        MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getLayoutParams();
        height = (height / 3) + topMargin;

        marginLayoutParams.topMargin = height;
        if (mHeadView != null) {
            ViewGroup.LayoutParams params = mHeadView.getLayoutParams();
            params.height = height;
            mHeadView.setLayoutParams(params);
        }
        setLayoutParams(marginLayoutParams);
    }

    /**
     * 设置item的点击事件
     *
     * @param childOnClick
     */
    public void setChildOnClick(ChildOnClick childOnClick) {
        mChildOnClick = childOnClick;
    }

    /**
     * 设置下拉刷新事件
     */
    public void setOnPullDownRefresh(OnPullDownRefresh pullDownRefresh) {
        mOnPullDownRefresh = pullDownRefresh;
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    private OnTouchListener mOnTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mOnClickView = v;
            return false;
        }
    };

    public interface ChildOnClick {
        void onChildClick(View view);
    }

    public interface OnPullDownRefresh {
        void onPullDownRefresh();
    }

    public void setHeadView(View headView) {
        mHeadView = headView;
    }


    /**
     * 延时操作
     *
     * @param activity
     * @param runnable
     * @param time
     */
    public void runOnUIThread(final Activity activity, final Runnable runnable, final int time) {
        new Thread() {
            @Override
            public void run() {
                try {
                    sleep(time);
                    if (activity != null)
                        activity.runOnUiThread(runnable);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }
}


下面是可自定义的刷新View 在RefreshStateListener 里监听改变状态就好了


public class KiciHeadView extends LinearLayout implements RefreshStateListener {

    public KiciHeadView(Context context) {
        this(context, null);
    }

    public KiciHeadView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public KiciHeadView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private View mView;
    private Animation an;

    private void initView() {
        mView = View.inflate(getContext(), R.layout.kici_view_headview, this);
        mView1 = findViewById(R.id.view1);
        mView2 = (TextView) findViewById(R.id.view2);
    }

    private View mView1; //tup
    private TextView mView2;

    @Override
    public void onPulling(float y) {
        mView1.setBackgroundResource(R.drawable.progress_round);
        mView1.setRotation(360 * y);
        mView2.setText("下拉刷新");
    }

    @Override
    public void onMoreThanRefresh() {

        mView1.setRotation(360);
        mView2.setText("松开刷新");
    }

    @Override
    public void onRehresh() {
        if (an == null) {
            an = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            an.setInterpolator(new LinearInterpolator());//不停顿
            an.setRepeatCount(-1);//重复次数
            an.setFillAfter(true);//停在最后
            an.setDuration(1500);
            mView1.setAnimation(an);
        }
        //动画开始
        an.start();
        mView2.setText("正在刷新...");
    }

    @Override
    public void onRefreshComplete() {
        if (an == null)
            return;
        mView2.setText("刷新成功");
        an.cancel();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mView1.setBackground(null);
        } else {
            mView1.setBackgroundDrawable(null);
        }
    }

    @Override
    public void onRefreshFailure() {
        if (an == null)
            return;
        mView2.setText("刷新失败");
        an.cancel();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mView1.setBackground(null);
        } else {
            mView1.setBackgroundDrawable(null);
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值