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); } } }