blob: ee68b818a83079d45b52fcbf0c0ee5015d700e62 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wallpaper.widget;
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED;
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wallpaper.R;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
/** A {@code ViewGroup} which provides the specific actions for the user to interact with. */
public class BottomActionBar extends FrameLayout {
/** The action items in the bottom action bar. */
public enum BottomAction {
CANCEL, ROTATION, INFORMATION, EDIT, APPLY,
}
private final Map<BottomAction, View> mActionList = new EnumMap<>(BottomAction.class);
private final BottomSheetBehavior<ViewGroup> mBottomSheetBehavior;
private final TextView mAttributionTitle;
private final TextView mAttributionSubtitle1;
private final TextView mAttributionSubtitle2;
public BottomActionBar(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.bottom_actions_layout, this, true);
mAttributionTitle = findViewById(R.id.preview_attribution_pane_title);
mAttributionSubtitle1 = findViewById(R.id.preview_attribution_pane_subtitle1);
mAttributionSubtitle2 = findViewById(R.id.preview_attribution_pane_subtitle2);
mActionList.put(BottomAction.CANCEL, findViewById(R.id.action_cancel));
mActionList.put(BottomAction.ROTATION, findViewById(R.id.action_rotation));
mActionList.put(BottomAction.INFORMATION, findViewById(R.id.action_information));
mActionList.put(BottomAction.EDIT, findViewById(R.id.action_edit));
mActionList.put(BottomAction.APPLY, findViewById(R.id.action_apply));
ViewGroup bottomSheet = findViewById(R.id.action_bottom_sheet);
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
mBottomSheetBehavior.setState(STATE_COLLAPSED);
// Workaround as we don't have access to bottomDialogCornerRadius, mBottomSheet radii are
// set to dialogCornerRadius by default.
GradientDrawable bottomSheetBackground = (GradientDrawable) bottomSheet.getBackground();
float[] radii = bottomSheetBackground.getCornerRadii();
for (int i = 0; i < radii.length; i++) {
radii[i]*=2f;
}
bottomSheetBackground = ((GradientDrawable)bottomSheetBackground.mutate());
bottomSheetBackground.setCornerRadii(radii);
bottomSheet.setBackground(bottomSheetBackground);
ImageView informationIcon = findViewById(R.id.action_information);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == STATE_COLLAPSED) {
informationIcon.setColorFilter(getContext().getColor(R.color.material_grey500));
} else if (newState == STATE_EXPANDED) {
informationIcon.setColorFilter(getContext().getColor(R.color.accent_color));
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {}
});
}
@Override
public void onVisibilityAggregated(boolean isVisible) {
super.onVisibilityAggregated(isVisible);
if (!isVisible) {
mBottomSheetBehavior.setState(STATE_COLLAPSED);
}
}
/**
* Sets the click listener to the specific action.
*
* @param bottomAction the specific action
* @param actionClickListener the click listener for the action
*/
public void setActionClickListener(
BottomAction bottomAction, OnClickListener actionClickListener) {
mActionList.get(bottomAction).setOnClickListener(actionClickListener);
}
/** Clears all the actions' click listeners */
public void clearActionClickListeners() {
mActionList.forEach((bottomAction, view) -> view.setOnClickListener(null));
}
/**
* Populates attributions(wallpaper info) to the information page.
*
* <p>Once get called, the {@link OnClickListener} to show/hide the information page will be
* set for the {@code BottomAction.INFORMATION}.
*/
public void populateInfoPage(List<String> attributions, boolean showMetadata) {
resetInfoPage();
// Ensure the ClickListener can work normally if has info been populated, since it could be
// removed by #clearActionClickListeners.
setActionClickListener(BottomAction.INFORMATION, unused ->
mBottomSheetBehavior.setState(mBottomSheetBehavior.getState() == STATE_COLLAPSED
? STATE_EXPANDED
: STATE_COLLAPSED
)
);
if (attributions.size() > 0 && attributions.get(0) != null) {
mAttributionTitle.setText(attributions.get(0));
}
if (showMetadata) {
if (attributions.size() > 1 && attributions.get(1) != null) {
mAttributionSubtitle1.setVisibility(View.VISIBLE);
mAttributionSubtitle1.setText(attributions.get(1));
}
if (attributions.size() > 2 && attributions.get(2) != null) {
mAttributionSubtitle2.setVisibility(View.VISIBLE);
mAttributionSubtitle2.setText(attributions.get(2));
}
}
}
/** Shows {@link BottomActionBar}. */
public void show() {
setVisibility(VISIBLE);
}
/** Hides {@link BottomActionBar}. */
public void hide() {
setVisibility(GONE);
}
/**
* Shows the specific actions.
*
* @param actions the specific actions
*/
public void showActions(EnumSet<BottomAction> actions) {
showActions(actions, true);
}
/**
* Hides the specific actions.
*
* @param actions the specific actions
*/
public void hideActions(EnumSet<BottomAction> actions) {
showActions(actions, false);
if (actions.contains(BottomAction.INFORMATION)) {
mBottomSheetBehavior.setState(STATE_COLLAPSED);
}
}
/**
* Shows the specific actions only. In other words, the other actions will be hidden.
*
* @param actions the specific actions which will be shown. Others will be hidden.
*/
public void showActionsOnly(EnumSet<BottomAction> actions) {
showActions(actions);
hideActions(EnumSet.complementOf(actions));
}
/** Enables all the actions' {@link View}. */
public void enableActions() {
enableActions(true);
}
/** Disables all the actions' {@link View}. */
public void disableActions() {
enableActions(false);
}
private void enableActions(boolean enable) {
mActionList.forEach((bottomAction, view) -> view.setEnabled(enable));
}
private void showActions(EnumSet<BottomAction> actions, boolean show) {
actions.forEach(bottomAction ->
mActionList.get(bottomAction).setVisibility(show ? VISIBLE : GONE));
}
private void resetInfoPage() {
mAttributionTitle.setText(null);
mAttributionSubtitle1.setText(null);
mAttributionSubtitle1.setVisibility(GONE);
mAttributionSubtitle2.setText(null);
mAttributionSubtitle2.setVisibility(GONE);
}
}