1 /*
2  * Copyright (C) 2020 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 
17 package com.android.car.ui.preference;
18 
19 import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
20 
21 import android.content.Context;
22 import android.content.res.TypedArray;
23 import android.graphics.drawable.Drawable;
24 import android.util.AttributeSet;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.widget.ImageView;
28 
29 import androidx.annotation.DrawableRes;
30 import androidx.annotation.Nullable;
31 import androidx.core.content.ContextCompat;
32 import androidx.preference.PreferenceViewHolder;
33 
34 import com.android.car.ui.R;
35 import com.android.car.ui.utils.CarUiUtils;
36 
37 /**
38  * A preference that has an icon button that can be pressed independently of pressing the main
39  * body of the preference.
40  */
41 @SuppressWarnings("AndroidJdkLibsChecker")
42 public class CarUiTwoActionIconPreference extends CarUiTwoActionBasePreference {
43     @Nullable
44     protected Runnable mSecondaryActionOnClickListener;
45     @Nullable
46     private Drawable mSecondaryActionIcon;
47 
CarUiTwoActionIconPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)48     public CarUiTwoActionIconPreference(Context context,
49             AttributeSet attrs,
50             int defStyleAttr, int defStyleRes) {
51         super(context, attrs, defStyleAttr, defStyleRes);
52     }
53 
CarUiTwoActionIconPreference(Context context, AttributeSet attrs, int defStyleAttr)54     public CarUiTwoActionIconPreference(Context context, AttributeSet attrs, int defStyleAttr) {
55         super(context, attrs, defStyleAttr);
56     }
57 
CarUiTwoActionIconPreference(Context context, AttributeSet attrs)58     public CarUiTwoActionIconPreference(Context context, AttributeSet attrs) {
59         super(context, attrs);
60     }
61 
CarUiTwoActionIconPreference(Context context)62     public CarUiTwoActionIconPreference(Context context) {
63         super(context);
64     }
65 
66     @Override
init(@ullable AttributeSet attrs)67     protected void init(@Nullable AttributeSet attrs) {
68         super.init(attrs);
69 
70         TypedArray a = getContext().obtainStyledAttributes(attrs,
71                 R.styleable.CarUiTwoActionIconPreference);
72         try {
73             mSecondaryActionIcon = a.getDrawable(
74                     R.styleable.CarUiTwoActionIconPreference_secondaryActionIcon);
75         } finally {
76             a.recycle();
77         }
78 
79         setLayoutResourceInternal(R.layout.car_ui_preference_two_action_icon);
80     }
81 
82     @Override
performSecondaryActionClickInternal()83     protected void performSecondaryActionClickInternal() {
84         if (mSecondaryActionOnClickListener != null) {
85             mSecondaryActionOnClickListener.run();
86         }
87     }
88 
89     @Override
onBindViewHolder(PreferenceViewHolder holder)90     public void onBindViewHolder(PreferenceViewHolder holder) {
91         super.onBindViewHolder(holder);
92 
93         View firstActionContainer = requireViewByRefId(holder.itemView,
94                 R.id.car_ui_first_action_container);
95         View secondActionContainer = requireViewByRefId(holder.itemView,
96                 R.id.car_ui_second_action_container);
97         ViewGroup secondaryButton = requireViewByRefId(holder.itemView,
98                 R.id.car_ui_secondary_action);
99         ImageView iconView = requireViewByRefId(holder.itemView,
100                 R.id.car_ui_secondary_action_concrete);
101 
102         holder.itemView.setFocusable(false);
103         holder.itemView.setClickable(false);
104         firstActionContainer.setOnClickListener(this::performClickUnrestricted);
105         firstActionContainer.setEnabled(isEnabled() || isClickableWhileDisabled());
106         firstActionContainer.setFocusable(isEnabled() || isClickableWhileDisabled());
107 
108         secondActionContainer.setVisibility(mSecondaryActionVisible ? View.VISIBLE : View.GONE);
109         iconView.setImageDrawable(mSecondaryActionIcon);
110         iconView.setEnabled(isSecondaryActionEnabled() || isClickableWhileDisabled());
111         secondaryButton.setEnabled(isSecondaryActionEnabled() || isClickableWhileDisabled());
112         secondaryButton.setFocusable(isSecondaryActionEnabled() || isClickableWhileDisabled());
113         secondaryButton.setOnClickListener(v -> performSecondaryActionClick());
114 
115         CarUiUtils.makeAllViewsEnabledAndUxRestricted(secondaryButton, isSecondaryActionEnabled(),
116                 isUxRestricted());
117     }
118 
119     /**
120      * Sets the icon of the secondary action.
121      *
122      * The icon will be tinted to the primary text color, and resized to fit the space.
123      *
124      * @param drawable A {@link Drawable} to set as the icon.
125      */
setSecondaryActionIcon(@ullable Drawable drawable)126     public void setSecondaryActionIcon(@Nullable Drawable drawable) {
127         mSecondaryActionIcon = drawable;
128         notifyChanged();
129     }
130 
131     /**
132      * Sets the icon of the secondary action.
133      *
134      * The icon will be tinted to the primary text color, and resized to fit the space.
135      *
136      * @param resid A drawable resource id to set as the icon.
137      */
setSecondaryActionIcon(@rawableRes int resid)138     public void setSecondaryActionIcon(@DrawableRes int resid) {
139         setSecondaryActionIcon(ContextCompat.getDrawable(getContext(), resid));
140     }
141 
142     /**
143      * Sets the on-click listener of the secondary action button.
144      */
setOnSecondaryActionClickListener(@ullable Runnable onClickListener)145     public void setOnSecondaryActionClickListener(@Nullable Runnable onClickListener) {
146         mSecondaryActionOnClickListener = onClickListener;
147         notifyChanged();
148     }
149 }
150