实现BottomAppBar随滚动显示与隐藏的功能需求
实现WebView滚动时BottomAppBar的显示/隐藏效果
我之前也做过类似的需求,分享一个亲测有效的方案——核心是监听WebView的滚动方向,配合属性动画控制BottomAppBar的滑入滑出,完全能实现你想要的滚动交互效果:
1. 先调整布局结构
确保BottomAppBar处于可灵活控制的布局容器中(比如ConstraintLayout),示例布局如下:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 替换成自定义的可监听滚动的WebView --> <com.yourpackage.ObservableWebView android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/bottom_app_bar"/> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bottom_app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:menu="@menu/your_bottom_menu"/> </androidx.constraintlayout.widget.ConstraintLayout>
2. 自定义可监听滚动的WebView
原生WebView没有直接的滚动监听接口,我们可以重写onScrollChanged方法来捕获滚动方向:
public class ObservableWebView extends WebView { private OnScrollChangeListener scrollChangeListener; // 滚动阈值,避免轻微滚动触发频繁动画 private static final int SCROLL_THRESHOLD = 15; private int scrollDistance = 0; public ObservableWebView(Context context) { super(context); } public ObservableWebView(Context context, AttributeSet attrs) { super(context, attrs); } public ObservableWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (scrollChangeListener == null) return; // 先判断WebView内容是否足够滚动(避免内容不足一屏时触发动画) boolean canScroll = getContentHeight() * getScale() > getHeight() + getScrollY(); if (!canScroll) return; int scrollDelta = t - oldt; scrollDistance += scrollDelta; // 超过阈值才触发方向回调 if (Math.abs(scrollDistance) > SCROLL_THRESHOLD) { scrollChangeListener.onScrollDirectionChanged(scrollDelta > 0); scrollDistance = 0; } } public void setOnScrollChangeListener(OnScrollChangeListener listener) { this.scrollChangeListener = listener; } public interface OnScrollChangeListener { // isScrollingDown为true表示向下滚动,false表示向上 void onScrollDirectionChanged(boolean isScrollingDown); } }
3. 实现BottomAppBar的动画控制
在Activity/Fragment中,绑定滚动监听并执行显示/隐藏动画:
public class MainActivity extends AppCompatActivity { private ObservableWebView webView; private BottomAppBar bottomAppBar; private int bottomBarHeight; // 记录当前Bar的显示状态,避免重复执行动画 private boolean isBarVisible = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.web_view); bottomAppBar = findViewById(R.id.bottom_app_bar); // 等待视图绘制完成后获取BottomAppBar的高度 bottomAppBar.post(() -> bottomBarHeight = bottomAppBar.getHeight()); // 设置WebView滚动监听 webView.setOnScrollChangeListener(isScrollingDown -> { if (isScrollingDown && isBarVisible) { hideBottomBar(); } else if (!isScrollingDown && !isBarVisible) { showBottomBar(); } }); // 加载测试网页 webView.loadUrl("https://www.example.com"); } private void hideBottomBar() { isBarVisible = false; bottomAppBar.animate() .translationY(bottomBarHeight) .setDuration(300) .setInterpolator(new AccelerateInterpolator()) .start(); } private void showBottomBar() { isBarVisible = true; bottomAppBar.animate() .translationY(0) .setDuration(300) .setInterpolator(new DecelerateInterpolator()) .start(); } }
可选优化点
- 如果需要和SwipeRefreshLayout配合,记得在WebView滚动到顶部时才允许下拉刷新,避免冲突;
- 可以根据WebView的滚动位置,调整动画的触发时机,比如滚动到内容顶部时强制显示Bar。
这个方案我在多个项目里用过,滚动交互流畅度和逻辑完整性都没问题,完全能匹配你想要的参考效果~
内容的提问来源于stack exchange,提问作者WWJD
相关产品推荐
相关产品推荐

