父容器onTouch和子View的OnClick兼容解决,定制特殊刷新,底部回弹
来源:互联网 发布:标准差 知乎 编辑:程序博客网 时间:2024/06/01 19:39
最近一个功能是定制特殊的刷新是拉伸特定布局,刷新状态标识也是特定的位置,我是重写了一个linearlayout–ParentCanOnTouchLinearLayout,但是由于子View有很多OnClick事件,导致父容器的(拉伸)滑动效果(onTouch事件失效)
本文旨在解决父子兼容,并没有封装死 刷新事件,开放了按下 和move中的产生的高度,和up的回调。
先看一下实际完成效果
思路分析:
- 头部拉伸
- 重写ParentCanOnTouchLinearLayout中onInterceptTouchEvent
- 重写ParentCanOnTouchLinearLayout中onTouchEvent拉伸高度的获取
- 根据自定义的接口去处理 定制的刷新 这个可以根据你的实际情况,由于我这里比较特殊 就没有封装好了 类似下拉刷新固定刷新事件
头部拉伸效果分析
无论拉伸是采用什么逻辑,都只需要知道手下滑的距离,作为基本参数,然后按比例给你想要拉伸的布局设置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
- 父容器onTouch和子View的OnClick兼容解决,定制特殊刷新,底部回弹
- android view 的onTouch 和 onClick 事件
- Android View的onTouch和onClick和onLongClick事件
- Android View的onTouch和onClick和onLongClick事件
- View的OnTouch和OnClick事件不能并存问题
- Android View的onTouch、onClick和onLongClick事件分析
- 如何解决ViewFlipper的onClick和onTouch的冲突事件
- 悬浮窗onTouch和onCLick的冲突
- android的onClick()和onTouch()方法详解
- 一个view如何同时响应onTouch和onClick事件
- ontouch与onclick共存情况的view响应问题
- Android中view的onTouch&onClick事件分发机制详解
- requestDisallowInterceptTouchEvent解决子View和父View滑动的冲突
- android onClick和onTouch事件
- Android关于OnTouch 和OnClick
- onTouch和onClick事件处理
- mui之上拉刷新和mui-content结合解决ios上拉不回弹的bug
- Android关于OnTouch 和OnClick同时调用冲突的解决方案
- 连接树莓派的方法
- JAVA入门第一季-4.流程控制语句(一)
- yum 安装Tomcat7
- Codeforces Round #373 (Div. 2)-B. Anatoly and Cockroaches
- java中非阻塞网络编程中NIO知识点介绍
- 父容器onTouch和子View的OnClick兼容解决,定制特殊刷新,底部回弹
- 几种c/c++中字符串转整形的方法
- Qt通过UDP传图片,实现自定义分包和组包
- 如何在activity和fragment获取控件的大小
- jquery 定义对象并进行操作
- | 是逻辑变量的运算,取“或”,|| 则是布尔变量的运算,取“或”
- HttpURLConnection post解析
- java至今所学的关键词
- ssh登录缓慢