Bottom sheets: buttons types and behaviors

This commit is contained in:
sergosm 2020-09-30 14:48:07 +03:00
parent 02b9af6782
commit c2264c3838
4 changed files with 223 additions and 77 deletions

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/buttons_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:gravity="center"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small">
<include
android:id="@+id/third_button"
layout="@layout/bottom_sheet_dialog_button"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_height"
android:visibility="gone"
tools:visibility="visible" />
<View
android:id="@+id/buttons_divider_top"
android:layout_width="match_parent"
android:layout_height="@dimen/content_padding"
tools:visibility="visible" />
<include
android:id="@+id/right_bottom_button"
layout="@layout/bottom_sheet_dialog_button"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_height"
android:visibility="gone"
tools:visibility="visible" />
<View
android:id="@+id/buttons_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/content_padding"
tools:visibility="visible" />
<include
android:id="@+id/dismiss_button"
layout="@layout/bottom_sheet_dialog_button"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_height" />
</LinearLayout>

View file

@ -35,10 +35,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="10dp" android:layout_height="10dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:visibility="gone" android:background="@drawable/bg_contextmenu_shadow_top_light"
android:background="@drawable/bg_contextmenu_shadow_top_light" /> android:visibility="gone" />
</FrameLayout> </FrameLayout>
<include layout="@layout/bottom_buttons" />
</LinearLayout> </LinearLayout>

View file

