[Expressive Battery] Refactor pref with anomaly hint.

- WarningFramePreference & warning_frame_preference.xml is a battery customized layout which looks like a standard Preference layout with an optional app icon & warning chip.
- PowerGaugePreference extends the WarningFramePreference to display the app Preference with optional warning chip in Battery > Battery Usage.
- PowerUsageTimePreference extends the WarningFramePreference to display the usage time with optional warning chip in Battery > Battery Usage > App battery usage.

Bug: 349652542
Test: atest BatteryUsageBreakdownControllerTest PowerGaugePreferenceTest PowerUsageTimeControllerTest
Flag: com.android.settingslib.widget.theme.flags.is_expressive_design_enabled
Change-Id: I5d22703ccc487c54a2bbbc1d9737b92a2de54ba5
This commit is contained in:
mxyyiyi
2025-02-07 14:43:15 +08:00
parent 8efba3fee5
commit a2bdafaf5e
11 changed files with 178 additions and 260 deletions

View File

@@ -93,10 +93,10 @@ public class PowerUsageTimeController extends BasePreferenceController {
|| (summaryTimeMs == 0 && !TextUtils.equals(anomalyHintKey, preference.getKey()))) {
return false;
}
preference.setTimeTitle(mContext.getString(titleResId));
preference.setTimeSummary(getPowerUsageTimeInfo(summaryTimeMs));
preference.setTitle(mContext.getString(titleResId));
preference.setSummary(getPowerUsageTimeInfo(summaryTimeMs));
if (TextUtils.equals(anomalyHintKey, preference.getKey())) {
preference.setAnomalyHint(anomalyHintText);
preference.setHint(anomalyHintText);
}
preference.setVisible(true);
return true;

View File

@@ -17,74 +17,17 @@
package com.android.settings.fuelgauge;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settingslib.widget.GroupSectionDividerMixin;
/** Custom preference for displaying the app power usage time. */
public class PowerUsageTimePreference extends Preference {
public class PowerUsageTimePreference extends WarningFramePreference implements
GroupSectionDividerMixin {
private static final String TAG = "PowerUsageTimePreference";
@VisibleForTesting CharSequence mTimeTitle;
@VisibleForTesting CharSequence mTimeSummary;
@VisibleForTesting CharSequence mAnomalyHintText;
public PowerUsageTimePreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.power_usage_time);
}
void setTimeTitle(CharSequence timeTitle) {
if (!TextUtils.equals(mTimeTitle, timeTitle)) {
mTimeTitle = timeTitle;
notifyChanged();
}
}
void setTimeSummary(CharSequence timeSummary) {
if (!TextUtils.equals(mTimeSummary, timeSummary)) {
mTimeSummary = timeSummary;
notifyChanged();
}
}
void setAnomalyHint(CharSequence anomalyHintText) {
if (!TextUtils.equals(mAnomalyHintText, anomalyHintText)) {
mAnomalyHintText = anomalyHintText;
notifyChanged();
}
}
private void showAnomalyHint(PreferenceViewHolder view) {
if (TextUtils.isEmpty(mAnomalyHintText)) {
return;
}
final View anomalyHintView = view.findViewById(R.id.anomaly_hints);
if (anomalyHintView == null) {
return;
}
final TextView warningInfo = anomalyHintView.findViewById(R.id.warning_info);
if (warningInfo == null) {
return;
}
warningInfo.setText(mAnomalyHintText);
anomalyHintView.setVisibility(View.VISIBLE);
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
((TextView) view.findViewById(R.id.time_title)).setText(mTimeTitle);
((TextView) view.findViewById(R.id.time_summary)).setText(mTimeSummary);
showAnomalyHint(view);
setSelectable(false);
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2025 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.settings.fuelgauge;
import android.annotation.Nullable;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Space;
import android.widget.TextView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settingslib.Utils;
/**
* Custom preference for displaying the {@link Preference} with an optional hint chip.
*/
public class WarningFramePreference extends Preference {
private final int mTitleColorNormal;
private final int mSummaryColorNormal;
@Nullable private CharSequence mHintText;
public WarningFramePreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.warning_frame_preference);
mTitleColorNormal =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
mSummaryColorNormal =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary);
}
/** Sets the text of hint to show. */
public void setHint(@Nullable CharSequence hintText) {
if (!TextUtils.equals(mHintText, hintText)) {
mHintText = hintText;
notifyChanged();
}
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
final LinearLayout warningChipFrame =
(LinearLayout) view.findViewById(R.id.warning_chip_frame);
final Space warningPaddingPlaceHolder =
warningChipFrame.findViewById(R.id.warning_padding_placeholder);
warningPaddingPlaceHolder.setVisibility(getIcon() != null ? View.VISIBLE : View.GONE);
if (!TextUtils.isEmpty(mHintText)) {
((TextView) warningChipFrame.findViewById(R.id.warning_info)).setText(mHintText);
warningChipFrame.setVisibility(View.VISIBLE);
} else {
warningChipFrame.setVisibility(View.GONE);
}
((TextView) view.findViewById(android.R.id.title)).setTextColor(mTitleColorNormal);
((TextView) view.findViewById(android.R.id.summary)).setTextColor(mSummaryColorNormal);
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C) 2023 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.settings.fuelgauge.batteryusage;
import android.annotation.Nullable;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
class AnomalyAppItemPreference extends PowerGaugePreference {
private static final String TAG = "AnomalyAppItemPreference";
private CharSequence mAnomalyHintText;
AnomalyAppItemPreference(Context context) {
super(context, /* attrs */ null);
setLayoutResource(R.layout.anomaly_app_item_preference);
}
void setAnomalyHint(@Nullable CharSequence anomalyHintText) {
if (!TextUtils.equals(mAnomalyHintText, anomalyHintText)) {
mAnomalyHintText = anomalyHintText;
notifyChanged();
}
}
@Override
public void onBindViewHolder(PreferenceViewHolder viewHolder) {
super.onBindViewHolder(viewHolder);
final LinearLayout warningChipView =
(LinearLayout) viewHolder.findViewById(R.id.warning_chip);
if (!TextUtils.isEmpty(mAnomalyHintText)) {
((TextView) warningChipView.findViewById(R.id.warning_info)).setText(mAnomalyHintText);
warningChipView.setVisibility(View.VISIBLE);
} else {
warningChipView.setVisibility(View.GONE);
}
}
}

