Add clock size controls and logical clock collisions

This commit is contained in:
ajp_anton
2026-06-08 03:28:56 +00:00
parent 805d12c62e
commit cb32644cc8
14 changed files with 293 additions and 43 deletions
@@ -22,6 +22,7 @@ final class ClockLayout {
private final boolean fixedPlacement; private final boolean fixedPlacement;
private final int width; private final int width;
private final int height; private final int height;
private final float textSizePx;
private int placedLeft; private int placedLeft;
private ClockLayout( private ClockLayout(
@@ -33,7 +34,8 @@ final class ClockLayout {
int placedLeft, int placedLeft,
boolean fixedPlacement, boolean fixedPlacement,
int width, int width,
int height int height,
float textSizePx
) { ) {
this.source = source; this.source = source;
this.model = model; this.model = model;
@@ -44,6 +46,7 @@ final class ClockLayout {
this.fixedPlacement = fixedPlacement; this.fixedPlacement = fixedPlacement;
this.width = width; this.width = width;
this.height = height; this.height = height;
this.textSizePx = textSizePx;
} }
static ClockLayout measure( static ClockLayout measure(
@@ -54,7 +57,8 @@ final class ClockLayout {
int rootWidth, int rootWidth,
Bounds cutoutBounds, Bounds cutoutBounds,
boolean middleAutoNearestSide, boolean middleAutoNearestSide,
AnchorSide middleSide AnchorSide middleSide,
float textSizePx
) { ) {
if (source == null || model == null || model.rows.isEmpty()) { if (source == null || model == null || model.rows.isEmpty()) {
return null; return null;
@@ -64,6 +68,7 @@ final class ClockLayout {
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); ViewGroup.LayoutParams.WRAP_CONTENT));
ClockProxyRenderer.copyTextStyleIfChanged(source, probe); ClockProxyRenderer.copyTextStyleIfChanged(source, probe);
applyTextSizeOverride(probe, textSizePx);
ArrayList<MeasuredClockRow> measuredRows = new ArrayList<>(); ArrayList<MeasuredClockRow> measuredRows = new ArrayList<>();
for (int i = 0; i < model.rows.size(); i++) { for (int i = 0; i < model.rows.size(); i++) {
ClockLayoutTextFactory.Row row = model.rows.get(i); ClockLayoutTextFactory.Row row = model.rows.get(i);
@@ -121,7 +126,8 @@ final class ClockLayout {
0, 0,
false, false,
alignment.width, alignment.width,
bounds.height); bounds.height,
effectiveTextSize(source, textSizePx));
} }
static ClockLayout simpleText( static ClockLayout simpleText(
@@ -172,7 +178,8 @@ final class ClockLayout {
0, 0,
false, false,
width, width,
measured.height); measured.height,
source.getTextSize());
} }
static int centeredTextBaseline(TextView source, int containerHeight) { static int centeredTextBaseline(TextView source, int containerHeight) {
@@ -338,7 +345,8 @@ final class ClockLayout {
bounds.left, bounds.left,
true, true,
bounds.width, bounds.width,
bounds.height); bounds.height,
textSizePx);
} }
private static void addSplitSegment( private static void addSplitSegment(
@@ -493,7 +501,26 @@ final class ClockLayout {
ClockPlacement placement() { ClockPlacement placement() {
String description = model != null ? model.contentDescription : String.valueOf(source.getText()); String description = model != null ? model.contentDescription : String.valueOf(source.getText());
return new ClockPlacement(source, description, rows, new Bounds(placedLeft, top, width, height)); return new ClockPlacement(
source,
description,
rows,
new Bounds(placedLeft, top, width, height),
android.graphics.Color.TRANSPARENT,
textSizePx);
}
private static void applyTextSizeOverride(TextView view, float textSizePx) {
if (view != null && textSizePx > 0f && view.getTextSize() != textSizePx) {
view.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, textSizePx);
}
}
private static float effectiveTextSize(TextView source, float textSizePx) {
if (textSizePx > 0f) {
return textSizePx;
}
return source != null ? source.getTextSize() : 0f;
} }
private record MeasuredClockRow( private record MeasuredClockRow(
@@ -51,7 +51,7 @@ final class ClockProxyRenderer {
for (int i = 0; i < placement.rows.size(); i++) { for (int i = 0; i < placement.rows.size(); i++) {
ClockRow row = placement.rows.get(i); ClockRow row = placement.rows.get(i);
TextView view = views.get(i); TextView view = views.get(i);
if (copyTextStyleIfChanged(placement.source, view)) { if (copyTextStyleIfChanged(placement.source, view, placement.textSizePx)) {
hostChanged = true; hostChanged = true;
} }
if (applyTextColorOverrideIfNeeded(view, placement.textColorOverride)) { if (applyTextColorOverrideIfNeeded(view, placement.textColorOverride)) {
@@ -176,13 +176,18 @@ final class ClockProxyRenderer {
} }
static boolean copyTextStyleIfChanged(TextView source, TextView target) { static boolean copyTextStyleIfChanged(TextView source, TextView target) {
return copyTextStyleIfChanged(source, target, 0f);
}
static boolean copyTextStyleIfChanged(TextView source, TextView target, float textSizePx) {
boolean changed = false; boolean changed = false;
if (target.getCurrentTextColor() != source.getCurrentTextColor()) { if (target.getCurrentTextColor() != source.getCurrentTextColor()) {
target.setTextColor(source.getCurrentTextColor()); target.setTextColor(source.getCurrentTextColor());
changed = true; changed = true;
} }
if (target.getTextSize() != source.getTextSize()) { float desiredTextSize = textSizePx > 0f ? textSizePx : source.getTextSize();
target.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, source.getTextSize()); if (target.getTextSize() != desiredTextSize) {
target.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, desiredTextSize);
changed = true; changed = true;
} }
if (!Objects.equals(target.getTypeface(), source.getTypeface())) { if (!Objects.equals(target.getTypeface(), source.getTypeface())) {
@@ -12,6 +12,7 @@ final class ClockPlacement {
final ArrayList<ClockRow> rows; final ArrayList<ClockRow> rows;
final Bounds bounds; final Bounds bounds;
final int textColorOverride; final int textColorOverride;
final float textSizePx;
ClockPlacement( ClockPlacement(
TextView source, TextView source,
@@ -19,7 +20,7 @@ final class ClockPlacement {
ArrayList<ClockRow> rows, ArrayList<ClockRow> rows,
Bounds bounds Bounds bounds
) { ) {
this(source, contentDescription, rows, bounds, android.graphics.Color.TRANSPARENT); this(source, contentDescription, rows, bounds, android.graphics.Color.TRANSPARENT, 0f);
} }
ClockPlacement( ClockPlacement(
@@ -28,12 +29,24 @@ final class ClockPlacement {
ArrayList<ClockRow> rows, ArrayList<ClockRow> rows,
Bounds bounds, Bounds bounds,
int textColorOverride int textColorOverride
) {
this(source, contentDescription, rows, bounds, textColorOverride, 0f);
}
ClockPlacement(
TextView source,
String contentDescription,
ArrayList<ClockRow> rows,
Bounds bounds,
int textColorOverride,
float textSizePx
) { ) {
this.source = source; this.source = source;
this.contentDescription = contentDescription; this.contentDescription = contentDescription;
this.rows = rows; this.rows = rows;
this.bounds = bounds; this.bounds = bounds;
this.textColorOverride = textColorOverride; this.textColorOverride = textColorOverride;
this.textSizePx = textSizePx;
} }
} }
@@ -145,7 +145,7 @@ public final class UnlockedIconSnapshotRenderController {
return new RenderResult(false, false, false); return new RenderResult(false, false, false);
} }
} }
currentClockLayout = buildClockLayout(root, anchors, settings); currentClockLayout = buildClockLayout(root, anchors, settings, scene);
currentClockGeometry = clockGeometrySignature( currentClockGeometry = clockGeometrySignature(
root, root,
currentClockLayout, currentClockLayout,
@@ -184,7 +184,7 @@ public final class UnlockedIconSnapshotRenderController {
lastCollectedIconsByRoot.put(root, collectedIcons); lastCollectedIconsByRoot.put(root, collectedIcons);
} }
if (currentClockLayout == null && clockEnabledForScene(settings, scene)) { if (currentClockLayout == null && clockEnabledForScene(settings, scene)) {
currentClockLayout = buildClockLayout(root, anchors, settings); currentClockLayout = buildClockLayout(root, anchors, settings, scene);
currentClockGeometry = clockGeometrySignature( currentClockGeometry = clockGeometrySignature(
root, root,
currentClockLayout, currentClockLayout,
@@ -694,13 +694,16 @@ public final class UnlockedIconSnapshotRenderController {
private ClockLayout buildClockLayout( private ClockLayout buildClockLayout(
View root, View root,
RootAnchors anchors, RootAnchors anchors,
SbtSettings settings SbtSettings settings,
SceneKey scene
) { ) {
return buildClockLayout( return buildClockLayout(
root, root,
anchors != null ? anchors.clockView : null, anchors != null ? anchors.clockView : null,
anchors != null ? anchors.clockContainer : null, anchors != null ? anchors.clockContainer : null,
anchors,
settings, settings,
scene,
UnlockedLayoutPlanner.cutoutBounds(ViewGeometry.middleCutout(root), settings != null ? settings.clockMiddleCutoutGapPx : 0)); UnlockedLayoutPlanner.cutoutBounds(ViewGeometry.middleCutout(root), settings != null ? settings.clockMiddleCutoutGapPx : 0));
} }
@@ -708,7 +711,9 @@ public final class UnlockedIconSnapshotRenderController {
View root, View root,
TextView source, TextView source,
View clockContainer, View clockContainer,
RootAnchors anchors,
SbtSettings settings, SbtSettings settings,
SceneKey scene,
Bounds cutoutBounds Bounds cutoutBounds
) { ) {
if (root == null || source == null || settings == null) { if (root == null || source == null || settings == null) {
@@ -723,15 +728,53 @@ public final class UnlockedIconSnapshotRenderController {
return null; return null;
} }
int baselineY = stableClockBaselineY(root, source, clockContainer); int baselineY = stableClockBaselineY(root, source, clockContainer);
int statusbarHeight = statusbarHeightForClock(root, sourceBounds, anchors, scene);
float textSizePx = clockTextSizePx(statusbarHeight, settings, scene);
int verticalOffsetPx = stepsToPx(settings.clockVerticalOffsetPx, statusbarHeight);
return ClockLayout.measure( return ClockLayout.measure(
source, source,
model, model,
UnlockedLayoutPlanner.positionFor(settings.clockPosition), UnlockedLayoutPlanner.positionFor(settings.clockPosition),
baselineY - textOffsetScaler.scale(settings.clockVerticalOffsetPx, source), baselineY - verticalOffsetPx,
root.getWidth(), root.getWidth(),
cutoutBounds, cutoutBounds,
settings.clockMiddleAutoNearestSide, settings.clockMiddleAutoNearestSide,
UnlockedLayoutPlanner.sideFor(settings.clockMiddleCutoutSide)); UnlockedLayoutPlanner.sideFor(settings.clockMiddleCutoutSide),
textSizePx);
}
private float clockTextSizePx(int statusbarHeight, SbtSettings settings, SceneKey scene) {
int steps = scene != null && scene.isLockscreen()
? settings.clockLockTextSizeSteps
: settings.clockTextSizeSteps;
return Math.max(1f, Math.max(1, statusbarHeight) * Math.max(1, steps) / 100f);
}
private int statusbarHeightForClock(
View root,
Bounds sourceBounds,
RootAnchors anchors,
SceneKey scene
) {
int stored = StatusbarHeightStore.get(root);
if (stored > 0) {
return stored;
}
Bounds statusBounds = StatusbarHeightSource.bounds(root, scene, anchors);
if (statusBounds != null && statusBounds.top >= 0 && statusBounds.height > 0) {
return Math.max(1, statusBounds.top + statusBounds.height);
}
if (sourceBounds != null && sourceBounds.top >= 0 && sourceBounds.height > 0) {
return Math.max(1, sourceBounds.top + sourceBounds.height);
}
return Math.max(1, root != null ? root.getHeight() : 1);
}
private int stepsToPx(int steps, int statusbarHeight) {
if (steps == 0 || statusbarHeight <= 0) {
return 0;
}
return Math.round((float) steps * statusbarHeight / 100f);
} }
private Integer clockGeometrySignature( private Integer clockGeometrySignature(
@@ -870,7 +913,8 @@ public final class UnlockedIconSnapshotRenderController {
model.contentDescription, model.contentDescription,
rows, rows,
previousPlacement.bounds, previousPlacement.bounds,
statusBarTintTargetColor()); statusBarTintTargetColor(),
previousPlacement.textSizePx);
} }
private Integer clockSourceGeometrySignature(TextView source) { private Integer clockSourceGeometrySignature(TextView source) {
@@ -930,7 +974,8 @@ public final class UnlockedIconSnapshotRenderController {
currentText.contentDescription, currentText.contentDescription,
rows, rows,
previous.bounds, previous.bounds,
currentText.textColorOverride); currentText.textColorOverride,
currentText.textSizePx);
} }
private ClockRow matchingClockRow(ClockRow previousRow, ArrayList<ClockRow> currentRows) { private ClockRow matchingClockRow(ClockRow previousRow, ArrayList<ClockRow> currentRows) {
@@ -30,6 +30,7 @@ final class UnlockedLayoutBand {
int clipEndPx; int clipEndPx;
private int solverCollisionTop = Integer.MIN_VALUE; private int solverCollisionTop = Integer.MIN_VALUE;
private int solverCollisionHeight = Integer.MIN_VALUE; private int solverCollisionHeight = Integer.MIN_VALUE;
private int solverVerticalScaleHeight = 0;
private UnlockedLayoutBand( private UnlockedLayoutBand(
LayoutItemKind kind, LayoutItemKind kind,
@@ -133,6 +134,11 @@ final class UnlockedLayoutBand {
return this; return this;
} }
UnlockedLayoutBand withSolverVerticalScale(int sourceHeight) {
solverVerticalScaleHeight = Math.max(0, sourceHeight);
return this;
}
static UnlockedLayoutBand dotIcons( static UnlockedLayoutBand dotIcons(
LayoutItemKind kind, LayoutItemKind kind,
ViewGroup host, ViewGroup host,
@@ -373,8 +379,20 @@ final class UnlockedLayoutBand {
ArrayList<Bounds> solverCollisionBoxes() { ArrayList<Bounds> solverCollisionBoxes() {
ArrayList<Bounds> boxes = collisionBoxes(); ArrayList<Bounds> boxes = collisionBoxes();
if (isTextKind() if (solverVerticalScaleHeight > 0 && !boxes.isEmpty()) {
|| solverCollisionTop == Integer.MIN_VALUE ArrayList<Bounds> solverBoxes = new ArrayList<>();
for (Bounds box : boxes) {
int top = pixelToStepFloor(box.top, solverVerticalScaleHeight);
int bottom = pixelToStepCeil(box.top + box.height, solverVerticalScaleHeight);
solverBoxes.add(new Bounds(
box.left,
top,
box.width,
Math.max(1, bottom - top)));
}
return solverBoxes;
}
if (solverCollisionTop == Integer.MIN_VALUE
|| solverCollisionHeight <= 0 || solverCollisionHeight <= 0
|| boxes.isEmpty()) { || boxes.isEmpty()) {
return boxes; return boxes;
@@ -390,6 +408,20 @@ final class UnlockedLayoutBand {
return solverBoxes; return solverBoxes;
} }
private int pixelToStepFloor(int px, int sourceHeight) {
if (sourceHeight <= 0) {
return px;
}
return (int) Math.floor((px * 100.0) / sourceHeight);
}
private int pixelToStepCeil(int px, int sourceHeight) {
if (sourceHeight <= 0) {
return px;
}
return (int) Math.ceil((px * 100.0) / sourceHeight);
}
private Bounds collisionBounds(SnapshotPlacement placement) { private Bounds collisionBounds(SnapshotPlacement placement) {
Bounds relative = relativeCollisionBounds(placement); Bounds relative = relativeCollisionBounds(placement);
Bounds bounds = placement.bounds; Bounds bounds = placement.bounds;
@@ -708,7 +740,8 @@ final class UnlockedLayoutBand {
placement.contentDescription, placement.contentDescription,
rows, rows,
new Bounds(clipLeft, placement.bounds.top, Math.max(0, clipRight - clipLeft), placement.bounds.height), new Bounds(clipLeft, placement.bounds.top, Math.max(0, clipRight - clipLeft), placement.bounds.height),
placement.textColorOverride); placement.textColorOverride,
placement.textSizePx);
} }
private boolean isTextKind() { private boolean isTextKind() {
@@ -21,6 +21,7 @@ import se.ajpanton.statusbartweak.runtime.layoutsolver.PackedStatusBarLayoutSolv
import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle; import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle;
import se.ajpanton.statusbartweak.runtime.mode.SceneKey; import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
import se.ajpanton.statusbartweak.runtime.notifications.NotificationUnreadTracker; import se.ajpanton.statusbartweak.runtime.notifications.NotificationUnreadTracker;
import se.ajpanton.statusbartweak.shell.settings.SbtDefaults;
import se.ajpanton.statusbartweak.shell.settings.SbtSettings; import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
final class UnlockedLayoutPlanner { final class UnlockedLayoutPlanner {
@@ -90,11 +91,15 @@ final class UnlockedLayoutPlanner {
LayoutEdges edges = layoutEdges(root, settings, anchors, scene, aodStatusAnchorBounds); LayoutEdges edges = layoutEdges(root, settings, anchors, scene, aodStatusAnchorBounds);
int statusbarHeight = statusbarHeight(root, anchors, scene, aodStatusContentBounds); int statusbarHeight = statusbarHeight(root, anchors, scene, aodStatusContentBounds);
if (clockEnabledForScene(settings, scene) && clockLayout != null && clockLayout.width() > 0) { if (clockEnabledForScene(settings, scene) && clockLayout != null && clockLayout.width() > 0) {
int clockHeightSteps = clockTextSizeSteps(settings, scene);
bands.add(UnlockedLayoutBand.clock( bands.add(UnlockedLayoutBand.clock(
clockHost, clockHost,
clockLayout, clockLayout,
positionFor(settings.clockPosition), positionFor(settings.clockPosition),
sideFor(settings.clockMiddleCutoutSide))); sideFor(settings.clockMiddleCutoutSide))
.withSolverCollision(
logicalRowTop(clockHeightSteps, settings.clockVerticalOffsetPx),
clockHeightSteps));
} }
ClockLayout carrierLayout = carrierLayout( ClockLayout carrierLayout = carrierLayout(
root, root,
@@ -109,7 +114,8 @@ final class UnlockedLayoutPlanner {
carrierHost, carrierHost,
carrierLayout, carrierLayout,
positionFor(settings.layoutCarrierPosition), positionFor(settings.layoutCarrierPosition),
sideFor(settings.layoutCarrierMiddleSide))); sideFor(settings.layoutCarrierMiddleSide))
.withSolverVerticalScale(statusbarHeight));
} }
int statusCount = statusCountForScene(settings, scene); int statusCount = statusCountForScene(settings, scene);
if (scene != null && scene.isAod() && !isUsableAodAnchor(aodStatusAnchorBounds)) { if (scene != null && scene.isAod() && !isUsableAodAnchor(aodStatusAnchorBounds)) {
@@ -147,14 +153,14 @@ final class UnlockedLayoutPlanner {
placements, placements,
stepsToPx(verticalOffsetSteps, statusbarHeight)); stepsToPx(verticalOffsetSteps, statusbarHeight));
if (!placements.isEmpty()) { if (!placements.isEmpty()) {
bands.add(UnlockedLayoutBand.icons( UnlockedLayoutBand band = UnlockedLayoutBand.icons(
LayoutItemKind.STATUS, LayoutItemKind.STATUS,
statusHost, statusHost,
statusRenderer, statusRenderer,
placements, placements,
positionFor(stringAt(positions, i, settings.layoutStatusPosition)), positionFor(stringAt(positions, i, settings.layoutStatusPosition)),
sideFor(stringAt(middleSides, i, settings.layoutStatusMiddleSide))) sideFor(stringAt(middleSides, i, settings.layoutStatusMiddleSide)));
.withSolverCollision( bands.add(band.withSolverCollision(
logicalRowTop(statusHeightSteps, verticalOffsetSteps), logicalRowTop(statusHeightSteps, verticalOffsetSteps),
statusHeightSteps)); statusHeightSteps));
} }
@@ -200,7 +206,7 @@ final class UnlockedLayoutPlanner {
if (!placements.isEmpty()) { if (!placements.isEmpty()) {
LayoutPosition position = positionFor(stringAt(positions, i, settings.layoutNotifPosition)); LayoutPosition position = positionFor(stringAt(positions, i, settings.layoutNotifPosition));
AnchorSide middleSide = sideFor(stringAt(middleSides, i, settings.layoutNotifMiddleSide)); AnchorSide middleSide = sideFor(stringAt(middleSides, i, settings.layoutNotifMiddleSide));
bands.add(dotNotificationScene UnlockedLayoutBand band = dotNotificationScene
? UnlockedLayoutBand.dotIcons( ? UnlockedLayoutBand.dotIcons(
LayoutItemKind.NOTIFICATIONS, LayoutItemKind.NOTIFICATIONS,
notificationHost, notificationHost,
@@ -208,17 +214,14 @@ final class UnlockedLayoutPlanner {
placements, placements,
position, position,
middleSide) middleSide)
.withSolverCollision(
logicalRowTop(notificationHeightSteps, verticalOffsetSteps),
notificationHeightSteps)
: UnlockedLayoutBand.icons( : UnlockedLayoutBand.icons(
LayoutItemKind.NOTIFICATIONS, LayoutItemKind.NOTIFICATIONS,
notificationHost, notificationHost,
notificationRenderer, notificationRenderer,
placements, placements,
position, position,
middleSide) middleSide);
.withSolverCollision( bands.add(band.withSolverCollision(
logicalRowTop(notificationHeightSteps, verticalOffsetSteps), logicalRowTop(notificationHeightSteps, verticalOffsetSteps),
notificationHeightSteps)); notificationHeightSteps));
} }
@@ -263,10 +266,17 @@ final class UnlockedLayoutPlanner {
return new LayoutPlan(null, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), null); return new LayoutPlan(null, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), null);
} }
ArrayList<LayoutItemKind> itemOrder = orderedKinds(settings.layoutItemOrder); ArrayList<LayoutItemKind> itemOrder = orderedKinds(settings.layoutItemOrder);
splitClockIfNeeded(root, bands, itemOrder, clockCutoutBounds, settings); splitClockIfNeeded(root, bands, itemOrder, clockCutoutBounds, settings, scene);
sortBandsForItemOrder(bands, itemOrder); sortBandsForItemOrder(bands, itemOrder);
int itemPadding = Math.max(0, settings.layoutItemPaddingPx); int itemPadding = Math.max(0, settings.layoutItemPaddingPx);
solveWithPackedLayout(root, edges, bands, layoutCutoutBounds, settings, itemPadding, scene); solveWithPackedLayout(
root,
edges,
bands,
layoutCutoutBounds,
settings,
itemPadding,
scene);
ArrayList<SnapshotPlacement> statusPlacements = new ArrayList<>(); ArrayList<SnapshotPlacement> statusPlacements = new ArrayList<>();
ArrayList<SnapshotPlacement> notificationPlacements = new ArrayList<>(); ArrayList<SnapshotPlacement> notificationPlacements = new ArrayList<>();
@@ -1120,6 +1130,15 @@ final class UnlockedLayoutPlanner {
return Math.max(1, height); return Math.max(1, height);
} }
private int clockTextSizeSteps(SbtSettings settings, SceneKey scene) {
if (settings == null) {
return SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT;
}
return scene != null && scene.isLockscreen()
? settings.clockLockTextSizeSteps
: settings.clockTextSizeSteps;
}
private int statusIconHeightSteps(SbtSettings settings, SceneKey scene) { private int statusIconHeightSteps(SbtSettings settings, SceneKey scene) {
if (scene != null && scene.isLockscreen()) { if (scene != null && scene.isLockscreen()) {
return settings.layoutStatusLockIconHeightSteps; return settings.layoutStatusLockIconHeightSteps;
@@ -1260,7 +1279,8 @@ final class UnlockedLayoutPlanner {
ArrayList<UnlockedLayoutBand> bands, ArrayList<UnlockedLayoutBand> bands,
ArrayList<LayoutItemKind> itemOrder, ArrayList<LayoutItemKind> itemOrder,
Bounds cutoutBounds, Bounds cutoutBounds,
SbtSettings settings SbtSettings settings,
SceneKey scene
) { ) {
if (root == null || cutoutBounds == null || bands == null || settings == null) { if (root == null || cutoutBounds == null || bands == null || settings == null) {
return; return;
@@ -1291,16 +1311,23 @@ final class UnlockedLayoutPlanner {
return; return;
} }
bands.remove(index); bands.remove(index);
int clockHeightSteps = clockTextSizeSteps(settings, scene);
bands.add(index, UnlockedLayoutBand.fixedClock( bands.add(index, UnlockedLayoutBand.fixedClock(
clockBand.host, clockBand.host,
splitLayouts.get(1), splitLayouts.get(1),
SplitRegion.RIGHT, SplitRegion.RIGHT,
clockBand.middleSide)); clockBand.middleSide)
.withSolverCollision(
logicalRowTop(clockHeightSteps, settings.clockVerticalOffsetPx),
clockHeightSteps));
bands.add(index, UnlockedLayoutBand.fixedClock( bands.add(index, UnlockedLayoutBand.fixedClock(
clockBand.host, clockBand.host,
splitLayouts.get(0), splitLayouts.get(0),
SplitRegion.LEFT, SplitRegion.LEFT,
clockBand.middleSide)); clockBand.middleSide)
.withSolverCollision(
logicalRowTop(clockHeightSteps, settings.clockVerticalOffsetPx),
clockHeightSteps));
} }
private ArrayList<UnlockedLayoutBand> bandsForPosition( private ArrayList<UnlockedLayoutBand> bandsForPosition(
@@ -1643,7 +1670,8 @@ final class UnlockedLayoutPlanner {
first.contentDescription, first.contentDescription,
rows, rows,
union, union,
first.textColorOverride); first.textColorOverride,
first.textSizePx);
} }
static Bounds cutoutBounds(Rect cutout, int cutoutGap) { static Bounds cutoutBounds(Rect cutout, int cutoutGap) {
@@ -1487,6 +1487,8 @@ final class UnlockedStockSourceCollector {
settings.clockMiddleAutoNearestSide, settings.clockMiddleAutoNearestSide,
settings.clockMiddleCutoutGapPx, settings.clockMiddleCutoutGapPx,
settings.clockVerticalOffsetPx, settings.clockVerticalOffsetPx,
settings.clockTextSizeSteps,
settings.clockLockTextSizeSteps,
settings.clockShowSeconds, settings.clockShowSeconds,
settings.clockShowDatePrefix, settings.clockShowDatePrefix,
settings.clockCustomFormatEnabled, settings.clockCustomFormatEnabled,
@@ -82,6 +82,7 @@ public final class SbtDefaults {
public static final int CLOCK_VERTICAL_OFFSET_PX_DEFAULT = 0; public static final int CLOCK_VERTICAL_OFFSET_PX_DEFAULT = 0;
public static final int CLOCK_VERTICAL_OFFSET_PX_MIN = -99; public static final int CLOCK_VERTICAL_OFFSET_PX_MIN = -99;
public static final int CLOCK_VERTICAL_OFFSET_PX_MAX = 99; public static final int CLOCK_VERTICAL_OFFSET_PX_MAX = 99;
public static final int CLOCK_TEXT_SIZE_STEPS_DEFAULT = 40;
public static final boolean CLOCK_SHOW_SECONDS_DEFAULT = false; public static final boolean CLOCK_SHOW_SECONDS_DEFAULT = false;
public static final boolean CLOCK_SHOW_DATE_PREFIX_DEFAULT = false; public static final boolean CLOCK_SHOW_DATE_PREFIX_DEFAULT = false;
public static final boolean CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT = false; public static final boolean CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT = false;
@@ -94,6 +94,8 @@ public final class SbtSettings {
public static final String KEY_CLOCK_MIDDLE_AUTO_NEAREST_SIDE = "clock_middle_auto_nearest_side"; public static final String KEY_CLOCK_MIDDLE_AUTO_NEAREST_SIDE = "clock_middle_auto_nearest_side";
public static final String KEY_CLOCK_MIDDLE_CUTOUT_GAP_PX = "clock_middle_cutout_gap_px"; public static final String KEY_CLOCK_MIDDLE_CUTOUT_GAP_PX = "clock_middle_cutout_gap_px";
public static final String KEY_CLOCK_VERTICAL_OFFSET_PX = "clock_vertical_offset_px"; public static final String KEY_CLOCK_VERTICAL_OFFSET_PX = "clock_vertical_offset_px";
public static final String KEY_CLOCK_TEXT_SIZE_STEPS = "clock_text_size_steps";
public static final String KEY_CLOCK_LOCK_TEXT_SIZE_STEPS = "layout_lock_clock_text_size_steps";
public static final String KEY_CLOCK_SHOW_SECONDS = "clock_show_seconds"; public static final String KEY_CLOCK_SHOW_SECONDS = "clock_show_seconds";
public static final String KEY_CLOCK_SHOW_DATE_PREFIX = "clock_show_date_prefix"; public static final String KEY_CLOCK_SHOW_DATE_PREFIX = "clock_show_date_prefix";
public static final String KEY_CLOCK_CUSTOM_FORMAT_ENABLED = "clock_custom_format_enabled"; public static final String KEY_CLOCK_CUSTOM_FORMAT_ENABLED = "clock_custom_format_enabled";
@@ -328,6 +330,8 @@ public final class SbtSettings {
public final boolean clockMiddleAutoNearestSide; public final boolean clockMiddleAutoNearestSide;
public final int clockMiddleCutoutGapPx; public final int clockMiddleCutoutGapPx;
public final int clockVerticalOffsetPx; public final int clockVerticalOffsetPx;
public final int clockTextSizeSteps;
public final int clockLockTextSizeSteps;
public final boolean clockShowSeconds; public final boolean clockShowSeconds;
public final boolean clockShowDatePrefix; public final boolean clockShowDatePrefix;
public final boolean clockCustomFormatEnabled; public final boolean clockCustomFormatEnabled;
@@ -458,6 +462,8 @@ public final class SbtSettings {
boolean clockMiddleAutoNearestSide, boolean clockMiddleAutoNearestSide,
int clockMiddleCutoutGapPx, int clockMiddleCutoutGapPx,
int clockVerticalOffsetPx, int clockVerticalOffsetPx,
int clockTextSizeSteps,
int clockLockTextSizeSteps,
boolean clockShowSeconds, boolean clockShowSeconds,
boolean clockShowDatePrefix, boolean clockShowDatePrefix,
boolean clockCustomFormatEnabled, boolean clockCustomFormatEnabled,
@@ -630,6 +636,8 @@ public final class SbtSettings {
clockVerticalOffsetPx, clockVerticalOffsetPx,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX); SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
this.clockTextSizeSteps = clampIconHeightSteps(clockTextSizeSteps);
this.clockLockTextSizeSteps = clampIconHeightSteps(clockLockTextSizeSteps);
this.clockShowSeconds = clockShowSeconds; this.clockShowSeconds = clockShowSeconds;
this.clockShowDatePrefix = clockShowDatePrefix; this.clockShowDatePrefix = clockShowDatePrefix;
this.clockCustomFormatEnabled = clockCustomFormatEnabled; this.clockCustomFormatEnabled = clockCustomFormatEnabled;
@@ -889,6 +897,8 @@ public final class SbtSettings {
SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT, SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.CLOCK_MIDDLE_CUTOUT_GAP_PX_DEFAULT, SbtDefaults.CLOCK_MIDDLE_CUTOUT_GAP_PX_DEFAULT,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT,
SbtDefaults.CLOCK_SHOW_DATE_PREFIX_DEFAULT, SbtDefaults.CLOCK_SHOW_DATE_PREFIX_DEFAULT,
SbtDefaults.CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT, SbtDefaults.CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT,
@@ -1212,6 +1222,10 @@ public final class SbtSettings {
clampInt(prefs.getInt(KEY_CLOCK_VERTICAL_OFFSET_PX, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT), clampInt(prefs.getInt(KEY_CLOCK_VERTICAL_OFFSET_PX, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX), SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
clampIconHeightSteps(prefs.getInt(KEY_CLOCK_TEXT_SIZE_STEPS,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT)),
clampIconHeightSteps(prefs.getInt(KEY_CLOCK_LOCK_TEXT_SIZE_STEPS,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT)),
prefs.getBoolean(KEY_CLOCK_SHOW_SECONDS, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT), prefs.getBoolean(KEY_CLOCK_SHOW_SECONDS, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT),
prefs.getBoolean(KEY_CLOCK_SHOW_DATE_PREFIX, SbtDefaults.CLOCK_SHOW_DATE_PREFIX_DEFAULT), prefs.getBoolean(KEY_CLOCK_SHOW_DATE_PREFIX, SbtDefaults.CLOCK_SHOW_DATE_PREFIX_DEFAULT),
prefs.getBoolean(KEY_CLOCK_CUSTOM_FORMAT_ENABLED, SbtDefaults.CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT), prefs.getBoolean(KEY_CLOCK_CUSTOM_FORMAT_ENABLED, SbtDefaults.CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT),
@@ -1526,6 +1540,10 @@ public final class SbtSettings {
clampInt(bundle.getInt(KEY_CLOCK_VERTICAL_OFFSET_PX, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT), clampInt(bundle.getInt(KEY_CLOCK_VERTICAL_OFFSET_PX, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX), SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
clampIconHeightSteps(bundle.getInt(KEY_CLOCK_TEXT_SIZE_STEPS,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT)),
clampIconHeightSteps(bundle.getInt(KEY_CLOCK_LOCK_TEXT_SIZE_STEPS,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT)),
bundle.getBoolean(KEY_CLOCK_SHOW_SECONDS, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT), bundle.getBoolean(KEY_CLOCK_SHOW_SECONDS, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT),
bundle.getBoolean(KEY_CLOCK_SHOW_DATE_PREFIX, SbtDefaults.CLOCK_SHOW_DATE_PREFIX_DEFAULT), bundle.getBoolean(KEY_CLOCK_SHOW_DATE_PREFIX, SbtDefaults.CLOCK_SHOW_DATE_PREFIX_DEFAULT),
bundle.getBoolean(KEY_CLOCK_CUSTOM_FORMAT_ENABLED, SbtDefaults.CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT), bundle.getBoolean(KEY_CLOCK_CUSTOM_FORMAT_ENABLED, SbtDefaults.CLOCK_CUSTOM_FORMAT_ENABLED_DEFAULT),
@@ -139,6 +139,10 @@ public class SbtSettingsProvider extends ContentProvider {
prefs.getInt(SbtSettings.KEY_CLOCK_MIDDLE_CUTOUT_GAP_PX, SbtDefaults.CLOCK_MIDDLE_CUTOUT_GAP_PX_DEFAULT)); prefs.getInt(SbtSettings.KEY_CLOCK_MIDDLE_CUTOUT_GAP_PX, SbtDefaults.CLOCK_MIDDLE_CUTOUT_GAP_PX_DEFAULT));
out.putInt(SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX, out.putInt(SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX,
prefs.getInt(SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT)); prefs.getInt(SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT));
out.putInt(SbtSettings.KEY_CLOCK_TEXT_SIZE_STEPS,
prefs.getInt(SbtSettings.KEY_CLOCK_TEXT_SIZE_STEPS, SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT));
out.putInt(SbtSettings.KEY_CLOCK_LOCK_TEXT_SIZE_STEPS,
prefs.getInt(SbtSettings.KEY_CLOCK_LOCK_TEXT_SIZE_STEPS, SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT));
out.putBoolean(SbtSettings.KEY_CLOCK_SHOW_SECONDS, out.putBoolean(SbtSettings.KEY_CLOCK_SHOW_SECONDS,
prefs.getBoolean(SbtSettings.KEY_CLOCK_SHOW_SECONDS, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT)); prefs.getBoolean(SbtSettings.KEY_CLOCK_SHOW_SECONDS, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT));
out.putBoolean(SbtSettings.KEY_CLOCK_SHOW_DATE_PREFIX, out.putBoolean(SbtSettings.KEY_CLOCK_SHOW_DATE_PREFIX,
@@ -92,6 +92,7 @@ public final class LayoutFragment extends Fragment {
root.findViewById(R.id.clock_vertical_offset_plus_fast), root.findViewById(R.id.clock_vertical_offset_plus_fast),
root.findViewById(R.id.clock_vertical_offset_reset), root.findViewById(R.id.clock_vertical_offset_reset),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT);
addClockTextSizeControl(root, prefs);
bindStepper(prefs, bindStepper(prefs,
SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX,
root.findViewById(R.id.notif_vertical_offset_input), root.findViewById(R.id.notif_vertical_offset_input),
@@ -226,6 +227,7 @@ public final class LayoutFragment extends Fragment {
countDefault, countDefault,
legacyEnabledDefault); legacyEnabledDefault);
LayoutXmlCardSupport.setIndexedCardTitle(requireContext(), sourceCard, sectionTitleId, 0, count); LayoutXmlCardSupport.setIndexedCardTitle(requireContext(), sourceCard, sectionTitleId, 0, count);
setCompatPadding(sourceCard, count <= 1);
boolean cardsMode = LockedNotificationModeUi.MODE_CARDS.equals( boolean cardsMode = LockedNotificationModeUi.MODE_CARDS.equals(
LockedNotificationModeUi.currentMode(requireContext())); LockedNotificationModeUi.currentMode(requireContext()));
LayoutSectionCopySupport.addDropdownRow( LayoutSectionCopySupport.addDropdownRow(
@@ -273,6 +275,8 @@ public final class LayoutFragment extends Fragment {
middleSideDefault, middleSideDefault,
verticalOffsetDefault, verticalOffsetDefault,
copyTag); copyTag);
setTopMargin(copy, 0);
setCompatPadding(copy, false);
cardsParent.addView(copy, Math.min(insertIndex, cardsParent.getChildCount())); cardsParent.addView(copy, Math.min(insertIndex, cardsParent.getChildCount()));
} }
}; };
@@ -319,6 +323,19 @@ public final class LayoutFragment extends Fragment {
null); null);
} }
private void addClockTextSizeControl(View root, SharedPreferences prefs) {
View row = LayoutXmlCardSupport.directSectionChild(root.findViewById(R.id.clock_position_group));
if (row == null || !(row.getParent() instanceof LinearLayout parent)) {
return;
}
int index = parent.indexOfChild(row);
parent.addView(iconHeightControl(
prefs,
SbtSettings.KEY_CLOCK_TEXT_SIZE_STEPS,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
R.string.layout_clock_text_size_steps), Math.max(0, index));
}
private void addChipHeightControl(View root, SharedPreferences prefs) { private void addChipHeightControl(View root, SharedPreferences prefs) {
View offsetInput = root.findViewById(R.id.chip_vertical_offset_input); View offsetInput = root.findViewById(R.id.chip_vertical_offset_input);
if (offsetInput == null) { if (offsetInput == null) {
@@ -473,6 +490,20 @@ public final class LayoutFragment extends Fragment {
return null; return null;
} }
private void setTopMargin(View view, int topDp) {
if (view == null || !(view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams params)) {
return;
}
params.topMargin = ViewTreeSupport.dp(requireContext(), topDp);
view.setLayoutParams(params);
}
private void setCompatPadding(View view, boolean enabled) {
if (view instanceof MaterialCardView card) {
card.setUseCompatPadding(enabled);
}
}
private void removeGeneratedCopyCards(@Nullable LinearLayout parent, String tag) { private void removeGeneratedCopyCards(@Nullable LinearLayout parent, String tag) {
if (parent == null) { if (parent == null) {
return; return;
@@ -246,12 +246,14 @@ final class LayoutSectionCopySupport {
"layout_lock_clock_middle_auto_nearest_side", "layout_lock_clock_middle_auto_nearest_side",
"layout_lock_clock_middle_side", "layout_lock_clock_middle_side",
"layout_lock_clock_vertical_offset_px", "layout_lock_clock_vertical_offset_px",
SbtSettings.KEY_CLOCK_LOCK_TEXT_SIZE_STEPS,
null, null,
SbtDefaults.CLOCK_ENABLED_LOCKSCREEN_DEFAULT, SbtDefaults.CLOCK_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.CLOCK_POSITION_DEFAULT, SbtDefaults.CLOCK_POSITION_DEFAULT,
SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT, SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT, SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
1); 1);
} }
return new KeySet( return new KeySet(
@@ -260,12 +262,14 @@ final class LayoutSectionCopySupport {
SbtSettings.KEY_CLOCK_MIDDLE_AUTO_NEAREST_SIDE, SbtSettings.KEY_CLOCK_MIDDLE_AUTO_NEAREST_SIDE,
SbtSettings.KEY_CLOCK_MIDDLE_CUTOUT_SIDE, SbtSettings.KEY_CLOCK_MIDDLE_CUTOUT_SIDE,
SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX, SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX,
SbtSettings.KEY_CLOCK_TEXT_SIZE_STEPS,
null, null,
SbtDefaults.CLOCK_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.CLOCK_ENABLED_UNLOCKED_DEFAULT,
SbtDefaults.CLOCK_POSITION_DEFAULT, SbtDefaults.CLOCK_POSITION_DEFAULT,
SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT, SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT, SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
1); 1);
} }
@@ -114,6 +114,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT, SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT,
sceneKey("clock_vertical_offset_px"), sceneKey("clock_vertical_offset_px"),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT);
addClockTextSizeControl(context, prefs, clockCard);
LayoutSectionCopySupport.addDropdown( LayoutSectionCopySupport.addDropdown(
context, context,
prefs, prefs,
@@ -357,10 +358,11 @@ abstract class LockedSceneLayoutFragment extends Fragment {
countKey, countKey,
count, count,
rebuild[0]); rebuild[0]);
setCompatPadding(primary, count <= 1);
addCopyDropdownToCard(context, prefs, primary, copySection, cardsMode, refresh); addCopyDropdownToCard(context, prefs, primary, copySection, cardsMode, refresh);
wrapper.addView(primary); wrapper.addView(primary);
for (int i = 1; i < count; i++) { for (int i = 1; i < count; i++) {
wrapper.addView(configuredIconContainerCard( View copy = configuredIconContainerCard(
context, context,
prefs, prefs,
cardId, cardId,
@@ -390,7 +392,10 @@ abstract class LockedSceneLayoutFragment extends Fragment {
null, null,
null, null,
count, count,
null)); null);
setTopMargin(context, copy, 0);
setCompatPadding(copy, false);
wrapper.addView(copy);
} }
}; };
rebuild[0].run(); rebuild[0].run();
@@ -513,6 +518,25 @@ abstract class LockedSceneLayoutFragment extends Fragment {
return card; return card;
} }
private void addClockTextSizeControl(Context context, SharedPreferences prefs, View card) {
View row = LayoutXmlCardSupport.directSectionChild(
card != null ? card.findViewById(R.id.clock_position_group) : null);
if (row == null || !(row.getParent() instanceof LinearLayout parent)) {
return;
}
int index = parent.indexOfChild(row);
parent.addView(
sizeStepper(
context,
prefs,
R.string.layout_clock_text_size_steps,
SbtSettings.KEY_CLOCK_LOCK_TEXT_SIZE_STEPS,
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
Math.max(0, index));
}
private void configureSingleEnabledCheckbox( private void configureSingleEnabledCheckbox(
View root, View root,
SharedPreferences prefs, SharedPreferences prefs,
@@ -839,6 +863,20 @@ abstract class LockedSceneLayoutFragment extends Fragment {
return content instanceof LinearLayout layout ? layout : null; return content instanceof LinearLayout layout ? layout : null;
} }
private void setTopMargin(Context context, View view, int topDp) {
if (view == null || !(view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams params)) {
return;
}
params.topMargin = ViewTreeSupport.dp(context, topDp);
view.setLayoutParams(params);
}
private void setCompatPadding(View view, boolean enabled) {
if (view instanceof com.google.android.material.card.MaterialCardView card) {
card.setUseCompatPadding(enabled);
}
}
private View outlinedCard(Context context, int titleId, View content) { private View outlinedCard(Context context, int titleId, View content) {
return ViewTreeSupport.outlinedCard( return ViewTreeSupport.outlinedCard(
context, context,
+1
View File
@@ -198,6 +198,7 @@
<string name="layout_copy_from">Copy from</string> <string name="layout_copy_from">Copy from</string>
<string name="layout_icon_container_count">Number of containers</string> <string name="layout_icon_container_count">Number of containers</string>
<string name="layout_icon_height_steps">Icon height (% of statusbar)</string> <string name="layout_icon_height_steps">Icon height (% of statusbar)</string>
<string name="layout_clock_text_size_steps">Clock text size (% of statusbar)</string>
<string name="layout_chip_height_steps">Chip height (% of statusbar)</string> <string name="layout_chip_height_steps">Chip height (% of statusbar)</string>
<string name="layout_locked_notifications_title">Locked notifications mode</string> <string name="layout_locked_notifications_title">Locked notifications mode</string>
<string name="layout_locked_notifications_hint">Mirrors the Samsung notification display style for AOD and lockscreen.</string> <string name="layout_locked_notifications_hint">Mirrors the Samsung notification display style for AOD and lockscreen.</string>