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.core.CarUi.MIN_TARGET_API;
20 import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
21 
22 import android.annotation.TargetApi;
23 import android.content.Context;
24 import android.util.AttributeSet;
25 import android.view.View;
26 import android.widget.Switch;
27 
28 import androidx.annotation.Nullable;
29 import androidx.preference.PreferenceViewHolder;
30 
31 import com.android.car.ui.R;
32 import com.android.car.ui.utils.CarUiUtils;
33 
34 import java.util.function.Consumer;
35 
36 /**
37  * A preference that has a switch that can be toggled independently of pressing the main
38  * body of the preference.
39  */
40 @SuppressWarnings("AndroidJdkLibsChecker")
41 @TargetApi(MIN_TARGET_API)
42 public class CarUiTwoActionSwitchPreference extends CarUiTwoActionBasePreference {
43     @Nullable
44     protected Consumer<Boolean> mSecondaryActionOnClickListener;
45     private boolean mSecondaryActionChecked;
46 
CarUiTwoActionSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)47     public CarUiTwoActionSwitchPreference(Context context,
48             AttributeSet attrs,
49             int defStyleAttr, int defStyleRes) {
50         super(context, attrs, defStyleAttr, defStyleRes);
51     }
52 
CarUiTwoActionSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr)53     public CarUiTwoActionSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
54         super(context, attrs, defStyleAttr);
55     }
56 
CarUiTwoActionSwitchPreference(Context context, AttributeSet attrs)57     public CarUiTwoActionSwitchPreference(Context context, AttributeSet attrs) {
58         super(context, attrs);
59     }
60 
CarUiTwoActionSwitchPreference(Context context)61     public CarUiTwoActionSwitchPreference(Context context) {
62         super(context);
63     }
64 
65     @Override
init(@ullable AttributeSet attrs)66     protected void init(@Nullable AttributeSet attrs) {
67         super.init(attrs);
68 
69         setLayoutResourceInternal(R.layout.car_ui_preference_two_action_switch);
70     }
71 
72     @Override
performSecondaryActionClickInternal()73     protected void performSecondaryActionClickInternal() {
74         mSecondaryActionChecked = !mSecondaryActionChecked;
75         notifyChanged();
76         if (mSecondaryActionOnClickListener != null) {
77             mSecondaryActionOnClickListener.accept(mSecondaryActionChecked);
78         }
79     }
80 
81     @Override
onBindViewHolder(PreferenceViewHolder holder)82     public void onBindViewHolder(PreferenceViewHolder holder) {
83         super.onBindViewHolder(holder);
84 
85         View firstActionContainer = requireViewByRefId(holder.itemView,
86                 R.id.car_ui_first_action_container);
87         View secondActionContainer = requireViewByRefId(holder.itemView,
88                 R.id.car_ui_second_action_container);
89         View secondaryAction = requireViewByRefId(holder.itemView,
90                 R.id.car_ui_secondary_action);
91         Switch s = requireViewByRefId(holder.itemView,
92                 R.id.car_ui_secondary_action_concrete);
93 
94         holder.itemView.setFocusable(false);
95         holder.itemView.setClickable(false);
96         firstActionContainer.setOnClickListener(this::performClickUnrestricted);
97         firstActionContainer.setEnabled(
98                 isEnabled() || isUxRestricted() || isClickableWhileDisabled());
99         firstActionContainer.setFocusable(
100                 isEnabled() || isUxRestricted() || isClickableWhileDisabled());
101 
102         secondActionContainer.setVisibility(mSecondaryActionVisible ? View.VISIBLE : View.GONE);
103         s.setChecked(mSecondaryActionChecked);
104         s.setEnabled(isSecondaryActionEnabled());
105 
106         secondaryAction.setOnClickListener(v -> performSecondaryActionClick());
107         secondaryAction.setEnabled(
108                 isSecondaryActionEnabled() || isUxRestricted() || isClickableWhileDisabled());
109         secondaryAction.setFocusable(
110                 isSecondaryActionEnabled() || isUxRestricted() || isClickableWhileDisabled());
111 
112         CarUiUtils.makeAllViewsEnabledAndUxRestricted(secondaryAction, isSecondaryActionEnabled(),
113                 isUxRestricted());
114     }
115 
116     /**
117      * Sets the checked state of the switch in the secondary action space.
118      * @param checked Whether the switch should be checked or not.
119      */
setSecondaryActionChecked(boolean checked)120     public void setSecondaryActionChecked(boolean checked) {
121         mSecondaryActionChecked = checked;
122         notifyChanged();
123     }
124 
125     /**
126      * Returns the checked state of the switch in the secondary action space.
127      * @return Whether the switch is checked or not.
128      */
isSecondaryActionChecked()129     public boolean isSecondaryActionChecked() {
130         return mSecondaryActionChecked;
131     }
132 
133     /**
134      * Sets the on-click listener of the secondary action button.
135      *
136      * The listener is called with the current checked state of the switch.
137      */
setOnSecondaryActionClickListener(@ullable Consumer<Boolean> onClickListener)138     public void setOnSecondaryActionClickListener(@Nullable Consumer<Boolean> onClickListener) {
139         mSecondaryActionOnClickListener = onClickListener;
140         notifyChanged();
141     }
142 }
143