1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.settings.widget;
17 
18 import android.content.Context;
19 import android.util.AttributeSet;
20 import android.view.View;
21 import android.widget.Button;
22 
23 import androidx.annotation.Nullable;
24 import androidx.preference.Preference;
25 import androidx.preference.PreferenceViewHolder;
26 
27 import com.android.settings.R;
28 
29 import com.google.android.material.card.MaterialCardView;
30 
31 import java.util.Optional;
32 
33 /** Preference that wrapped by {@link MaterialCardView} */
34 public class CardPreference extends Preference {
35     @Nullable private View.OnClickListener mPrimaryBtnClickListener = null;
36     @Nullable private View.OnClickListener mSecondaryBtnClickListener = null;
37     @Nullable private String mPrimaryButtonText = null;
38     @Nullable private String mSecondaryButtonText = null;
39     private Optional<Button> mPrimaryButton = Optional.empty();
40     private Optional<Button> mSecondaryButton = Optional.empty();
41     private Optional<View> mButtonsGroup = Optional.empty();
42     private boolean mPrimaryButtonVisible = false;
43     private boolean mSecondaryButtonVisible = false;
44 
CardPreference(Context context)45     public CardPreference(Context context) {
46         this(context, null /* attrs */);
47     }
48 
CardPreference(Context context, @Nullable AttributeSet attrs)49     public CardPreference(Context context, @Nullable AttributeSet attrs) {
50         super(context, attrs, R.attr.cardPreferenceStyle);
51     }
52 
53     @Override
onBindViewHolder(PreferenceViewHolder holder)54     public void onBindViewHolder(PreferenceViewHolder holder) {
55         super.onBindViewHolder(holder);
56         initButtonsAndLayout(holder);
57     }
58 
initButtonsAndLayout(PreferenceViewHolder holder)59     private void initButtonsAndLayout(PreferenceViewHolder holder) {
60         mPrimaryButton = Optional.ofNullable((Button) holder.findViewById(android.R.id.button1));
61         mSecondaryButton = Optional.ofNullable((Button) holder.findViewById(android.R.id.button2));
62         mButtonsGroup = Optional.ofNullable(holder.findViewById(R.id.card_preference_buttons));
63         setPrimaryButtonText(mPrimaryButtonText);
64         setPrimaryButtonClickListener(mPrimaryBtnClickListener);
65         setPrimaryButtonVisible(mPrimaryButtonVisible);
66         setSecondaryButtonText(mSecondaryButtonText);
67         setSecondaryButtonClickListener(mSecondaryBtnClickListener);
68         setSecondaryButtonVisible(mSecondaryButtonVisible);
69     }
70 
71     /** Clear layout state if needed */
resetLayoutState()72     public void resetLayoutState() {
73         setPrimaryButtonVisible(false);
74         setSecondaryButtonVisible(false);
75     }
76 
77     /**
78      * Register a callback to be invoked when the primary button is clicked.
79      *
80      * @param l the callback that will run
81      */
setPrimaryButtonClickListener(View.OnClickListener l)82     public void setPrimaryButtonClickListener(View.OnClickListener l) {
83         mPrimaryButton.ifPresent(button -> button.setOnClickListener(l));
84         mPrimaryBtnClickListener = l;
85     }
86 
87     /**
88      * Register a callback to be invoked when the secondary button is clicked.
89      *
90      * @param l the callback that will run
91      */
setSecondaryButtonClickListener(View.OnClickListener l)92     public void setSecondaryButtonClickListener(View.OnClickListener l) {
93         mSecondaryButton.ifPresent(button -> button.setOnClickListener(l));
94         mSecondaryBtnClickListener = l;
95     }
96 
97     /**
98      * Sets the text to be displayed on primary button.
99      *
100      * @param text text to be displayed
101      */
setPrimaryButtonText(String text)102     public void setPrimaryButtonText(String text) {
103         mPrimaryButton.ifPresent(button -> button.setText(text));
104         mPrimaryButtonText = text;
105     }
106 
107     /**
108      * Sets the text to be displayed on secondary button.
109      *
110      * @param text text to be displayed
111      */
setSecondaryButtonText(String text)112     public void setSecondaryButtonText(String text) {
113         mSecondaryButton.ifPresent(button -> button.setText(text));
114         mSecondaryButtonText = text;
115     }
116 
117     /**
118      * Set the visible on the primary button.
119      *
120      * @param visible {@code true} for visible
121      */
setPrimaryButtonVisible(boolean visible)122     public void setPrimaryButtonVisible(boolean visible) {
123         mPrimaryButton.ifPresent(
124                 button -> button.setVisibility(visible ? View.VISIBLE : View.GONE));
125         mPrimaryButtonVisible = visible;
126         updateButtonGroupsVisibility();
127     }
128 
129     /**
130      * Set the visible on the secondary button.
131      *
132      * @param visible {@code true} for visible
133      */
setSecondaryButtonVisible(boolean visible)134     public void setSecondaryButtonVisible(boolean visible) {
135         mSecondaryButton.ifPresent(
136                 button -> button.setVisibility(visible ? View.VISIBLE : View.GONE));
137         mSecondaryButtonVisible = visible;
138         updateButtonGroupsVisibility();
139     }
140 
141     /**
142      * Sets the text of content description on primary button.
143      *
144      * @param text text for the content description
145      */
setPrimaryButtonContentDescription(String text)146     public void setPrimaryButtonContentDescription(String text) {
147         mPrimaryButton.ifPresent(button -> button.setContentDescription(text));
148     }
149 
150     /**
151      * Sets the text of content description on secondary button.
152      *
153      * @param text text for the content description
154      */
setSecondaryButtonContentDescription(String text)155     public void setSecondaryButtonContentDescription(String text) {
156         mSecondaryButton.ifPresent(button -> button.setContentDescription(text));
157     }
158 
updateButtonGroupsVisibility()159     private void updateButtonGroupsVisibility() {
160         int visibility =
161                 (mPrimaryButtonVisible || mSecondaryButtonVisible) ? View.VISIBLE : View.GONE;
162         mButtonsGroup.ifPresent(group -> group.setVisibility(visibility));
163     }
164 }
165