BottomSheet is an Android component which presents a dismissable view from the bottom of the screen. BottomSheet can be a usefull replacement for dialogs and menus but can hold any view so the use cases are endless. This repository includes the BottomSheet component itself but also includes a set of common view componenets presented in a bottom sheet. These are located in the commons module.
BottomSheet has been used in production at Flipboard for a while now so it is thoroughly tested. Here is a GIF of it in action inside of Flipboard!
Installation
If all you want is the BottomSheet component and don't need things from commons you can skip that dependency.
dependencies {
compile 'com.flipboard:bottomsheet-core:1.0.0'
compile 'com.flipboard:bottomsheet-commons:1.0.0' // optional
}
Getting Started
Get started by wrapping your layout in a BottomSheet. So if you currently have this:
<LinearLayout android:id="@+id/root" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:id="@+id/view1" android:layout_width="match_parent" android:layout_height="match_parent"/> <View android:id="@+id/view2" android:layout_width="match_parent" android:layout_height="match_parent"/> LinearLayout>
You would have to update it to look like this:
<com.flipboard.bottomsheet.BottomSheet android:id="@+id/bottomsheet" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/root" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:id="@+id/view1" android:layout_width="match_parent" android:layout_height="match_parent"/> <View android:id="@+id/view2" android:layout_width="match_parent" android:layout_height="match_parent"/> LinearLayout> com.flipboard.bottomsheet.BottomSheet>
Back in your activity or fragment you would get a reference to the BottomSheet like any other view.
BottomSheet bottomSheet = (BottomSheet) findViewById(R.id.bottomsheet);
Now all you need to do is show a view in the bottomSheet:
bottomSheet.showWithSheetView(LayoutInflater.from(context).inflate(R.layout.my_sheet_layout, bottomSheet, false));
You could also use one of the sheet views from the commons module.
bottomSheet.showWithSheetView(new IntentPickerSheetView(this, shareIntent, "Share with...", new IntentPickerSheetView.OnIntentPickedListener() { @Override public void onIntentPicked(Intent intent) { bottomSheet.dismissSheet(); startActivity(intent); } });
That's it for the simplest of use cases. Check out the API documentation below to find out how to customize BottomSheet to fit your use cases.
API
BottomSheet
/** * Set the presented sheet to be in an expanded state. */ public void expandSheet(); /** * Set the presented sheet to be in a peeked state. */ public void peekSheet(); /** * @return The peeked state translation for the presented sheet view. Translation is counted from the bottom of the view. */ public float getPeekSheetTranslation(); /** * @return The maximum translation for the presented sheet view. Translation is counted from the bottom of the view. */ public float getMaxSheetTranslation(); /** * @return The currently presented sheet view. If no sheet is currently presented null will returned. */ public View getContentView(); /** * @return The currently presented sheet view. If no sheet is currently presented null will returned. */ public View getSheetView(); /** * Set the content view of the bottom sheet. This is the view which is shown under the sheet * being presented. This is usually the root view of your application. * * @param contentView The content view of your application. */ public void setContentView(View contentView); /** * Convenience for showWithSheetView(sheetView, null, null) */ public void showWithSheetView(View sheetView); /** * Convenience for showWithSheetView(sheetView, viewTransformer, null) */ public void showWithSheetView(View sheetView, ViewTransformer viewTransformer); /** * Present a sheet view to the user. * * @param sheetView The sheet to be presented. * @param viewTransformer The view transformer to use when presenting the sheet. * @param onSheetDismissedListener The listener to notify when the sheet is dismissed. */ public void showWithSheetView(View sheetView, ViewTransformer viewTransformer, OnSheetDismissedListener onSheetDismissedListener); /** * Dismiss the sheet currently being presented. */ public void dismissSheet(); /** * @return The current state of the sheet. */ public State getState(); /** * @return Whether or not a sheet is currently presented. */ public boolean isSheetShowing(); /** * Set the default view transformer to use for showing a sheet. Usually applications will use * a similar transformer for most use cases of bottom sheet so this is a convenience instead of * passing a new transformer each time a sheet is shown. This choice is overridden by any * view transformer passed to showWithSheetView(). * * @param defaultViewTransformer The view transformer user by default. */ public void setDefaultViewTransformer(ViewTransformer defaultViewTransformer); /** * Enable or disable dimming of the content view while a sheet is presented. If enabled a * transparent black dim is overlayed on top of the content view indicating that the sheet is the * foreground view. This dim is animated into place is coordination with the sheet view. * Defaults to true. * * @param shouldDimContentView whether or not to dim the content view. */ public void setShouldDimContentView(boolean shouldDimContentView); /** * @return whether the content view is being dimmed while presenting a sheet or not. */ public boolean shouldDimContentView(); /** * Enable or disable the use of a hardware layer for the presented sheet while animating. * This settings defaults to true and should only be changed if you know that putting the * sheet in a layer will negatively effect performance. One such example is if the sheet contains * a view which needs to frequently be re-drawn. * * @param useHardwareLayerWhileAnimating whether or not to use a hardware layer. */ public void setUseHardwareLayerWhileAnimating(boolean useHardwareLayerWhileAnimating); /** * Set a OnSheetStateChangeListener which will be notified when the state of the presented sheet changes. * * @param onSheetStateChangeListener the listener to be notified. */ public void setOnSheetStateChangeListener(OnSheetStateChangeListener onSheetStateChangeListener);
OnSheetDismissedListener
/** * Called when the presented sheet has been dismissed. * * @param bottomSheet The bottom sheet which contained the presented sheet. */ void onDismissed(BottomSheet bottomSheet);
ViewTransformer
/** * Called on every frame while animating the presented sheet. This method allows you to coordinate * other animations (usually on the content view) with the sheet view's translation. * * @param translation The current translation of the presented sheet view. * @param maxTranslation The max translation of the presented sheet view. * @param peekedTranslation The peeked state translation of the presented sheet view. * @param parent The BottomSheet presenting the sheet view. * @param view The content view to transform. */ void transformView(float translation, float maxTranslation, float peekedTranslation, BottomSheet parent, View view);
Common Components
These are located in the optional bottomsheet-commons dependency
and implement common use cases for bottom sheet.
IntentPickerSheetView
This component presents an intent chooser in the form of a BottomSheet view. Give it an intent such as a share intent and let the user choose what activity they want to share the intent with in a BottomSheet. Here is a GIF of it in action!
Here is a sample use case of this component taken from the sample application.
IntentPickerSheetView intentPickerSheet = new IntentPickerSheetView(MainActivity.this, shareIntent, "Share with...", new IntentPickerSheetView.OnIntentPickedListener() { @Override public void onIntentPicked(Intent intent) { bottomSheet.dismissSheet(); startActivity(intent); } }); // Filter out built in sharing options such as bluetooth and beam. intentPickerSheet.setFilter(new IntentPickerSheetView.Filter() { @Override public boolean include(IntentPickerSheetView.ActvityInfo info) { return !info.componentName.getPackageName().startsWith("com.android"); } }); // Sort activities in reverse order for no good reason intentPickerSheet.setSortMethod(new Comparator<IntentPickerSheetView.ActvityInfo>() { @Override public int compare(IntentPickerSheetView.ActvityInfo lhs, IntentPickerSheetView.ActvityInfo rhs) { return rhs.label.compareTo(lhs.label); } }); bottomSheet.showWithSheetView(intentPickerSheet);
Contributing
We welcome pull requests for bug fixes, new features, and improvements to BottomSheet. Contributors to the main BottomSheet repository must accept Flipboard's Apache-style Individual Contributor License Agreement (CLA) before any changes can be merged.