@ -8,11 +8,11 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.LayerDrawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@ -50,8 +50,11 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
protected int themeRes; protected int themeRes;
protected View dismissButton; protected View dismissButton;
protected View rightButton; protected View rightButton;
protected View thirdButton;
private LinearLayout itemsContainer; private LinearLayout itemsContainer;
private LinearLayout buttonsContainer;
protected View buttonsShadow;
@StringRes @StringRes
protected int dismissButtonStringRes = R.string.shared_string_cancel; protected int dismissButtonStringRes = R.string.shared_string_cancel;
@ -74,45 +77,21 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
createMenuItems(savedInstanceState); createMenuItems(savedInstanceState);
Context ctx = requireContext(); Activity activity = requireActivity();
View mainView = View.inflate(new ContextThemeWrapper(ctx, themeRes), R.layout.bottom_sheet_menu_base, null); LayoutInflater themedInflater = UiUtilities.getInflater(activity, nightMode);
View mainView = themedInflater.inflate(R.layout.bottom_sheet_menu_base, null);
if (useScrollableItemsContainer()) { if (useScrollableItemsContainer()) {
itemsContainer = (LinearLayout) mainView.findViewById(R.id.scrollable_items_container); itemsContainer = mainView.findViewById(R.id.scrollable_items_container);
} else { } else {
mainView.findViewById(R.id.scroll_view).setVisibility(View.GONE); mainView.findViewById(R.id.scroll_view).setVisibility(View.GONE);
itemsContainer = (LinearLayout) mainView.findViewById(R.id.non_scrollable_items_container); itemsContainer = mainView.findViewById(R.id.non_scrollable_items_container);
itemsContainer.setVisibility(View.VISIBLE); itemsContainer.setVisibility(View.VISIBLE);
} }
buttonsShadow = mainView.findViewById(R.id.buttons_shadow);
inflateMenuItems(); inflateMenuItems();
setupScrollShadow(mainView);
dismissButton = mainView.findViewById(R.id.dismiss_button); setupBottomButtons((ViewGroup) mainView);
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId());
dismissButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDismissButtonClickAction();
dismiss();
}
});
if (hideButtonsContainer()) {
mainView.findViewById(R.id.buttons_container).setVisibility(View.GONE);
} else {
int rightBottomButtonTextId = getRightBottomButtonTextId();
if (rightBottomButtonTextId != DEFAULT_VALUE) {
mainView.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE);
rightButton = mainView.findViewById(R.id.right_bottom_button);
UiUtilities.setupDialogButton(nightMode, rightButton, getRightBottomButtonType(), rightBottomButtonTextId);
rightButton.setVisibility(View.VISIBLE);
rightButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onRightBottomButtonClick();
}
});
}
}
updateBottomButtons();
setupHeightAndBackground(mainView); setupHeightAndBackground(mainView);
return mainView; return mainView;
} }
@ -183,7 +162,6 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
} }
final int screenHeight = AndroidUtils.getScreenHeight(activity); final int screenHeight = AndroidUtils.getScreenHeight(activity);
final int statusBarHeight = AndroidUtils.getStatusBarHeight(activity); final int statusBarHeight = AndroidUtils.getStatusBarHeight(activity);
final int contentHeight = getContentHeight(screenHeight - statusBarHeight);
mainView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { mainView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override @Override
@ -194,12 +172,13 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
} else { } else {
obs.removeGlobalOnLayoutListener(this); obs.removeGlobalOnLayoutListener(this);
} }
final int contentHeight = getContentHeight(screenHeight - statusBarHeight);
final View contentView = useScrollableItemsContainer() ? mainView.findViewById(R.id.scroll_view) : itemsContainer; final View contentView = useScrollableItemsContainer() ? mainView.findViewById(R.id.scroll_view) : itemsContainer;
if (contentView.getHeight() > contentHeight) { if (contentView.getHeight() > contentHeight) {
if (useScrollableItemsContainer() || useExpandableList()) { if (useScrollableItemsContainer() || useExpandableList()) {
contentView.getLayoutParams().height = contentHeight; contentView.getLayoutParams().height = contentHeight;
mainView.findViewById(R.id.buttons_shadow).setVisibility(View.VISIBLE); buttonsShadow.setVisibility(View.VISIBLE);
} else { } else {
contentView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; contentView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
} }
@ -222,7 +201,13 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
private int getContentHeight(int availableScreenHeight) { private int getContentHeight(int availableScreenHeight) {
int customHeight = getCustomHeight(); int customHeight = getCustomHeight();
int maxHeight = availableScreenHeight - getResources().getDimensionPixelSize(R.dimen.dialog_button_ex_height); int buttonsHeight = 0;
if (useVerticalButtons()) {
buttonsHeight = AndroidUtils.dpToPx(getContext(), 112);
} else {
buttonsHeight = getResources().getDimensionPixelSize(R.dimen.dialog_button_ex_height);
}
int maxHeight = availableScreenHeight - buttonsHeight;
if (customHeight != DEFAULT_VALUE && customHeight <= maxHeight) { if (customHeight != DEFAULT_VALUE && customHeight <= maxHeight) {
return customHeight; return customHeight;
} }
@ -280,6 +265,18 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
} }
protected int getThirdBottomButtonTextId() {
return DEFAULT_VALUE;
}
protected DialogButtonType getThirdBottomButtonType() {
return DialogButtonType.PRIMARY;
}
protected void onThirdBottomButtonClick() {
}
protected boolean isDismissButtonEnabled() { protected boolean isDismissButtonEnabled() {
return true; return true;
} }
@ -288,6 +285,40 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
return true; return true;
} }
protected void setupBottomButtons(ViewGroup view) {
Activity activity = requireActivity();
LayoutInflater themedInflater = UiUtilities.getInflater(activity, nightMode);
if (!hideButtonsContainer()) {
if (useVerticalButtons()) {
buttonsContainer = (LinearLayout) themedInflater.inflate(R.layout.bottom_buttons_vertical, view);
setupThirdButton();
} else {
buttonsContainer = (LinearLayout) themedInflater.inflate(R.layout.bottom_buttons, view);
}
setupRightButton();
setupDismissButton();
updateBottomButtons();
}
}
boolean useVerticalButtons() {
Activity activity = requireActivity();
int rightBottomButtonTextId = getRightBottomButtonTextId();
if (getDismissButtonTextId() != DEFAULT_VALUE && rightBottomButtonTextId != DEFAULT_VALUE) {
if (getThirdBottomButtonTextId() != DEFAULT_VALUE) {
return true;
}
String rightButtonText = getString(rightBottomButtonTextId);
boolean portrait = AndroidUiHelper.isOrientationPortrait(activity);
int dialogWidth = portrait ? AndroidUtils.getScreenWidth(activity) : getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
int measuredTextWidth = AndroidUtils.getTextWidth(getResources().getDimensionPixelSize(R.dimen.default_desc_text_size), rightButtonText);
int availableTextWidth = (dialogWidth - AndroidUtils.dpToPx(activity, 96)) / 2;
return measuredTextWidth > availableTextWidth;
}
return false;
}
protected void updateBottomButtons() { protected void updateBottomButtons() {
if (dismissButton != null) { if (dismissButton != null) {
boolean enabled = isDismissButtonEnabled(); boolean enabled = isDismissButtonEnabled();
@ -301,6 +332,54 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
} }
} }
private void setupDismissButton() {
dismissButton = buttonsContainer.findViewById(R.id.dismiss_button);
int buttonTextId = getDismissButtonTextId();
if (buttonTextId != DEFAULT_VALUE) {
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), buttonTextId);
dismissButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDismissButtonClickAction();
dismiss();
}
});
}
AndroidUiHelper.updateVisibility(dismissButton, buttonTextId != DEFAULT_VALUE);
}
private void setupRightButton() {
rightButton = buttonsContainer.findViewById(R.id.right_bottom_button);
int buttonTextId = getRightBottomButtonTextId();
if (buttonTextId != DEFAULT_VALUE) {
UiUtilities.setupDialogButton(nightMode, rightButton, getRightBottomButtonType(), buttonTextId);
rightButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onRightBottomButtonClick();
}
});
}
AndroidUiHelper.updateVisibility(rightButton, buttonTextId != DEFAULT_VALUE);
AndroidUiHelper.updateVisibility(buttonsContainer.findViewById(R.id.buttons_divider), buttonTextId != DEFAULT_VALUE);
}
private void setupThirdButton() {
thirdButton = buttonsContainer.findViewById(R.id.third_button);
int buttonTextId = getThirdBottomButtonTextId();
if (buttonTextId != DEFAULT_VALUE) {
UiUtilities.setupDialogButton(nightMode, thirdButton, getThirdBottomButtonType(), buttonTextId);
thirdButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onThirdBottomButtonClick();
}
});
}
AndroidUiHelper.updateVisibility(thirdButton, buttonTextId != DEFAULT_VALUE);
AndroidUiHelper.updateVisibility(buttonsContainer.findViewById(R.id.buttons_divider_top), buttonTextId != DEFAULT_VALUE);
}
@ColorRes @ColorRes
protected int getBgColorId() { protected int getBgColorId() {
return nightMode ? R.color.list_background_color_dark : R.color.list_background_color_light; return nightMode ? R.color.list_background_color_dark : R.color.list_background_color_light;
@ -325,7 +404,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
private LayerDrawable createBackgroundDrawable(@NonNull Context ctx, @DrawableRes int shadowDrawableResId) { private LayerDrawable createBackgroundDrawable(@NonNull Context ctx, @DrawableRes int shadowDrawableResId) {
Drawable shadowDrawable = ContextCompat.getDrawable(ctx, shadowDrawableResId); Drawable shadowDrawable = ContextCompat.getDrawable(ctx, shadowDrawableResId);
Drawable[] layers = new Drawable[]{shadowDrawable, getColoredBg(ctx)}; Drawable[] layers = new Drawable[] {shadowDrawable, getColoredBg(ctx)};
return new LayerDrawable(layers); return new LayerDrawable(layers);
} }
@ -335,4 +414,21 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
} }
return !app.getSettings().isLightContent(); return !app.getSettings().isLightContent();
} }
private void setupScrollShadow(View view) {
final View scrollView;
if (useScrollableItemsContainer()) {
scrollView = view.findViewById(R.id.scroll_view);
} else {
scrollView = itemsContainer;
}
scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
@Override
public void onScrollChanged() {
boolean scrollToBottomAvailable = scrollView.canScrollVertically(1);
AndroidUiHelper.updateVisibility(buttonsShadow, scrollToBottomAvailable);
}
});
}
} }

