blob: cb858c85e8889253f0fa6c2d2cc4a77e2e463df7 [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.settingslib.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import com.android.settingslib.utils.BuildCompatUtils;
import java.util.ArrayList;
import java.util.List;
/**
* MainSwitchBar is a View with a customized Switch.
* This component is used as the main switch of the page
* to enable or disable the prefereces on the page.
*/
public class MainSwitchBar extends LinearLayout implements CompoundButton.OnCheckedChangeListener {
private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>();
@ColorInt
private int mBackgroundColor;
@ColorInt
private int mBackgroundActivatedColor;
protected TextView mTextView;
protected Switch mSwitch;
private Drawable mBackgroundOn;
private Drawable mBackgroundOff;
private Drawable mBackgroundDisabled;
private View mFrameView;
public MainSwitchBar(Context context) {
this(context, null);
}
public MainSwitchBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MainSwitchBar(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MainSwitchBar(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
LayoutInflater.from(context).inflate(R.layout.settingslib_main_switch_bar, this);
if (!BuildCompatUtils.isAtLeastS()) {
final TypedArray a = context.obtainStyledAttributes(
new int[]{android.R.attr.colorAccent});
mBackgroundActivatedColor = a.getColor(0, 0);
mBackgroundColor = context.getColor(R.color.material_grey_600);
a.recycle();
}
setFocusable(true);
setClickable(true);
mFrameView = findViewById(R.id.frame);
mTextView = (TextView) findViewById(R.id.switch_text);
mSwitch = (Switch) findViewById(android.R.id.switch_widget);
if (BuildCompatUtils.isAtLeastS()) {
mBackgroundOn = getContext().getDrawable(R.drawable.settingslib_switch_bar_bg_on);
mBackgroundOff = getContext().getDrawable(R.drawable.settingslib_switch_bar_bg_off);
mBackgroundDisabled = getContext().getDrawable(
R.drawable.settingslib_switch_bar_bg_disabled);
}
addOnSwitchChangeListener((switchView, isChecked) -> setChecked(isChecked));
setChecked(mSwitch.isChecked());
if (attrs != null) {
final TypedArray a = context.obtainStyledAttributes(attrs,
androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
0 /*defStyleRes*/);
final CharSequence title = a.getText(
androidx.preference.R.styleable.Preference_android_title);
setTitle(title);
a.recycle();
}
setBackground(true);
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
propagateChecked(isChecked);
}
@Override
public boolean performClick() {
return mSwitch.performClick();
}
/**
* Update the switch status
*/
public void setChecked(boolean checked) {
if (mSwitch != null) {
mSwitch.setChecked(checked);
}
setBackground(checked);
}
/**
* Return the status of the Switch
*/
public boolean isChecked() {
return mSwitch.isChecked();
}
/**
* Return the Switch
*/
public final Switch getSwitch() {
return mSwitch;
}
/**
* Set the title text
*/
public void setTitle(CharSequence text) {
if (mTextView != null) {
mTextView.setText(text);
}
}
/**
* Show the MainSwitchBar
*/
public void show() {
setVisibility(View.VISIBLE);
mSwitch.setOnCheckedChangeListener(this);
}
/**
* Hide the MainSwitchBar
*/
public void hide() {
if (isShowing()) {
setVisibility(View.GONE);
mSwitch.setOnCheckedChangeListener(null);
}
}
/**
* Return the displaying status of MainSwitchBar
*/
public boolean isShowing() {
return (getVisibility() == View.VISIBLE);
}
/**
* Adds a listener for switch changes
*/
public void addOnSwitchChangeListener(OnMainSwitchChangeListener listener) {
if (!mSwitchChangeListeners.contains(listener)) {
mSwitchChangeListeners.add(listener);
}
}
/**
* Remove a listener for switch changes
*/
public void removeOnSwitchChangeListener(OnMainSwitchChangeListener listener) {
mSwitchChangeListeners.remove(listener);
}
/**
* Enable or disable the text and switch.
*/
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
mTextView.setEnabled(enabled);
mSwitch.setEnabled(enabled);
if (BuildCompatUtils.isAtLeastS()) {
if (enabled) {
mFrameView.setBackground(isChecked() ? mBackgroundOn : mBackgroundOff);
} else {
mFrameView.setBackground(mBackgroundDisabled);
}
}
}
private void propagateChecked(boolean isChecked) {
setBackground(isChecked);
final int count = mSwitchChangeListeners.size();
for (int n = 0; n < count; n++) {
mSwitchChangeListeners.get(n).onSwitchChanged(mSwitch, isChecked);
}
}
private void setBackground(boolean isChecked) {
if (!BuildCompatUtils.isAtLeastS()) {
setBackgroundColor(isChecked ? mBackgroundActivatedColor : mBackgroundColor);
} else {
mFrameView.setBackground(isChecked ? mBackgroundOn : mBackgroundOff);
}
}
static class SavedState extends BaseSavedState {
boolean mChecked;
boolean mVisible;
SavedState(Parcelable superState) {
super(superState);
}
/**
* Constructor called from {@link #CREATOR}
*/
private SavedState(Parcel in) {
super(in);
mChecked = (Boolean) in.readValue(null);
mVisible = (Boolean) in.readValue(null);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeValue(mChecked);
out.writeValue(mVisible);
}
@Override
public String toString() {
return "MainSwitchBar.SavedState{"
+ Integer.toHexString(System.identityHashCode(this))
+ " checked=" + mChecked
+ " visible=" + mVisible + "}";
}
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.mChecked = mSwitch.isChecked();
ss.mVisible = isShowing();
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mSwitch.setChecked(ss.mChecked);
setChecked(ss.mChecked);
setBackground(ss.mChecked);
setVisibility(ss.mVisible ? View.VISIBLE : View.GONE);
mSwitch.setOnCheckedChangeListener(ss.mVisible ? this : null);
requestLayout();
}
}