diff --git a/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java b/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java index e01daa4..f179551 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/runtime/features/battery/BatteryBarController.java @@ -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( diff --git a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/BatteryBarGeometry.java b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/BatteryBarGeometry.java index 5eda403..3d9a91f 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/BatteryBarGeometry.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/BatteryBarGeometry.java @@ -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() { diff --git a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtDefaults.java b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtDefaults.java index 7e4dc0b..809f372 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtDefaults.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtDefaults.java @@ -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; diff --git a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettings.java b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettings.java index b7c9d9d..a190bcd 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettings.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettings.java @@ -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 batteryBarGeometryOverrideEnabledScenarios; public final Map batteryBarGeometryOverrides; + public final Map batteryBarScenarioEnabled; public final int batteryBarMinLevel; public final int batteryBarMaxLevel; public final String batteryBarDefaultDischargeColor; @@ -449,6 +456,7 @@ public final class SbtSettings { String batteryBarCurvedGeometryMode, Set batteryBarGeometryOverrideEnabledScenarios, Map batteryBarGeometryOverrides, + Map 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 readBatteryBarScenarioEnabledMapFromPrefs(SharedPreferences prefs) { + if (prefs == null) { + return Collections.emptyMap(); + } + HashMap 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 readBatteryBarScenarioEnabledMapFromBundle(Bundle bundle) { + if (bundle == null) { + return Collections.emptyMap(); + } + HashMap 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 sanitizeBatteryBarScenarioSet(Set 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 sanitizeBatteryBarScenarioEnabledMap(Map source) { + if (source == null || source.isEmpty()) { + return Collections.emptyMap(); + } + HashMap result = new HashMap<>(); + for (Map.Entry 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; diff --git a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettingsProvider.java b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettingsProvider.java index a65372e..5c01707 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettingsProvider.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/shell/settings/SbtSettingsProvider.java @@ -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)); diff --git a/app/src/main/java/se/ajpanton/statusbartweak/shell/ui/BatteryBarFragment.java b/app/src/main/java/se/ajpanton/statusbartweak/shell/ui/BatteryBarFragment.java index cd88156..39411ba 100644 --- a/app/src/main/java/se/ajpanton/statusbartweak/shell/ui/BatteryBarFragment.java +++ b/app/src/main/java/se/ajpanton/statusbartweak/shell/ui/BatteryBarFragment.java @@ -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, diff --git a/app/src/main/res/layout/fragment_battery_bar.xml b/app/src/main/res/layout/fragment_battery_bar.xml index 77ca2ed..2306f14 100644 --- a/app/src/main/res/layout/fragment_battery_bar.xml +++ b/app/src/main/res/layout/fragment_battery_bar.xml @@ -17,38 +17,6 @@ android:text="@string/battery_bar_title" android:textAppearance="?attr/textAppearanceHeadline5" /> - - - - - - - - - - - - - - - - - - - - - - + android:text="@string/battery_bar_enabled" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:orientation="vertical" /> Hide charging battery chip (unlocked) Misc Battery bar - Master toggle + Base settings Enable battery bar + Use base settings Position Top edge of screen Bottom of status bar @@ -146,15 +147,9 @@ Thickness (dp) Edge offset (dp) Follow screen edges - Scenario overrides - Optional geometry overrides. Disabled scenarios use the default geometry above. - Unlocked Transparent statusbar Fullscreen Lockscreen - Edit - Edit %1$s geometry - %1$s, %2$s, %3$ddp thick Battery mapping ...0 at %1$d%% ...full at %1$d%%