Skip to content

Instantly share code, notes, and snippets.

@fiskurgit
Last active January 25, 2019 04:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fiskurgit/2344ac8b8a0a6cd97ff8d0c5d445090b to your computer and use it in GitHub Desktop.
Save fiskurgit/2344ac8b8a0a6cd97ff8d0c5d445090b to your computer and use it in GitHub Desktop.
Material Design 2 BottomSheetDialog that doesn't draw over the bottom navigation bar.
package online.fisk.kroki.views;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.CoordinatorLayout;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import timber.log.Timber;
/*
FiskBottomSheetDialog dialog = new FiskBottomSheetDialog(activity, R.layout.some_layout, R.style.AppTheme);
View view = dialog.getContentView();
*/
public class FiskBottomsheetDialog {
private final Dialog dialog;
private View contentView;
private boolean cancelable = true;
private CoordinatorLayout coordinatorLayout;
private Dialog.OnDismissListener onDismissListener = null;
private BottomSheetBehavior bottomSheetBehavior;
public FiskBottomsheetDialog(Activity context, int layout, int theme) {
dialog = new Dialog(context, theme);
Window window = dialog.getWindow();
if (window != null) {
window.setDimAmount(0);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
contentView = context.getLayoutInflater().inflate(layout, null);
//Curved top corners:
GradientDrawable curvedBackground = new GradientDrawable();
curvedBackground.setColor(Color.WHITE);
float cornerRadius = 8 * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
curvedBackground.setCornerRadii(new float[]{cornerRadius, cornerRadius, cornerRadius, cornerRadius, 0, 0, 0, 0});
contentView.setBackground(curvedBackground);
//Full screen coordinator to hold the bottomsheet
coordinatorLayout = new CoordinatorLayout(context);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
layoutParams.gravity = Gravity.CENTER;
coordinatorLayout.setLayoutParams(layoutParams);
coordinatorLayout.setBackgroundColor(Color.parseColor("#00000000"));
bottomSheetBehavior = new BottomSheetBehavior();
bottomSheetBehavior.setSkipCollapsed(true);
bottomSheetBehavior.setHideable(true);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT);
params.setBehavior(bottomSheetBehavior);
contentView.setLayoutParams(params);
coordinatorLayout.addView(contentView);
//Any click on the dimmed coordinator in the background should dismiss the dialog (unless setCanceleable(false); has been called):
coordinatorLayout.setOnClickListener(_view -> {
if (cancelable) BottomSheetBehavior.from(contentView).setState(BottomSheetBehavior.STATE_HIDDEN);
});
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
dialog.dismiss();
if (onDismissListener != null) onDismissListener.onDismiss(dialog);
break;
}
}
//slideOffset is float in range 0 to 1 - remapped to 0 to 153 (0x99000000)
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
int alpha = (int) map(slideOffset, 0f, 1f, 0f, 153f);
int overlayColor = Color.argb(alpha, Color.red(Color.BLACK), Color.green(Color.BLACK), Color.blue(Color.BLACK));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && window != null) {
window.setStatusBarColor(overlayColor);
}
coordinatorLayout.setBackgroundColor(overlayColor);
}
});
dialog.setContentView(coordinatorLayout);
//Without this the bottom sheet doesn't animate, despite the default state being hidden
BottomSheetBehavior.from(contentView).setState(BottomSheetBehavior.STATE_HIDDEN);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) dialog.create();
}
public void show() {
dialog.show();
contentView.post(() -> BottomSheetBehavior.from(contentView).setState(BottomSheetBehavior.STATE_EXPANDED));
}
public void dismiss() {
BottomSheetBehavior.from(contentView).setState(BottomSheetBehavior.STATE_HIDDEN);
}
public void setOnShowListener(DialogInterface.OnShowListener onShowListener) {
dialog.setOnShowListener(onShowListener);
}
public void setCancelable(boolean cancelable) {
this.cancelable = cancelable;
dialog.setCancelable(cancelable);
}
public View getContentView() {
return contentView;
}
public CoordinatorLayout getCoordinatorLayout() {
return coordinatorLayout;
}
public void setOnDismissListener(Dialog.OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
}
private float map(float value, float start1, float stop1, float start2, float stop2) {
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
}
public Dialog getDialog() {
return dialog;
}
public void setMaxWidth(float dp){
int maxWidth = Math.round(contentView.getContext().getResources().getDisplayMetrics().density * dp);
Display display = dialog.getWindow().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
if(size.x > maxWidth){
contentView.getLayoutParams().width = maxWidth;
((CoordinatorLayout.LayoutParams)contentView.getLayoutParams()).gravity = Gravity.CENTER_HORIZONTAL;
}
}
public void setMaxWidth(int dimenRes){
float dp = contentView.getContext().getResources().getDimension(dimenRes);
setMaxWidth(dp);
}
}
@hendrowijaya96
Copy link

how to expand this bottom sheet?

@hendrowijaya96
Copy link

hideable not working

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment