实现CollapsingToolbarLayout中按钮的动态滚动固定效果
解决CollapsingToolbarLayout折叠时按钮位置联动问题
我完全理解你想要实现的效果——就像WhatsApp群组详情里的编辑按钮那样:当CollapsingToolbarLayout完全展开时,按钮停在Toolbar区域的底部右侧;当折叠完成后,按钮平滑上移并固定在顶部Toolbar的右侧。
你当前的问题出在按钮直接嵌套在设置了app:layout_collapseMode="pin"的Toolbar里,这导致按钮会跟着Toolbar一起被固定在顶部,无法响应CollapsingToolbarLayout的展开/折叠状态。下面是具体的解决方案:
第一步:调整布局结构
把按钮从Toolbar内部移出,作为CollapsingToolbarLayout的独立子View,这样它才能跟随折叠区域的变化调整位置:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/col" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimaryDark" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:elevation="4dp" android:transitionName="@string/pic_transition_name"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/clpsToolbarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:collapsedTitleTextAppearance="@style/CollapsedText" app:contentScrim="@color/colorPrimary" app:expandedTitleTextAppearance="@style/ExpandedText" app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> <ImageView android:id="@+id/iv_gallery" android:layout_width="match_parent" android:layout_height="320dp" android:layout_gravity="center_horizontal" app:layout_collapseMode="parallax" /> <!-- 保持Toolbar的pin模式,确保折叠后固定在顶部 --> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:gravity="center" app:layout_collapseMode="pin" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> <!-- 按钮移到这里,作为CollapsingToolbarLayout的子View --> <Button android:id="@+id/mmv_toggle_detail" android:layout_width="60dp" android:layout_height="60dp" android:layout_gravity="right|bottom" android:layout_marginRight="16dp" android:layout_marginBottom="8dp" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <!-- 必须添加可滚动的内容View,否则CollapsingToolbarLayout不会触发折叠 --> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <!-- 替换成你的实际内容布局 --> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:textSize="18sp" android:text="这里是可滚动的示例内容,用于触发CollapsingToolbarLayout的折叠效果" /> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
第二步:添加折叠偏移监听,实现平滑联动
通过监听AppBarLayout的折叠进度,动态调整按钮的translationY值,让它随着折叠过程平滑上移:
public class YourActivity extends AppCompatActivity { private AppBarLayout appBarLayout; private Button toggleButton; private int toolbarHeight; private int buttonBottomMargin; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout); appBarLayout = findViewById(R.id.appbar); toggleButton = findViewById(R.id.mmv_toggle_detail); // 获取Toolbar的高度(对应?attr/actionBarSize) toolbarHeight = getResources().getDimensionPixelSize(R.dimen.abc_action_bar_default_height_material); // 获取按钮的底部margin(对应布局里的8dp) buttonBottomMargin = getResources().getDimensionPixelSize(R.dimen.button_bottom_margin); // 监听折叠偏移变化 appBarLayout.addOnOffsetChangedListener((appBar, verticalOffset) -> { // verticalOffset范围:0(完全展开) → -appBar.getTotalScrollRange()(完全折叠) float collapseRatio = Math.abs(verticalOffset) / (float) appBar.getTotalScrollRange(); // 计算按钮需要上移的距离:从Toolbar底部到顶部,总移动距离是Toolbar高度减去底部margin float translationY = -(collapseRatio * (toolbarHeight - buttonBottomMargin)); toggleButton.setTranslationY(translationY); }); } }
关键要点说明
- 布局调整原因:把按钮放到
CollapsingToolbarLayout内,才能让它处于可联动的折叠区域中;初始的layout_gravity="right|bottom"确保展开时按钮在Toolbar底部右侧,和WhatsApp的初始位置一致。 - 平滑联动逻辑:通过
collapseRatio(折叠进度,0到1之间)计算按钮的偏移量,让它随着折叠过程匀速上移,完全折叠时刚好停在Toolbar顶部右侧。 - 必要前提:布局中必须包含可滚动的子View(如
NestedScrollView/RecyclerView),并且设置app:layout_behavior="@string/appbar_scrolling_view_behavior",否则CollapsingToolbarLayout不会触发折叠效果。
内容的提问来源于stack exchange,提问作者Badr Bujbara
相关产品推荐
相关产品推荐

