BottomSheet的使用

BottomSheet

简介

BottomSheet是指底部弹出的视图。在使用DrawerLayout时可以实现从屏幕左侧和右侧弹出布局,但是不能从底部弹出。因此了解到了BottomSheet。

BottomSheet的具体实现包括:

  • BottomSheetBehavior:一般直接作用在View上,一般在xml布局中直接对view设置属性,轻量级,代码少,灵活行高。适用于复杂页面下的半瓶弹出效果。使用CoordinatorLayout布局和行为属性app:layout_behavior="@string/bottom_sheet_behavior"。

  • BottomSheetDialog:使用方法和对话框的使用基本一致,通过setContentView()设定布局,调用show展示。一般用于底部弹出的对话框或者弹窗。

  • BottomSheetDialogFragment:使用方法和普通的Fragment一样,可以将交互和UI写在Fragment内。

【精选】探索BottomSheet的背后秘密-CSDN博客

BottomSheet的五个状态

  • STATE_COLLAPSED:折叠状态。一般是半屏状态。可通过app:behavior_peekHeight来设置默认显示的高度。

  • STATE_EXPANDED:完全展开状态。默认是屏幕高度。

  • STATE_HIDDEN:隐藏状态,并不是GONE,而是出于屏幕的最下方,不可见。

  • STATE_DRAGGING:拖拽状态。手指在屏幕上拖动视图(手指未离开屏幕前)。

  • STATE_SETTING:拖拽结束直到到达终点位置(STATE_COLLAPSED或者STATE_EXPANDED)这段时间。

BottomSheetBehavior的使用

BottomSheetBehavior的使用需要借助行为属性app:layout_behavior="@string/bottom_sheet_behavior"。所以一般嵌套在CoordinatorLayout中使用。

<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="match_parent"
    android:id="@+id/parent_layout"
    tools:context=".MainActivity">
​
    <TextView
        android:id="@+id/hello_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:layout_gravity="center" />
​
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#479bf7"
               
        //特别指定的属性
        app:behavior_hideable="true"
        app:behavior_peekHeight="20dp"
        app:layout_behavior="@string/bottom_sheet_behavior"
        />
​
</androidx.coordinatorlayout.widget.CoordinatorLayout>

主要就是指定行为属性"@string/bottom_sheet_behavior",和一些相关的属性,没什么特别的。

常用属性:

app:behavior_hideable="false" 
//该属性表示该视图是否可以完全隐藏,如果设置为true,该视图在屏幕上完全隐藏,用户也就没法拖拽出来,可以通过监听在代码中调出
app:behavior_peekHeight="20dp"
//最小可见高度,也是折叠时显示在屏幕上的高度
app:behavior_skipCollapsed="true"
//设置为true可以使得底部表单直接从折叠状态跳转到完全展开的状态,而不经过中间的折叠状态
app:behavior_fitToContents="true"
//设置为true表示使用内容高度,和warp_content有相似的效果

其实这时运行代码,一个可以拖拽出来也可以拉回去的底部弹窗就已经完成了。

通常也会这样使用:

布局文件中不用修改其他代码,不过需要将< RecyclerView>的app:behavior_hideable=""属性设为true

实现点击底部弹窗完全隐藏,点击TextView让它完全展开,再次点击让它完全隐藏

public class MainActivity extends AppCompatActivity {
    RecyclerView recyclerView;
    Adapter adapter;
    List<Integer> ims = new ArrayList<>();
    BottomSheetBehavior bottomSheetBehavior;
    TextView hello;
    CoordinatorLayout parentLayout;
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Collections.addAll(ims, R.drawable.i1, R.drawable.i2, R.drawable.i3, R.drawable.i4,
        R.drawable.i5, R.drawable.i6);
        recyclerView = (RecyclerView) findViewById(R.id.recycler);
        adapter = new Adapter(ims);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        recyclerView.setAdapter(adapter);
​
        bottomSheetBehavior = BottomSheetBehavior.from(recyclerView);
        //传入拥有行为属性"@string/bottom_sheet_behavior"的视图,获取控制视图底部弹出和收回动作的BottomSheetBehavior对象
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);//默认视图的状态为隐藏
​
        hello = findViewById(R.id.hello_text);
        //获取控制底部弹窗的控件,设置监听事件
        hello.setOnClickListener(view -> {
            Log.d("TAG", "onCreate: " + bottomSheetBehavior.getState());
            if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_HIDDEN
            || bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
                //如果当前是隐藏的,或者是折叠的 就完全展开
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            } else if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED){
                //如果是完全展开的 就隐藏
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
            }
        });
​
        //因为BottomSheetBehavior没有直接提供点击试图外关闭底部弹窗的功能,
        // 所以通常获取父布局CoordinatorLayout的实例并设置监听,将底部弹窗关闭
        parentLayout = findViewById(R.id.parent_layout);
        parentLayout.setOnClickListener(view -> {
            if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
            }
        });
    }
}

