父容器onTouch和子View的OnClick兼容解决,定制特殊刷新,底部回弹

来源:互联网 发布:标准差 知乎 编辑:程序博客网 时间:2024/06/01 19:39

最近一个功能是定制特殊的刷新是拉伸特定布局,刷新状态标识也是特定的位置,我是重写了一个linearlayout–ParentCanOnTouchLinearLayout,但是由于子View有很多OnClick事件,导致父容器的(拉伸)滑动效果(onTouch事件失效)
本文旨在解决父子兼容,并没有封装死 刷新事件,开放了按下 和move中的产生的高度,和up的回调。

先看一下实际完成效果
实际效果
思路分析:

  1. 头部拉伸
  2. 重写ParentCanOnTouchLinearLayout中onInterceptTouchEvent
  3. 重写ParentCanOnTouchLinearLayout中onTouchEvent拉伸高度的获取
  4. 根据自定义的接口去处理 定制的刷新 这个可以根据你的实际情况,由于我这里比较特殊 就没有封装好了 类似下拉刷新固定刷新事件

头部拉伸效果分析

无论拉伸是采用什么逻辑,都只需要知道手下滑的距离,作为基本参数,然后按比例给你想要拉伸的布局设置params.height

考虑到我这里的实际场景 采用的是两个 view作为占位

<View                    android:id="@+id/refreshZone1"                    android:layout_width="match_parent"                    android:layout_height="1dp"                    android:background="@color/main_color" /><View                    android:id="@+id/refreshZone2"                    android:layout_width="match_parent"                    android:layout_height="1dp"                    android:background="@color/main_color" />

重写ParentCanOnTouchLinearLayout中onInterceptTouchEvent

因为如果子view中有很多点击事件会导致父view onTouch事件失效我们需要在子view使其失效前,干掉子view的点击事件。
当然只是在满足我们上下拉的时候去干掉,其他的时候依然执行子view点击事件

   private int yyy = -1;    private int xxx = -1;    private boolean isMove = false;    /**     * 核心方法     * @param event     * @return     */    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                isMove = false;                //此处为break所以返回值为false执行 子OnClick 所以父onTouch中没有Down 所以子view中初始化也要在move的第一个 坐标中获取                break;            case MotionEvent.ACTION_CANCEL:            case MotionEvent.ACTION_UP:                if (!isMove) {                    return false;                }                Log.i("rex", "onInterceptTouchEvent --- ACTION_UP");                isMove = false;                break;            case MotionEvent.ACTION_MOVE:                if (!isMove) {                    yyy = (int) event.getRawY();                    xxx = (int) event.getRawX();                }                isMove = true;                Log.i("rex", "yyy --- " + yyy);                Log.i("rex", "onInterceptTouchEvent --- ACTION_MOVE");                Log.i("rex", "yyy --- " + yyy);                //细节优化 短距离移除                float moveY = event.getRawY();                float moveX = event.getRawX();                Log.i("rex", "moveY --- " + moveY);                Log.i("rex", "moveX --- " + moveX);                //如果是非点击事件就拦截 让父布局接手onTouch 否则执行子ViewOnClick                if (Math.abs(moveY - yyy) > dip2px(getContext(), 20) || Math.abs(moveX - xxx) > dip2px(getContext(), 20)) {                    final ViewParent parent = getParent();                    if (parent != null) {                        parent.requestDisallowInterceptTouchEvent(true);                    }                    Log.i("rex", "确定当前为父view滑动");                    return true;                }//                if (Math.abs(moveY - yyy) < Math.abs(moveX - xxx)) {//                    Log.i("rex", "onInterceptTouchEvent --- 横滑");////                    return false;//                }                break;        }        return false;    }

