Android底部Sheet

时间:2020-02-23 14:28:46  来源:igfitidea点击:

在本教程中,我们将讨论并实现随Android支持v23.2一起引入的android底表小部件。

Android底部Sheet

根据Google材料设计文档;

底页是从屏幕底部边缘向上滑动的页。
由于用户触发了操作,因此显示底页,并且通过向上滑动也可以显示其他内容。

底页可以是模式的(从屏幕底部向上滑动以显示更多内容),也可以是固定的(与应用集成以显示支持内容时)。

BottomSheets可以实现为BottomSheetBehaviorBottomSheetDialogBottomSheetDialogFragment

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
          }
      });