Restructure battery bar scenario settings

This commit is contained in:
ajp_anton
2026-06-22 01:37:08 +00:00
parent b0270b8ceb
commit dd215cde82
8 changed files with 800 additions and 449 deletions
@@ -386,12 +386,7 @@ final class BatteryBarController {
return;
}
SbtSettings settings = RuntimeSettingsCache.get(root.getContext());
if (!settings.batteryBarEnabled || root.getWidth() <= 0 || root.getHeight() <= 0) {
removeBatteryBarView(root);
return;
}
int color = resolveBarColor(root, settings);
if (!shouldRenderOnRoot(root)) {
if (root.getWidth() <= 0 || root.getHeight() <= 0) {
removeBatteryBarView(root);
return;
}
@@ -402,6 +397,15 @@ final class BatteryBarController {
if (transientStatusBarReveal) {
scenario = visibleStatusBarScenarioForRoot(root);
}
if (!isBatteryBarEnabled(settings, scenario)) {
removeBatteryBarView(root);
return;
}
int color = resolveBarColor(root, settings);
if (!shouldRenderOnRoot(root)) {
removeBatteryBarView(root);
return;
}
BatteryBarGeometry geometry = BatteryBarGeometry.resolve(settings, scenario);
if (isFullscreenScenario(scenario)) {
removeEmbeddedBatteryBarView(root);
@@ -543,6 +547,7 @@ final class BatteryBarController {
+ plugged + "|"
+ color + "|"
+ settings.batteryBarEnabled + "|"
+ settings.batteryBarScenarioEnabled + "|"
+ settings.batteryBarPosition + "|"
+ settings.batteryBarAlignment + "|"
+ settings.batteryBarThicknessDp + "|"
@@ -579,6 +584,21 @@ final class BatteryBarController {
: BatteryBarGeometry.Scenario.UNLOCKED_PORTRAIT;
}
private boolean isBatteryBarEnabled(
SbtSettings settings,
BatteryBarGeometry.Scenario scenario
) {
if (settings == null || scenario == null) {
return false;
}
if (scenario == BatteryBarGeometry.Scenario.UNLOCKED_PORTRAIT
|| scenario == BatteryBarGeometry.Scenario.UNLOCKED_LANDSCAPE) {
return settings.batteryBarEnabled;
}
Boolean scenarioEnabled = settings.batteryBarScenarioEnabled.get(scenario.id);
return scenarioEnabled == null || scenarioEnabled;
}
private BatteryBarGeometry.Scenario visibleStatusBarScenarioForRoot(View root) {
boolean landscape = isLandscapeForRoot(root, isFullscreenSystemBarState());
if (isPhoneRoot(root) && isUnlockedScene() && isTransparentStatusBarActive()) {
@@ -1064,7 +1084,7 @@ final class BatteryBarController {
? geometry
: BatteryBarGeometry.global(settings);
int thickness = Math.max(1, dpToPx(getContext(), activeGeometry.thicknessDp));
int edgeOffset = Math.max(0, dpToPx(getContext(), settings.batteryBarEdgeOffsetDp));
int edgeOffset = Math.max(0, dpToPx(getContext(), activeGeometry.edgeOffsetDp));
float fraction = resolveFraction(batteryLevel, settings);
if (shouldDrawCurvedTop(activeGeometry)) {
buildCurvedPath(
@@ -21,6 +21,7 @@ public final class BatteryBarGeometry {
public final String position;
public final String alignment;
public final int thicknessDp;
public final int edgeOffsetDp;
public final String curvedGeometryMode;
public BatteryBarGeometry(
@@ -28,13 +29,19 @@ public final class BatteryBarGeometry {
String alignment,
int thicknessDp
) {
this(position, alignment, thicknessDp, SbtDefaults.BATTERY_BAR_CURVED_GEOMETRY_MODE_DEFAULT);
this(
position,
alignment,
thicknessDp,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_DEFAULT,
SbtDefaults.BATTERY_BAR_CURVED_GEOMETRY_MODE_DEFAULT);
}
public BatteryBarGeometry(
String position,
String alignment,
int thicknessDp,
int edgeOffsetDp,
String curvedGeometryMode
) {
this.position = sanitizePosition(position);
@@ -43,6 +50,10 @@ public final class BatteryBarGeometry {
thicknessDp,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MIN,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MAX);
this.edgeOffsetDp = clamp(
edgeOffsetDp,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MIN,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MAX);
this.curvedGeometryMode = sanitizeCurvedGeometryMode(curvedGeometryMode);
}
@@ -57,6 +68,7 @@ public final class BatteryBarGeometry {
settings.batteryBarPosition,
settings.batteryBarAlignment,
settings.batteryBarThicknessDp,
settings.batteryBarEdgeOffsetDp,
settings.batteryBarCurvedGeometryMode);
}
@@ -80,18 +92,19 @@ public final class BatteryBarGeometry {
return safeFallback;
}
String[] parts = value.split("\\|", -1);
if (parts.length != 4) {
if (parts.length != 5) {
return safeFallback;
}
return new BatteryBarGeometry(
parts[0],
parts[1],
parseInt(parts[2], safeFallback.thicknessDp),
parts[3]);
parseInt(parts[3], safeFallback.edgeOffsetDp),
parts[4]);
}
public String encode() {
return position + "|" + alignment + "|" + thicknessDp + "|" + curvedGeometryMode;
return position + "|" + alignment + "|" + thicknessDp + "|" + edgeOffsetDp + "|" + curvedGeometryMode;
}
public String signature() {
@@ -51,7 +51,7 @@ public final class SbtDefaults {
public static final boolean AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT = false;
public static final boolean BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT_DEFAULT = true;
public static final boolean BATTERY_AOD_UNPLUGGED_PERCENT_DEFAULT = true;
public static final boolean BATTERY_BAR_ENABLED_DEFAULT = false;
public static final boolean BATTERY_BAR_ENABLED_DEFAULT = true;
public static final String BATTERY_BAR_POSITION_DEFAULT = "top";
public static final String BATTERY_BAR_ALIGNMENT_DEFAULT = "ltr";
public static final int BATTERY_BAR_THICKNESS_DP_DEFAULT = 2;
@@ -78,6 +78,8 @@ public final class SbtSettings {
public static final String KEY_BATTERY_BAR_GEOMETRY_OVERRIDE_ENABLED_PREFIX =
"battery_bar_geometry_override_enabled_";
public static final String KEY_BATTERY_BAR_GEOMETRY_PREFIX = "battery_bar_geometry_";
public static final String KEY_BATTERY_BAR_SCENARIO_ENABLED_PREFIX =
"battery_bar_scenario_enabled_";
public static final String KEY_BATTERY_BAR_MIN_LEVEL = "battery_bar_min_level";
public static final String KEY_BATTERY_BAR_MAX_LEVEL = "battery_bar_max_level";
public static final String KEY_BATTERY_BAR_DEFAULT_DISCHARGE_COLOR = "battery_bar_default_discharge_color";
@@ -283,6 +285,10 @@ public final class SbtSettings {
return KEY_BATTERY_BAR_GEOMETRY_PREFIX + scenarioId;
}
public static String batteryBarScenarioEnabledKey(String scenarioId) {
return KEY_BATTERY_BAR_SCENARIO_ENABLED_PREFIX + scenarioId;
}
private static String suffixedKey(String base, int index) {
return indexedKey(base, index);
}
@@ -316,6 +322,7 @@ public final class SbtSettings {
public final String batteryBarCurvedGeometryMode;
public final Set<String> batteryBarGeometryOverrideEnabledScenarios;
public final Map<String, String> batteryBarGeometryOverrides;
public final Map<String, Boolean> batteryBarScenarioEnabled;
public final int batteryBarMinLevel;
public final int batteryBarMaxLevel;
public final String batteryBarDefaultDischargeColor;
@@ -449,6 +456,7 @@ public final class SbtSettings {
String batteryBarCurvedGeometryMode,
Set<String> batteryBarGeometryOverrideEnabledScenarios,
Map<String, String> batteryBarGeometryOverrides,
Map<String, Boolean> batteryBarScenarioEnabled,
int batteryBarMinLevel,
int batteryBarMaxLevel,
String batteryBarDefaultDischargeColor,
@@ -593,6 +601,7 @@ public final class SbtSettings {
this.batteryBarGeometryOverrideEnabledScenarios =
sanitizeBatteryBarScenarioSet(batteryBarGeometryOverrideEnabledScenarios);
this.batteryBarGeometryOverrides = sanitizeBatteryBarScenarioMap(batteryBarGeometryOverrides);
this.batteryBarScenarioEnabled = sanitizeBatteryBarScenarioEnabledMap(batteryBarScenarioEnabled);
int clampedMinLevel = clampInt(
batteryBarMinLevel,
SbtDefaults.BATTERY_BAR_MIN_LEVEL_MIN,
@@ -886,6 +895,7 @@ public final class SbtSettings {
SbtDefaults.BATTERY_BAR_CURVED_GEOMETRY_MODE_DEFAULT,
Collections.emptySet(),
Collections.emptyMap(),
Collections.emptyMap(),
SbtDefaults.BATTERY_BAR_MIN_LEVEL_DEFAULT,
SbtDefaults.BATTERY_BAR_MAX_LEVEL_DEFAULT,
SbtDefaults.BATTERY_BAR_DEFAULT_DISCHARGE_COLOR_DEFAULT,
@@ -1224,6 +1234,7 @@ public final class SbtSettings {
SbtDefaults.BATTERY_BAR_CURVED_GEOMETRY_MODE_DEFAULT),
readBatteryBarScenarioSetFromPrefs(prefs),
readBatteryBarScenarioMapFromPrefs(prefs),
readBatteryBarScenarioEnabledMapFromPrefs(prefs),
clampInt(prefs.getInt(KEY_BATTERY_BAR_MIN_LEVEL, SbtDefaults.BATTERY_BAR_MIN_LEVEL_DEFAULT),
SbtDefaults.BATTERY_BAR_MIN_LEVEL_MIN,
SbtDefaults.BATTERY_BAR_MIN_LEVEL_MAX),
@@ -1531,6 +1542,7 @@ public final class SbtSettings {
SbtDefaults.BATTERY_BAR_CURVED_GEOMETRY_MODE_DEFAULT),
readBatteryBarScenarioSetFromBundle(bundle),
readBatteryBarScenarioMapFromBundle(bundle),
readBatteryBarScenarioEnabledMapFromBundle(bundle),
clampInt(bundle.getInt(KEY_BATTERY_BAR_MIN_LEVEL, SbtDefaults.BATTERY_BAR_MIN_LEVEL_DEFAULT),
SbtDefaults.BATTERY_BAR_MIN_LEVEL_MIN,
SbtDefaults.BATTERY_BAR_MIN_LEVEL_MAX),
@@ -1948,6 +1960,34 @@ public final class SbtSettings {
return result;
}
private static Map<String, Boolean> readBatteryBarScenarioEnabledMapFromPrefs(SharedPreferences prefs) {
if (prefs == null) {
return Collections.emptyMap();
}
HashMap<String, Boolean> result = new HashMap<>();
for (BatteryBarGeometry.Scenario scenario : BatteryBarGeometry.Scenario.values()) {
String key = batteryBarScenarioEnabledKey(scenario.id);
if (prefs.contains(key)) {
result.put(scenario.id, prefs.getBoolean(key, true));
}
}
return result;
}
private static Map<String, Boolean> readBatteryBarScenarioEnabledMapFromBundle(Bundle bundle) {
if (bundle == null) {
return Collections.emptyMap();
}
HashMap<String, Boolean> result = new HashMap<>();
for (BatteryBarGeometry.Scenario scenario : BatteryBarGeometry.Scenario.values()) {
String key = batteryBarScenarioEnabledKey(scenario.id);
if (bundle.containsKey(key)) {
result.put(scenario.id, bundle.getBoolean(key, true));
}
}
return result;
}
private static Set<String> sanitizeBatteryBarScenarioSet(Set<String> source) {
if (source == null || source.isEmpty()) {
return Collections.emptySet();
@@ -1976,6 +2016,21 @@ public final class SbtSettings {
return result.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(result);
}
private static Map<String, Boolean> sanitizeBatteryBarScenarioEnabledMap(Map<String, Boolean> source) {
if (source == null || source.isEmpty()) {
return Collections.emptyMap();
}
HashMap<String, Boolean> result = new HashMap<>();
for (Map.Entry<String, Boolean> entry : source.entrySet()) {
String id = entry.getKey();
Boolean value = entry.getValue();
if (isBatteryBarScenarioId(id) && value != null) {
result.put(id, value);
}
}
return result.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(result);
}
private static boolean isBatteryBarScenarioId(String id) {
if (id == null) {
return false;
@@ -107,8 +107,12 @@ public class SbtSettingsProvider extends ContentProvider {
for (BatteryBarGeometry.Scenario scenario : BatteryBarGeometry.Scenario.values()) {
String enabledKey = BatteryBarGeometry.enabledKey(scenario);
String valueKey = BatteryBarGeometry.valueKey(scenario);
String scenarioEnabledKey = SbtSettings.batteryBarScenarioEnabledKey(scenario.id);
out.putBoolean(enabledKey, prefs.getBoolean(enabledKey, false));
out.putString(valueKey, prefs.getString(valueKey, null));
if (prefs.contains(scenarioEnabledKey)) {
out.putBoolean(scenarioEnabledKey, prefs.getBoolean(scenarioEnabledKey, true));
}
}
out.putInt(SbtSettings.KEY_BATTERY_BAR_MIN_LEVEL,
prefs.getInt(SbtSettings.KEY_BATTERY_BAR_MIN_LEVEL, SbtDefaults.BATTERY_BAR_MIN_LEVEL_DEFAULT));
@@ -25,10 +25,12 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.slider.RangeSlider;
import com.google.android.material.switchmaterial.SwitchMaterial;
@@ -85,9 +87,9 @@ public final class BatteryBarFragment extends Fragment {
TextView colourHelp = root.findViewById(R.id.battery_bar_colour_help);
MaterialButton addThresholdButton = root.findViewById(R.id.battery_bar_add_threshold_button);
LinearLayout thresholdsContainer = root.findViewById(R.id.battery_bar_thresholds_container);
View geometrySection = root.findViewById(R.id.battery_bar_geometry_section);
LinearLayout scenarioOverridesContainer =
root.findViewById(R.id.battery_bar_scenario_overrides_container);
View baseControls = root.findViewById(R.id.battery_bar_base_controls);
LinearLayout scenarioCardsContainer =
root.findViewById(R.id.battery_bar_scenario_cards_container);
mappingSlider.setValueFrom(0f);
mappingSlider.setValueTo(100f);
mappingSlider.setStepSize(1f);
@@ -130,7 +132,7 @@ public final class BatteryBarFragment extends Fragment {
minLevelLabel,
maxLevelLabel,
false);
setSectionEnabled(geometrySection, enabled.isChecked());
setSectionEnabled(baseControls, enabled.isChecked());
updateColourButtonLabel(
defaultDischargeButton,
R.string.battery_bar_default_discharge_colour,
@@ -154,7 +156,7 @@ public final class BatteryBarFragment extends Fragment {
enabled.setOnCheckedChangeListener((buttonView, isChecked) -> {
prefs.edit().putBoolean(SbtSettings.KEY_BATTERY_BAR_ENABLED, isChecked).apply();
SbtSettings.ensureReadable(requireContext());
setSectionEnabled(geometrySection, isChecked);
setSectionEnabled(baseControls, isChecked);
});
positionGroup.setOnCheckedChangeListener((group, checkedId) -> {
@@ -192,8 +194,8 @@ public final class BatteryBarFragment extends Fragment {
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MIN,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MAX,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_DEFAULT);
renderScenarioOverrides(scenarioOverridesContainer, prefs);
setSectionEnabled(geometrySection, enabled.isChecked());
renderScenarioCards(scenarioCardsContainer, prefs);
setSectionEnabled(baseControls, enabled.isChecked());
mappingSlider.addOnChangeListener((slider, value, fromUser) -> {
if (!fromUser) {
@@ -434,17 +436,16 @@ public final class BatteryBarFragment extends Fragment {
return;
}
view.setAlpha(enabled ? 1f : 0.82f);
if (view.getClass() != TextView.class) {
view.setEnabled(enabled);
}
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
setSectionEnabled(group.getChildAt(i), enabled);
}
} else {
if (view.getClass() == TextView.class) {
view.setEnabled(true);
} else {
view.setEnabled(enabled);
}
} else if (view.getClass() == TextView.class) {
view.setEnabled(true);
}
}
@@ -504,142 +505,531 @@ public final class BatteryBarFragment extends Fragment {
}
}
private void renderScenarioOverrides(LinearLayout container, SharedPreferences prefs) {
private void renderScenarioCards(LinearLayout container, SharedPreferences prefs) {
if (container == null) {
return;
}
container.removeAllViews();
addScenarioOverrideRow(container, prefs, new ScenarioGroup(
R.string.battery_bar_scenario_group_unlocked,
BatteryBarGeometry.Scenario.UNLOCKED_PORTRAIT,
BatteryBarGeometry.Scenario.UNLOCKED_LANDSCAPE));
addScenarioOverrideRow(container, prefs, new ScenarioGroup(
addScenarioCard(container, prefs, new ScenarioGroup(
R.string.battery_bar_scenario_group_transparent,
BatteryBarGeometry.Scenario.TRANSPARENT_PORTRAIT,
BatteryBarGeometry.Scenario.TRANSPARENT_LANDSCAPE));
addScenarioOverrideRow(container, prefs, new ScenarioGroup(
addScenarioCard(container, prefs, new ScenarioGroup(
R.string.battery_bar_scenario_group_fullscreen,
BatteryBarGeometry.Scenario.FULLSCREEN_PORTRAIT,
BatteryBarGeometry.Scenario.FULLSCREEN_LANDSCAPE));
addScenarioOverrideRow(container, prefs, new ScenarioGroup(
addScenarioCard(container, prefs, new ScenarioGroup(
R.string.battery_bar_lockscreen_override,
BatteryBarGeometry.Scenario.LOCKSCREEN));
}
private void addScenarioOverrideRow(
private void addScenarioCard(
LinearLayout container,
SharedPreferences prefs,
ScenarioGroup scenarioGroup
) {
Context context = container.getContext();
LinearLayout row = new LinearLayout(context);
row.setGravity(Gravity.CENTER_VERTICAL);
row.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams rowParams = new LinearLayout.LayoutParams(
MaterialCardView card = new MaterialCardView(context);
LinearLayout.LayoutParams cardParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
rowParams.topMargin = ViewTreeSupport.dp(context, 8);
row.setLayoutParams(rowParams);
cardParams.topMargin = ViewTreeSupport.dp(context, 16);
card.setLayoutParams(cardParams);
card.setUseCompatPadding(true);
card.setStrokeColor(ContextCompat.getColor(context, R.color.sbt_card_outline));
card.setStrokeWidth(ViewTreeSupport.dp(context, 1));
LinearLayout textColumn = new LinearLayout(context);
textColumn.setOrientation(LinearLayout.VERTICAL);
textColumn.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout content = new LinearLayout(context);
content.setOrientation(LinearLayout.VERTICAL);
content.setPadding(
ViewTreeSupport.dp(context, 16),
ViewTreeSupport.dp(context, 16),
ViewTreeSupport.dp(context, 16),
ViewTreeSupport.dp(context, 16));
card.addView(content);
TextView title = sectionTitle(context, scenarioGroup.labelRes());
content.addView(title);
SwitchMaterial enabledSwitch = new SwitchMaterial(context);
enabledSwitch.setText(R.string.battery_bar_enabled);
enabledSwitch.setChecked(scenarioGroupEnabled(prefs, scenarioGroup));
content.addView(enabledSwitch);
SwitchMaterial useBaseSwitch = new SwitchMaterial(context);
useBaseSwitch.setText(R.string.battery_bar_use_base_settings);
useBaseSwitch.setChecked(scenarioGroupUsesBase(prefs, scenarioGroup));
content.addView(useBaseSwitch);
LinearLayout controlsRoot = new LinearLayout(context);
controlsRoot.setOrientation(LinearLayout.VERTICAL);
content.addView(controlsRoot);
GeometryControls controls = createGeometryControls(context, controlsRoot);
BatteryBarGeometry geometry = scenarioGroupGeometryFromPrefs(prefs, scenarioGroup);
applyGeometryToControls(controls, geometry);
Runnable refreshEnabled = () -> setSectionEnabled(
controlsRoot,
enabledSwitch.isChecked() && !useBaseSwitch.isChecked());
enabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
setScenarioGroupEnabled(prefs, scenarioGroup, isChecked);
refreshEnabled.run();
});
useBaseSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
applyGeometryToControls(controls, globalGeometryFromPrefs(prefs));
}
setScenarioGroupUseBase(prefs, scenarioGroup, isChecked, geometryFromControls(controls, prefs));
refreshEnabled.run();
});
bindScenarioGeometryControls(prefs, scenarioGroup, controls);
refreshEnabled.run();
container.addView(card);
}
private GeometryControls createGeometryControls(Context context, LinearLayout root) {
root.addView(sectionLabel(context, R.string.battery_bar_position_title));
RadioGroup positionGroup = new RadioGroup(context);
positionGroup.setLayoutParams(matchWrapParams(8));
RadioButton positionFollow = optionRadio(context, R.string.battery_bar_curved_geometry_length);
RadioButton positionTop = optionRadio(context, R.string.battery_bar_position_top);
RadioButton positionBottom = optionRadio(context, R.string.battery_bar_position_bottom);
positionFollow.setId(R.id.battery_bar_curved_geometry_length);
positionTop.setId(R.id.battery_bar_position_top);
positionBottom.setId(R.id.battery_bar_position_bottom);
positionGroup.addView(positionFollow);
positionGroup.addView(positionTop);
positionGroup.addView(positionBottom);
root.addView(positionGroup);
root.addView(sectionLabel(context, R.string.battery_bar_alignment_title));
LinearLayout alignmentRow = new LinearLayout(context);
alignmentRow.setOrientation(LinearLayout.HORIZONTAL);
alignmentRow.setLayoutParams(matchWrapParams(8));
RadioButton alignLtr = new RadioButton(context);
RadioButton alignCenter = new RadioButton(context);
RadioButton alignRtl = new RadioButton(context);
View alignLtrCell = alignmentCell(context, alignLtr, R.drawable.sbt_align_ltr);
View alignCenterCell = alignmentCell(context, alignCenter, R.drawable.sbt_align_center);
View alignRtlCell = alignmentCell(context, alignRtl, R.drawable.sbt_align_rtl);
alignmentRow.addView(alignLtrCell);
alignmentRow.addView(alignCenterCell);
alignmentRow.addView(alignRtlCell);
root.addView(alignmentRow);
root.addView(sectionLabel(context, R.string.battery_bar_thickness_title));
NumberControls thickness = numberControls(context);
root.addView(thickness.row);
root.addView(sectionLabel(context, R.string.battery_bar_edge_offset_title));
NumberControls edgeOffset = numberControls(context);
root.addView(edgeOffset.row);
return new GeometryControls(
positionGroup,
positionFollow,
positionTop,
positionBottom,
alignLtrCell,
alignCenterCell,
alignRtlCell,
alignLtr,
alignCenter,
alignRtl,
thickness.input,
thickness.minus,
thickness.plus,
edgeOffset.input,
edgeOffset.minus,
edgeOffset.plus);
}
private TextView sectionTitle(Context context, int textRes) {
TextView view = new TextView(context);
view.setText(textRes);
view.setTextAppearance(android.R.style.TextAppearance_Material_Medium);
view.setAllCaps(true);
view.setLetterSpacing(0.03f);
view.setTypeface(view.getTypeface(), android.graphics.Typeface.BOLD);
return view;
}
private TextView sectionLabel(Context context, int textRes) {
TextView view = new TextView(context);
view.setText(textRes);
view.setTextAppearance(android.R.style.TextAppearance_Material_Body2);
view.setLayoutParams(matchWrapParams(16));
return view;
}
private LinearLayout.LayoutParams matchWrapParams(int topMarginDp) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.topMargin = ViewTreeSupport.dp(requireContext(), topMarginDp);
return params;
}
private RadioButton optionRadio(Context context, int textRes) {
RadioButton radio = new RadioButton(context);
radio.setText(textRes);
radio.setMinHeight(ViewTreeSupport.dp(context, 36));
return radio;
}
private View alignmentCell(Context context, RadioButton radio, int drawableRes) {
LinearLayout cell = new LinearLayout(context);
cell.setOrientation(LinearLayout.VERTICAL);
cell.setGravity(Gravity.CENTER);
cell.setClickable(true);
cell.setFocusable(true);
cell.setPadding(
ViewTreeSupport.dp(context, 4),
ViewTreeSupport.dp(context, 4),
ViewTreeSupport.dp(context, 4),
ViewTreeSupport.dp(context, 4));
cell.setLayoutParams(new LinearLayout.LayoutParams(
0,
ViewGroup.LayoutParams.WRAP_CONTENT,
1f));
SwitchMaterial enabledSwitch = new SwitchMaterial(context);
enabledSwitch.setText(scenarioGroup.labelRes());
enabledSwitch.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
radio.setMinHeight(0);
radio.setMinWidth(0);
radio.setPadding(0, 0, 0, 0);
radio.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
textColumn.addView(enabledSwitch);
cell.addView(radio);
TextView summary = new TextView(context);
summary.setTextAppearance(android.R.style.TextAppearance_Material_Body2);
summary.setPadding(ViewTreeSupport.dp(context, 48), 0, 0, 0);
textColumn.addView(summary);
MaterialButton editButton = new MaterialButton(context, null, com.google.android.material.R.attr.materialButtonOutlinedStyle);
editButton.setText(R.string.battery_bar_edit_override);
row.addView(textColumn);
row.addView(editButton);
container.addView(row);
bindScenarioOverride(scenarioGroup, enabledSwitch, editButton, summary, prefs);
AppCompatImageView image = new AppCompatImageView(context);
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(
ViewTreeSupport.dp(context, 24),
ViewTreeSupport.dp(context, 24));
imageParams.topMargin = ViewTreeSupport.dp(context, 4);
image.setLayoutParams(imageParams);
image.setImageResource(drawableRes);
cell.addView(image);
return cell;
}
private void bindScenarioOverride(
ScenarioGroup scenarioGroup,
SwitchMaterial enabledSwitch,
MaterialButton editButton,
TextView summary,
SharedPreferences prefs
) {
if (scenarioGroup == null || prefs == null) {
private NumberControls numberControls(Context context) {
LinearLayout row = new LinearLayout(context);
row.setGravity(Gravity.CENTER_VERTICAL);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setLayoutParams(matchWrapParams(8));
MaterialButton minus = new MaterialButton(
context,
null,
com.google.android.material.R.attr.materialButtonOutlinedStyle);
minus.setText("-");
minus.setLayoutParams(new LinearLayout.LayoutParams(
ViewTreeSupport.dp(context, 40),
ViewGroup.LayoutParams.WRAP_CONTENT));
ViewTreeSupport.styleStepperButton(minus);
EditText input = new EditText(context);
LinearLayout.LayoutParams inputParams = new LinearLayout.LayoutParams(
ViewTreeSupport.dp(context, 72),
ViewGroup.LayoutParams.WRAP_CONTENT);
inputParams.leftMargin = ViewTreeSupport.dp(context, 8);
inputParams.rightMargin = ViewTreeSupport.dp(context, 8);
input.setLayoutParams(inputParams);
input.setEms(3);
input.setGravity(Gravity.CENTER);
input.setInputType(InputType.TYPE_CLASS_NUMBER);
input.setSingleLine(true);
input.setMaxLines(1);
input.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
MaterialButton plus = new MaterialButton(
context,
null,
com.google.android.material.R.attr.materialButtonOutlinedStyle);
plus.setText("+");
plus.setLayoutParams(new LinearLayout.LayoutParams(
ViewTreeSupport.dp(context, 40),
ViewGroup.LayoutParams.WRAP_CONTENT));
ViewTreeSupport.styleStepperButton(plus);
row.addView(minus);
row.addView(input);
row.addView(plus);
return new NumberControls(row, input, minus, plus);
}
private void applyGeometryToControls(GeometryControls controls, BatteryBarGeometry geometry) {
if (controls == null || geometry == null) {
return;
}
boolean enabled = scenarioGroupEnabled(prefs, scenarioGroup);
if (enabledSwitch != null) {
enabledSwitch.setChecked(enabled);
enabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
SharedPreferences.Editor editor = prefs.edit();
BatteryBarGeometry geometry = scenarioGroupGeometryFromPrefs(prefs, scenarioGroup);
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
editor.putBoolean(BatteryBarGeometry.enabledKey(scenario), isChecked);
if (isChecked) {
editor.putString(BatteryBarGeometry.valueKey(scenario), geometry.encode());
}
}
editor.apply();
SbtSettings.ensureReadable(requireContext());
updateScenarioSummary(scenarioGroup, summary, editButton, prefs);
applyPositionSelection(
controls.positionFollow,
controls.positionTop,
controls.positionBottom,
geometry.position,
geometry.curvedGeometryMode);
applyAlignmentSelection(controls.alignLtr, controls.alignRtl, controls.alignCenter, geometry.alignment);
setIntInput(controls.thicknessInput, geometry.thicknessDp);
setIntInput(controls.edgeOffsetInput, geometry.edgeOffsetDp);
}
private void bindScenarioGeometryControls(
SharedPreferences prefs,
ScenarioGroup scenarioGroup,
GeometryControls controls
) {
if (prefs == null || scenarioGroup == null || controls == null) {
return;
}
controls.positionGroup.setOnCheckedChangeListener((group, checkedId) ->
persistScenarioGeometry(prefs, scenarioGroup, geometryFromControls(controls, prefs)));
bindScenarioAlignmentCell(prefs, scenarioGroup, controls, controls.alignRtlCell, "rtl");
bindScenarioAlignmentCell(prefs, scenarioGroup, controls, controls.alignCenterCell, "center");
bindScenarioAlignmentCell(prefs, scenarioGroup, controls, controls.alignLtrCell, "ltr");
bindScenarioAlignmentCell(prefs, scenarioGroup, controls, controls.alignRtl, "rtl");
bindScenarioAlignmentCell(prefs, scenarioGroup, controls, controls.alignCenter, "center");
bindScenarioAlignmentCell(prefs, scenarioGroup, controls, controls.alignLtr, "ltr");
bindScenarioNumberControl(
prefs,
scenarioGroup,
controls,
controls.thicknessInput,
controls.thicknessMinus,
controls.thicknessPlus,
false);
bindScenarioNumberControl(
prefs,
scenarioGroup,
controls,
controls.edgeOffsetInput,
controls.edgeOffsetMinus,
controls.edgeOffsetPlus,
true);
}
private void bindScenarioAlignmentCell(
SharedPreferences prefs,
ScenarioGroup scenarioGroup,
GeometryControls controls,
View clickTarget,
String value
) {
if (clickTarget == null) {
return;
}
clickTarget.setOnClickListener(v -> {
if (!clickTarget.isEnabled()) {
return;
}
applyAlignmentSelection(controls.alignLtr, controls.alignRtl, controls.alignCenter, value);
persistScenarioGeometry(prefs, scenarioGroup, geometryFromControls(controls, prefs));
});
}
private void bindScenarioNumberControl(
SharedPreferences prefs,
ScenarioGroup scenarioGroup,
GeometryControls controls,
EditText input,
MaterialButton minus,
MaterialButton plus,
boolean edgeOffset
) {
final boolean[] updating = new boolean[]{false};
if (minus != null) {
minus.setOnClickListener(v -> {
int current = scenarioNumberValue(input, controls, prefs, edgeOffset);
setScenarioNumberValue(input, current - 1, edgeOffset, updating);
persistScenarioGeometry(prefs, scenarioGroup, geometryFromControls(controls, prefs));
});
}
if (editButton != null) {
editButton.setOnClickListener(v -> showScenarioGeometryDialog(
scenarioGroup,
prefs,
summary,
editButton));
if (plus != null) {
plus.setOnClickListener(v -> {
int current = scenarioNumberValue(input, controls, prefs, edgeOffset);
setScenarioNumberValue(input, current + 1, edgeOffset, updating);
persistScenarioGeometry(prefs, scenarioGroup, geometryFromControls(controls, prefs));
});
}
updateScenarioSummary(scenarioGroup, summary, editButton, prefs);
}
private void updateScenarioSummary(
ScenarioGroup scenarioGroup,
TextView summary,
MaterialButton editButton,
SharedPreferences prefs
) {
if (scenarioGroup == null || prefs == null) {
if (input == null) {
return;
}
boolean enabled = scenarioGroupEnabled(prefs, scenarioGroup);
BatteryBarGeometry geometry = scenarioGroupGeometryFromPrefs(prefs, scenarioGroup);
if (summary != null) {
summary.setText(getString(
R.string.battery_bar_override_summary,
batteryBarPositionLabel(geometry),
geometry.alignment,
geometry.thicknessDp));
summary.setAlpha(enabled ? 1f : 0.65f);
input.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (updating[0] || s == null || s.toString().trim().isEmpty()) {
return;
}
setScenarioNumberValue(
input,
scenarioNumberValue(input, controls, prefs, edgeOffset),
edgeOffset,
updating);
persistScenarioGeometry(prefs, scenarioGroup, geometryFromControls(controls, prefs));
}
});
input.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
return;
}
setScenarioNumberValue(
input,
scenarioNumberValue(input, controls, prefs, edgeOffset),
edgeOffset,
updating);
persistScenarioGeometry(prefs, scenarioGroup, geometryFromControls(controls, prefs));
});
}
private int scenarioNumberValue(
EditText input,
GeometryControls controls,
SharedPreferences prefs,
boolean edgeOffset
) {
BatteryBarGeometry fallback = globalGeometryFromPrefs(prefs);
int current = ViewTreeSupport.parseInt(
input,
edgeOffset ? fallback.edgeOffsetDp : fallback.thicknessDp);
return edgeOffset
? ViewTreeSupport.clamp(
current,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MIN,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MAX)
: ViewTreeSupport.clamp(
current,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MIN,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MAX);
}
private void setScenarioNumberValue(
EditText input,
int value,
boolean edgeOffset,
boolean[] updating
) {
int clamped = edgeOffset
? ViewTreeSupport.clamp(
value,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MIN,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_MAX)
: ViewTreeSupport.clamp(
value,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MIN,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MAX);
persistIntInput(input, clamped, updating);
}
private void persistIntInput(EditText input, int value, boolean[] updating) {
if (input == null) {
return;
}
if (editButton != null) {
editButton.setEnabled(enabled);
updating[0] = true;
input.setText(String.valueOf(value));
input.setSelection(input.getText().length());
updating[0] = false;
}
private BatteryBarGeometry geometryFromControls(GeometryControls controls, SharedPreferences prefs) {
BatteryBarGeometry fallback = globalGeometryFromPrefs(prefs);
if (controls == null) {
return fallback;
}
int checkedPosition = controls.positionGroup.getCheckedRadioButtonId();
String alignment = controls.alignRtl.isChecked()
? "rtl"
: controls.alignCenter.isChecked() ? "center" : "ltr";
return new BatteryBarGeometry(
positionValue(checkedPosition),
alignment,
scenarioNumberValue(controls.thicknessInput, controls, prefs, false),
scenarioNumberValue(controls.edgeOffsetInput, controls, prefs, true),
curvedGeometryValue(checkedPosition));
}
private void persistScenarioGeometry(
SharedPreferences prefs,
ScenarioGroup scenarioGroup,
BatteryBarGeometry geometry
) {
if (prefs == null || scenarioGroup == null || geometry == null) {
return;
}
SharedPreferences.Editor editor = prefs.edit();
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
editor.putBoolean(BatteryBarGeometry.enabledKey(scenario), true);
editor.putString(BatteryBarGeometry.valueKey(scenario), geometry.encode());
}
editor.apply();
SbtSettings.ensureReadable(requireContext());
}
private boolean scenarioGroupEnabled(SharedPreferences prefs, ScenarioGroup scenarioGroup) {
if (prefs == null || scenarioGroup == null) {
return false;
return true;
}
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
if (!prefs.getBoolean(SbtSettings.batteryBarScenarioEnabledKey(scenario.id), true)) {
return false;
}
}
return true;
}
private void setScenarioGroupEnabled(
SharedPreferences prefs,
ScenarioGroup scenarioGroup,
boolean enabled
) {
if (prefs == null || scenarioGroup == null) {
return;
}
SharedPreferences.Editor editor = prefs.edit();
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
editor.putBoolean(SbtSettings.batteryBarScenarioEnabledKey(scenario.id), enabled);
}
editor.apply();
SbtSettings.ensureReadable(requireContext());
}
private boolean scenarioGroupUsesBase(SharedPreferences prefs, ScenarioGroup scenarioGroup) {
if (prefs == null || scenarioGroup == null) {
return true;
}
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
if (prefs.getBoolean(BatteryBarGeometry.enabledKey(scenario), false)) {
return true;
return false;
}
}
return false;
return true;
}
private void setScenarioGroupUseBase(
SharedPreferences prefs,
ScenarioGroup scenarioGroup,
boolean useBase,
BatteryBarGeometry current
) {
if (prefs == null || scenarioGroup == null) {
return;
}
SharedPreferences.Editor editor = prefs.edit();
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
editor.putBoolean(BatteryBarGeometry.enabledKey(scenario), !useBase);
if (!useBase && current != null) {
editor.putString(BatteryBarGeometry.valueKey(scenario), current.encode());
}
}
editor.apply();
SbtSettings.ensureReadable(requireContext());
}
private BatteryBarGeometry globalGeometryFromPrefs(SharedPreferences prefs) {
@@ -653,6 +1043,9 @@ public final class BatteryBarFragment extends Fragment {
prefs.getInt(
SbtSettings.KEY_BATTERY_BAR_THICKNESS_DP,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_DEFAULT),
prefs.getInt(
SbtSettings.KEY_BATTERY_BAR_EDGE_OFFSET_DP,
SbtDefaults.BATTERY_BAR_EDGE_OFFSET_DP_DEFAULT),
prefs.getString(
SbtSettings.KEY_BATTERY_BAR_CURVED_GEOMETRY_MODE,
SbtDefaults.BATTERY_BAR_CURVED_GEOMETRY_MODE_DEFAULT));
@@ -675,113 +1068,46 @@ public final class BatteryBarFragment extends Fragment {
return globalGeometryFromPrefs(prefs);
}
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
if (prefs.contains(BatteryBarGeometry.valueKey(scenario))) {
if (prefs.getBoolean(BatteryBarGeometry.enabledKey(scenario), false)
&& prefs.contains(BatteryBarGeometry.valueKey(scenario))) {
return scenarioGeometryFromPrefs(prefs, scenario);
}
}
return globalGeometryFromPrefs(prefs);
}
private void showScenarioGeometryDialog(
ScenarioGroup scenarioGroup,
SharedPreferences prefs,
TextView summary,
MaterialButton editButton
) {
BatteryBarGeometry current = scenarioGroupGeometryFromPrefs(prefs, scenarioGroup);
LinearLayout content = new LinearLayout(requireContext());
content.setOrientation(LinearLayout.VERTICAL);
int padding = Math.round(20 * getResources().getDisplayMetrics().density);
content.setPadding(padding, 0, padding, 0);
TextView positionTitle = dialogLabel(R.string.battery_bar_position_title);
content.addView(positionTitle);
RadioGroup positionGroup = new RadioGroup(requireContext());
RadioButton positionFollow = dialogRadio(R.string.battery_bar_curved_geometry_length);
RadioButton positionTop = dialogRadio(R.string.battery_bar_position_top);
RadioButton positionBottom = dialogRadio(R.string.battery_bar_position_bottom);
positionFollow.setId(R.id.battery_bar_curved_geometry_length);
positionTop.setId(R.id.battery_bar_position_top);
positionBottom.setId(R.id.battery_bar_position_bottom);
positionGroup.addView(positionFollow);
positionGroup.addView(positionTop);
positionGroup.addView(positionBottom);
applyPositionSelection(positionFollow, positionTop, positionBottom,
current.position, current.curvedGeometryMode);
content.addView(positionGroup);
TextView alignmentTitle = dialogLabel(R.string.battery_bar_alignment_title);
alignmentTitle.setPadding(0, padding / 2, 0, 0);
content.addView(alignmentTitle);
RadioGroup alignmentGroup = new RadioGroup(requireContext());
RadioButton alignmentLtr = dialogRadio(R.string.battery_bar_alignment_ltr);
RadioButton alignmentCenter = dialogRadio(R.string.battery_bar_alignment_center);
RadioButton alignmentRtl = dialogRadio(R.string.battery_bar_alignment_rtl);
alignmentGroup.addView(alignmentLtr);
alignmentGroup.addView(alignmentCenter);
alignmentGroup.addView(alignmentRtl);
applyAlignmentSelection(alignmentLtr, alignmentRtl, alignmentCenter, current.alignment);
content.addView(alignmentGroup);
EditText thicknessInput = dialogNumberInput(current.thicknessDp);
content.addView(dialogLabel(R.string.battery_bar_thickness_title));
content.addView(thicknessInput);
androidx.appcompat.app.AlertDialog dialog = new MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.battery_bar_override_dialog_title, getString(scenarioGroup.labelRes())))
.setView(content)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, (dialogInterface, which) -> {
int checkedPosition = positionGroup.getCheckedRadioButtonId();
BatteryBarGeometry updated = new BatteryBarGeometry(
positionValue(checkedPosition),
alignmentRtl.isChecked()
? "rtl"
: alignmentCenter.isChecked() ? "center" : "ltr",
ViewTreeSupport.clamp(
ViewTreeSupport.parseInt(thicknessInput, current.thicknessDp),
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MIN,
SbtDefaults.BATTERY_BAR_THICKNESS_DP_MAX),
curvedGeometryValue(checkedPosition));
SharedPreferences.Editor editor = prefs.edit();
for (BatteryBarGeometry.Scenario scenario : scenarioGroup.scenarios()) {
editor.putString(BatteryBarGeometry.valueKey(scenario), updated.encode());
}
editor.apply();
SbtSettings.ensureReadable(requireContext());
updateScenarioSummary(scenarioGroup, summary, editButton, prefs);
})
.show();
tintDialogButtons(dialog, requireContext());
}
private record ScenarioGroup(
int labelRes,
BatteryBarGeometry.Scenario... scenarios
) {
}
private TextView dialogLabel(int resId) {
TextView view = new TextView(requireContext());
view.setText(resId);
view.setTextAppearance(android.R.style.TextAppearance_Material_Body1);
return view;
private record GeometryControls(
RadioGroup positionGroup,
RadioButton positionFollow,
RadioButton positionTop,
RadioButton positionBottom,
View alignLtrCell,
View alignCenterCell,
View alignRtlCell,
RadioButton alignLtr,
RadioButton alignCenter,
RadioButton alignRtl,
EditText thicknessInput,
MaterialButton thicknessMinus,
MaterialButton thicknessPlus,
EditText edgeOffsetInput,
MaterialButton edgeOffsetMinus,
MaterialButton edgeOffsetPlus
) {
}
private RadioButton dialogRadio(int resId) {
RadioButton radioButton = new RadioButton(requireContext());
radioButton.setId(View.generateViewId());
radioButton.setText(resId);
return radioButton;
}
private EditText dialogNumberInput(int value) {
EditText input = new EditText(requireContext());
input.setInputType(InputType.TYPE_CLASS_NUMBER);
input.setSingleLine(true);
input.setGravity(Gravity.CENTER);
input.setText(String.valueOf(value));
return input;
private record NumberControls(
LinearLayout row,
EditText input,
MaterialButton minus,
MaterialButton plus
) {
}
private void adjustMapping(SharedPreferences prefs,
+174 -236
View File
@@ -17,38 +17,6 @@
android:text="@string/battery_bar_title"
android:textAppearance="?attr/textAppearanceHeadline5" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:cardUseCompatPadding="true"
app:strokeColor="@color/sbt_card_outline"
app:strokeWidth="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/battery_bar_master_toggle_title"
android:textAppearance="?attr/textAppearanceSubtitle1"
android:textAllCaps="true"
android:letterSpacing="0.03"
android:textStyle="bold" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/battery_bar_enabled_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/battery_bar_enabled" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:id="@+id/battery_bar_geometry_section"
android:layout_width="match_parent"
@@ -72,53 +40,172 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/battery_bar_position_title"
android:text="@string/battery_bar_base_settings_title"
android:textAppearance="?attr/textAppearanceSubtitle1"
android:textAllCaps="true"
android:letterSpacing="0.03"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/battery_bar_position_group"
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/battery_bar_enabled_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<RadioButton
android:id="@+id/battery_bar_curved_geometry_length"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:text="@string/battery_bar_curved_geometry_length" />
<RadioButton
android:id="@+id/battery_bar_position_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:text="@string/battery_bar_position_top" />
<RadioButton
android:id="@+id/battery_bar_position_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:text="@string/battery_bar_position_bottom" />
</RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/battery_bar_thickness_title"
android:textAppearance="?attr/textAppearanceBody2" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal">
android:text="@string/battery_bar_enabled" />
<LinearLayout
android:id="@+id/battery_bar_base_controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/battery_bar_position_title"
android:textAppearance="?attr/textAppearanceBody2" />
<RadioGroup
android:id="@+id/battery_bar_position_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<RadioButton
android:id="@+id/battery_bar_curved_geometry_length"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:text="@string/battery_bar_curved_geometry_length" />
<RadioButton
android:id="@+id/battery_bar_position_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:text="@string/battery_bar_position_top" />
<RadioButton
android:id="@+id/battery_bar_position_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:text="@string/battery_bar_position_bottom" />
</RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/battery_bar_alignment_title"
android:textAppearance="?attr/textAppearanceBody2" />
<LinearLayout
android:id="@+id/battery_bar_alignment_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/battery_bar_alignment_cell_ltr"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="4dp">
<RadioButton
android:id="@+id/battery_bar_alignment_ltr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="0dp"
android:minWidth="0dp"
android:padding="0dp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="4dp"
android:contentDescription="@null"
app:srcCompat="@drawable/sbt_align_ltr" />
</LinearLayout>
<LinearLayout
android:id="@+id/battery_bar_alignment_cell_center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="4dp">
<RadioButton
android:id="@+id/battery_bar_alignment_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="0dp"
android:minWidth="0dp"
android:padding="0dp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="4dp"
android:contentDescription="@null"
app:srcCompat="@drawable/sbt_align_center" />
</LinearLayout>
<LinearLayout
android:id="@+id/battery_bar_alignment_cell_rtl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="4dp">
<RadioButton
android:id="@+id/battery_bar_alignment_rtl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="0dp"
android:minWidth="0dp"
android:padding="0dp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="4dp"
android:contentDescription="@null"
app:srcCompat="@drawable/sbt_align_rtl" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/battery_bar_thickness_title"
android:textAppearance="?attr/textAppearanceBody2" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/battery_bar_thickness_minus"
@@ -146,21 +233,21 @@
android:layout_width="40dp"
android:layout_height="wrap_content"
android:text="+" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/battery_bar_edge_offset_title"
android:textAppearance="?attr/textAppearanceBody2" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/battery_bar_edge_offset_title"
android:textAppearance="?attr/textAppearanceBody2" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/battery_bar_edge_offset_minus"
@@ -188,166 +275,17 @@
android:layout_width="40dp"
android:layout_height="wrap_content"
android:text="+" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:cardUseCompatPadding="true"
app:strokeColor="@color/sbt_card_outline"
app:strokeWidth="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/battery_bar_alignment_title"
android:textAppearance="?attr/textAppearanceSubtitle1"
android:textAllCaps="true"
android:letterSpacing="0.03"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/battery_bar_alignment_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/battery_bar_alignment_cell_ltr"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="4dp">
<RadioButton
android:id="@+id/battery_bar_alignment_ltr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="0dp"
android:minWidth="0dp"
android:padding="0dp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="4dp"
android:contentDescription="@null"
app:srcCompat="@drawable/sbt_align_ltr" />
</LinearLayout>
<LinearLayout
android:id="@+id/battery_bar_alignment_cell_center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="4dp">
<RadioButton
android:id="@+id/battery_bar_alignment_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="0dp"
android:minWidth="0dp"
android:padding="0dp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="4dp"
android:contentDescription="@null"
app:srcCompat="@drawable/sbt_align_center" />
</LinearLayout>
<LinearLayout
android:id="@+id/battery_bar_alignment_cell_rtl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="4dp">
<RadioButton
android:id="@+id/battery_bar_alignment_rtl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="0dp"
android:minWidth="0dp"
android:padding="0dp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="4dp"
android:contentDescription="@null"
app:srcCompat="@drawable/sbt_align_rtl" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
<LinearLayout
android:id="@+id/battery_bar_scenario_cards_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:cardUseCompatPadding="true"
app:strokeColor="@color/sbt_card_outline"
app:strokeWidth="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:letterSpacing="0.03"
android:text="@string/battery_bar_scenario_overrides_title"
android:textAllCaps="true"
android:textAppearance="?attr/textAppearanceSubtitle1"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/battery_bar_scenario_overrides_hint"
android:textAppearance="?attr/textAppearanceBody2" />
<LinearLayout
android:id="@+id/battery_bar_scenario_overrides_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="vertical" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
android:orientation="vertical" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
+2 -7
View File
@@ -134,8 +134,9 @@
<string name="status_chips_hide_battery_label">Hide charging battery chip (unlocked)</string>
<string name="misc_title">Misc</string>
<string name="battery_bar_title">Battery bar</string>
<string name="battery_bar_master_toggle_title">Master toggle</string>
<string name="battery_bar_base_settings_title">Base settings</string>
<string name="battery_bar_enabled">Enable battery bar</string>
<string name="battery_bar_use_base_settings">Use base settings</string>
<string name="battery_bar_position_title">Position</string>
<string name="battery_bar_position_top">Top edge of screen</string>
<string name="battery_bar_position_bottom">Bottom of status bar</string>
@@ -146,15 +147,9 @@
<string name="battery_bar_thickness_title">Thickness (dp)</string>
<string name="battery_bar_edge_offset_title">Edge offset (dp)</string>
<string name="battery_bar_curved_geometry_length">Follow screen edges</string>
<string name="battery_bar_scenario_overrides_title">Scenario overrides</string>
<string name="battery_bar_scenario_overrides_hint">Optional geometry overrides. Disabled scenarios use the default geometry above.</string>
<string name="battery_bar_scenario_group_unlocked">Unlocked</string>
<string name="battery_bar_scenario_group_transparent">Transparent statusbar</string>
<string name="battery_bar_scenario_group_fullscreen">Fullscreen</string>
<string name="battery_bar_lockscreen_override">Lockscreen</string>
<string name="battery_bar_edit_override">Edit</string>
<string name="battery_bar_override_dialog_title">Edit %1$s geometry</string>
<string name="battery_bar_override_summary">%1$s, %2$s, %3$ddp thick</string>
<string name="battery_bar_mapping_title">Battery mapping</string>
<string name="battery_bar_mapping_min_label">...0 at %1$d%%</string>
<string name="battery_bar_mapping_max_label">...full at %1$d%%</string>