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