Android自定义底部导航栏实现上滑隐藏下滑显示方案问询
实现自定义底部导航栏的滑动隐藏/显示效果(无第三方库)
嘿,我看了你用LinearLayout和RelativeLayout自定义的底部导航栏,要实现上滑隐藏、下滑显示的效果其实不难,咱们一步步来搞定它:
核心思路
监听页面内容区域的滚动方向,判断是上滑还是下滑,然后通过属性动画平滑地控制底部导航栏的显示与隐藏——上滑时让导航栏向下移出屏幕,下滑时再拉回原位置。
步骤1:准备工作(在MainActivity中)
首先获取底部导航栏的实例,并提前拿到它的高度,方便后续动画计算:
private RelativeLayout bottomToolbar; private int bottomToolbarHeight; // 记录上次滚动位置,避免频繁触发动画 private int lastScrollY = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取底部导航栏控件 bottomToolbar = findViewById(R.id.bottom_toolbar); // 获取导航栏高度(需要等布局完成后才能拿到准确值) bottomToolbar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { bottomToolbarHeight = bottomToolbar.getHeight(); // 拿到高度后移除监听,避免重复回调 bottomToolbar.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); }
步骤2:监听内容区域的滚动事件
你的页面内容是放在MageNative_frame_container这个FrameLayout里的Fragment,所以需要在Fragment中的滚动控件(比如RecyclerView/ScrollView)添加滚动监听:
如果用的是RecyclerView:
// 在你的目标Fragment中 RecyclerView recyclerView = findViewById(R.id.your_recyclerview_id); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // dy > 0 表示上滑,dy < 0 表示下滑 // 加个阈值(比如20px)避免轻微滚动就触发动画 if (dy > 20 && bottomToolbar.getVisibility() == View.VISIBLE) { // 调用MainActivity的隐藏方法 ((MainActivity) getActivity()).hideBottomToolbar(); } else if (dy < -20 && bottomToolbar.getVisibility() == View.GONE) { // 调用MainActivity的显示方法 ((MainActivity) getActivity()).showBottomToolbar(); } lastScrollY = recyclerView.computeVerticalScrollOffset(); } });
如果用的是ScrollView:
// 在你的目标Fragment中 ScrollView scrollView = findViewById(R.id.your_scrollview_id); scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { @Override public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { int dy = scrollY - oldScrollY; // 同样加阈值避免误触发 if (dy > 20 && bottomToolbar.getVisibility() == View.VISIBLE) { ((MainActivity) getActivity()).hideBottomToolbar(); } else if (dy < -20 && bottomToolbar.getVisibility() == View.GONE) { ((MainActivity) getActivity()).showBottomToolbar(); } lastScrollY = scrollY; } });
步骤3:实现平滑的显示/隐藏动画
在MainActivity中添加两个方法,用属性动画实现导航栏的平滑移动:
// 隐藏底部导航栏:向下移出屏幕 private void hideBottomToolbar() { bottomToolbar.animate() .translationY(bottomToolbarHeight) // 移动距离等于导航栏高度 .setDuration(300) // 动画时长300ms .setInterpolator(new AccelerateInterpolator()) // 加速插值器,动画越来越快 .withEndAction(new Runnable() { @Override public void run() { bottomToolbar.setVisibility(View.GONE); // 动画结束后隐藏,避免占位置 } }); } // 显示底部导航栏:从下方移回原位置 private void showBottomToolbar() { bottomToolbar.setVisibility(View.VISIBLE); // 先设置可见,再执行动画 bottomToolbar.animate() .translationY(0) .setDuration(300) .setInterpolator(new DecelerateInterpolator()); // 减速插值器,动画越来越慢,更自然 }
额外优化建议
- 统一管理监听逻辑:如果多个Fragment都需要这个效果,可以写一个
BaseFragment,把滚动监听的逻辑放在里面,其他Fragment继承它即可,减少重复代码。 - 内容不足时不触发:可以判断滚动控件的总滚动范围,如果内容没有超过屏幕高度,就不执行隐藏逻辑。
- 避免动画重复触发:除了加滚动阈值,还可以通过
lastScrollY判断滚动趋势,防止来回滚动时频繁触发动画。
内容的提问来源于stack exchange,提问作者Areeb Khan
相关产品推荐
相关产品推荐