View File

@@ -381,15 +381,15 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
continue;
}
final String prefKey = entry.getKey();
AnomalyAppItemPreference preference = mRootPreferenceGroup.findPreference(prefKey);
PowerGaugePreference preference = mRootPreferenceGroup.findPreference(prefKey);
if (preference != null) {
isAdded = true;
} else {
preference = (AnomalyAppItemPreference) mPreferenceCache.get(prefKey);
preference = (PowerGaugePreference) mPreferenceCache.get(prefKey);
}
// Creates new instance if cached preference is not found.
if (preference == null) {
preference = new AnomalyAppItemPreference(mPrefContext);
preference = new PowerGaugePreference(mPrefContext);
preference.setKey(prefKey);
mPreferenceCache.put(prefKey, preference);
}
@@ -398,7 +398,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
preference.setOrder(++preferenceOrder);
preference.setSingleLineTitle(true);
// Updates App item preference style
preference.setAnomalyHint(isAnomalyBatteryDiffEntry(entry) ? mAnomalyHintString : null);
preference.setHint(isAnomalyBatteryDiffEntry(entry) ? mAnomalyHintString : null);
// Sets the BatteryDiffEntry to preference for launching detailed page.
preference.setBatteryDiffEntry(entry);
preference.setSelectable(entry.validForRestriction());

View File

@@ -28,7 +28,7 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.widget.AppPreference;
import com.android.settings.fuelgauge.WarningFramePreference;
/**
* Custom preference for displaying battery usage info as a bar and an icon on the left for the
@@ -37,7 +37,7 @@ import com.android.settingslib.widget.AppPreference;
* <p>The battery usage info could be usage percentage or usage time. The preference won't show any
* icon if it is null.
*/
public class PowerGaugePreference extends AppPreference {
public class PowerGaugePreference extends WarningFramePreference {
// Please see go/battery-usage-app-list-alpha
private static final float SELECTABLE_ALPHA = 1f;
@@ -51,7 +51,6 @@ public class PowerGaugePreference extends AppPreference {
private CharSequence mContentDescription;
private CharSequence mProgress;
private CharSequence mProgressContentDescription;
private boolean mShowAnomalyIcon;
public PowerGaugePreference(
Context context, Drawable icon, CharSequence contentDescription, BatteryEntry info) {
@@ -79,7 +78,6 @@ public class PowerGaugePreference extends AppPreference {
setWidgetLayoutResource(R.layout.preference_widget_summary);
mInfo = info;
mContentDescription = contentDescription;
mShowAnomalyIcon = false;
mTitleColorNormal =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
}
@@ -108,17 +106,6 @@ public class PowerGaugePreference extends AppPreference {
return mProgress.toString();
}
/** Sets whether to show anomaly icon */
public void shouldShowAnomalyIcon(boolean showAnomalyIcon) {
mShowAnomalyIcon = showAnomalyIcon;
notifyChanged();
}
/** Gets whether to show anomaly icon */
public boolean showAnomalyIcon() {
return mShowAnomalyIcon;
}
public void setBatteryDiffEntry(BatteryDiffEntry entry) {
mBatteryDiffEntry = entry;
}
@@ -149,12 +136,6 @@ public class PowerGaugePreference extends AppPreference {
if (!TextUtils.isEmpty(mProgressContentDescription)) {
subtitle.setContentDescription(mProgressContentDescription);
}
if (mShowAnomalyIcon) {
subtitle.setCompoundDrawablesRelativeWithIntrinsicBounds(
R.drawable.ic_warning_24dp, 0, 0, 0);
} else {
subtitle.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0);
}
if (mContentDescription != null) {
final TextView titleView = (TextView) view.findViewById(android.R.id.title);
titleView.setContentDescription(mContentDescription);