看看效果。

BottomSheetBehaior的状态监听

bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(View bottomSheet, int newState) {
               //监听BottomSheet状态的改变
            }
 
            @Override
            public void onSlide(View bottomSheet, float slideOffset) {
               //监听拖拽中的回调,根据slideOffset可以做一些动画
            }
        });

BottomSheetDialog的使用

基本使用:

我新创建了一个布局,这个布局中只有一个RecyclerView,让它实现和上面一样的效果。布局名叫the_layout。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
​
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_vi"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#479bf7"
        />
</LinearLayout>

在MainActivity中编写代码:

public class MainActivity extends AppCompatActivity {
​
    BottomSheetDialog bottomSheetDialog;
    TextView hello;
    List<Integer> ims = new ArrayList<>();
​
    @SuppressLint({"ResourceType", "MissingInflatedId"})
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        hello = (TextView) findViewById(R.id.hello_text);
​
        Collections.addAll(ims, R.drawable.i1, R.drawable.i2, R.drawable.i3, R.drawable.i4,
                R.drawable.i5, R.drawable.i6);
        //初始化列表数据
​
        bottomSheetDialog = new BottomSheetDialog(this);
        //1.首先初始化底部弹出对话框
        bottomSheetDialog.setContentView(R.layout.the_layout);
        //2.给底部弹出对话框加载布局
        RecyclerView recyclerView = bottomSheetDialog.findViewById(R.id.recycler_vi);
        if (recyclerView != null) {
            recyclerView.setAdapter(new Adapter(ims));
            recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        }
        //3.加载页面信息
​
        hello.setOnClickListener(view -> {
            Log.d("click", "onCreate: ");
            bottomSheetDialog.show();
        });
        //4.展示
    }
}

注意:这里的第三步的加载数据,获取控件时一定要用BottomSheetDialog对象去调用findViewById方法。

常用方法:

bottomSheetDialog.setContentView();//传入R.layout.*或者用LayoutInflater加载的View
bottomSheetDialog.setCanceledOnTouchOutside(boolean cancel);//设置是否与可以点击弹窗以外的区域关闭弹窗,默认true
bottomSheetDialog.show();//显示
bottomSheetDialog.dismiss();//关闭
bottomSheetDialog.setOnShowListener(DialogInterface.OnShowListener listener);//设置对话框显示时的监听器。
bottomSheetDialog.setOnDismissListener(DialogInterface.OnDismissListener listener);//设置对话框关闭时的监听器。
//还可以添加BottomSheetBehavior进行设置
​
BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(view);//传入的是与BottomSheetDialog相关的控件,视图
// 设置最小高度
behavior.setPeekHeight(500);

在构造函数中可以指定自定义主题进行优化显示

使用shape约束圆角。

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#479bf7"/>
    <corners android:topLeftRadius="10dp"
        android:topRightRadius="10dp"/>
    <stroke android:color="@color/black"
        android:width=".1dp"
        />
</shape>

将这个shape用android:background属性应用到布局文件中就行了。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/ss"
    >
​
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_vi"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
</LinearLayout>

如果更改BottomSheetDialog的主题可以在构造函数中指定。

bottomSheetDialog = new BottomSheetDialog(this, R.style.BottomSheetDialogTheme);

BottomSheetDialogFragment的使用

BottomSheetDialog的两种用法:

用法一:

重写BottomSheetDialogFragment中的OnCreateDialog方法。

public class BSFragment extends BottomSheetDialogFragment {
    private List<Integer> ims = new ArrayList<>();
    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
        View view = View.inflate(getContext(), R.layout.the_layout, null);
​
        Collections.addAll(ims, R.drawable.i1, R.drawable.i2, R.drawable.i3, R.drawable.i4,
                R.drawable.i5, R.drawable.i6);
        bottomSheetDialog.setContentView(view);
        RecyclerView recyclerView = bottomSheetDialog.findViewById(R.id.recycler_vi);
        if (recyclerView != null) {
            recyclerView.setAdapter(new Adapter(ims));
            recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3));
        }
        
        return bottomSheetDialog;
    }
}

在onCreateDialog方法中创建BottonSheetDialog进行显示。

在MainActivity中

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    TextView hello = findViewById(R.id.hello_text);
    hello.setOnClickListener(view -> {
        BSFragment fragment = new BSFragment();
        fragment.show(getSupportFragmentManager(), "1");
    });
​
​
}

获取到Fragment类的实例后调用show()方法进行显示,第一个参数获取supportFragmentManager,第二个参数是Tag。

BottomSheet详解 - 掘金 (juejin.cn)

BottomSheet 的使用介绍(BottomSheetBeahvior,BottomSheetDialog,BottomSheetDialogFragment)-CSDN博客

【精选】探索BottomSheet的背后秘密-CSDN博客

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值