重写ParentCanOnTouchLinearLayout中onTouchEvent拉伸高度的获取

  private OnPullDownImpl impl;    private boolean isNeedReresh;    private boolean isRefreshing;    private int y1 = -1;    private int max = 300;    private int height = -1;    private int paddingTop;    public interface OnPullDownImpl {        void moveHeight(int height);        void up();        void refreshHeigh();    }    public void setOnPullDownImpl(OnPullDownImpl impl) {        this.impl = impl;    }    public boolean isCanReresh() {        return isNeedReresh && !isRefreshing;    }    public void setRefreshing(boolean is) {        isRefreshing = is;    }    public boolean isRefreshing() {        return isRefreshing;    }    public void reSet() {        isRefreshing = false;        isNeedReresh = false;        y1 = -1;        height = -1;    }  @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN://其实这里毫无意义,因为onInterceptTouchEvent为true  所以初始值应该在move中取                if (y1 == -1) {                    isNeedReresh = false;                    y1 = (int) event.getRawY();                }                Log.i("rex", "onTouchEvent --- ACTION_DOWN y1===" + y1);                break;            case MotionEvent.ACTION_MOVE:                if (y1 == -1) {                    //当为子View Ontouch时候 可能不走上面的down                    isNeedReresh = false;                    y1 = (int) event.getRawY();                }                height = (int) event.getRawY() - y1;                Log.i("rex", "height=====" + height);                if (height > 120) {                    isNeedReresh = true;                    impl.refreshHeigh();                }                if (0 < height && height < max) {                    if (impl != null) {                        //下拉                        impl.moveHeight(height);                    }                }                if (height < 0) {                    //底部拉伸                    if (height < -max) {                        height = -max;                    }                    setPadding(0, height, 0, 0);                }                break;            case MotionEvent.ACTION_UP:                Log.i("rex", "ACTION_UP");                if (impl != null) {                    //拓展                    impl.up();                }                paddingTop = getPaddingTop();                if (paddingTop < 0) {                    //底部回弹                    if (mRunnable != null) {                        removeCallbacks(mRunnable);                        mRunnable = null;                    }                    mRunnable = runnable;                    postDelayed(mRunnable, 20);                }                break;        }        return true;    }    private Runnable mRunnable = null;    //循环回弹的Runnable     private Runnable runnable = new Runnable() {        @Override        public void run() {            paddingTop = paddingTop + 20;            if (paddingTop > -6) {                setPadding(0, 0, 0, 0);            } else {                setPadding(0, paddingTop, 0, 0);                postDelayed(this, 20);            }        }    };/**     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)     */    public static int dip2px(Context context, float dpValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (dpValue * scale + 0.5f);    }

根据自定义的接口去处理 定制的刷新

 /**     * 设置界面更新     */    int y = -1;    private Runnable mRunnable = null;    private void setRootRresh() {        /**         * 初始化 自定义刷新控件         */        ballView2 = (BallView2) view.findViewById(R.id.ballView2);        llRefreshRex = (ParentCanOnTouchLinearLayout) view.findViewById(R.id.llRefreshRex);        final View view1 = view.findViewById(R.id.refreshZone1);        final View view2 = view.findViewById(R.id.refreshZone2);        final ViewGroup.LayoutParams lp = view1.getLayoutParams();        final Runnable runnable = new Runnable() {            @Override            public void run() {                lp.height = lp.height - 10;                view1.setLayoutParams(lp);                view2.setLayoutParams(lp);                if (lp.height < 6) {                    lp.height = 0;                    view1.setLayoutParams(lp);                    view2.setLayoutParams(lp);                    y = -1;                    if (llRefreshRex.isCanReresh()) {                        llRefreshRex.setRefreshing(true);                        Log.i("rex", "请求刷新!");                        initDatas();                    } else if (llRefreshRex.isRefreshing()) {                        //不做处理                        Log.i("rex", "正在刷新中");                    } else {                        //不刷新                        ballView2.setVisibility(View.GONE);                        llRefreshRex.reSet();                    }                } else {                    view1.postDelayed(this, 20);                }            }        };        llRefreshRex.setOnPullDownImpl(new ParentCanOnTouchLinearLayout.OnPullDownImpl() {            @Override            public void moveHeight(int height) {                lp.height = height / 3;                view1.setLayoutParams(lp);                view2.setLayoutParams(lp);            }            @Override            public void refreshHeigh() {                ballView2.setVisibility(View.VISIBLE);            }            @Override            public void up() {                if (mRunnable != null) {                    view1.removeCallbacks(mRunnable);                    mRunnable = null;                }                mRunnable = runnable;                view1.postDelayed(mRunnable, 20);            }        });    }
1 0
原创粉丝点击