You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现CoordinatorLayout中BottomSheet滑动时ImageView同步缩放?

问题:BottomSheet滑动时ImageView无法跟随缩放

我的CoordinatorLayout布局内包含一个ImageView和一个设置了BottomSheetBehavior的NestedScrollView,希望实现BottomSheet上下滑动时ImageView同步调整尺寸,但目前未达到预期效果,请问该如何解决?


示例布局

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#CFCACA"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/cartoon"
        android:layout_marginBottom="50dp"/>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_insetEdge="bottom"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="50dp"
                android:layout_marginStart="50dp"
                android:orientation="horizontal">

                <ImageView
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:src="@drawable/ic_baseline_volume_up_24"/>

                <ImageButton
                    android:layout_width="0dp"
                    android:layout_height="40dp"
                    android:backgroundTint="@color/white"
                    android:layout_marginStart="50dp"
                    android:layout_marginEnd="50dp"
                    android:src="@drawable/ic_baseline_play_arrow_24"
                    android:background="@drawable/img_button_shape"
                    android:layout_weight="1"
                    android:layout_gravity="center"/>

                <ImageView
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_gravity="end"
                    android:src="@drawable/ic_baseline_volume_up_24"/>

            </LinearLayout>

            <LinearLayout
                android:id="@+id/layout"
                android:layout_width="match_parent"
                android:layout_height="355dp"
                android:minHeight="100dp"
                android:layout_marginTop="15dp"
                android:background="@drawable/curvy_layout"
                android:orientation="vertical">

                <View
                    android:id="@+id/view"
                    android:layout_width="50dp"
                    android:layout_height="5dp"
                    android:background="@color/black"
                    android:layout_gravity="center"
                    android:layout_marginTop="15dp"/>

                <com.google.android.material.tabs.TabLayout
                    android:id="@+id/tabLayout"
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    app:tabMode="scrollable"
                    app:tabBackground="@drawable/tab_bg"
                    app:tabSelectedTextColor="@color/white"
                    app:tabIndicatorHeight="0dp"
                    android:layout_marginTop="20sp"
                    android:layout_marginStart="20dp"
                    android:layout_marginEnd="20dp"/>

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/verticalView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scrollbars="vertical"
                    android:layout_marginTop="30dp"
                    app:layout_behavior="@string/appbar_scrolling_view_behavior"
                    android:layout_marginStart="10sp"
                    android:layout_marginEnd="10dp"/>

            </LinearLayout>

        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

对应代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    View bottomSheet = findViewById(R.id.bottom_sheet);
    LinearLayout layout = findViewById(R.id.layout);
    View view = findViewById(R.id.view);
    TabLayout tabLayout = findViewById(R.id.tabLayout);
    RecyclerView recyclerView = findViewById(R.id.verticalView);
    imageView = findViewById(R.id.img);
    mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);

    mBottomSheetBehavior.setHideable(false);
    mBottomSheetBehavior.setPeekHeight(layout.getMinimumHeight());

    tabLayout.setBackgroundColor(Color.TRANSPARENT);
    
    // 设置RecyclerView
    GridLayoutManager layoutManager = new GridLayoutManager(this,4);
    assert recyclerView != null;
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setHasFixedSize(true);
    bottomSheet.setNestedScrollingEnabled(false);

    getTabsList();
    // 设置TabLayout
    assert tabLayout != null;
    createTabLayout(tabLayout,recyclerView);
}

解决方案

默认情况下BottomSheet的滑动不会联动其他View,需要手动监听滑动事件,根据偏移量动态调整ImageView尺寸,具体步骤如下:

1. 监听BottomSheet滑动事件

给BottomSheetBehavior添加回调,在onSlide方法中获取滑动偏移量(范围0~1,0为完全收起,1为完全展开)。

2. 动态调整ImageView尺寸

定义ImageView的最大/最小高度,根据偏移量计算目标高度并更新布局参数:

mBottomSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
    @Override
    public void onStateChanged(@NonNull View bottomSheet, int newState) {
        // 状态变化回调(可选,比如处理展开/收起完成后的逻辑)
    }

    @Override
    public void onSlide(@NonNull View bottomSheet, float slideOffset) {
        if (imageView == null) return;
        
        // 从dimens文件读取预设的最大/最小高度
        int maxHeight = getResources().getDimensionPixelSize(R.dimen.img_max_height);
        int minHeight = getResources().getDimensionPixelSize(R.dimen.img_min_height);
        
        // 根据滑动偏移量计算目标高度:收起时缩小到最小,展开时恢复最大
        int targetHeight = (int) (minHeight + (maxHeight - minHeight) * (1 - slideOffset));
        
        // 更新ImageView布局参数
        ViewGroup.LayoutParams params = imageView.getLayoutParams();
        params.height = targetHeight;
        imageView.setLayoutParams(params);
    }
});

3. 布局与资源优化

  • 给ImageView添加android:adjustViewBounds="true",保证图片按比例缩放:
<ImageView
    android:id="@+id/img"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/cartoon"
    android:layout_marginBottom="50dp"
    android:adjustViewBounds="true"/>
  • 在res/values/dimens.xml中定义最大/最小高度:
<dimen name="img_max_height">300dp</dimen>
<dimen name="img_min_height">100dp</dimen>

内容的提问来源于stack exchange,提问作者Taki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:35:04