返回
底部表单拖动异常?锁定这个核心要素,彻底摆脱烦人的BUG
Android
2024-01-18 19:00:38
BottomSheetDialog 拖曳冲突问题简介
一般webview的向下滑动/拖动的效果应该是可以正常显现出来的,而BottomSheetDialog控件本身自带的拖动效果也是将其整个View给消失掉的,这样两者在同时向下拖动时就会产生部分冲突。(如果没有冲突,那么必定是谷歌在设计时以及做了处理。)因此,可以把问题的解决关键集中在BottomSheetDialog的整个view上,让其不可滑动,同时让webview可以实现向上滑动。
解决问题
该问题的解决策略,包含两个方面:
- BottomSheetDialog不可滑动
在Activity中,覆写 BottomSheetDialog
的 behavior()
方法。并在方法中修改其 setDraggable()
为 false
。这样做可以阻止BottomSheetDialog在向下滑动时,导致异常,而使用 BottomSheetBehavior.setPeekHeight()
控制弹出高度和显示的比例。
- webView可以向上滑动
需要使用嵌套滚动,也就是嵌套滑动功能,实现WebView和BottomSheetDialog共存时,可以同时处理滑动事件。
- 定义一个NestedScrollingParent的容器, 此处以
LinearLayout
为例。
public class MyCoordinatorLayout extends LinearLayout implements NestedScrollingParent {
public MyCoordinatorLayout(Context context) {
super(context);
}
public MyCoordinatorLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyCoordinatorLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mTouchY = ev.getRawY();
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
@Override
public void onNestedScrollAccepted(View child, View target, int axes, int type) {
super.onNestedScrollAccepted(child, target, axes, type);
}
@Override
public void onStopNestedScroll(View target) {
super.onStopNestedScroll(target);
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
if (dyUnconsumed < 0) { //WebView向下滑动
showBottomSheetDialog();
}
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
}
@Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
return super.onNestedFling(target, velocityX, velocityY, consumed);
}
@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
return super.onNestedPreFling(target, velocityX, velocityY);
}
}
- 将上述定义的
MyCoordinatorLayout
应用于Activity布局, 其代码如下:
<com.example.nested.MyCoordinatorLayout
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/show_bottom_sheet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="show_bottom_sheet" />
</com.example.nested.MyCoordinatorLayout>
- 给按钮设置点击监听器, 显示BottomSheetDialog:
findViewById(R.id.show_bottom_sheet).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showBottomSheetDialog();
}
});
- 显示BottomSheetDialog:
private void showBottomSheetDialog() {
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(MainActivity.this);
bottomSheetDialog.setContentView(R.layout.bottom_sheet_dialog);
BottomSheetBehavior<View> behavior = BottomSheetBehavior.from((View) bottomSheetDialog.getWindow().findViewById(R.id.design_bottom_sheet));
behavior.setPeekHeight(300);
behavior.setDraggable(false);
bottomSheetDialog.show();
}
总结
通过上述操作,BottomSheetDialog和WebView都能够实现正常的使用,互不干扰。