当前位置: 代码迷 >> 综合 >> CoordinatorLayout 解决滑动不跟手问题
  详细解决方案

CoordinatorLayout 解决滑动不跟手问题

热度:38   发布时间:2023-12-17 05:13:00.0

滑动coordinatorLayout 后不跟手,反向滑动不能暂停之前的滑动。需要在AppBarLayout使用自定义的behavior

效果图

首先,新建behavior文件AppBarLayoutBehavior.java

 import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.OverScroller;import java.lang.reflect.Field;public class AppBarLayoutBehavior extends AppBarLayout.Behavior {private static final String TAG = "AppbarLayoutBehavior";private static final int TYPE_FLING = 1;private boolean isFlinging;private boolean shouldBlockNestedScroll;public AppBarLayoutBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {LogUtil.d(TAG, "onInterceptTouchEvent:" + child.getTotalScrollRange());shouldBlockNestedScroll = isFlinging;switch (ev.getActionMasked()) {case MotionEvent.ACTION_DOWN://手指触摸屏幕的时候停止fling事件stopAppbarLayoutFling(child);break;default:break;}return super.onInterceptTouchEvent(parent, child, ev);}/*** 反射获取私有的flingRunnable 属性,考虑support 28以后变量名修改的问题* @return Field* @throws NoSuchFieldException*/private Field getFlingRunnableField() throws NoSuchFieldException {Class<?> superclass = this.getClass().getSuperclass();try {// support design 27及一下版本Class<?> headerBehaviorType = null;if (superclass != null) {headerBehaviorType = superclass.getSuperclass();}if (headerBehaviorType != null) {return headerBehaviorType.getDeclaredField("mFlingRunnable");}else {return null;}} catch (NoSuchFieldException e) {e.printStackTrace();// 可能是28及以上版本Class<?> headerBehaviorType = superclass.getSuperclass().getSuperclass();if (headerBehaviorType != null) {return headerBehaviorType.getDeclaredField("flingRunnable");} else {return null;}}}/*** 反射获取私有的scroller 属性,考虑support 28以后变量名修改的问题* @return Field* @throws NoSuchFieldException*/private Field getScrollerField() throws NoSuchFieldException {Class<?> superclass = this.getClass().getSuperclass();try {// support design 27及一下版本Class<?> headerBehaviorType = null;if (superclass != null) {headerBehaviorType = superclass.getSuperclass();}if (headerBehaviorType != null) {return headerBehaviorType.getDeclaredField("mScroller");}else {return null;}} catch (NoSuchFieldException e) {e.printStackTrace();// 可能是28及以上版本Class<?> headerBehaviorType = superclass.getSuperclass().getSuperclass();if (headerBehaviorType != null) {return headerBehaviorType.getDeclaredField("scroller");}else {return null;}}}/*** 停止appbarLayout的fling事件* @param appBarLayout*/private void stopAppbarLayoutFling(AppBarLayout appBarLayout) {//通过反射拿到HeaderBehavior中的flingRunnable变量try {Field flingRunnableField = getFlingRunnableField();Field scrollerField = getScrollerField();if (flingRunnableField != null) {flingRunnableField.setAccessible(true);}if (scrollerField != null) {scrollerField.setAccessible(true);}Runnable flingRunnable = null;if (flingRunnableField != null) {flingRunnable = (Runnable) flingRunnableField.get(this);}OverScroller overScroller = (OverScroller) scrollerField.get(this);if (flingRunnable != null) {LogUtil.d(TAG, "存在flingRunnable");appBarLayout.removeCallbacks(flingRunnable);flingRunnableField.set(this, null);}if (overScroller != null && !overScroller.isFinished()) {overScroller.abortAnimation();}} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}@Overridepublic boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child,View directTargetChild, View target,int nestedScrollAxes, int type) {LogUtil.d(TAG, "onStartNestedScroll");stopAppbarLayoutFling(child);return super.onStartNestedScroll(parent, child, directTargetChild, target,nestedScrollAxes, type);}@Overridepublic void onNestedPreScroll(CoordinatorLayout coordinatorLayout,AppBarLayout child, View target,int dx, int dy, int[] consumed, int type) {LogUtil.d(TAG, "onNestedPreScroll:" + child.getTotalScrollRange()+ " ,dx:" + dx + " ,dy:" + dy + " ,type:" + type);//type返回1时,表示当前target处于非touch的滑动,//该bug的引起是因为appbar在滑动时,CoordinatorLayout内的实现NestedScrollingChild2接口的滑动//子类还未结束其自身的fling//所以这里监听子类的非touch时的滑动,然后block掉滑动事件传递给AppBarLayoutif (type == TYPE_FLING) {isFlinging = true;}if (!shouldBlockNestedScroll) {super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);}}@Overridepublic void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,View target, int dxConsumed, int dyConsumed, intdxUnconsumed, int dyUnconsumed, int type) {LogUtil.d(TAG, "onNestedScroll: target:" + target.getClass() + " ,"+ child.getTotalScrollRange() + " ,dxConsumed:"+ dxConsumed + " ,dyConsumed:" + dyConsumed + " " + ",type:" + type);if (!shouldBlockNestedScroll) {super.onNestedScroll(coordinatorLayout, child, target, dxConsumed,dyConsumed, dxUnconsumed, dyUnconsumed, type);}}@Overridepublic void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl,View target, int type) {LogUtil.d(TAG, "onStopNestedScroll");super.onStopNestedScroll(coordinatorLayout, abl, target, type);isFlinging = false;shouldBlockNestedScroll = false;}private static class LogUtil{static void d(String tag, String string){Log.d(tag,string);}}}

 

整个页面布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/parentLayout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><RelativeLayoutandroid:id="@+id/tool"style="@style/topbar_bg"android:background="@color/titleColor"><ImageView style="@style/topbar_return_img" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:layout_centerInParent="true"android:gravity="center"android:orientation="vertical"><TextViewandroid:id="@+id/titleText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/details"android:textColor="@color/white"android:textSize="16sp" /></LinearLayout></RelativeLayout><android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@+id/bottomLayout"android:layout_below="@+id/tool"android:fitsSystemWindows="true"><android.support.design.widget.AppBarLayoutandroid:id="@+id/app_bar"android:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true"app:layout_behavior=".utils.AppBarLayoutBehavior"><android.support.design.widget.CollapsingToolbarLayoutandroid:id="@+id/toolbar_layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true"app:layout_scrollFlags="scroll|exitUntilCollapsed"app:statusBarScrim="@android:color/transparent"><LinearLayoutandroid:id="@+id/itemLayout"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/shape_press_bound"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="12dp"android:layout_marginTop="10dp"android:layout_marginRight="12dp"android:layout_marginBottom="5dp"><TextViewandroid:id="@+id/postInfo"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/userName"android:layout_alignLeft="@+id/userName"android:layout_marginTop="8dp"android:text=""android:textColor="@color/second_text_color"android:textSize="12sp" /></RelativeLayout><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:layout_marginTop="15dp"android:background="@color/color_background_grey" /></LinearLayout></android.support.design.widget.CollapsingToolbarLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioGroupandroid:id="@+id/radioGroup"android:layout_width="match_parent"android:layout_height="44dp"android:background="@color/white"android:gravity="center_vertical"android:orientation="horizontal"app:layout_scrollFlags="scroll"><RadioButtonandroid:id="@+id/replyCount"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:button="@null"android:checked="true"android:paddingLeft="12dp"android:paddingRight="30dp"android:text="@string/comment_count"android:textColor="@color/selector_tweet_detail_tab"android:textSize="14sp" /><Spaceandroid:layout_width="0dp"android:layout_height="1dp"android:layout_weight="1" /><RadioButtonandroid:id="@+id/likeCount"android:layout_width="wrap_content"android:layout_height="match_parent"android:button="@null"android:paddingLeft="30dp"android:paddingRight="15dp"android:text="@string/like_count"android:textColor="@color/selector_tweet_detail_tab"android:textSize="14sp" /></RadioGroup></LinearLayout></android.support.design.widget.AppBarLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"app:layout_behavior="@string/appbar_scrolling_view_behavior"><Viewandroid:layout_width="match_parent"android:layout_height="2px"android:background="@color/colorLine" /><!-- viewpager可以有多个fragment,里面可以用smartRefreshLayout --><android.support.v4.view.ViewPagerandroid:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior" /></LinearLayout></android.support.design.widget.CoordinatorLayout></RelativeLayout>

 

 

参考:https://www.jianshu.com/p/507091d4cc0f