View file

@ -28,46 +28,14 @@ public class ExitBottomSheetDialogFragment extends MenuBottomSheetDialogFragment
items.add(new ShortDescriptionItem.Builder() items.add(new ShortDescriptionItem.Builder()
.setDescription(getString(R.string.plan_route_exit_dialog_descr)) .setDescription(getString(R.string.plan_route_exit_dialog_descr))
.setTitle(getString(R.string.exit_without_saving)) .setTitle(getString(R.string.
exit_without_saving))
.setLayoutId(R.layout.bottom_sheet_item_list_title_with_descr) .setLayoutId(R.layout.bottom_sheet_item_list_title_with_descr)
.create()); .create());
items.add(new DividerSpaceItem(getContext(), items.add(new DividerSpaceItem(getContext(),
getResources().getDimensionPixelSize(R.dimen.bottom_sheet_exit_button_margin))); getResources().getDimensionPixelSize(R.dimen.bottom_sheet_exit_button_margin)));
items.add(new BottomSheetItemButton.Builder()
.setButtonType(UiUtilities.DialogButtonType.SECONDARY)
.setTitle(getString(R.string.shared_string_exit))
.setLayoutId(R.layout.bottom_sheet_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment targetFragment = getTargetFragment();
if (targetFragment != null) {
targetFragment.onActivityResult(REQUEST_CODE, EXIT_RESULT_CODE, null);
}
dismiss();
}
})
.create());
items.add(new DividerSpaceItem(getContext(),
getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin)));
items.add(new BottomSheetItemButton.Builder()
.setTitle(getString(R.string.shared_string_save))
.setLayoutId(R.layout.bottom_sheet_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment targetFragment = getTargetFragment();
if (targetFragment != null) {
targetFragment.onActivityResult(REQUEST_CODE, SAVE_RESULT_CODE, null);
}
dismiss();
}
})
.create());
} }
@Override @Override
@ -75,6 +43,39 @@ public class ExitBottomSheetDialogFragment extends MenuBottomSheetDialogFragment
return R.string.shared_string_cancel; return R.string.shared_string_cancel;
} }
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_save;
}
@Override
protected int getThirdBottomButtonTextId() {
return R.string.shared_string_exit;
}
@Override
protected void onRightBottomButtonClick() {
Fragment targetFragment = getTargetFragment();
if (targetFragment != null) {
targetFragment.onActivityResult(REQUEST_CODE, SAVE_RESULT_CODE, null);
}
dismiss();
}
@Override
protected void onThirdBottomButtonClick() {
Fragment targetFragment = getTargetFragment();
if (targetFragment != null) {
targetFragment.onActivityResult(REQUEST_CODE, EXIT_RESULT_CODE, null);
}
dismiss();
}
@Override
protected UiUtilities.DialogButtonType getThirdBottomButtonType() {
return (UiUtilities.DialogButtonType.SECONDARY);
}
public static void showInstance(@NonNull FragmentManager fragmentManager, @Nullable Fragment targetFragment) { public static void showInstance(@NonNull FragmentManager fragmentManager, @Nullable Fragment targetFragment) {
if (!fragmentManager.isStateSaved()) { if (!fragmentManager.isStateSaved()) {
ExitBottomSheetDialogFragment fragment = new ExitBottomSheetDialogFragment(); ExitBottomSheetDialogFragment fragment = new ExitBottomSheetDialogFragment();