Add clock size controls and logical clock collisions
This commit is contained in:
@@ -22,6 +22,7 @@ final class ClockLayout {
|
||||
private final boolean fixedPlacement;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final float textSizePx;
|
||||
private int placedLeft;
|
||||
|
||||
private ClockLayout(
|
||||
@@ -33,7 +34,8 @@ final class ClockLayout {
|
||||
int placedLeft,
|
||||
boolean fixedPlacement,
|
||||
int width,
|
||||
int height
|
||||
int height,
|
||||
float textSizePx
|
||||
) {
|
||||
this.source = source;
|
||||
this.model = model;
|
||||
@@ -44,6 +46,7 @@ final class ClockLayout {
|
||||
this.fixedPlacement = fixedPlacement;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.textSizePx = textSizePx;
|
||||
}
|
||||
|
||||
static ClockLayout measure(
|
||||
@@ -54,7 +57,8 @@ final class ClockLayout {
|
||||
int rootWidth,
|
||||
Bounds cutoutBounds,
|
||||
boolean middleAutoNearestSide,
|
||||
AnchorSide middleSide
|
||||
AnchorSide middleSide,
|
||||
float textSizePx
|
||||
) {
|
||||
if (source == null || model == null || model.rows.isEmpty()) {
|
||||
return null;
|
||||
@@ -64,6 +68,7 @@ final class ClockLayout {
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
ClockProxyRenderer.copyTextStyleIfChanged(source, probe);
|
||||
applyTextSizeOverride(probe, textSizePx);
|
||||
ArrayList<MeasuredClockRow> measuredRows = new ArrayList<>();
|
||||
for (int i = 0; i < model.rows.size(); i++) {
|
||||
ClockLayoutTextFactory.Row row = model.rows.get(i);
|
||||
@@ -121,7 +126,8 @@ final class ClockLayout {
|
||||
0,
|
||||
false,
|
||||
alignment.width,
|
||||
bounds.height);
|
||||
bounds.height,
|
||||
effectiveTextSize(source, textSizePx));
|
||||
}
|
||||
|
||||
static ClockLayout simpleText(
|
||||
@@ -172,7 +178,8 @@ final class ClockLayout {
|
||||
0,
|
||||
false,
|
||||
width,
|
||||
measured.height);
|
||||
measured.height,
|
||||
source.getTextSize());
|
||||
}
|
||||
|
||||
static int centeredTextBaseline(TextView source, int containerHeight) {
|
||||
@@ -338,7 +345,8 @@ final class ClockLayout {
|
||||
bounds.left,
|
||||
true,
|
||||
bounds.width,
|
||||
bounds.height);
|
||||
bounds.height,
|
||||
textSizePx);
|
||||
}
|
||||
|
||||
private static void addSplitSegment(
|
||||
@@ -493,7 +501,26 @@ final class ClockLayout {
|
||||
|
||||
ClockPlacement placement() {
|
||||
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(
|
||||
|
||||
@@ -51,7 +51,7 @@ final class ClockProxyRenderer {
|
||||
for (int i = 0; i < placement.rows.size(); i++) {
|
||||
ClockRow row = placement.rows.get(i);
|
||||
TextView view = views.get(i);
|
||||
if (copyTextStyleIfChanged(placement.source, view)) {
|
||||
if (copyTextStyleIfChanged(placement.source, view, placement.textSizePx)) {
|
||||
hostChanged = true;
|
||||
}
|
||||
if (applyTextColorOverrideIfNeeded(view, placement.textColorOverride)) {
|
||||
@@ -176,13 +176,18 @@ final class ClockProxyRenderer {
|
||||
}
|
||||
|
||||
static boolean copyTextStyleIfChanged(TextView source, TextView target) {
|
||||
return copyTextStyleIfChanged(source, target, 0f);
|
||||
}
|
||||
|
||||
static boolean copyTextStyleIfChanged(TextView source, TextView target, float textSizePx) {
|
||||
boolean changed = false;
|
||||
if (target.getCurrentTextColor() != source.getCurrentTextColor()) {
|
||||
target.setTextColor(source.getCurrentTextColor());
|
||||
changed = true;
|
||||
}
|
||||
if (target.getTextSize() != source.getTextSize()) {
|
||||
target.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, source.getTextSize());
|
||||
float desiredTextSize = textSizePx > 0f ? textSizePx : source.getTextSize();
|
||||
if (target.getTextSize() != desiredTextSize) {
|
||||
target.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, desiredTextSize);
|
||||
changed = true;
|
||||
}
|
||||
if (!Objects.equals(target.getTypeface(), source.getTypeface())) {
|
||||
|
||||
@@ -12,6 +12,7 @@ final class ClockPlacement {
|
||||
final ArrayList<ClockRow> rows;
|
||||
final Bounds bounds;
|
||||
final int textColorOverride;
|
||||
final float textSizePx;
|
||||
|
||||
ClockPlacement(
|
||||
TextView source,
|
||||
@@ -19,7 +20,7 @@ final class ClockPlacement {
|
||||
ArrayList<ClockRow> rows,
|
||||
Bounds bounds
|
||||
) {
|
||||
this(source, contentDescription, rows, bounds, android.graphics.Color.TRANSPARENT);
|
||||
this(source, contentDescription, rows, bounds, android.graphics.Color.TRANSPARENT, 0f);
|
||||
}
|
||||
|
||||
ClockPlacement(
|
||||
@@ -28,12 +29,24 @@ final class ClockPlacement {
|
||||
ArrayList<ClockRow> rows,
|
||||
Bounds bounds,
|
||||
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.contentDescription = contentDescription;
|
||||
this.rows = rows;
|
||||
this.bounds = bounds;
|
||||
this.textColorOverride = textColorOverride;
|
||||
this.textSizePx = textSizePx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+52
-7
@@ -145,7 +145,7 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
return new RenderResult(false, false, false);
|
||||
}
|
||||
}
|
||||
currentClockLayout = buildClockLayout(root, anchors, settings);
|
||||
currentClockLayout = buildClockLayout(root, anchors, settings, scene);
|
||||
currentClockGeometry = clockGeometrySignature(
|
||||
root,
|
||||
currentClockLayout,
|
||||
@@ -184,7 +184,7 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
lastCollectedIconsByRoot.put(root, collectedIcons);
|
||||
}
|
||||
if (currentClockLayout == null && clockEnabledForScene(settings, scene)) {
|
||||
currentClockLayout = buildClockLayout(root, anchors, settings);
|
||||
currentClockLayout = buildClockLayout(root, anchors, settings, scene);
|
||||
currentClockGeometry = clockGeometrySignature(
|
||||
root,
|
||||
currentClockLayout,
|
||||
@@ -694,13 +694,16 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
private ClockLayout buildClockLayout(
|
||||
View root,
|
||||
RootAnchors anchors,
|
||||
SbtSettings settings
|
||||
SbtSettings settings,
|
||||
SceneKey scene
|
||||
) {
|
||||
return buildClockLayout(
|
||||
root,
|
||||
anchors != null ? anchors.clockView : null,
|
||||
anchors != null ? anchors.clockContainer : null,
|
||||
anchors,
|
||||
settings,
|
||||
scene,
|
||||
UnlockedLayoutPlanner.cutoutBounds(ViewGeometry.middleCutout(root), settings != null ? settings.clockMiddleCutoutGapPx : 0));
|
||||
}
|
||||
|
||||
@@ -708,7 +711,9 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
View root,
|
||||
TextView source,
|
||||
View clockContainer,
|
||||
RootAnchors anchors,
|
||||
SbtSettings settings,
|
||||
SceneKey scene,
|
||||
Bounds cutoutBounds
|
||||
) {
|
||||
if (root == null || source == null || settings == null) {
|
||||
@@ -723,15 +728,53 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
return null;
|
||||
}
|
||||
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(
|
||||
source,
|
||||
model,
|
||||
UnlockedLayoutPlanner.positionFor(settings.clockPosition),
|
||||
baselineY - textOffsetScaler.scale(settings.clockVerticalOffsetPx, source),
|
||||
baselineY - verticalOffsetPx,
|
||||
root.getWidth(),
|
||||
cutoutBounds,
|
||||
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(
|
||||
@@ -870,7 +913,8 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
model.contentDescription,
|
||||
rows,
|
||||
previousPlacement.bounds,
|
||||
statusBarTintTargetColor());
|
||||
statusBarTintTargetColor(),
|
||||
previousPlacement.textSizePx);
|
||||
}
|
||||
|
||||
private Integer clockSourceGeometrySignature(TextView source) {
|
||||
@@ -930,7 +974,8 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
currentText.contentDescription,
|
||||
rows,
|
||||
previous.bounds,
|
||||
currentText.textColorOverride);
|
||||
currentText.textColorOverride,
|
||||
currentText.textSizePx);
|
||||
}
|
||||
|
||||
private ClockRow matchingClockRow(ClockRow previousRow, ArrayList<ClockRow> currentRows) {
|
||||
|
||||
+36
-3
@@ -30,6 +30,7 @@ final class UnlockedLayoutBand {
|
||||
int clipEndPx;
|
||||
private int solverCollisionTop = Integer.MIN_VALUE;
|
||||
private int solverCollisionHeight = Integer.MIN_VALUE;
|
||||
private int solverVerticalScaleHeight = 0;
|
||||
|
||||
private UnlockedLayoutBand(
|
||||
LayoutItemKind kind,
|
||||
@@ -133,6 +134,11 @@ final class UnlockedLayoutBand {
|
||||
return this;
|
||||
}
|
||||
|
||||
UnlockedLayoutBand withSolverVerticalScale(int sourceHeight) {
|
||||
solverVerticalScaleHeight = Math.max(0, sourceHeight);
|
||||
return this;
|
||||
}
|
||||
|
||||
static UnlockedLayoutBand dotIcons(
|
||||
LayoutItemKind kind,
|
||||
ViewGroup host,
|
||||
@@ -373,8 +379,20 @@ final class UnlockedLayoutBand {
|
||||
|
||||
ArrayList<Bounds> solverCollisionBoxes() {
|
||||
ArrayList<Bounds> boxes = collisionBoxes();
|
||||
if (isTextKind()
|
||||
|| solverCollisionTop == Integer.MIN_VALUE
|
||||
if (solverVerticalScaleHeight > 0 && !boxes.isEmpty()) {
|
||||
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
|
||||
|| boxes.isEmpty()) {
|
||||
return boxes;
|
||||
@@ -390,6 +408,20 @@ final class UnlockedLayoutBand {
|
||||
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) {
|
||||
Bounds relative = relativeCollisionBounds(placement);
|
||||
Bounds bounds = placement.bounds;
|
||||
@@ -708,7 +740,8 @@ final class UnlockedLayoutBand {
|
||||
placement.contentDescription,
|
||||
rows,
|
||||
new Bounds(clipLeft, placement.bounds.top, Math.max(0, clipRight - clipLeft), placement.bounds.height),
|
||||
placement.textColorOverride);
|
||||
placement.textColorOverride,
|
||||
placement.textSizePx);
|
||||
}
|
||||
|
||||
private boolean isTextKind() {
|
||||
|
||||
+49
-21
@@ -21,6 +21,7 @@ import se.ajpanton.statusbartweak.runtime.layoutsolver.PackedStatusBarLayoutSolv
|
||||
import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle;
|
||||
import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
|
||||
import se.ajpanton.statusbartweak.runtime.notifications.NotificationUnreadTracker;
|
||||
import se.ajpanton.statusbartweak.shell.settings.SbtDefaults;
|
||||
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
||||
|
||||
final class UnlockedLayoutPlanner {
|
||||
@@ -90,11 +91,15 @@ final class UnlockedLayoutPlanner {
|
||||
LayoutEdges edges = layoutEdges(root, settings, anchors, scene, aodStatusAnchorBounds);
|
||||
int statusbarHeight = statusbarHeight(root, anchors, scene, aodStatusContentBounds);
|
||||
if (clockEnabledForScene(settings, scene) && clockLayout != null && clockLayout.width() > 0) {
|
||||
int clockHeightSteps = clockTextSizeSteps(settings, scene);
|
||||
bands.add(UnlockedLayoutBand.clock(
|
||||
clockHost,
|
||||
clockLayout,
|
||||
positionFor(settings.clockPosition),
|
||||
sideFor(settings.clockMiddleCutoutSide)));
|
||||
sideFor(settings.clockMiddleCutoutSide))
|
||||
.withSolverCollision(
|
||||
logicalRowTop(clockHeightSteps, settings.clockVerticalOffsetPx),
|
||||
clockHeightSteps));
|
||||
}
|
||||
ClockLayout carrierLayout = carrierLayout(
|
||||
root,
|
||||
@@ -109,7 +114,8 @@ final class UnlockedLayoutPlanner {
|
||||
carrierHost,
|
||||
carrierLayout,
|
||||
positionFor(settings.layoutCarrierPosition),
|
||||
sideFor(settings.layoutCarrierMiddleSide)));
|
||||
sideFor(settings.layoutCarrierMiddleSide))
|
||||
.withSolverVerticalScale(statusbarHeight));
|
||||
}
|
||||
int statusCount = statusCountForScene(settings, scene);
|
||||
if (scene != null && scene.isAod() && !isUsableAodAnchor(aodStatusAnchorBounds)) {
|
||||
@@ -147,16 +153,16 @@ final class UnlockedLayoutPlanner {
|
||||
placements,
|
||||
stepsToPx(verticalOffsetSteps, statusbarHeight));
|
||||
if (!placements.isEmpty()) {
|
||||
bands.add(UnlockedLayoutBand.icons(
|
||||
UnlockedLayoutBand band = UnlockedLayoutBand.icons(
|
||||
LayoutItemKind.STATUS,
|
||||
statusHost,
|
||||
statusRenderer,
|
||||
placements,
|
||||
positionFor(stringAt(positions, i, settings.layoutStatusPosition)),
|
||||
sideFor(stringAt(middleSides, i, settings.layoutStatusMiddleSide)))
|
||||
.withSolverCollision(
|
||||
logicalRowTop(statusHeightSteps, verticalOffsetSteps),
|
||||
statusHeightSteps));
|
||||
sideFor(stringAt(middleSides, i, settings.layoutStatusMiddleSide)));
|
||||
bands.add(band.withSolverCollision(
|
||||
logicalRowTop(statusHeightSteps, verticalOffsetSteps),
|
||||
statusHeightSteps));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,7 +206,7 @@ final class UnlockedLayoutPlanner {
|
||||
if (!placements.isEmpty()) {
|
||||
LayoutPosition position = positionFor(stringAt(positions, i, settings.layoutNotifPosition));
|
||||
AnchorSide middleSide = sideFor(stringAt(middleSides, i, settings.layoutNotifMiddleSide));
|
||||
bands.add(dotNotificationScene
|
||||
UnlockedLayoutBand band = dotNotificationScene
|
||||
? UnlockedLayoutBand.dotIcons(
|
||||
LayoutItemKind.NOTIFICATIONS,
|
||||
notificationHost,
|
||||
@@ -208,19 +214,16 @@ final class UnlockedLayoutPlanner {
|
||||
placements,
|
||||
position,
|
||||
middleSide)
|
||||
.withSolverCollision(
|
||||
logicalRowTop(notificationHeightSteps, verticalOffsetSteps),
|
||||
notificationHeightSteps)
|
||||
: UnlockedLayoutBand.icons(
|
||||
LayoutItemKind.NOTIFICATIONS,
|
||||
notificationHost,
|
||||
notificationRenderer,
|
||||
placements,
|
||||
position,
|
||||
middleSide)
|
||||
.withSolverCollision(
|
||||
logicalRowTop(notificationHeightSteps, verticalOffsetSteps),
|
||||
notificationHeightSteps));
|
||||
middleSide);
|
||||
bands.add(band.withSolverCollision(
|
||||
logicalRowTop(notificationHeightSteps, verticalOffsetSteps),
|
||||
notificationHeightSteps));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,10 +266,17 @@ final class UnlockedLayoutPlanner {
|
||||
return new LayoutPlan(null, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), null);
|
||||
}
|
||||
ArrayList<LayoutItemKind> itemOrder = orderedKinds(settings.layoutItemOrder);
|
||||
splitClockIfNeeded(root, bands, itemOrder, clockCutoutBounds, settings);
|
||||
splitClockIfNeeded(root, bands, itemOrder, clockCutoutBounds, settings, scene);
|
||||
sortBandsForItemOrder(bands, itemOrder);
|
||||
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> notificationPlacements = new ArrayList<>();
|
||||
@@ -1120,6 +1130,15 @@ final class UnlockedLayoutPlanner {
|
||||
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) {
|
||||
if (scene != null && scene.isLockscreen()) {
|
||||
return settings.layoutStatusLockIconHeightSteps;
|
||||
@@ -1260,7 +1279,8 @@ final class UnlockedLayoutPlanner {
|
||||
ArrayList<UnlockedLayoutBand> bands,
|
||||
ArrayList<LayoutItemKind> itemOrder,
|
||||
Bounds cutoutBounds,
|
||||
SbtSettings settings
|
||||
SbtSettings settings,
|
||||
SceneKey scene
|
||||
) {
|
||||
if (root == null || cutoutBounds == null || bands == null || settings == null) {
|
||||
return;
|
||||
@@ -1291,16 +1311,23 @@ final class UnlockedLayoutPlanner {
|
||||
return;
|
||||
}
|
||||
bands.remove(index);
|
||||
int clockHeightSteps = clockTextSizeSteps(settings, scene);
|
||||
bands.add(index, UnlockedLayoutBand.fixedClock(
|
||||
clockBand.host,
|
||||
splitLayouts.get(1),
|
||||
SplitRegion.RIGHT,
|
||||
clockBand.middleSide));
|
||||
clockBand.middleSide)
|
||||
.withSolverCollision(
|
||||
logicalRowTop(clockHeightSteps, settings.clockVerticalOffsetPx),
|
||||
clockHeightSteps));
|
||||
bands.add(index, UnlockedLayoutBand.fixedClock(
|
||||
clockBand.host,
|
||||
splitLayouts.get(0),
|
||||
SplitRegion.LEFT,
|
||||
clockBand.middleSide));
|
||||
clockBand.middleSide)
|
||||
.withSolverCollision(
|
||||
logicalRowTop(clockHeightSteps, settings.clockVerticalOffsetPx),
|
||||
clockHeightSteps));
|
||||
}
|
||||
|
||||
private ArrayList<UnlockedLayoutBand> bandsForPosition(
|
||||
@@ -1643,7 +1670,8 @@ final class UnlockedLayoutPlanner {
|
||||
first.contentDescription,
|
||||
rows,
|
||||
union,
|
||||
first.textColorOverride);
|
||||
first.textColorOverride,
|
||||
first.textSizePx);
|
||||
}
|
||||
|
||||
static Bounds cutoutBounds(Rect cutout, int cutoutGap) {
|
||||
|
||||
+2
@@ -1487,6 +1487,8 @@ final class UnlockedStockSourceCollector {
|
||||
settings.clockMiddleAutoNearestSide,
|
||||
settings.clockMiddleCutoutGapPx,
|
||||
settings.clockVerticalOffsetPx,
|
||||
settings.clockTextSizeSteps,
|
||||
settings.clockLockTextSizeSteps,
|
||||
settings.clockShowSeconds,
|
||||
settings.clockShowDatePrefix,
|
||||
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_MIN = -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_DATE_PREFIX_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_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_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_DATE_PREFIX = "clock_show_date_prefix";
|
||||
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 int clockMiddleCutoutGapPx;
|
||||
public final int clockVerticalOffsetPx;
|
||||
public final int clockTextSizeSteps;
|
||||
public final int clockLockTextSizeSteps;
|
||||
public final boolean clockShowSeconds;
|
||||
public final boolean clockShowDatePrefix;
|
||||
public final boolean clockCustomFormatEnabled;
|
||||
@@ -458,6 +462,8 @@ public final class SbtSettings {
|
||||
boolean clockMiddleAutoNearestSide,
|
||||
int clockMiddleCutoutGapPx,
|
||||
int clockVerticalOffsetPx,
|
||||
int clockTextSizeSteps,
|
||||
int clockLockTextSizeSteps,
|
||||
boolean clockShowSeconds,
|
||||
boolean clockShowDatePrefix,
|
||||
boolean clockCustomFormatEnabled,
|
||||
@@ -630,6 +636,8 @@ public final class SbtSettings {
|
||||
clockVerticalOffsetPx,
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||
this.clockTextSizeSteps = clampIconHeightSteps(clockTextSizeSteps);
|
||||
this.clockLockTextSizeSteps = clampIconHeightSteps(clockLockTextSizeSteps);
|
||||
this.clockShowSeconds = clockShowSeconds;
|
||||
this.clockShowDatePrefix = clockShowDatePrefix;
|
||||
this.clockCustomFormatEnabled = clockCustomFormatEnabled;
|
||||
@@ -889,6 +897,8 @@ public final class SbtSettings {
|
||||
SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
|
||||
SbtDefaults.CLOCK_MIDDLE_CUTOUT_GAP_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_DATE_PREFIX_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),
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||
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_DATE_PREFIX, SbtDefaults.CLOCK_SHOW_DATE_PREFIX_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),
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||
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_DATE_PREFIX, SbtDefaults.CLOCK_SHOW_DATE_PREFIX_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));
|
||||
out.putInt(SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX,
|
||||
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,
|
||||
prefs.getBoolean(SbtSettings.KEY_CLOCK_SHOW_SECONDS, SbtDefaults.CLOCK_SHOW_SECONDS_DEFAULT));
|
||||
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_reset),
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT);
|
||||
addClockTextSizeControl(root, prefs);
|
||||
bindStepper(prefs,
|
||||
SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX,
|
||||
root.findViewById(R.id.notif_vertical_offset_input),
|
||||
@@ -226,6 +227,7 @@ public final class LayoutFragment extends Fragment {
|
||||
countDefault,
|
||||
legacyEnabledDefault);
|
||||
LayoutXmlCardSupport.setIndexedCardTitle(requireContext(), sourceCard, sectionTitleId, 0, count);
|
||||
setCompatPadding(sourceCard, count <= 1);
|
||||
boolean cardsMode = LockedNotificationModeUi.MODE_CARDS.equals(
|
||||
LockedNotificationModeUi.currentMode(requireContext()));
|
||||
LayoutSectionCopySupport.addDropdownRow(
|
||||
@@ -273,6 +275,8 @@ public final class LayoutFragment extends Fragment {
|
||||
middleSideDefault,
|
||||
verticalOffsetDefault,
|
||||
copyTag);
|
||||
setTopMargin(copy, 0);
|
||||
setCompatPadding(copy, false);
|
||||
cardsParent.addView(copy, Math.min(insertIndex, cardsParent.getChildCount()));
|
||||
}
|
||||
};
|
||||
@@ -319,6 +323,19 @@ public final class LayoutFragment extends Fragment {
|
||||
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) {
|
||||
View offsetInput = root.findViewById(R.id.chip_vertical_offset_input);
|
||||
if (offsetInput == null) {
|
||||
@@ -473,6 +490,20 @@ public final class LayoutFragment extends Fragment {
|
||||
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) {
|
||||
if (parent == null) {
|
||||
return;
|
||||
|
||||
@@ -246,12 +246,14 @@ final class LayoutSectionCopySupport {
|
||||
"layout_lock_clock_middle_auto_nearest_side",
|
||||
"layout_lock_clock_middle_side",
|
||||
"layout_lock_clock_vertical_offset_px",
|
||||
SbtSettings.KEY_CLOCK_LOCK_TEXT_SIZE_STEPS,
|
||||
null,
|
||||
SbtDefaults.CLOCK_ENABLED_LOCKSCREEN_DEFAULT,
|
||||
SbtDefaults.CLOCK_POSITION_DEFAULT,
|
||||
SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
|
||||
SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT,
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT,
|
||||
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
|
||||
1);
|
||||
}
|
||||
return new KeySet(
|
||||
@@ -260,12 +262,14 @@ final class LayoutSectionCopySupport {
|
||||
SbtSettings.KEY_CLOCK_MIDDLE_AUTO_NEAREST_SIDE,
|
||||
SbtSettings.KEY_CLOCK_MIDDLE_CUTOUT_SIDE,
|
||||
SbtSettings.KEY_CLOCK_VERTICAL_OFFSET_PX,
|
||||
SbtSettings.KEY_CLOCK_TEXT_SIZE_STEPS,
|
||||
null,
|
||||
SbtDefaults.CLOCK_ENABLED_UNLOCKED_DEFAULT,
|
||||
SbtDefaults.CLOCK_POSITION_DEFAULT,
|
||||
SbtDefaults.CLOCK_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
|
||||
SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT,
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT,
|
||||
SbtDefaults.CLOCK_TEXT_SIZE_STEPS_DEFAULT,
|
||||
1);
|
||||
}
|
||||
|
||||
|
||||
+40
-2
@@ -114,6 +114,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
||||
SbtDefaults.CLOCK_MIDDLE_CUTOUT_SIDE_DEFAULT,
|
||||
sceneKey("clock_vertical_offset_px"),
|
||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_DEFAULT);
|
||||
addClockTextSizeControl(context, prefs, clockCard);
|
||||
LayoutSectionCopySupport.addDropdown(
|
||||
context,
|
||||
prefs,
|
||||
@@ -357,10 +358,11 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
||||
countKey,
|
||||
count,
|
||||
rebuild[0]);
|
||||
setCompatPadding(primary, count <= 1);
|
||||
addCopyDropdownToCard(context, prefs, primary, copySection, cardsMode, refresh);
|
||||
wrapper.addView(primary);
|
||||
for (int i = 1; i < count; i++) {
|
||||
wrapper.addView(configuredIconContainerCard(
|
||||
View copy = configuredIconContainerCard(
|
||||
context,
|
||||
prefs,
|
||||
cardId,
|
||||
@@ -390,7 +392,10 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
||||
null,
|
||||
null,
|
||||
count,
|
||||
null));
|
||||
null);
|
||||
setTopMargin(context, copy, 0);
|
||||
setCompatPadding(copy, false);
|
||||
wrapper.addView(copy);
|
||||
}
|
||||
};
|
||||
rebuild[0].run();
|
||||
@@ -513,6 +518,25 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
||||
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(
|
||||
View root,
|
||||
SharedPreferences prefs,
|
||||
@@ -839,6 +863,20 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
||||
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) {
|
||||
return ViewTreeSupport.outlinedCard(
|
||||
context,
|
||||
|
||||
@@ -198,6 +198,7 @@
|
||||
<string name="layout_copy_from">Copy from</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_clock_text_size_steps">Clock text size (% 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_hint">Mirrors the Samsung notification display style for AOD and lockscreen.</string>
|
||||
|
||||
Reference in New Issue
Block a user