Android底部Sheet
在本教程中,我们将讨论并实现随Android支持v23.2一起引入的android底表小部件。
Android底部Sheet
根据Google材料设计文档;
底页是从屏幕底部边缘向上滑动的页。
由于用户触发了操作,因此显示底页,并且通过向上滑动也可以显示其他内容。
底页可以是模式的(从屏幕底部向上滑动以显示更多内容),也可以是固定的(与应用集成以显示支持内容时)。
BottomSheets可以实现为BottomSheetBehavior,BottomSheetDialog和BottomSheetDialogFragment。
Android BottomSheet行为
BottomSheetBehavior是用于持久性底部工作表的一种" layout_behavior"。
它需要将CoordinatorLayout设置为该布局的根元素,并向子视图添加xml属性ʻapp:layout_behavior:android.support.design.widget.BottomSheetBehavior`。
让我们看一下将放置在CoordinatorLayout中的示例xml子视图。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:behavior_hideable="false"
app:behavior_peekHeight="120dp"
android:orientation="vertical"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum"
</LinearLayout>
从以上代码片段中得出的结论很少:
- layout_behavior将视图设置为底页
- behavior_peekHeight设置工作表的可见部分
- behavior_hideable设置是否可以通过进一步向下拖动视图来隐藏该视图。
它接受布尔值。
让我们在Android Studio中创建一个新项目,将模板设置为"基本活动",然后在" activity_main.xml"中的xml片段上方添加。
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.theitroad.bottomsheet.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main"
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:behavior_hideable="false"
app:behavior_peekHeight="120dp"
android:orientation="vertical"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum"
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
让我们运行一次应用程序,看看它的行为。
设置app:behavior_hideable =" true",一旦向下拖动,底部工作表将保持隐藏状态。
" BottomSheetBehavior"类允许我们以编程方式设置视图的当前状态。
以下是用于处理状态的重要常量:
STATE_COLLAPSED:使用在peekHeight属性上设置的值来设置底部工作表的高度。
STATE_DRAGGING:正在拖动底部的工作表
STATE_EXPANDED:底部工作表已完全展开
STATE_HIDDEN:底部工作表从屏幕上完全隐藏
让我们跳到本教程的业务端。
我们将开发一个应用程序,该应用程序在底部的表格内显示一个RecyclerView以及可供选择的项目。
Android底表示例项目结构
Android底表示例代码
下面定义了" activity_main.xml"布局。
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:id="@+id/coordinatorLayout"
tools:context="com.theitroad.bottomsheet.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
android:id="@+id/bottom_sheet"
android:background="@android:color/white"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textStyle="bold"
android:text="SELECT AN ITEM"
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="16dp"
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
MainActivity.java在下面给出。
package com.theitroad.bottomsheet;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements ItemAdapter.ItemListener {
BottomSheetBehavior behavior;
RecyclerView recyclerView;
private ItemAdapter mAdapter;
CoordinatorLayout coordinatorLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
View bottomSheet = findViewById(R.id.bottom_sheet);
behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
//React to state change
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
//React to dragging events
}
});
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ArrayList items = new ArrayList();
items.add("Item 1");
items.add("Item 2");
items.add("Item 3");
items.add("Item 4");
items.add("Item 5");
items.add("Item 6");
mAdapter = new ItemAdapter(items, this);
recyclerView.setAdapter(mAdapter);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
}
@Override
public void onItemClick(String item) {
Snackbar.make(coordinatorLayout,item + " is selected", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
以下是从上面的代码得出的推论。
behavior = BottomSheetBehavior.from(bottomSheet); from(View view)是BottomSheetBehavior类的静态方法,用于从View实例的布局参数中获取行为的实例。
在BottomSheetBehavior实例上调用BottomSheetCallback,以便我们接收底部工作表的回调,例如状态更改和偏移量更改。
ItemAdapter.java类具有RecyclerView适配器的实现,如下所示。
package com.theitroad.bottomsheet;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
class ItemAdapter extends RecyclerView.Adapter {
private List mItems;
private ItemListener mListener;
ItemAdapter(List items, ItemListener listener) {
mItems = items;
mListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.bottom_sheet_item, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setData(mItems.get(position));
}
@Override
public int getItemCount() {
return mItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView textView;
String item;
ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
textView = (TextView) itemView.findViewById(R.id.textView);
}
void setData(String item) {
this.item = item;
textView.setText(item);
}
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onItemClick(item);
}
}
}
interface ItemListener {
void onItemClick(String item);
}
}
上面的代码与我们之前在RecyclerView教程中实现的代码相似,但您所看到的界面除外。
该接口是在MainActivity.java类中实现的,目的是使RecyclerView的onItemClick功能类似于ListView。
回到MainActivity.java类,
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);展开底部工作表。
单击RecyclerView项将显示SnackBar并折叠底部表。
让我们看看实际的应用程序。
在上面的输出中,我们可以看到可以将BottomSheet向下拖动而无需选择项目。
为防止未选择任何项目而使其塌陷,请将BottomSheetCallBack设置为:
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
//React to dragging events
}
});

