Improve chip rendering and debug overlays
This commit is contained in:
+56
-10
@@ -140,6 +140,8 @@ final class StockLayoutCanvasController {
|
|||||||
Collections.newSetFromMap(new WeakHashMap<>());
|
Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
private final Set<View> dirtyUnlockedLayoutRoots =
|
private final Set<View> dirtyUnlockedLayoutRoots =
|
||||||
Collections.newSetFromMap(new WeakHashMap<>());
|
Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
|
private final Set<View> pendingDrawerStatusChipRefreshRoots =
|
||||||
|
Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
private final Set<ClassLoader> hookedPluginClassLoaders =
|
private final Set<ClassLoader> hookedPluginClassLoaders =
|
||||||
Collections.newSetFromMap(new IdentityHashMap<>());
|
Collections.newSetFromMap(new IdentityHashMap<>());
|
||||||
private final Set<ClassLoader> pendingPluginClassLoaders =
|
private final Set<ClassLoader> pendingPluginClassLoaders =
|
||||||
@@ -288,6 +290,7 @@ final class StockLayoutCanvasController {
|
|||||||
}
|
}
|
||||||
if (expansion <= 0.01f) {
|
if (expansion <= 0.01f) {
|
||||||
notificationDrawerWasOpen = false;
|
notificationDrawerWasOpen = false;
|
||||||
|
flushDeferredDrawerStatusChipRefreshes();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (expansion <= 0.05f) {
|
if (expansion <= 0.05f) {
|
||||||
@@ -337,6 +340,7 @@ final class StockLayoutCanvasController {
|
|||||||
} else if (previousState == STATUS_BAR_STATE_SHADE_LOCKED
|
} else if (previousState == STATUS_BAR_STATE_SHADE_LOCKED
|
||||||
&& currentState != STATUS_BAR_STATE_SHADE_LOCKED) {
|
&& currentState != STATUS_BAR_STATE_SHADE_LOCKED) {
|
||||||
notificationDrawerWasOpen = false;
|
notificationDrawerWasOpen = false;
|
||||||
|
flushDeferredDrawerStatusChipRefreshes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1153,9 +1157,6 @@ final class StockLayoutCanvasController {
|
|||||||
if (activeScene == null) {
|
if (activeScene == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!runtimeContext.getModeStateRepository().isSystemUiShadeLocked() && !activeScene.isAod()) {
|
|
||||||
notificationDrawerWasOpen = false;
|
|
||||||
}
|
|
||||||
if (isNotificationShadeWindowRoot(root)) {
|
if (isNotificationShadeWindowRoot(root)) {
|
||||||
if (shouldPrepareCarrierlessAodNotificationTransition(settings, activeScene)) {
|
if (shouldPrepareCarrierlessAodNotificationTransition(settings, activeScene)) {
|
||||||
prepareCarrierlessAodNotificationTransition(root);
|
prepareCarrierlessAodNotificationTransition(root);
|
||||||
@@ -1331,8 +1332,8 @@ final class StockLayoutCanvasController {
|
|||||||
if (activeScene != null && activeScene.isUnlocked()) {
|
if (activeScene != null && activeScene.isUnlocked()) {
|
||||||
if (isKnownRootGeometryChanged(root)) {
|
if (isKnownRootGeometryChanged(root)) {
|
||||||
ownedIconHostManager.setUnlockedHostsVisible(root, false);
|
ownedIconHostManager.setUnlockedHostsVisible(root, false);
|
||||||
|
removeDebugOverlay(root);
|
||||||
}
|
}
|
||||||
removeDebugOverlay(root);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1385,13 +1386,19 @@ final class StockLayoutCanvasController {
|
|||||||
private void markStatusChipLifecycleDirtyIfNeeded(View view, View fallbackRoot) {
|
private void markStatusChipLifecycleDirtyIfNeeded(View view, View fallbackRoot) {
|
||||||
if (view == null || !isStatusChipCandidate(view)) {
|
if (view == null || !isStatusChipCandidate(view)) {
|
||||||
View root = view != null ? unlockedStatusBarRootFor(view) : fallbackRoot;
|
View root = view != null ? unlockedStatusBarRootFor(view) : fallbackRoot;
|
||||||
|
if (deferDrawerStatusChipRefresh(root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
requestUnlockedLayoutRefresh(root);
|
requestUnlockedLayoutRefresh(root);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
View root = unlockedStatusBarRootFor(view);
|
||||||
|
if (deferDrawerStatusChipRefresh(root != null ? root : fallbackRoot)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int signature = statusChipLayoutSignature(view);
|
int signature = statusChipLayoutSignature(view);
|
||||||
Integer previous = statusChipLifecycleLayoutSignatureByView.put(view, signature);
|
Integer previous = statusChipLifecycleLayoutSignatureByView.put(view, signature);
|
||||||
if (previous == null || previous != signature) {
|
if (previous == null || previous != signature) {
|
||||||
View root = unlockedStatusBarRootFor(view);
|
|
||||||
requestUnlockedLayoutRefresh(root != null ? root : fallbackRoot);
|
requestUnlockedLayoutRefresh(root != null ? root : fallbackRoot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1408,6 +1415,9 @@ final class StockLayoutCanvasController {
|
|||||||
if (root == null || !root.isAttachedToWindow()) {
|
if (root == null || !root.isAttachedToWindow()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (deferDrawerStatusChipRefresh(root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int signature = statusChipContentSignature(chipSource);
|
int signature = statusChipContentSignature(chipSource);
|
||||||
Integer previous = statusChipContentSignatureByRoot.put(root, signature);
|
Integer previous = statusChipContentSignatureByRoot.put(root, signature);
|
||||||
if (previous != null && previous == signature) {
|
if (previous != null && previous == signature) {
|
||||||
@@ -1434,10 +1444,39 @@ final class StockLayoutCanvasController {
|
|||||||
requestUnlockedLayoutRefresh(root);
|
requestUnlockedLayoutRefresh(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean deferDrawerStatusChipRefresh(View root) {
|
||||||
|
if (!notificationDrawerWasOpen || root == null || !root.isAttachedToWindow()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SceneKey activeScene = runtimeContext.getModeStateRepository().getActiveScene();
|
||||||
|
if (activeScene == null || !activeScene.isUnlocked()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pendingDrawerStatusChipRefreshRoots.add(root);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flushDeferredDrawerStatusChipRefreshes() {
|
||||||
|
if (pendingDrawerStatusChipRefreshRoots.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ArrayDeque<View> roots = new ArrayDeque<>(pendingDrawerStatusChipRefreshRoots);
|
||||||
|
pendingDrawerStatusChipRefreshRoots.clear();
|
||||||
|
while (!roots.isEmpty()) {
|
||||||
|
View root = roots.removeFirst();
|
||||||
|
if (root != null && root.isAttachedToWindow()) {
|
||||||
|
requestStatusChipRefresh(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void requestStatusChipRefresh(View root) {
|
private void requestStatusChipRefresh(View root) {
|
||||||
if (root == null || !root.isAttachedToWindow()) {
|
if (root == null || !root.isAttachedToWindow()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (deferDrawerStatusChipRefresh(root)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
unlockedIconRenderController.forceChipRefresh(root);
|
unlockedIconRenderController.forceChipRefresh(root);
|
||||||
requestUnlockedLayoutRefresh(root);
|
requestUnlockedLayoutRefresh(root);
|
||||||
}
|
}
|
||||||
@@ -1517,7 +1556,8 @@ final class StockLayoutCanvasController {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int result = 17;
|
int result = 17;
|
||||||
result = 31 * result + System.identityHashCode(view);
|
result = 31 * result + view.getClass().getName().hashCode();
|
||||||
|
result = 31 * result + view.getId();
|
||||||
result = 31 * result + view.getVisibility();
|
result = 31 * result + view.getVisibility();
|
||||||
result = 31 * result + view.getWidth();
|
result = 31 * result + view.getWidth();
|
||||||
result = 31 * result + view.getHeight();
|
result = 31 * result + view.getHeight();
|
||||||
@@ -1528,8 +1568,10 @@ final class StockLayoutCanvasController {
|
|||||||
}
|
}
|
||||||
if (view instanceof ImageView imageView) {
|
if (view instanceof ImageView imageView) {
|
||||||
Drawable drawable = imageView.getDrawable();
|
Drawable drawable = imageView.getDrawable();
|
||||||
result = 31 * result + System.identityHashCode(drawable);
|
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
|
result = 31 * result + drawable.getClass().getName().hashCode();
|
||||||
|
result = 31 * result + drawable.getIntrinsicWidth();
|
||||||
|
result = 31 * result + drawable.getIntrinsicHeight();
|
||||||
result = 31 * result + drawable.getBounds().hashCode();
|
result = 31 * result + drawable.getBounds().hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1559,8 +1601,10 @@ final class StockLayoutCanvasController {
|
|||||||
}
|
}
|
||||||
if (view instanceof ImageView imageView) {
|
if (view instanceof ImageView imageView) {
|
||||||
Drawable drawable = imageView.getDrawable();
|
Drawable drawable = imageView.getDrawable();
|
||||||
result = 31 * result + System.identityHashCode(drawable);
|
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
|
result = 31 * result + drawable.getClass().getName().hashCode();
|
||||||
|
result = 31 * result + drawable.getIntrinsicWidth();
|
||||||
|
result = 31 * result + drawable.getIntrinsicHeight();
|
||||||
result = 31 * result + drawable.getAlpha();
|
result = 31 * result + drawable.getAlpha();
|
||||||
result = 31 * result + drawable.getLevel();
|
result = 31 * result + drawable.getLevel();
|
||||||
result = 31 * result + drawable.getBounds().hashCode();
|
result = 31 * result + drawable.getBounds().hashCode();
|
||||||
@@ -1936,13 +1980,13 @@ final class StockLayoutCanvasController {
|
|||||||
if (!aodScene && renderResult.shouldOwnLockscreen()) {
|
if (!aodScene && renderResult.shouldOwnLockscreen()) {
|
||||||
hideOrDiscoverLockedStatusBarIconSurfaces(root);
|
hideOrDiscoverLockedStatusBarIconSurfaces(root);
|
||||||
}
|
}
|
||||||
if (aodScene) {
|
if (aodScene || renderResult.shouldOwnLockscreen()) {
|
||||||
applyDebugOverlayIfNeeded(
|
applyDebugOverlayIfNeeded(
|
||||||
root,
|
root,
|
||||||
true,
|
true,
|
||||||
settings,
|
settings,
|
||||||
renderResult.layoutChanged(),
|
renderResult.layoutChanged(),
|
||||||
true,
|
aodScene,
|
||||||
activeScene);
|
activeScene);
|
||||||
} else {
|
} else {
|
||||||
removeDebugOverlay(root);
|
removeDebugOverlay(root);
|
||||||
@@ -2069,6 +2113,7 @@ final class StockLayoutCanvasController {
|
|||||||
) {
|
) {
|
||||||
int result = 17;
|
int result = 17;
|
||||||
result = 31 * result + (layoutEnabled ? 1 : 0);
|
result = 31 * result + (layoutEnabled ? 1 : 0);
|
||||||
|
result = 31 * result + (scene != null ? scene.hashCode() : 0);
|
||||||
result = 31 * result + (root != null ? root.getWidth() : 0);
|
result = 31 * result + (root != null ? root.getWidth() : 0);
|
||||||
result = 31 * result + (root != null ? root.getHeight() : 0);
|
result = 31 * result + (root != null ? root.getHeight() : 0);
|
||||||
if (settings != null) {
|
if (settings != null) {
|
||||||
@@ -3874,6 +3919,7 @@ final class StockLayoutCanvasController {
|
|||||||
statusChipContentSignatureByRoot.clear();
|
statusChipContentSignatureByRoot.clear();
|
||||||
statusChipLayoutSignatureByRoot.clear();
|
statusChipLayoutSignatureByRoot.clear();
|
||||||
statusChipLifecycleLayoutSignatureByView.clear();
|
statusChipLifecycleLayoutSignatureByView.clear();
|
||||||
|
pendingDrawerStatusChipRefreshRoots.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean containsAny(String value, Set<String> tokens) {
|
private static boolean containsAny(String value, Set<String> tokens) {
|
||||||
|
|||||||
+41
-59
@@ -107,9 +107,8 @@ public final class DebugBoundsOverlayController {
|
|||||||
removeOverlays(parent);
|
removeOverlays(parent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ViewGroup overlayParent = overlayParent(root, parent, layoutEnabled, aodStockVisualizersEnabled, settings);
|
removeOverlaysFromOwnedHosts(parent);
|
||||||
removeOverlayFromOtherParent(parent, overlayParent);
|
OverlayView host = ensureOverlay(parent);
|
||||||
OverlayView host = ensureOverlay(overlayParent);
|
|
||||||
if (host == null) {
|
if (host == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -122,7 +121,7 @@ public final class DebugBoundsOverlayController {
|
|||||||
host.layout(0, 0, width, height);
|
host.layout(0, 0, width, height);
|
||||||
}
|
}
|
||||||
host.setSpecs(specs);
|
host.setSpecs(specs);
|
||||||
if (overlayParent.getChildAt(overlayParent.getChildCount() - 1) != host) {
|
if (parent.getChildAt(parent.getChildCount() - 1) != host) {
|
||||||
host.bringToFront();
|
host.bringToFront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,18 +133,22 @@ public final class DebugBoundsOverlayController {
|
|||||||
boolean aodStockVisualizersEnabled,
|
boolean aodStockVisualizersEnabled,
|
||||||
SceneKey scene
|
SceneKey scene
|
||||||
) {
|
) {
|
||||||
if (!layoutEnabled || root == null || settings == null
|
if (!layoutEnabled || root == null || settings == null) {
|
||||||
|| !aodStockVisualizersEnabled
|
|
||||||
|| !settings.debugVisualizeAodStockContainers) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int result = 17;
|
int result = 17;
|
||||||
ViewGroup notificationContainer = aodNotificationContainer(root, scene);
|
if (aodStockVisualizersEnabled && settings.debugVisualizeAodStockContainers) {
|
||||||
result = 31 * result + signature(
|
ViewGroup notificationContainer = aodNotificationContainer(root, scene);
|
||||||
aodNotificationBounds(root, scene));
|
result = 31 * result + signature(
|
||||||
result = 31 * result + signature(liveAodStatusIconsBounds(root));
|
aodNotificationBounds(root, scene));
|
||||||
result = 31 * result + signature(
|
result = 31 * result + signature(liveAodStatusIconsBounds(root));
|
||||||
derivedAodStatusbarBounds(root, notificationContainer, settings, scene));
|
result = 31 * result + signature(
|
||||||
|
derivedAodStatusbarBounds(root, notificationContainer, settings, scene));
|
||||||
|
}
|
||||||
|
result = 31 * result + hostSignature(root, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST);
|
||||||
|
result = 31 * result + hostSignature(root, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST);
|
||||||
|
result = 31 * result + hostSignature(root, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST);
|
||||||
|
result = 31 * result + hostSignature(root, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,6 +258,12 @@ public final class DebugBoundsOverlayController {
|
|||||||
}
|
}
|
||||||
int right = bounds.left + bounds.width;
|
int right = bounds.left + bounds.width;
|
||||||
int bottom = bounds.top + bounds.height;
|
int bottom = bounds.top + bounds.height;
|
||||||
|
if (bounds.left == 0
|
||||||
|
&& bounds.top == 0
|
||||||
|
&& bounds.width >= root.getWidth()
|
||||||
|
&& bounds.height >= root.getHeight()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return bounds.left >= 0
|
return bounds.left >= 0
|
||||||
&& bounds.top >= 0
|
&& bounds.top >= 0
|
||||||
&& right <= root.getWidth()
|
&& right <= root.getWidth()
|
||||||
@@ -410,49 +419,15 @@ public final class DebugBoundsOverlayController {
|
|||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ViewGroup overlayParent(
|
private void removeOverlaysFromOwnedHosts(ViewGroup rootParent) {
|
||||||
View root,
|
|
||||||
ViewGroup rootParent,
|
|
||||||
boolean layoutEnabled,
|
|
||||||
boolean aodStockVisualizersEnabled,
|
|
||||||
SbtSettings settings
|
|
||||||
) {
|
|
||||||
if (layoutEnabled
|
|
||||||
&& aodStockVisualizersEnabled
|
|
||||||
&& settings != null
|
|
||||||
&& settings.debugVisualizeAodStockContainers) {
|
|
||||||
View chipHost = findDirectTaggedChild(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST);
|
|
||||||
if (chipHost instanceof ViewGroup chipHostGroup) {
|
|
||||||
return chipHostGroup;
|
|
||||||
}
|
|
||||||
View statusHost = findDirectTaggedChild(rootParent, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST);
|
|
||||||
if (statusHost instanceof ViewGroup statusHostGroup) {
|
|
||||||
return statusHostGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rootParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOverlayFromOtherParent(ViewGroup rootParent, ViewGroup overlayParent) {
|
|
||||||
if (rootParent == null) {
|
if (rootParent == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeOverlayIfParentDiffers(rootParent, overlayParent);
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST));
|
||||||
removeOverlayIfParentDiffers(
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST));
|
||||||
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST),
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST));
|
||||||
overlayParent);
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CARRIER_HOST));
|
||||||
removeOverlayIfParentDiffers(
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST));
|
||||||
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST),
|
|
||||||
overlayParent);
|
|
||||||
removeOverlayIfParentDiffers(
|
|
||||||
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST),
|
|
||||||
overlayParent);
|
|
||||||
removeOverlayIfParentDiffers(
|
|
||||||
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CARRIER_HOST),
|
|
||||||
overlayParent);
|
|
||||||
removeOverlayIfParentDiffers(
|
|
||||||
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST),
|
|
||||||
overlayParent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeOverlays(ViewGroup rootParent) {
|
private void removeOverlays(ViewGroup rootParent) {
|
||||||
@@ -467,12 +442,6 @@ public final class DebugBoundsOverlayController {
|
|||||||
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST));
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeOverlayIfParentDiffers(ViewGroup parent, ViewGroup expectedParent) {
|
|
||||||
if (parent != null && parent != expectedParent) {
|
|
||||||
removeOverlay(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOverlay(ViewGroup parent) {
|
private void removeOverlay(ViewGroup parent) {
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
return;
|
return;
|
||||||
@@ -511,6 +480,19 @@ public final class DebugBoundsOverlayController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int hostSignature(View root, String tag) {
|
||||||
|
if (!(root instanceof ViewGroup parent)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
View host = findDirectTaggedChild(parent, tag);
|
||||||
|
Bounds bounds = boundsRelativeTo(root, host);
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + signature(bounds);
|
||||||
|
result = 31 * result + (host instanceof ViewGroup group ? group.getChildCount() : 0);
|
||||||
|
result = 31 * result + taggedContainerBounds(host).hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private Bounds boundsRelativeTo(View root, View view) {
|
private Bounds boundsRelativeTo(View root, View view) {
|
||||||
if (root == null || view == null) {
|
if (root == null || view == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.graphics.PorterDuff;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -946,7 +947,7 @@ final class SnapshotRenderer {
|
|||||||
int oldMeasuredWidth = view.getMeasuredWidth();
|
int oldMeasuredWidth = view.getMeasuredWidth();
|
||||||
int oldMeasuredHeight = view.getMeasuredHeight();
|
int oldMeasuredHeight = view.getMeasuredHeight();
|
||||||
ViewFrameState frameState = captureFrameState(view);
|
ViewFrameState frameState = captureFrameState(view);
|
||||||
IdentityHashMap<TextView, Integer> oldMaxWidths = clearTextMaxWidths(view);
|
IdentityHashMap<TextView, TextSnapshotState> textSnapshotStates = prepareTextSnapshotState(view);
|
||||||
try {
|
try {
|
||||||
int widthSpec = View.MeasureSpec.makeMeasureSpec(Math.max(1, width), View.MeasureSpec.EXACTLY);
|
int widthSpec = View.MeasureSpec.makeMeasureSpec(Math.max(1, width), View.MeasureSpec.EXACTLY);
|
||||||
int heightSpec = View.MeasureSpec.makeMeasureSpec(Math.max(1, height), View.MeasureSpec.EXACTLY);
|
int heightSpec = View.MeasureSpec.makeMeasureSpec(Math.max(1, height), View.MeasureSpec.EXACTLY);
|
||||||
@@ -955,7 +956,7 @@ final class SnapshotRenderer {
|
|||||||
clampDescendantsToParent(view);
|
clampDescendantsToParent(view);
|
||||||
view.draw(canvas);
|
view.draw(canvas);
|
||||||
} finally {
|
} finally {
|
||||||
restoreTextMaxWidths(oldMaxWidths);
|
restoreTextSnapshotState(textSnapshotStates);
|
||||||
restoreFrameState(frameState);
|
restoreFrameState(frameState);
|
||||||
if (oldMeasuredWidth > 0 && oldMeasuredHeight > 0) {
|
if (oldMeasuredWidth > 0 && oldMeasuredHeight > 0) {
|
||||||
view.measure(
|
view.measure(
|
||||||
@@ -1052,32 +1053,53 @@ final class SnapshotRenderer {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdentityHashMap<TextView, Integer> clearTextMaxWidths(View view) {
|
private IdentityHashMap<TextView, TextSnapshotState> prepareTextSnapshotState(View view) {
|
||||||
IdentityHashMap<TextView, Integer> oldMaxWidths = new IdentityHashMap<>();
|
IdentityHashMap<TextView, TextSnapshotState> states = new IdentityHashMap<>();
|
||||||
collectTextMaxWidths(view, oldMaxWidths);
|
collectTextSnapshotState(view, states);
|
||||||
for (Map.Entry<TextView, Integer> entry : oldMaxWidths.entrySet()) {
|
for (Map.Entry<TextView, TextSnapshotState> entry : states.entrySet()) {
|
||||||
entry.getKey().setMaxWidth(Integer.MAX_VALUE);
|
TextView textView = entry.getKey();
|
||||||
|
textView.setMaxWidth(Integer.MAX_VALUE);
|
||||||
|
textView.setHorizontalFadingEdgeEnabled(false);
|
||||||
|
textView.setSelected(false);
|
||||||
|
textView.setEllipsize(null);
|
||||||
}
|
}
|
||||||
return oldMaxWidths;
|
return states;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void collectTextMaxWidths(View view, IdentityHashMap<TextView, Integer> out) {
|
private void collectTextSnapshotState(View view, IdentityHashMap<TextView, TextSnapshotState> out) {
|
||||||
if (view instanceof TextView textView) {
|
if (view instanceof TextView textView) {
|
||||||
out.put(textView, textView.getMaxWidth());
|
out.put(textView, new TextSnapshotState(
|
||||||
|
textView.getMaxWidth(),
|
||||||
|
textView.isHorizontalFadingEdgeEnabled(),
|
||||||
|
textView.isSelected(),
|
||||||
|
textView.getEllipsize()));
|
||||||
}
|
}
|
||||||
if (view instanceof ViewGroup group) {
|
if (view instanceof ViewGroup group) {
|
||||||
for (int i = 0; i < group.getChildCount(); i++) {
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
collectTextMaxWidths(group.getChildAt(i), out);
|
collectTextSnapshotState(group.getChildAt(i), out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restoreTextMaxWidths(IdentityHashMap<TextView, Integer> oldMaxWidths) {
|
private void restoreTextSnapshotState(IdentityHashMap<TextView, TextSnapshotState> states) {
|
||||||
for (Map.Entry<TextView, Integer> entry : oldMaxWidths.entrySet()) {
|
for (Map.Entry<TextView, TextSnapshotState> entry : states.entrySet()) {
|
||||||
entry.getKey().setMaxWidth(entry.getValue());
|
TextView textView = entry.getKey();
|
||||||
|
TextSnapshotState state = entry.getValue();
|
||||||
|
textView.setMaxWidth(state.maxWidth);
|
||||||
|
textView.setHorizontalFadingEdgeEnabled(state.horizontalFadingEdgeEnabled);
|
||||||
|
textView.setSelected(state.selected);
|
||||||
|
textView.setEllipsize(state.ellipsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private record TextSnapshotState(
|
||||||
|
int maxWidth,
|
||||||
|
boolean horizontalFadingEdgeEnabled,
|
||||||
|
boolean selected,
|
||||||
|
TextUtils.TruncateAt ellipsize
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
private void drawAppIcon(Context context, SnapshotSource source, Bitmap bitmap) {
|
private void drawAppIcon(Context context, SnapshotSource source, Bitmap bitmap) {
|
||||||
bitmap.eraseColor(Color.TRANSPARENT);
|
bitmap.eraseColor(Color.TRANSPARENT);
|
||||||
if (context == null || source == null || source.keyHint() == null) {
|
if (context == null || source == null || source.keyHint() == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user