Merge "Cache checkAbiRelease even though it has no outputs" into androidx-main
diff --git a/appfunctions/appfunctions-common/api/current.txt b/appfunctions/appfunctions-common/api/current.txt
index ba35715..997db32 100644
--- a/appfunctions/appfunctions-common/api/current.txt
+++ b/appfunctions/appfunctions-common/api/current.txt
@@ -38,7 +38,6 @@
}
public abstract class AppFunctionException extends java.lang.Exception {
- ctor public AppFunctionException(int errorCode, optional String? errorMessage);
method public final String? getErrorMessage();
property public final String? errorMessage;
field public static final androidx.appfunctions.AppFunctionException.Companion Companion;
@@ -81,9 +80,9 @@
}
public final class AppFunctionUnknownException extends androidx.appfunctions.AppFunctionException {
- ctor public AppFunctionUnknownException(int unknownErrorCode, optional String? errorMessage);
- method public int getUnknownErrorCode();
- property public final int unknownErrorCode;
+ ctor public AppFunctionUnknownException(int errorCode, optional String? errorMessage);
+ method public int getErrorCode();
+ property public final int errorCode;
}
}
diff --git a/appfunctions/appfunctions-common/api/restricted_current.txt b/appfunctions/appfunctions-common/api/restricted_current.txt
index ba35715..997db32 100644
--- a/appfunctions/appfunctions-common/api/restricted_current.txt
+++ b/appfunctions/appfunctions-common/api/restricted_current.txt
@@ -38,7 +38,6 @@
}
public abstract class AppFunctionException extends java.lang.Exception {
- ctor public AppFunctionException(int errorCode, optional String? errorMessage);
method public final String? getErrorMessage();
property public final String? errorMessage;
field public static final androidx.appfunctions.AppFunctionException.Companion Companion;
@@ -81,9 +80,9 @@
}
public final class AppFunctionUnknownException extends androidx.appfunctions.AppFunctionException {
- ctor public AppFunctionUnknownException(int unknownErrorCode, optional String? errorMessage);
- method public int getUnknownErrorCode();
- property public final int unknownErrorCode;
+ ctor public AppFunctionUnknownException(int errorCode, optional String? errorMessage);
+ method public int getErrorCode();
+ property public final int errorCode;
}
}
diff --git a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionAppExceptionsTest.kt b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionAppExceptionsTest.kt
index 2172ea5..2e43099 100644
--- a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionAppExceptionsTest.kt
+++ b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionAppExceptionsTest.kt
@@ -22,17 +22,17 @@
class AppFunctionAppExceptionsTest {
@Test
fun testErrorCategory_AppError() {
- assertThat(AppFunctionAppUnknownException().errorCode)
+ assertThat(AppFunctionAppUnknownException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_APP_UNKNOWN_ERROR)
assertThat(AppFunctionAppUnknownException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_APP)
- assertThat(AppFunctionPermissionRequiredException().errorCode)
+ assertThat(AppFunctionPermissionRequiredException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_PERMISSION_REQUIRED)
assertThat(AppFunctionPermissionRequiredException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_APP)
- assertThat(AppFunctionNotSupportedException().errorCode)
+ assertThat(AppFunctionNotSupportedException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_NOT_SUPPORTED)
assertThat(AppFunctionNotSupportedException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_APP)
diff --git a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionExceptionTest.kt b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionExceptionTest.kt
index a8cbef9..c2e0b38 100644
--- a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionExceptionTest.kt
+++ b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionExceptionTest.kt
@@ -110,7 +110,7 @@
val exception = AppFunctionException.fromPlatformExtensionsClass(platformException)
assertThat(exception).isInstanceOf(exceptionClass)
- assertThat(exception.errorCode).isEqualTo(errorCode)
+ assertThat(exception.internalErrorCode).isEqualTo(errorCode)
assertThat(exception.errorMessage).isEqualTo("testMessage")
assertThat(exception.extras.getString("testKey")).isEqualTo("testValue")
}
diff --git a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionRequestExceptionsTest.kt b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionRequestExceptionsTest.kt
index f98c39f..51fa82f6 100644
--- a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionRequestExceptionsTest.kt
+++ b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionRequestExceptionsTest.kt
@@ -22,37 +22,37 @@
class AppFunctionRequestExceptionsTest {
@Test
fun testErrorCategory_RequestError() {
- assertThat(AppFunctionDeniedException().errorCode)
+ assertThat(AppFunctionDeniedException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_DENIED)
assertThat(AppFunctionDeniedException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR)
- assertThat(AppFunctionInvalidArgumentException().errorCode)
+ assertThat(AppFunctionInvalidArgumentException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_INVALID_ARGUMENT)
assertThat(AppFunctionInvalidArgumentException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR)
- assertThat(AppFunctionDisabledException().errorCode)
+ assertThat(AppFunctionDisabledException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_DISABLED)
assertThat(AppFunctionDisabledException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR)
- assertThat(AppFunctionFunctionNotFoundException().errorCode)
+ assertThat(AppFunctionFunctionNotFoundException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_FUNCTION_NOT_FOUND)
assertThat(AppFunctionFunctionNotFoundException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR)
- assertThat(AppFunctionElementNotFoundException().errorCode)
+ assertThat(AppFunctionElementNotFoundException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_RESOURCE_NOT_FOUND)
assertThat(AppFunctionElementNotFoundException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR)
- assertThat(AppFunctionLimitExceededException().errorCode)
+ assertThat(AppFunctionLimitExceededException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_LIMIT_EXCEEDED)
assertThat(AppFunctionLimitExceededException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR)
- assertThat(AppFunctionElementAlreadyExistsException().errorCode)
+ assertThat(AppFunctionElementAlreadyExistsException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_RESOURCE_ALREADY_EXISTS)
assertThat(AppFunctionElementAlreadyExistsException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR)
diff --git a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionSystemExceptionsTest.kt b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionSystemExceptionsTest.kt
index 89ccbf0..0722f0a 100644
--- a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionSystemExceptionsTest.kt
+++ b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/AppFunctionSystemExceptionsTest.kt
@@ -22,12 +22,12 @@
class AppFunctionSystemExceptionsTest {
@Test
fun testErrorCategory_SystemError() {
- assertThat(AppFunctionSystemUnknownException().errorCode)
+ assertThat(AppFunctionSystemUnknownException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_SYSTEM_ERROR)
assertThat(AppFunctionSystemUnknownException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_SYSTEM)
- assertThat(AppFunctionCancelledException().errorCode)
+ assertThat(AppFunctionCancelledException().internalErrorCode)
.isEqualTo(AppFunctionException.ERROR_CANCELLED)
assertThat(AppFunctionCancelledException().errorCategory)
.isEqualTo(AppFunctionException.ERROR_CATEGORY_SYSTEM)
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt
index e273dd4..39f28e8 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt
@@ -28,27 +28,16 @@
public abstract class AppFunctionException
internal constructor(
/** The error code. */
- @ErrorCode internal val errorCode: Int,
+ @ErrorCode internal val internalErrorCode: Int,
/** The error message. */
public val errorMessage: String?,
internal val extras: Bundle
) : Exception(errorMessage) {
- /**
- * Create an [AppFunctionException].
- *
- * @param errorCode The error code.
- * @param errorMessage The error message.
- */
- public constructor(
- @ErrorCode errorCode: Int,
- errorMessage: String? = null,
- ) : this(errorCode, errorMessage, Bundle.EMPTY)
-
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public fun toPlatformExtensionsClass():
com.android.extensions.appfunctions.AppFunctionException {
return com.android.extensions.appfunctions.AppFunctionException(
- errorCode,
+ internalErrorCode,
errorMessage,
extras
)
@@ -66,7 +55,7 @@
*/
@ErrorCategory
internal val errorCategory: Int =
- when (errorCode) {
+ when (internalErrorCode) {
in 1000..1999 -> ERROR_CATEGORY_REQUEST_ERROR
in 2000..2999 -> ERROR_CATEGORY_SYSTEM
in 3000..3999 -> ERROR_CATEGORY_APP
@@ -291,18 +280,24 @@
/**
* Thrown when an unknown error has occurred.
*
- * <p> This Exception is used when the error doesn't belong to any other AppFunctionException. Note
- * that this different from [AppFunctionAppUnknownException], in that the error wasn't necessarily
- * caused by the app.
+ * <p> This Exception is used when the error doesn't belong to any other AppFunctionException. This
+ * may happen due to version skews in the error codes between the platform and the sdk. E.g. if the
+ * app is running on a newer platform version (with a new error code) and an older sdk.
+ *
+ * <p>Note that this is different from [AppFunctionAppUnknownException], in that the error wasn't
+ * necessarily caused by the app.
*/
public class AppFunctionUnknownException
-internal constructor(
- public val unknownErrorCode: Int,
- errorMessage: String? = null,
- extras: Bundle
-) : AppFunctionException(unknownErrorCode, errorMessage, extras) {
+internal constructor(public val errorCode: Int, errorMessage: String? = null, extras: Bundle) :
+ AppFunctionException(errorCode, errorMessage, extras) {
+ /**
+ * Create an [AppFunctionUnknownException].
+ *
+ * @param errorCode The error code.
+ * @param errorMessage The error message.
+ */
public constructor(
- unknownErrorCode: Int,
+ errorCode: Int,
errorMessage: String? = null
- ) : this(unknownErrorCode, errorMessage, Bundle.EMPTY)
+ ) : this(errorCode, errorMessage, Bundle.EMPTY)
}
diff --git a/benchmark/benchmark-common/api/current.txt b/benchmark/benchmark-common/api/current.txt
index 44c9777..6dea054 100644
--- a/benchmark/benchmark-common/api/current.txt
+++ b/benchmark/benchmark-common/api/current.txt
@@ -54,6 +54,11 @@
@SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public final class MicrobenchmarkConfig {
ctor public MicrobenchmarkConfig();
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler, optional Integer? warmupCount);
ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler, optional Integer? warmupCount, optional Integer? measurementCount);
method public Integer? getMeasurementCount();
method public java.util.List<androidx.benchmark.MetricCapture> getMetrics();
diff --git a/benchmark/benchmark-common/api/restricted_current.txt b/benchmark/benchmark-common/api/restricted_current.txt
index f25ea8e..c94bb5b 100644
--- a/benchmark/benchmark-common/api/restricted_current.txt
+++ b/benchmark/benchmark-common/api/restricted_current.txt
@@ -57,6 +57,11 @@
@SuppressCompatibility @androidx.benchmark.ExperimentalBenchmarkConfigApi public final class MicrobenchmarkConfig {
ctor public MicrobenchmarkConfig();
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler);
+ ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler, optional Integer? warmupCount);
ctor public MicrobenchmarkConfig(optional java.util.List<? extends androidx.benchmark.MetricCapture> metrics, optional boolean traceAppTagEnabled, optional boolean perfettoSdkTracingEnabled, optional androidx.benchmark.ProfilerConfig? profiler, optional Integer? warmupCount, optional Integer? measurementCount);
method public Integer? getMeasurementCount();
method public java.util.List<androidx.benchmark.MetricCapture> getMetrics();
diff --git a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/DeviceInfoTest.kt b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/DeviceInfoTest.kt
index 456635c..61d9775 100644
--- a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/DeviceInfoTest.kt
+++ b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/DeviceInfoTest.kt
@@ -62,6 +62,26 @@
}
@Test
+ fun willMethodTracingAffectMeasurements() {
+ // first clause - 26 through 30 (inclusive) affected
+ assertFalse(DeviceInfo.willMethodTracingAffectMeasurements(25, -1))
+ assertTrue(DeviceInfo.willMethodTracingAffectMeasurements(26, -1L))
+ assertTrue(DeviceInfo.willMethodTracingAffectMeasurements(30, -1L))
+ assertFalse(DeviceInfo.willMethodTracingAffectMeasurements(31, 310000000L))
+
+ // second clause - art API 34 regression
+ assertFalse(DeviceInfo.willMethodTracingAffectMeasurements(33, 330000000L))
+ assertTrue(DeviceInfo.willMethodTracingAffectMeasurements(33, 340000000L))
+ assertTrue(DeviceInfo.willMethodTracingAffectMeasurements(33, 341513000L - 1))
+ assertFalse(DeviceInfo.willMethodTracingAffectMeasurements(33, 341513000L))
+
+ // third clause - art API 34 regression and internal build ID
+ assertFalse(DeviceInfo.willMethodTracingAffectMeasurements(33, 990090000L))
+ assertTrue(DeviceInfo.willMethodTracingAffectMeasurements(34, 990090000L))
+ assertFalse(DeviceInfo.willMethodTracingAffectMeasurements(35, 990090000L))
+ }
+
+ @Test
fun artMainlineVersion() =
validateArtMainlineVersion(artMainlineVersion = DeviceInfo.artMainlineVersion)
}
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/DeviceInfo.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/DeviceInfo.kt
index 3083747..002ab09 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/DeviceInfo.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/DeviceInfo.kt
@@ -302,6 +302,16 @@
private const val ART_MAINLINE_MIN_VERSION_VERIFY_CLEARS_RUNTIME_IMAGE = 350800000L
/**
+ * ART mainline 990090000 means the module is built from source in the system image and isn't
+ * updatable, and thus expectations should be conservative - assume that any potential bug on
+ * the current SDK version may be present on this device.
+ *
+ * Ideally, we'd have a minimum release build ID, but these may not be consistently and easily
+ * sortable.
+ */
+ private const val ART_MAINLINE_INTERNAL_BUILD_MIN = 990000000
+
+ /**
* Used when mainline version failed to detect, but this is accepted due to low API level (<34)
* where presence isn't guaranteed (e.g. go devices)
*/
@@ -320,15 +330,18 @@
else -> ART_MAINLINE_VERSION_UNDETECTED
}
- val methodTracingAffectsMeasurements =
- Build.VERSION.SDK_INT in 26..30 || // b/313868903
- artMainlineVersion in ART_MAINLINE_VERSIONS_AFFECTING_METHOD_TRACING // b/303660864
+ fun willMethodTracingAffectMeasurements(sdkInt: Int, artVersion: Long): Boolean =
+ sdkInt in 26..30 || // b/313868903
+ artVersion in ART_MAINLINE_VERSIONS_AFFECTING_METHOD_TRACING || // b/303660864
+ (sdkInt == 34 && artVersion >= ART_MAINLINE_INTERNAL_BUILD_MIN) // b/303686344#comment31
- fun isClassLoadTracingAvailable(targetApiLevel: Int, targetArtMainlineVersion: Long?): Boolean =
- targetApiLevel >= 35 ||
- (targetApiLevel >= 31 &&
- (targetArtMainlineVersion == null ||
- targetArtMainlineVersion >= ART_MAINLINE_MIN_VERSION_CLASS_LOAD_TRACING))
+ val methodTracingAffectsMeasurements =
+ willMethodTracingAffectMeasurements(Build.VERSION.SDK_INT, artMainlineVersion)
+
+ fun isClassLoadTracingAvailable(sdkInt: Int, artVersion: Long?): Boolean =
+ sdkInt >= 35 ||
+ (sdkInt >= 31 &&
+ (artVersion == null || artVersion >= ART_MAINLINE_MIN_VERSION_CLASS_LOAD_TRACING))
val supportsClassLoadTracing =
isClassLoadTracingAvailable(Build.VERSION.SDK_INT, artMainlineVersion)
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/MicrobenchmarkConfig.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/MicrobenchmarkConfig.kt
index 102de5e..d2dd087 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/MicrobenchmarkConfig.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/MicrobenchmarkConfig.kt
@@ -23,6 +23,7 @@
*/
@ExperimentalBenchmarkConfigApi
class MicrobenchmarkConfig
+@JvmOverloads
constructor(
/**
* Timing metrics for primary phase, post-warmup
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt
index 4810691..aaa9668 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Metric.kt
@@ -23,9 +23,7 @@
import androidx.benchmark.Shell
import androidx.benchmark.macro.BatteryCharge.hasMinimumCharge
import androidx.benchmark.macro.PowerMetric.Companion.deviceSupportsHighPrecisionTracking
-import androidx.benchmark.macro.PowerMetric.Type
import androidx.benchmark.macro.PowerRail.hasMetrics
-import androidx.benchmark.macro.TraceSectionMetric.Mode
import androidx.benchmark.macro.perfetto.BatteryDischargeQuery
import androidx.benchmark.macro.perfetto.FrameTimingQuery
import androidx.benchmark.macro.perfetto.FrameTimingQuery.SubMetric
@@ -730,8 +728,8 @@
.asMeasurements("artVerifyClass") +
if (
DeviceInfo.isClassLoadTracingAvailable(
- targetApiLevel = captureInfo.apiLevel,
- targetArtMainlineVersion = captureInfo.artMainlineVersion
+ sdkInt = captureInfo.apiLevel,
+ artVersion = captureInfo.artMainlineVersion
)
) {
traceSession
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt b/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
index 3325d22..f445c79 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
@@ -186,6 +186,12 @@
)
.joinToString()
)
+ // Acronyms that can be used in their all-caps form. "SQ" is included to allow "SQLite".
+ val allowedAcronyms = listOf("SQL", "SQ", "URL", "EGL", "GL", "KHR")
+ for (acronym in allowedAcronyms) {
+ args.add("--api-lint-allowed-acronym")
+ args.add(acronym)
+ }
val javaOnlyIssues = listOf("MissingJvmstatic", "ArrayReturn", "ValueClassDefinition")
val javaOnlyErrorLevel =
if (targetsJavaConsumers) {
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/AudioRestrictionController.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/AudioRestrictionController.kt
index 5a1ac48..954bda9 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/AudioRestrictionController.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/AudioRestrictionController.kt
@@ -67,8 +67,9 @@
get() = synchronized(lock) { field }
set(value: AudioRestrictionMode) {
synchronized(lock) {
+ val previousMode = computeAudioRestrictionMode()
field = value
- updateListenersMode()
+ updateListenersMode(previousMode)
}
}
@@ -80,15 +81,17 @@
mode: AudioRestrictionMode
) {
synchronized(lock) {
+ val previousMode = computeAudioRestrictionMode()
audioRestrictionModeMap[cameraGraph] = mode
- updateListenersMode()
+ updateListenersMode(previousMode)
}
}
override fun removeCameraGraph(cameraGraph: CameraGraph) {
synchronized(lock) {
+ val previousMode = computeAudioRestrictionMode()
audioRestrictionModeMap.remove(cameraGraph)
- updateListenersMode()
+ updateListenersMode(previousMode)
}
}
@@ -128,10 +131,12 @@
}
@GuardedBy("lock")
- private fun updateListenersMode() {
+ private fun updateListenersMode(previousMode: AudioRestrictionMode? = null) {
val mode = computeAudioRestrictionMode()
- for (listener in activeListeners) {
- listener.onCameraAudioRestrictionUpdated(mode)
+ if (previousMode != null && mode != previousMode) {
+ for (listener in activeListeners) {
+ listener.onCameraAudioRestrictionUpdated(mode)
+ }
}
}
}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/AudioRestrictionControllerImplTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/AudioRestrictionControllerImplTest.kt
index acdb35f..53b462e 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/AudioRestrictionControllerImplTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/AudioRestrictionControllerImplTest.kt
@@ -97,8 +97,8 @@
AUDIO_RESTRICTION_VIBRATION
)
- // Whenever a setter method is called, an update should be called on the listener
- verify(listener1, times(2))
+ // If the mode hasn't changed, there shouldn't be a second update call
+ verify(listener1, times(1))
.onCameraAudioRestrictionUpdated(AUDIO_RESTRICTION_VIBRATION_SOUND)
verify(listener1, never()).onCameraAudioRestrictionUpdated(AUDIO_RESTRICTION_VIBRATION)
}
@@ -114,8 +114,8 @@
)
audioRestrictionController.globalAudioRestrictionMode = AUDIO_RESTRICTION_VIBRATION
- // Whenever a setter method is called, an update should be called on the listener
- verify(listener1, times(2))
+ // If the mode hasn't changed, there shouldn't be a second update call
+ verify(listener1, times(1))
.onCameraAudioRestrictionUpdated(AUDIO_RESTRICTION_VIBRATION_SOUND)
verify(listener1, never()).onCameraAudioRestrictionUpdated(AUDIO_RESTRICTION_VIBRATION)
}
@@ -134,7 +134,7 @@
AUDIO_RESTRICTION_VIBRATION
)
- verify(listener1, times(2))
+ verify(listener1, times(1))
.onCameraAudioRestrictionUpdated(AUDIO_RESTRICTION_VIBRATION_SOUND)
audioRestrictionController.removeCameraGraph(cameraGraph1)
diff --git a/compose/foundation/foundation-layout/api/current.txt b/compose/foundation/foundation-layout/api/current.txt
index 0576ad7..7b4c673 100644
--- a/compose/foundation/foundation-layout/api/current.txt
+++ b/compose/foundation/foundation-layout/api/current.txt
@@ -111,81 +111,81 @@
method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier weight(androidx.compose.ui.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, optional boolean fill);
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.ContextualFlowColumnOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.ContextualFlowColumnOverflow.Companion Companion;
}
- public static final class ContextualFlowColumnOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Visible;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static final class ContextualFlowColumnOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Visible;
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnOverflowScope extends androidx.compose.foundation.layout.FlowColumnOverflowScope {
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnOverflowScope extends androidx.compose.foundation.layout.FlowColumnOverflowScope {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnScope extends androidx.compose.foundation.layout.ColumnScope {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxColumnWidth(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
- method public int getIndexInLine();
- method public int getLineIndex();
- method public float getMaxHeightInLine();
- method public float getMaxWidth();
- property public abstract int indexInLine;
- property public abstract int lineIndex;
- property public abstract float maxHeightInLine;
- property public abstract float maxWidth;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnScope extends androidx.compose.foundation.layout.ColumnScope {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxColumnWidth(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
+ method @Deprecated public int getIndexInLine();
+ method @Deprecated public int getLineIndex();
+ method @Deprecated public float getMaxHeightInLine();
+ method @Deprecated public float getMaxWidth();
+ property @Deprecated public abstract int indexInLine;
+ property @Deprecated public abstract int lineIndex;
+ property @Deprecated public abstract float maxHeightInLine;
+ property @Deprecated public abstract float maxWidth;
}
public final class ContextualFlowLayoutKt {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowColumn(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowColumnOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowColumnScope,? super java.lang.Integer,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowRow(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowRowOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowRowScope,? super java.lang.Integer,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowColumn(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowColumnOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowColumnScope,? super java.lang.Integer,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowRow(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowRowOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowRowScope,? super java.lang.Integer,kotlin.Unit> content);
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.ContextualFlowRowOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.ContextualFlowRowOverflow.Companion Companion;
}
- public static final class ContextualFlowRowOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Visible;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static final class ContextualFlowRowOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Visible;
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowOverflowScope extends androidx.compose.foundation.layout.FlowRowOverflowScope {
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowOverflowScope extends androidx.compose.foundation.layout.FlowRowOverflowScope {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowScope extends androidx.compose.foundation.layout.RowScope {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxRowHeight(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
- method public int getIndexInLine();
- method public int getLineIndex();
- method public float getMaxHeight();
- method public float getMaxWidthInLine();
- property public abstract int indexInLine;
- property public abstract int lineIndex;
- property public abstract float maxHeight;
- property public abstract float maxWidthInLine;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowScope extends androidx.compose.foundation.layout.RowScope {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxRowHeight(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
+ method @Deprecated public int getIndexInLine();
+ method @Deprecated public int getLineIndex();
+ method @Deprecated public float getMaxHeight();
+ method @Deprecated public float getMaxWidthInLine();
+ property @Deprecated public abstract int indexInLine;
+ property @Deprecated public abstract int lineIndex;
+ property @Deprecated public abstract float maxHeight;
+ property @Deprecated public abstract float maxWidthInLine;
}
@SuppressCompatibility @kotlin.RequiresOptIn(message="The API of this layout is experimental and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalLayoutApi {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.FlowColumnOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.FlowColumnOverflow.Companion Companion;
}
- public static final class FlowColumnOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Visible;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static final class FlowColumnOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Visible;
}
@SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface FlowColumnOverflowScope extends androidx.compose.foundation.layout.FlowColumnScope {
@@ -200,24 +200,26 @@
}
public final class FlowLayoutKt {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.FlowColumnOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.FlowRowOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.FlowColumnOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnScope,kotlin.Unit> content);
+ method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.FlowRowOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static void FlowRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowScope,kotlin.Unit> content);
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public abstract sealed class FlowLayoutOverflow {
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public abstract sealed class FlowLayoutOverflow {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.FlowRowOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.FlowRowOverflow.Companion Companion;
}
- public static final class FlowRowOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Visible;
+ @Deprecated public static final class FlowRowOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Visible;
}
@SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface FlowRowOverflowScope extends androidx.compose.foundation.layout.FlowRowScope {
diff --git a/compose/foundation/foundation-layout/api/restricted_current.txt b/compose/foundation/foundation-layout/api/restricted_current.txt
index 1a68ea9..438f4c8 100644
--- a/compose/foundation/foundation-layout/api/restricted_current.txt
+++ b/compose/foundation/foundation-layout/api/restricted_current.txt
@@ -116,81 +116,81 @@
method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier weight(androidx.compose.ui.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, optional boolean fill);
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.ContextualFlowColumnOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.ContextualFlowColumnOverflow.Companion Companion;
}
- public static final class ContextualFlowColumnOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Visible;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static final class ContextualFlowColumnOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowColumnOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowColumnOverflow Visible;
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnOverflowScope extends androidx.compose.foundation.layout.FlowColumnOverflowScope {
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnOverflowScope extends androidx.compose.foundation.layout.FlowColumnOverflowScope {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnScope extends androidx.compose.foundation.layout.ColumnScope {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxColumnWidth(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
- method public int getIndexInLine();
- method public int getLineIndex();
- method public float getMaxHeightInLine();
- method public float getMaxWidth();
- property public abstract int indexInLine;
- property public abstract int lineIndex;
- property public abstract float maxHeightInLine;
- property public abstract float maxWidth;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowColumnScope extends androidx.compose.foundation.layout.ColumnScope {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxColumnWidth(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
+ method @Deprecated public int getIndexInLine();
+ method @Deprecated public int getLineIndex();
+ method @Deprecated public float getMaxHeightInLine();
+ method @Deprecated public float getMaxWidth();
+ property @Deprecated public abstract int indexInLine;
+ property @Deprecated public abstract int lineIndex;
+ property @Deprecated public abstract float maxHeightInLine;
+ property @Deprecated public abstract float maxWidth;
}
public final class ContextualFlowLayoutKt {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowColumn(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowColumnOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowColumnScope,? super java.lang.Integer,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowRow(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowRowOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowRowScope,? super java.lang.Integer,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowColumn(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowColumnOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowColumnScope,? super java.lang.Integer,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void ContextualFlowRow(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.ContextualFlowRowOverflow overflow, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ContextualFlowRowScope,? super java.lang.Integer,kotlin.Unit> content);
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.ContextualFlowRowOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class ContextualFlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.ContextualFlowRowOverflow.Companion Companion;
}
- public static final class ContextualFlowRowOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Visible;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static final class ContextualFlowRowOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.ContextualFlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.ContextualFlowRowOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.ContextualFlowRowOverflow Visible;
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowOverflowScope extends androidx.compose.foundation.layout.FlowRowOverflowScope {
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowOverflowScope extends androidx.compose.foundation.layout.FlowRowOverflowScope {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowScope extends androidx.compose.foundation.layout.RowScope {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxRowHeight(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
- method public int getIndexInLine();
- method public int getLineIndex();
- method public float getMaxHeight();
- method public float getMaxWidthInLine();
- property public abstract int indexInLine;
- property public abstract int lineIndex;
- property public abstract float maxHeight;
- property public abstract float maxWidthInLine;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface ContextualFlowRowScope extends androidx.compose.foundation.layout.RowScope {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.ui.Modifier fillMaxRowHeight(androidx.compose.ui.Modifier, optional @FloatRange(from=0.0, to=1.0) float fraction);
+ method @Deprecated public int getIndexInLine();
+ method @Deprecated public int getLineIndex();
+ method @Deprecated public float getMaxHeight();
+ method @Deprecated public float getMaxWidthInLine();
+ property @Deprecated public abstract int indexInLine;
+ property @Deprecated public abstract int lineIndex;
+ property @Deprecated public abstract float maxHeight;
+ property @Deprecated public abstract float maxWidthInLine;
}
@SuppressCompatibility @kotlin.RequiresOptIn(message="The API of this layout is experimental and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalLayoutApi {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.FlowColumnOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowColumnOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.FlowColumnOverflow.Companion Companion;
}
- public static final class FlowColumnOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Visible;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static final class FlowColumnOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowColumnOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit> collapseIndicator, optional int minColumnsToShowCollapse, optional float minWidthToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowColumnOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowColumnOverflow Visible;
}
@SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface FlowColumnOverflowScope extends androidx.compose.foundation.layout.FlowColumnScope {
@@ -205,26 +205,28 @@
}
public final class FlowLayoutKt {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.FlowColumnOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.FlowRowOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, optional androidx.compose.foundation.layout.FlowColumnOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnScope,kotlin.Unit> content);
+ method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Horizontal itemHorizontalAlignment, optional int maxItemsInEachColumn, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowColumnScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public static void FlowRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, optional androidx.compose.foundation.layout.FlowRowOverflow overflow, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable public static void FlowRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Vertical itemVerticalAlignment, optional int maxItemsInEachRow, optional int maxLines, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowScope,kotlin.Unit> content);
method @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.compose.ui.layout.MeasurePolicy columnMeasurementHelper(androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, int maxItemsInMainAxis);
method @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.compose.ui.layout.MeasurePolicy rowMeasurementHelper(androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, int maxItemsInMainAxis);
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public abstract sealed class FlowLayoutOverflow {
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public abstract sealed class FlowLayoutOverflow {
}
- @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
- field public static final androidx.compose.foundation.layout.FlowRowOverflow.Companion Companion;
+ @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final class FlowRowOverflow extends androidx.compose.foundation.layout.FlowLayoutOverflow {
+ field @Deprecated public static final androidx.compose.foundation.layout.FlowRowOverflow.Companion Companion;
}
- public static final class FlowRowOverflow.Companion {
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> content);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getClip();
- method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getVisible();
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Clip;
- property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Visible;
+ @Deprecated public static final class FlowRowOverflow.Companion {
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow expandIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> content);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.FlowRowOverflow expandOrCollapseIndicator(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> expandIndicator, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit> collapseIndicator, optional int minRowsToShowCollapse, optional float minHeightToShowCollapse);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getClip();
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public androidx.compose.foundation.layout.FlowRowOverflow getVisible();
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Clip;
+ property @Deprecated @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public final androidx.compose.foundation.layout.FlowRowOverflow Visible;
}
@SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Stable public interface FlowRowOverflowScope extends androidx.compose.foundation.layout.FlowRowScope {
diff --git a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowColumnSample.kt b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowColumnSample.kt
index 6a7c208..96dae13 100644
--- a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowColumnSample.kt
+++ b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowColumnSample.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout.samples
import androidx.annotation.Sampled
diff --git a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowRowSample.kt b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowRowSample.kt
index f0eda4d..d10e927 100644
--- a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowRowSample.kt
+++ b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/ContextualFlowRowSample.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout.samples
import androidx.annotation.Sampled
diff --git a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowColumnSample.kt b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowColumnSample.kt
index ca95c71..5b45c21 100644
--- a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowColumnSample.kt
+++ b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowColumnSample.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout.samples
import androidx.annotation.Sampled
diff --git a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowRowSample.kt b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowRowSample.kt
index 15f5304..cd41109 100644
--- a/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowRowSample.kt
+++ b/compose/foundation/foundation-layout/samples/src/main/java/androidx/compose/foundation/layout/samples/FlowRowSample.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout.samples
import androidx.annotation.Sampled
diff --git a/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/ContextualFlowRowColumnTest.kt b/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/ContextualFlowRowColumnTest.kt
index 086f752..1ee8cd1 100644
--- a/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/ContextualFlowRowColumnTest.kt
+++ b/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/ContextualFlowRowColumnTest.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout
import androidx.compose.foundation.background
diff --git a/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/FlowRowColumnTest.kt b/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/FlowRowColumnTest.kt
index 9c2a063..f7038c5 100644
--- a/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/FlowRowColumnTest.kt
+++ b/compose/foundation/foundation-layout/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/layout/FlowRowColumnTest.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout
import androidx.compose.foundation.background
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/ContextualFlowLayout.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/ContextualFlowLayout.kt
index a22b962..885285d 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/ContextualFlowLayout.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/ContextualFlowLayout.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout
import androidx.annotation.FloatRange
@@ -62,6 +64,7 @@
* @see FlowRow
* @see ContextualFlowColumn
*/
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@Composable
@ExperimentalLayoutApi
fun ContextualFlowRow(
@@ -136,6 +139,7 @@
* @see FlowColumn
* @see ContextualFlowRow
*/
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@Composable
@ExperimentalLayoutApi
fun ContextualFlowColumn(
@@ -181,6 +185,7 @@
}
/** Defines the scope for items within a [ContextualFlowRow]. */
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@LayoutScopeMarker
@Stable
@ExperimentalLayoutApi
@@ -248,18 +253,21 @@
}
/** Scope for the overflow [ContextualFlowRow]. */
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@LayoutScopeMarker
@Stable
@ExperimentalLayoutApi
interface ContextualFlowRowOverflowScope : FlowRowOverflowScope
/** Scope for the overflow [ContextualFlowColumn]. */
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@LayoutScopeMarker
@Stable
@ExperimentalLayoutApi
interface ContextualFlowColumnOverflowScope : FlowColumnOverflowScope
/** Provides a scope for items within a [ContextualFlowColumn]. */
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@LayoutScopeMarker
@Stable
@ExperimentalLayoutApi
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayout.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayout.kt
index 8417dd1..0b50860 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayout.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayout.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout
import androidx.annotation.FloatRange
@@ -80,9 +82,9 @@
* @param overflow The strategy to handle overflowing items
* @param content The content as a [RowScope]
* @see FlowColumn
- * @see ContextualFlowRow
* @see [androidx.compose.foundation.layout.Row]
*/
+@Deprecated("The overflow parameter has been deprecated")
@Composable
@ExperimentalLayoutApi
fun FlowRow(
@@ -117,6 +119,58 @@
}
/**
+ * [FlowRow] is a layout that fills items from left to right (ltr) in LTR layouts or right to left
+ * (rtl) in RTL layouts and when it runs out of space, moves to the next "row" or "line" positioned
+ * on the bottom, and then continues filling items until the items run out.
+ *
+ * Example:
+ *
+ * @sample androidx.compose.foundation.layout.samples.SimpleFlowRow
+ *
+ * When a Modifier [RowScope.weight] is provided, it scales the item based on the number items that
+ * fall on the row it was placed in.
+ *
+ * Note that if two or more Text components are placed in a [Row], normally they should be aligned
+ * by their first baselines. [FlowRow] as a general purpose container does not do it automatically
+ * so developers need to handle this manually. This is achieved by adding a
+ * [RowScope.alignByBaseline] modifier to every such Text component. By default this modifier aligns
+ * by [androidx.compose.ui.layout.FirstBaseline]. If, however, you need to align Texts by
+ * [androidx.compose.ui.layout.LastBaseline] for example, use a more general [RowScope.alignBy]
+ * modifier.
+ *
+ * @param modifier The modifier to be applied to the Row.
+ * @param horizontalArrangement The horizontal arrangement of the layout's children.
+ * @param verticalArrangement The vertical arrangement of the layout's virtual rows.
+ * @param itemVerticalAlignment The cross axis/vertical alignment of an item in the column.
+ * @param maxItemsInEachRow The maximum number of items per row
+ * @param maxLines The max number of rows
+ * @param content The content as a [RowScope]
+ * @see FlowColumn
+ * @see [androidx.compose.foundation.layout.Row]
+ */
+@OptIn(ExperimentalLayoutApi::class)
+@Composable
+fun FlowRow(
+ modifier: Modifier = Modifier,
+ horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
+ verticalArrangement: Arrangement.Vertical = Arrangement.Top,
+ itemVerticalAlignment: Alignment.Vertical = Alignment.Top,
+ maxItemsInEachRow: Int = Int.MAX_VALUE,
+ maxLines: Int = Int.MAX_VALUE,
+ content: @Composable FlowRowScope.() -> Unit
+) =
+ FlowRow(
+ modifier,
+ horizontalArrangement,
+ verticalArrangement,
+ itemVerticalAlignment,
+ maxItemsInEachRow,
+ maxLines,
+ FlowRowOverflow.Clip,
+ content,
+ )
+
+/**
* [FlowColumn] is a layout that fills items from top to bottom, and when it runs out of space on
* the bottom, moves to the next "column" or "line" on the right or left based on ltr or rtl
* layouts, and then continues filling items from top to bottom.
@@ -144,6 +198,7 @@
* @see ContextualFlowColumn
* @see [androidx.compose.foundation.layout.Column]
*/
+@Deprecated("The overflow parameter has been deprecated")
@Composable
@ExperimentalLayoutApi
fun FlowColumn(
@@ -176,6 +231,54 @@
Layout(contents = list, measurePolicy = measurePolicy, modifier = modifier)
}
+/**
+ * [FlowColumn] is a layout that fills items from top to bottom, and when it runs out of space on
+ * the bottom, moves to the next "column" or "line" on the right or left based on ltr or rtl
+ * layouts, and then continues filling items from top to bottom.
+ *
+ * It supports ltr in LTR layouts, by placing the first column to the left, and then moving to the
+ * right It supports rtl in RTL layouts, by placing the first column to the right, and then moving
+ * to the left
+ *
+ * Example:
+ *
+ * @sample androidx.compose.foundation.layout.samples.SimpleFlowColumn
+ *
+ * When a Modifier [ColumnScope.weight] is provided, it scales the item based on the number items
+ * that fall on the column it was placed in.
+ *
+ * @param modifier The modifier to be applied to the Row.
+ * @param verticalArrangement The vertical arrangement of the layout's children.
+ * @param horizontalArrangement The horizontal arrangement of the layout's virtual columns
+ * @param itemHorizontalAlignment The cross axis/horizontal alignment of an item in the column.
+ * @param maxItemsInEachColumn The maximum number of items per column
+ * @param maxLines The max number of rows
+ * @param content The content as a [ColumnScope]
+ * @see FlowRow
+ * @see [androidx.compose.foundation.layout.Column]
+ */
+@Composable
+@ExperimentalLayoutApi
+fun FlowColumn(
+ modifier: Modifier = Modifier,
+ verticalArrangement: Arrangement.Vertical = Arrangement.Top,
+ horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
+ itemHorizontalAlignment: Alignment.Horizontal = Alignment.Start,
+ maxItemsInEachColumn: Int = Int.MAX_VALUE,
+ maxLines: Int = Int.MAX_VALUE,
+ content: @Composable FlowColumnScope.() -> Unit
+) =
+ FlowColumn(
+ modifier,
+ verticalArrangement,
+ horizontalArrangement,
+ itemHorizontalAlignment,
+ maxItemsInEachColumn,
+ maxLines,
+ FlowColumnOverflow.Clip,
+ content,
+ )
+
/** Scope for the children of [FlowRow]. */
@LayoutScopeMarker
@Stable
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutBuildingBlocks.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutBuildingBlocks.kt
index 956bd2c..5f056b2 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutBuildingBlocks.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutBuildingBlocks.kt
@@ -64,6 +64,7 @@
return ellipsisInfo
}
+ @Suppress("DEPRECATION")
fun getWrapInfo(
nextItemHasNext: Boolean,
nextIndexInLine: Int,
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutOverflow.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutOverflow.kt
index 686fcc8..5912c7c 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutOverflow.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/FlowLayoutOverflow.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.foundation.layout
import androidx.collection.IntIntPair
@@ -54,6 +56,7 @@
* - [expandOrCollapseIndicator]: Extends the [expandIndicator] functionality by adding a 'Collapse'
* option. After expanding the content, users can choose to collapse it back to the summary view.
*/
+@Deprecated("FlowLayout overflow is no longer maintained")
@ExperimentalLayoutApi
class FlowRowOverflow
private constructor(
@@ -188,6 +191,7 @@
* - [expandOrCollapseIndicator]: Extends the [expandIndicator] functionality by adding a 'Collapse'
* option. After expanding the content, users can choose to collapse it back to the summary view.
*/
+@Deprecated("FlowLayout overflow is no longer maintained")
@ExperimentalLayoutApi
class FlowColumnOverflow
private constructor(
@@ -204,6 +208,8 @@
seeMoreGetter,
collapseGetter
) {
+ @Deprecated("FlowLayout overflow is no longer maintained")
+ @ExperimentalLayoutApi
companion object {
/** Display all content, even if there is not enough space in the specified bounds. */
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
@@ -323,6 +329,7 @@
* - [expandOrCollapseIndicator]: Extends the [expandIndicator] functionality by adding a 'Collapse'
* option. After expanding the content, users can choose to collapse it back to the summary view.
*/
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@ExperimentalLayoutApi
class ContextualFlowRowOverflow
private constructor(
@@ -340,6 +347,8 @@
collapseGetter
) {
+ @Deprecated("FlowLayout overflow is no longer maintained")
+ @ExperimentalLayoutApi
companion object {
/** Display all content, even if there is not enough space in the specified bounds. */
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
@@ -462,6 +471,7 @@
* - [expandOrCollapseIndicator]: Extends the [expandIndicator] functionality by adding a 'Collapse'
* option. After expanding the content, users can choose to collapse it back to the summary view.
*/
+@Deprecated("ContextualFlowLayouts are no longer maintained")
@ExperimentalLayoutApi
class ContextualFlowColumnOverflow
private constructor(
@@ -479,6 +489,8 @@
collapseGetter
) {
+ @Deprecated("ContextualFlowLayouts are no longer maintained")
+ @ExperimentalLayoutApi
companion object {
/** Display all content, even if there is not enough space in the specified bounds. */
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
@@ -596,6 +608,7 @@
* @see [ContextualFlowRowOverflow]
* @see [ContextualFlowColumnOverflow]
*/
+@Deprecated("FlowLayout overflow is no longer maintained")
@ExperimentalLayoutApi
sealed class FlowLayoutOverflow(
internal val type: OverflowType,
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 48ebe5e..b4c8ef0 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -402,11 +402,15 @@
public final class CheckboxDefaults {
method @androidx.compose.runtime.Composable public androidx.compose.material3.CheckboxColors colors();
method @androidx.compose.runtime.Composable public androidx.compose.material3.CheckboxColors colors(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
+ method public float getStrokeWidth();
+ property public final float StrokeWidth;
field public static final androidx.compose.material3.CheckboxDefaults INSTANCE;
}
public final class CheckboxKt {
+ method @androidx.compose.runtime.Composable public static void Checkbox(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, androidx.compose.ui.graphics.drawscope.Stroke checkmarkStroke, androidx.compose.ui.graphics.drawscope.Stroke outlineStroke, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
method @androidx.compose.runtime.Composable public static void Checkbox(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
+ method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.ui.state.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, androidx.compose.ui.graphics.drawscope.Stroke checkmarkStroke, androidx.compose.ui.graphics.drawscope.Stroke outlineStroke, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.ui.state.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
}
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 48ebe5e..b4c8ef0 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -402,11 +402,15 @@
public final class CheckboxDefaults {
method @androidx.compose.runtime.Composable public androidx.compose.material3.CheckboxColors colors();
method @androidx.compose.runtime.Composable public androidx.compose.material3.CheckboxColors colors(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
+ method public float getStrokeWidth();
+ property public final float StrokeWidth;
field public static final androidx.compose.material3.CheckboxDefaults INSTANCE;
}
public final class CheckboxKt {
+ method @androidx.compose.runtime.Composable public static void Checkbox(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, androidx.compose.ui.graphics.drawscope.Stroke checkmarkStroke, androidx.compose.ui.graphics.drawscope.Stroke outlineStroke, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
method @androidx.compose.runtime.Composable public static void Checkbox(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
+ method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.ui.state.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, androidx.compose.ui.graphics.drawscope.Stroke checkmarkStroke, androidx.compose.ui.graphics.drawscope.Stroke outlineStroke, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.ui.state.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
}
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
index 6ab1a76..16faf52 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
@@ -43,6 +43,7 @@
import androidx.compose.material3.samples.CardSample
import androidx.compose.material3.samples.CenteredHorizontalFloatingToolbarWithFabSample
import androidx.compose.material3.samples.CenteredVerticalFloatingToolbarWithFabSample
+import androidx.compose.material3.samples.CheckboxRoundedStrokesSample
import androidx.compose.material3.samples.CheckboxSample
import androidx.compose.material3.samples.CheckboxWithTextSample
import androidx.compose.material3.samples.ChipGroupReflowSample
@@ -248,6 +249,7 @@
import androidx.compose.material3.samples.ToggleButtonWithIconSample
import androidx.compose.material3.samples.TonalSplitButtonSample
import androidx.compose.material3.samples.TonalToggleButtonSample
+import androidx.compose.material3.samples.TriStateCheckboxRoundedStrokesSample
import androidx.compose.material3.samples.TriStateCheckboxSample
import androidx.compose.material3.samples.TwoLineListItem
import androidx.compose.material3.samples.VerticalFloatingToolbarWithFabSample
@@ -585,12 +587,26 @@
CheckboxWithTextSample()
},
Example(
+ name = "CheckboxRoundedStrokesSample",
+ description = CheckboxesExampleDescription,
+ sourceUrl = CheckboxesExampleSourceUrl
+ ) {
+ CheckboxRoundedStrokesSample()
+ },
+ Example(
name = "TriStateCheckboxSample",
description = CheckboxesExampleDescription,
sourceUrl = CheckboxesExampleSourceUrl
) {
TriStateCheckboxSample()
- }
+ },
+ Example(
+ name = "TriStateCheckboxRoundedStrokesSample",
+ description = CheckboxesExampleDescription,
+ sourceUrl = CheckboxesExampleSourceUrl
+ ) {
+ TriStateCheckboxRoundedStrokesSample()
+ },
)
private const val ChipsExampleDescription = "Chips examples"
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/CheckboxSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/CheckboxSamples.kt
index c15860d..61d6130 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/CheckboxSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/CheckboxSamples.kt
@@ -27,6 +27,7 @@
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.selection.triStateToggleable
import androidx.compose.material3.Checkbox
+import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TriStateCheckbox
@@ -35,10 +36,15 @@
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.graphics.StrokeJoin
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import kotlin.math.floor
@Preview
@Sampled
@@ -79,6 +85,29 @@
@Preview
@Sampled
@Composable
+fun CheckboxRoundedStrokesSample() {
+ val strokeWidthPx = with(LocalDensity.current) { floor(CheckboxDefaults.StrokeWidth.toPx()) }
+ val checkmarkStroke =
+ remember(strokeWidthPx) {
+ Stroke(
+ width = strokeWidthPx,
+ cap = StrokeCap.Round,
+ join = StrokeJoin.Round,
+ )
+ }
+ val outlineStroke = remember(strokeWidthPx) { Stroke(width = strokeWidthPx) }
+ val checkedState = remember { mutableStateOf(true) }
+ Checkbox(
+ checked = checkedState.value,
+ onCheckedChange = { checkedState.value = it },
+ checkmarkStroke = checkmarkStroke,
+ outlineStroke = outlineStroke
+ )
+}
+
+@Preview
+@Sampled
+@Composable
fun TriStateCheckboxSample() {
Column {
// define dependent checkboxes states
@@ -146,3 +175,96 @@
}
}
}
+
+@Preview
+@Sampled
+@Composable
+fun TriStateCheckboxRoundedStrokesSample() {
+ val strokeWidthPx = with(LocalDensity.current) { floor(CheckboxDefaults.StrokeWidth.toPx()) }
+ val checkmarkStroke =
+ remember(strokeWidthPx) {
+ Stroke(
+ width = strokeWidthPx,
+ cap = StrokeCap.Round,
+ join = StrokeJoin.Round,
+ )
+ }
+ val outlineStroke = remember(strokeWidthPx) { Stroke(width = strokeWidthPx) }
+ Column {
+ // define dependent checkboxes states
+ val (state, onStateChange) = remember { mutableStateOf(true) }
+ val (state2, onStateChange2) = remember { mutableStateOf(true) }
+
+ // TriStateCheckbox state reflects state of dependent checkboxes
+ val parentState =
+ remember(state, state2) {
+ if (state && state2) ToggleableState.On
+ else if (!state && !state2) ToggleableState.Off else ToggleableState.Indeterminate
+ }
+ // click on TriStateCheckbox can set state for dependent checkboxes
+ val onParentClick = {
+ val s = parentState != ToggleableState.On
+ onStateChange(s)
+ onStateChange2(s)
+ }
+
+ // The sample below composes just basic checkboxes which are not fully accessible on their
+ // own. See the CheckboxWithTextSample as a way to ensure your checkboxes are fully
+ // accessible.
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier =
+ Modifier.triStateToggleable(
+ state = parentState,
+ onClick = onParentClick,
+ role = Role.Checkbox
+ )
+ ) {
+ TriStateCheckbox(
+ state = parentState,
+ onClick = null,
+ checkmarkStroke = checkmarkStroke,
+ outlineStroke = outlineStroke
+ )
+ Text("Receive Emails")
+ }
+ Spacer(Modifier.size(25.dp))
+ Column(Modifier.padding(24.dp, 0.dp, 0.dp, 0.dp)) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier =
+ Modifier.toggleable(
+ value = state,
+ onValueChange = onStateChange,
+ role = Role.Checkbox
+ )
+ ) {
+ Checkbox(
+ checked = state,
+ onCheckedChange = null,
+ checkmarkStroke = checkmarkStroke,
+ outlineStroke = outlineStroke
+ )
+ Text("Daily")
+ }
+ Spacer(Modifier.size(25.dp))
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier =
+ Modifier.toggleable(
+ value = state2,
+ onValueChange = onStateChange2,
+ role = Role.Checkbox
+ )
+ ) {
+ Checkbox(
+ checked = state2,
+ onCheckedChange = null,
+ checkmarkStroke = checkmarkStroke,
+ outlineStroke = outlineStroke
+ )
+ Text("Weekly")
+ }
+ }
+ }
+}
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxScreenshotTest.kt
index 7a2851b..e54b4b2 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxScreenshotTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxScreenshotTest.kt
@@ -29,8 +29,12 @@
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.graphics.StrokeJoin
+import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.input.InputMode
import androidx.compose.ui.input.InputModeManager
+import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalInputModeManager
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.state.ToggleableState
@@ -311,6 +315,73 @@
assertToggeableAgainstGolden("checkBox_${scheme.name}_customCheckboxColorsConstruct")
}
+ @Test
+ fun checkBox_customStroke_checked() {
+ rule.setMaterialContent(scheme.colorScheme) {
+ val stroke =
+ Stroke(
+ width = with(LocalDensity.current) { CheckboxDefaults.StrokeWidth.toPx() },
+ cap = StrokeCap.Round,
+ join = StrokeJoin.Round
+ )
+ Box(wrap.testTag(wrapperTestTag)) {
+ Checkbox(
+ modifier = wrap,
+ checked = true,
+ onCheckedChange = {},
+ checkmarkStroke = stroke,
+ outlineStroke = stroke
+ )
+ }
+ }
+ assertToggeableAgainstGolden("checkBox_${scheme.name}_customStroke_checked")
+ }
+
+ @Test
+ fun checkBox_customStroke_unchecked() {
+ rule.setMaterialContent(scheme.colorScheme) {
+ // Have the stroke thinner so we can verify it's being applied to the rounded box.
+ val stroke =
+ Stroke(
+ width = with(LocalDensity.current) { CheckboxDefaults.StrokeWidth.toPx() / 4 },
+ cap = StrokeCap.Round,
+ join = StrokeJoin.Round
+ )
+ Box(wrap.testTag(wrapperTestTag)) {
+ Checkbox(
+ modifier = wrap,
+ checked = false,
+ onCheckedChange = {},
+ checkmarkStroke = stroke,
+ outlineStroke = stroke
+ )
+ }
+ }
+ assertToggeableAgainstGolden("checkBox_${scheme.name}_customStroke_unchecked")
+ }
+
+ @Test
+ fun checkBox_customStroke_indeterminate() {
+ rule.setMaterialContent(scheme.colorScheme) {
+ val stroke =
+ Stroke(
+ width = with(LocalDensity.current) { CheckboxDefaults.StrokeWidth.toPx() },
+ cap = StrokeCap.Round,
+ join = StrokeJoin.Round
+ )
+ Box(wrap.testTag(wrapperTestTag)) {
+ TriStateCheckbox(
+ state = ToggleableState.Indeterminate,
+ checkmarkStroke = stroke,
+ outlineStroke = stroke,
+ modifier = wrap,
+ onClick = {}
+ )
+ }
+ }
+ assertToggeableAgainstGolden("checkBox_${scheme.name}_customStroke_indeterminate")
+ }
+
@Composable
private fun Checkboxes(colors: CheckboxColors) {
TriStateCheckbox(state = ToggleableState.Off, onClick = {}, colors = colors)
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxTest.kt
index 3b1550a..b979580 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/CheckboxTest.kt
@@ -27,6 +27,8 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.SemanticsProperties
@@ -54,6 +56,7 @@
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
@@ -230,11 +233,72 @@
)
}
- @OptIn(ExperimentalMaterial3Api::class)
+ @Test
+ fun checkBoxTest_MaterialSize_WhenChecked_withThickStroke_withoutMinimumTouchTarget() {
+ materialSizeTestForValue(
+ checkboxValue = On,
+ clickable = false, // Ensure a minimum size with clickable false and no min touch target
+ minimumTouchTarget = false,
+ strokeWidth = CheckboxDefaults.StrokeWidth * 3
+ )
+ }
+
+ @Test
+ fun checkBoxTest_MaterialSize_WhenChecked_withThinStroke_withoutMinimumTouchTarget() {
+ materialSizeTestForValue(
+ checkboxValue = On,
+ clickable = false, // Ensure a minimum size with clickable false and no min touch target
+ minimumTouchTarget = false,
+ strokeWidth = CheckboxDefaults.StrokeWidth / 3
+ )
+ }
+
+ @Test
+ fun checkBoxTest_MaterialSize_WhenUnchecked_withThickStroke_withoutMinimumTouchTarget() {
+ materialSizeTestForValue(
+ checkboxValue = Off,
+ clickable = false, // Ensure a minimum size with clickable false and no min touch target
+ minimumTouchTarget = false,
+ strokeWidth = CheckboxDefaults.StrokeWidth * 3
+ )
+ }
+
+ @Test
+ fun checkBoxTest_MaterialSize_WhenUnchecked_withThinStroke_withoutMinimumTouchTarget() {
+ materialSizeTestForValue(
+ checkboxValue = Off,
+ clickable = false, // Ensure a minimum size with clickable false and no min touch target
+ minimumTouchTarget = false,
+ strokeWidth = CheckboxDefaults.StrokeWidth / 3
+ )
+ }
+
+ @Test
+ fun checkBoxTest_MaterialSize_WhenIndeterminate_withThickStroke_withoutMinimumTouchTarget() {
+ materialSizeTestForValue(
+ checkboxValue = Indeterminate,
+ clickable = false, // Ensure a minimum size with clickable false and no min touch target
+ minimumTouchTarget = false,
+ strokeWidth = CheckboxDefaults.StrokeWidth * 3
+ )
+ }
+
+ @Test
+ fun checkBoxTest_MaterialSize_WhenIndeterminate_withThinStroke_withoutMinimumTouchTarget() {
+ materialSizeTestForValue(
+ checkboxValue = Indeterminate,
+ clickable = false, // Ensure a minimum size with clickable false and no min touch target
+ minimumTouchTarget = false,
+ strokeWidth = CheckboxDefaults.StrokeWidth / 3
+ )
+ }
+
+ @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
private fun materialSizeTestForValue(
checkboxValue: ToggleableState,
clickable: Boolean,
- minimumTouchTarget: Boolean
+ minimumTouchTarget: Boolean,
+ strokeWidth: Dp? = null,
) {
rule
.setMaterialContentForSizeAssertions {
@@ -242,14 +306,29 @@
LocalMinimumInteractiveComponentSize provides
if (minimumTouchTarget) 48.dp else 0.dp
) {
- TriStateCheckbox(
- state = checkboxValue,
- onClick =
- if (clickable) {
- {}
- } else null,
- enabled = false
- )
+ if (strokeWidth == null) {
+ TriStateCheckbox(
+ state = checkboxValue,
+ onClick =
+ if (clickable) {
+ {}
+ } else null,
+ enabled = false
+ )
+ } else {
+ val strokeWidthPx =
+ Stroke(width = with(LocalDensity.current) { strokeWidth.toPx() })
+ TriStateCheckbox(
+ state = checkboxValue,
+ onClick =
+ if (clickable) {
+ {}
+ } else null,
+ enabled = false,
+ checkmarkStroke = strokeWidthPx,
+ outlineStroke = strokeWidthPx
+ )
+ }
}
}
.run {
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt
index 0fd3f81..1888a07 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt
@@ -48,6 +48,7 @@
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.takeOrElse
+import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.unit.dp
@@ -96,6 +97,7 @@
colors: CheckboxColors = CheckboxDefaults.colors(),
interactionSource: MutableInteractionSource? = null
) {
+ val strokeWidthPx = with(LocalDensity.current) { floor(CheckboxDefaults.StrokeWidth.toPx()) }
TriStateCheckbox(
state = ToggleableState(checked),
onClick =
@@ -104,6 +106,72 @@
} else {
null
},
+ checkmarkStroke = Stroke(width = strokeWidthPx, cap = StrokeCap.Square),
+ outlineStroke = Stroke(width = strokeWidthPx),
+ modifier = modifier,
+ enabled = enabled,
+ colors = colors,
+ interactionSource = interactionSource
+ )
+}
+
+/**
+ * <a href="https://m3.material.io/components/checkbox/overview" class="external"
+ * target="_blank">Material Design checkbox</a>.
+ *
+ * Checkboxes allow users to select one or more items from a set. Checkboxes can turn an option on
+ * or off.
+ *
+ * 
+ *
+ * This Checkbox function offers greater flexibility in visual customization. Using the [Stroke]
+ * parameters, you can control the appearance of both the checkmark and the box that surrounds it.
+ *
+ * A sample of a `Checkbox` that uses a [Stroke] with rounded [StrokeCap] and
+ * [androidx.compose.ui.graphics.StrokeJoin]:
+ *
+ * @sample androidx.compose.material3.samples.CheckboxRoundedStrokesSample
+ * @param checked whether this checkbox is checked or unchecked
+ * @param onCheckedChange called when this checkbox is clicked. If `null`, then this checkbox will
+ * not be interactable, unless something else handles its input events and updates its state.
+ * @param checkmarkStroke stroke for the checkmark.
+ * @param outlineStroke stroke for the checkmark's box outline. Note that this stroke is applied
+ * when drawing the outline's rounded rectangle, so attributions such as
+ * [androidx.compose.ui.graphics.StrokeJoin] will be ignored.
+ * @param modifier the [Modifier] to be applied to this checkbox
+ * @param enabled controls the enabled state of this checkbox. When `false`, this component will not
+ * respond to user input, and it will appear visually disabled and disabled to accessibility
+ * services.
+ * @param colors [CheckboxColors] that will be used to resolve the colors used for this checkbox in
+ * different states. See [CheckboxDefaults.colors].
+ * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
+ * emitting [Interaction]s for this checkbox. You can use this to change the checkbox's appearance
+ * or preview the checkbox in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
+ * @see [TriStateCheckbox] if you require support for an indeterminate state.
+ */
+@Composable
+fun Checkbox(
+ checked: Boolean,
+ onCheckedChange: ((Boolean) -> Unit)?,
+ checkmarkStroke: Stroke,
+ outlineStroke: Stroke,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ colors: CheckboxColors = CheckboxDefaults.colors(),
+ interactionSource: MutableInteractionSource? = null
+) {
+ TriStateCheckbox(
+ state = ToggleableState(checked),
+ onClick =
+ if (onCheckedChange != null) {
+ { onCheckedChange(!checked) }
+ } else {
+ null
+ },
+ checkmarkStroke = checkmarkStroke,
+ outlineStroke = outlineStroke,
modifier = modifier,
enabled = enabled,
colors = colors,
@@ -148,6 +216,68 @@
colors: CheckboxColors = CheckboxDefaults.colors(),
interactionSource: MutableInteractionSource? = null
) {
+ val strokeWidthPx = with(LocalDensity.current) { floor(CheckboxDefaults.StrokeWidth.toPx()) }
+ TriStateCheckbox(
+ state = state,
+ onClick = onClick,
+ checkmarkStroke = Stroke(width = strokeWidthPx, cap = StrokeCap.Square),
+ outlineStroke = Stroke(width = strokeWidthPx),
+ modifier = modifier,
+ enabled = enabled,
+ colors = colors,
+ interactionSource = interactionSource
+ )
+}
+
+/**
+ * <a href="https://m3.material.io/components/checkbox/guidelines" class="external"
+ * target="_blank">Material Design checkbox</a> parent.
+ *
+ * Checkboxes can have a parent-child relationship with other checkboxes. When the parent checkbox
+ * is checked, all child checkboxes are checked. If a parent checkbox is unchecked, all child
+ * checkboxes are unchecked. If some, but not all, child checkboxes are checked, the parent checkbox
+ * becomes an indeterminate checkbox.
+ *
+ * 
+ *
+ * This Checkbox function offers greater flexibility in visual customization. Using the [Stroke]
+ * parameters, you can control the appearance of both the checkmark and the box that surrounds it.
+ *
+ * A sample of a `TriStateCheckbox` that uses a [Stroke] with rounded [StrokeCap] and
+ * [androidx.compose.ui.graphics.StrokeJoin]:
+ *
+ * @sample androidx.compose.material3.samples.TriStateCheckboxRoundedStrokesSample
+ * @param state whether this checkbox is checked, unchecked, or in an indeterminate state
+ * @param onClick called when this checkbox is clicked. If `null`, then this checkbox will not be
+ * interactable, unless something else handles its input events and updates its [state].
+ * @param checkmarkStroke stroke for the checkmark.
+ * @param outlineStroke stroke for the checkmark's box outline. Note that this stroke is applied
+ * when drawing the outline's rounded rectangle, so attributions such as
+ * [androidx.compose.ui.graphics.StrokeJoin] will be ignored.
+ * @param modifier the [Modifier] to be applied to this checkbox
+ * @param enabled controls the enabled state of this checkbox. When `false`, this component will not
+ * respond to user input, and it will appear visually disabled and disabled to accessibility
+ * services.
+ * @param colors [CheckboxColors] that will be used to resolve the colors used for this checkbox in
+ * different states. See [CheckboxDefaults.colors].
+ * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
+ * emitting [Interaction]s for this checkbox. You can use this to change the checkbox's appearance
+ * or preview the checkbox in different states. Note that if `null` is provided, interactions will
+ * still happen internally.
+ * @see [Checkbox] if you want a simple component that represents Boolean state
+ */
+@Composable
+fun TriStateCheckbox(
+ state: ToggleableState,
+ onClick: (() -> Unit)?,
+ checkmarkStroke: Stroke,
+ outlineStroke: Stroke,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ colors: CheckboxColors = CheckboxDefaults.colors(),
+ interactionSource: MutableInteractionSource? = null
+) {
val toggleableModifier =
if (onClick != null) {
Modifier.triStateToggleable(
@@ -175,7 +305,9 @@
)
.then(toggleableModifier)
.padding(CheckboxDefaultPadding),
- colors = colors
+ colors = colors,
+ checkmarkStroke = checkmarkStroke,
+ outlineStroke = outlineStroke
)
}
@@ -255,6 +387,12 @@
)
.also { defaultCheckboxColorsCached = it }
}
+
+ /**
+ * The default stroke width for a [Checkbox]. This width will be used for the checkmark when the
+ * `Checkbox` is in a checked or indeterminate states, or for the outline when it's unchecked.
+ */
+ val StrokeWidth = 2.dp
}
@Composable
@@ -262,7 +400,9 @@
enabled: Boolean,
value: ToggleableState,
modifier: Modifier,
- colors: CheckboxColors
+ colors: CheckboxColors,
+ checkmarkStroke: Stroke,
+ outlineStroke: Stroke,
) {
val transition = updateTransition(value)
val defaultAnimationSpec = MotionSchemeKeyTokens.DefaultSpatial.value<Float>()
@@ -306,31 +446,24 @@
val boxColor = colors.boxColor(enabled, value)
val borderColor = colors.borderColor(enabled, value)
Canvas(modifier.wrapContentSize(Alignment.Center).requiredSize(CheckboxSize)) {
- val strokeWidthPx = floor(StrokeWidth.toPx())
drawBox(
boxColor = boxColor.value,
borderColor = borderColor.value,
radius = RadiusSize.toPx(),
- strokeWidth = strokeWidthPx
+ stroke = outlineStroke
)
drawCheck(
checkColor = checkColor.value,
checkFraction = checkDrawFraction.value,
crossCenterGravitation = checkCenterGravitationShiftFraction.value,
- strokeWidthPx = strokeWidthPx,
+ stroke = checkmarkStroke,
drawingCache = checkCache
)
}
}
-private fun DrawScope.drawBox(
- boxColor: Color,
- borderColor: Color,
- radius: Float,
- strokeWidth: Float
-) {
- val halfStrokeWidth = strokeWidth / 2.0f
- val stroke = Stroke(strokeWidth)
+private fun DrawScope.drawBox(boxColor: Color, borderColor: Color, radius: Float, stroke: Stroke) {
+ val halfStrokeWidth = stroke.width / 2.0f
val checkboxSize = size.width
if (boxColor == borderColor) {
drawRoundRect(
@@ -342,15 +475,15 @@
} else {
drawRoundRect(
boxColor,
- topLeft = Offset(strokeWidth, strokeWidth),
- size = Size(checkboxSize - strokeWidth * 2, checkboxSize - strokeWidth * 2),
- cornerRadius = CornerRadius(max(0f, radius - strokeWidth)),
+ topLeft = Offset(stroke.width, stroke.width),
+ size = Size(checkboxSize - stroke.width * 2, checkboxSize - stroke.width * 2),
+ cornerRadius = CornerRadius(max(0f, radius - stroke.width)),
style = Fill
)
drawRoundRect(
borderColor,
topLeft = Offset(halfStrokeWidth, halfStrokeWidth),
- size = Size(checkboxSize - strokeWidth, checkboxSize - strokeWidth),
+ size = Size(checkboxSize - stroke.width, checkboxSize - stroke.width),
cornerRadius = CornerRadius(radius - halfStrokeWidth),
style = stroke
)
@@ -361,10 +494,9 @@
checkColor: Color,
checkFraction: Float,
crossCenterGravitation: Float,
- strokeWidthPx: Float,
+ stroke: Stroke,
drawingCache: CheckDrawingCache
) {
- val stroke = Stroke(width = strokeWidthPx, cap = StrokeCap.Square)
val width = size.width
val checkCrossX = 0.4f
val checkCrossY = 0.7f
@@ -380,13 +512,13 @@
val gravitatedRightY = lerp(rightY, 0.5f, crossCenterGravitation)
with(drawingCache) {
- checkPath.reset()
+ checkPath.rewind()
checkPath.moveTo(width * leftX, width * gravitatedLeftY)
checkPath.lineTo(width * gravitatedCrossX, width * gravitatedCrossY)
checkPath.lineTo(width * rightX, width * gravitatedRightY)
// TODO: replace with proper declarative non-android alternative when ready (b/158188351)
pathMeasure.setPath(checkPath, false)
- pathToDraw.reset()
+ pathToDraw.rewind()
pathMeasure.getSegment(0f, pathMeasure.length * checkFraction, pathToDraw, true)
}
drawPath(drawingCache.pathToDraw, checkColor, style = stroke)
@@ -607,5 +739,4 @@
// TODO(b/188529841): Update the padding and size when the Checkbox spec is finalized.
private val CheckboxDefaultPadding = 2.dp
private val CheckboxSize = 20.dp
-private val StrokeWidth = 2.dp
private val RadiusSize = 2.dp
diff --git a/compose/ui/ui-graphics/lint-baseline.xml b/compose/ui/ui-graphics/lint-baseline.xml
index 3255d39..862a7fe 100644
--- a/compose/ui/ui-graphics/lint-baseline.xml
+++ b/compose/ui/ui-graphics/lint-baseline.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.7.0-alpha02" type="baseline" client="gradle" dependencies="false" name="AGP (8.7.0-alpha02)" variant="all" version="8.7.0-alpha02">
+<issues format="6" by="lint 8.9.0-alpha06" type="baseline" client="gradle" dependencies="false" name="AGP (8.9.0-alpha06)" variant="all" version="8.9.0-alpha06">
<issue
id="NewApi"
- message="This Kotlin extension function will be hidden by `java.util.SequencedCollection` starting in API 35"
- errorLine1=" val node = s.removeLastKt()"
- errorLine2=" ~~~~~~~~~~~~~~~~">
+ message="Call requires API level 23 (current min is 21): `android.view.View#setForeground`"
+ errorLine1=" foreground = GraphicsContextHostDrawable(graphicsContext, block)"
+ errorLine2=" ~">
<location
- file="src/commonMain/kotlin/androidx/compose/ui/graphics/IntervalTree.kt"/>
+ file="src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt"/>
</issue>
<issue
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/URLSpanCache.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/URLSpanCache.android.kt
index 6418529..209fdb9 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/URLSpanCache.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/URLSpanCache.android.kt
@@ -42,8 +42,6 @@
*
* See b/253292081.
*/
-// "URL" violates naming guidelines, but that is intentional to match the platform API.
-@Suppress("AcronymName")
@OptIn(ExperimentalTextApi::class)
@InternalTextApi
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@@ -54,11 +52,9 @@
private val linkSpansWithListenerByAnnotation =
WeakHashMap<AnnotatedString.Range<LinkAnnotation>, ComposeClickableSpan>()
- @Suppress("AcronymName")
fun toURLSpan(urlAnnotation: UrlAnnotation): URLSpan =
spansByAnnotation.getOrPut(urlAnnotation) { URLSpan(urlAnnotation.url) }
- @Suppress("AcronymName")
fun toURLSpan(urlRange: AnnotatedString.Range<LinkAnnotation.Url>): URLSpan =
urlSpansByAnnotation.getOrPut(urlRange) { URLSpan(urlRange.item.url) }
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
index 73d5f2c..57eb795 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
+
package androidx.compose.ui.layout
import androidx.activity.ComponentActivity
@@ -1282,6 +1284,7 @@
}
}
+ @Suppress("DEPRECATION")
@OptIn(ExperimentalLayoutApi::class)
@Test
fun testNestedLookaheadPlacement() {
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/FocusSearchLeftInteropTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/FocusSearchLeftInteropTest.kt
index dacdc31..cfeedac 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/FocusSearchLeftInteropTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/viewinterop/FocusSearchLeftInteropTest.kt
@@ -47,6 +47,7 @@
import androidx.compose.ui.test.requestFocus
import androidx.compose.ui.unit.dp
import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
@@ -448,6 +449,7 @@
}
@Test
+ @SdkSuppress(minSdkVersion = 23) // b/387310914 -- flaky on API 21
fun viewComposableInRow() {
// Arrange.
setContent {
diff --git a/core/core-ktx/api/api_lint.ignore b/core/core-ktx/api/api_lint.ignore
index 3cac25a..2373a95 100644
--- a/core/core-ktx/api/api_lint.ignore
+++ b/core/core-ktx/api/api_lint.ignore
@@ -1,8 +1,4 @@
// Baseline format: 1.0
-AcronymName: androidx.core.database.sqlite.SQLiteDatabaseKt:
- Acronyms should not be capitalized in class names: was `SQLiteDatabaseKt`, should this be `SqLiteDatabaseKt`?
-
-
AutoBoxing: androidx.core.database.CursorKt#getDoubleOrNull(android.database.Cursor, int):
Must avoid boxed primitives (`java.lang.Double`)
AutoBoxing: androidx.core.database.CursorKt#getFloatOrNull(android.database.Cursor, int):
diff --git a/core/core/api/api_lint.ignore b/core/core/api/api_lint.ignore
index c28cad6..966f30a 100644
--- a/core/core/api/api_lint.ignore
+++ b/core/core/api/api_lint.ignore
@@ -1,6 +1,4 @@
// Baseline format: 1.0
-AcronymName: androidx.core.database.sqlite.SQLiteCursorCompat:
- Acronyms should not be capitalized in class names: was `SQLiteCursorCompat`, should this be `SqLiteCursorCompat`?
AcronymName: androidx.core.graphics.ColorUtils#blendARGB(int, int, float):
Acronyms should not be capitalized in method names: was `blendARGB`, should this be `blendArgb`?
AcronymName: androidx.core.graphics.ColorUtils#blendHSL(float[], float[], float, float[]):
diff --git a/credentials/credentials/src/androidTest/java/androidx/credentials/CredentialProviderFactoryTest.kt b/credentials/credentials/src/androidTest/java/androidx/credentials/CredentialProviderFactoryTest.kt
index 30a90a7..979a543 100644
--- a/credentials/credentials/src/androidTest/java/androidx/credentials/CredentialProviderFactoryTest.kt
+++ b/credentials/credentials/src/androidTest/java/androidx/credentials/CredentialProviderFactoryTest.kt
@@ -17,6 +17,7 @@
import android.os.Build
import androidx.credentials.ClearCredentialStateRequest.Companion.TYPE_CLEAR_RESTORE_CREDENTIAL
+import androidx.credentials.internal.FormFactorHelper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
@@ -239,4 +240,36 @@
assertThat(credentialProviderFactory.getBestAvailableProvider(request))
.isEqualTo(expectedProvider)
}
+
+ @Test
+ fun getBestAvailableProvider_onTV_preUSuccess() {
+ if (!FormFactorHelper.isTV(context)) {
+ return
+ }
+ clearState()
+ val expectedPreUProvider = FakeProvider(success = true)
+ credentialProviderFactory.testMode = true
+ credentialProviderFactory.testPreUProvider = expectedPreUProvider
+
+ val actualProvider = credentialProviderFactory.getBestAvailableProvider()
+
+ assertThat(actualProvider).isNotNull()
+ assertThat(actualProvider).isEqualTo(expectedPreUProvider)
+ }
+
+ @Test
+ fun getBestAvailableProvider_onAuto_preUSuccess() {
+ if (!FormFactorHelper.isAuto(context)) {
+ return
+ }
+ clearState()
+ val expectedPreUProvider = FakeProvider(success = true)
+ credentialProviderFactory.testMode = true
+ credentialProviderFactory.testPreUProvider = expectedPreUProvider
+
+ val actualProvider = credentialProviderFactory.getBestAvailableProvider()
+
+ assertThat(actualProvider).isNotNull()
+ assertThat(actualProvider).isEqualTo(expectedPreUProvider)
+ }
}
diff --git a/credentials/credentials/src/main/java/androidx/credentials/CredentialProviderFactory.kt b/credentials/credentials/src/main/java/androidx/credentials/CredentialProviderFactory.kt
index 0155a98..9d811357 100644
--- a/credentials/credentials/src/main/java/androidx/credentials/CredentialProviderFactory.kt
+++ b/credentials/credentials/src/main/java/androidx/credentials/CredentialProviderFactory.kt
@@ -24,6 +24,7 @@
import androidx.annotation.RestrictTo
import androidx.annotation.VisibleForTesting
import androidx.credentials.ClearCredentialStateRequest.Companion.TYPE_CLEAR_RESTORE_CREDENTIAL
+import androidx.credentials.internal.FormFactorHelper
/** Factory that returns the credential provider to be used by Credential Manager. */
@OptIn(ExperimentalDigitalCredentialApi::class)
@@ -94,6 +95,10 @@
* library. Post-U, providers will be registered with the framework, and enabled by the user.
*/
fun getBestAvailableProvider(shouldFallbackToPreU: Boolean = true): CredentialProvider? {
+ if (FormFactorHelper.isTV(context) || FormFactorHelper.isAuto(context)) {
+ return tryCreateClosedSourceProviderFromManifest()
+ }
+
if (Build.VERSION.SDK_INT >= 34) { // Android U
val postUProvider = tryCreatePostUProvider()
if (postUProvider == null && shouldFallbackToPreU) {
diff --git a/credentials/credentials/src/main/java/androidx/credentials/internal/FormFactorHelper.kt b/credentials/credentials/src/main/java/androidx/credentials/internal/FormFactorHelper.kt
new file mode 100644
index 0000000..e669f38
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/internal/FormFactorHelper.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.credentials.internal
+
+import android.content.Context
+import android.content.pm.PackageManager
+import androidx.annotation.RestrictTo
+
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+object FormFactorHelper {
+ /** Determines whether the device is a TV. */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @JvmStatic
+ fun isTV(ctx: Context): Boolean {
+ val pm = ctx.packageManager
+ return pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ }
+
+ /** Determines whether the device is a Wearable. */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @JvmStatic
+ fun isWear(ctx: Context): Boolean {
+ val pm = ctx.packageManager
+ return pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ }
+
+ /** Determines whether the device is a Auto. */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @JvmStatic
+ fun isAuto(ctx: Context): Boolean {
+ val pm = ctx.packageManager
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ }
+}
diff --git a/development/update_studio.sh b/development/update_studio.sh
index d4b0ff3..9d33240 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -15,8 +15,8 @@
# Versions that the user should update when running this script
echo Getting Studio version and link
-AGP_VERSION=${1:-8.9.0-alpha01}
-STUDIO_VERSION_STRING=${2:-"Android Studio Meerkat | 2024.3.1 Canary 1"}
+AGP_VERSION=${1:-8.9.0-beta01}
+STUDIO_VERSION_STRING=${2:-"Android Studio Meerkat | 2024.3.1 Beta 1"}
# Get studio version number from version name
STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep "<iframe " | sed "s/.* src=\"\([^\"]*\)\".*/\1/g"`
@@ -68,7 +68,7 @@
| tail -n +3 \
| sed '$ d') # Remove the last line
-ATP_VERSION=${4:-0.0.9-alpha02}
+ATP_VERSION=${4:-0.0.9-alpha03}
ARTIFACTS_TO_DOWNLOAD+="com.google.testing.platform:android-test-plugin:$ATP_VERSION,"
ARTIFACTS_TO_DOWNLOAD+="com.google.testing.platform:launcher:$ATP_VERSION,"
ARTIFACTS_TO_DOWNLOAD+="com.google.testing.platform:android-driver-instrumentation:$ATP_VERSION,"
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index 5b7b2a45..7a218f8 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -249,7 +249,7 @@
docs(project(":navigation:navigation-fragment"))
docs(project(":navigation:navigation-fragment-compose"))
docs(project(":navigation:navigation-fragment-ktx"))
- docs(project(":navigation:navigation-runtime"))
+ kmpDocs(project(":navigation:navigation-runtime"))
docs(project(":navigation:navigation-runtime-ktx"))
docs(project(":navigation:navigation-testing"))
docs(project(":navigation:navigation-ui"))
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 510a96e..52b9bda 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,13 +2,13 @@
# -----------------------------------------------------------------------------
# All of the following should be updated in sync.
# -----------------------------------------------------------------------------
-androidGradlePlugin = "8.9.0-alpha01"
+androidGradlePlugin = "8.9.0-beta01"
# NOTE: When updating the lint version we also need to update the `api` version
# supported by `IssueRegistry`'s.' For e.g. r.android.com/1331903
-androidLint = "31.9.0-alpha01"
+androidLint = "31.9.0-beta01"
# Once you have a chosen version of AGP to upgrade to, go to
# https://developer.android.com/studio/archive and find the matching version of Studio.
-androidStudio = "2024.3.1.1"
+androidStudio = "2024.3.1.10"
# -----------------------------------------------------------------------------
androidLintMin = "31.1.0"
diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys
index 322947c..b9e6596 100644
--- a/gradle/verification-keyring.keys
+++ b/gradle/verification-keyring.keys
@@ -4081,6 +4081,40 @@
=Q+9k
-----END PGP PUBLIC KEY BLOCK-----
+pub EB095DA7D2F6AC0E
+sub 603D72C90616CD6B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v@RELEASE_NAME@
+
+mQGNBGBm/LQBDADMr/VPcTvE6k3wEYxq5kZusnDCDTsI6RK51d4oMwaRc3Z0jtZ0
+CfyWocZBok4rMbZAVnE3Q8pMyikGGUnc8ZsWoPEmJyCpw/2Orj0QqZhIgYMQ31Uq
+tiGZF/G4w9phLIkFgU9BLGYjRNM69R0oE/Tj8mjguvnKzYM3GjkY6nDsgWCM5TJX
+01k4sdLs0dVg86m4keq+SeS9uEwnINZTh6kQUKsW6aHvvPXze/UPoaZqxgXDjF+F
+JrPwW8yDllkbzpbo53ulz1TL5RsIH3daUwxXG3ciovUXG/b2ZRuWjtH7Gn/AvCNL
+0RXdHK3A2I23zCooOE+we2D45QUHm/vcmvsnbxOU7Tslm2DsnYxBjf5dAl2yZn+J
+FSrV91Bbd5ZXi1UkkGjBzAgbHDwdMvL9K6fTO9NwjXyBpiHy6ukIOObn9uIgDSSa
+xPnqgeykSv+RZEea8ML4BSif5RJYlmILEzJhH4rtX9X+t8BZv+ZoaN6p/qYg4/2+
+XfSUPmCJjlUaIUUAEQEAAbkBjQRgZvy0AQwAtuysL4l1wLjDIgva/+mD76cekxRu
+54s7zYOkh/87NIZ6tPkPlw/w+m7CEohurx2sQSPrClJoaMqxlPgRCmmj5JQVEC79
+9pkvJZb+QwslD57P84LYntiqpr+nmmR6vgDlZxaiRa6OVUllUTYwDpHcQ8MocXan
+e4iAea99acxL60zOimPeaPVK9tXZQ1nKPVIWs6RSYna54FFZn0uXfG4Qx8xEAXYd
+cUj5oEh4JFtEcP+55YVWopfi+zIQwwJ7JaO6ZZhHco4OpCwTauB/hX2SVdSijV32
+O9IhHXO3xPIi+5RC/iwHrhF3kexNLlfVWMnb/RWC7ROQXdUEK4YQGLy7+dFd7lKQ
+5gbUoAhuqWOnHyaSAyNlFGum3FR5oroad0eKS5jzk2n4UMPNDAoo7yEi1cdCrykD
+Jeb1GQD6ucQx+oqLkc1OGwqVjJU3FDQj/yvSCPKmst9lSGS3JH9l6ac033Db2qAP
+kUxnhw2xN4LHk2Ioovn5SZu1IUzH8/i+HhpfABEBAAGJAbYEGAEKACAWIQR0QPH3
+0nusEV+VPVXrCV2n0vasDgUCYGb8tAIbDAAKCRDrCV2n0vasDkSBC/91fDW0V6U8
+pRwW6HFruAnq/0uQ2gISrmDlpJzsgSO6HQQfho1T/7uuYhnBGyU4dxIF4G9A+Ehh
+2iwhB90JzCNLstTW6ueSWMK+4hvBpfx3kCbs2oxu0z8ZHroxE9I7e5XqDQOazANn
+eLRZJ5SArg1dFGYveBRlyjE55CmDQyj58aJkMbLAAJrdrMkFZHwbeBKOs3ph0zn5
+NvSBDUP8A3wlUXuSySeXYCUIj2k4Q6zJodnhP76ivfpu0eZn4UnD0sI8YdoJOsNK
+gDRO6fR9kEEh/XGY082B1Ad6tO2nea1MIVF0GIgfh3ezd3YcG4Rip0uqIPr7yxpT
+mVEA8wVvpWg8+wY2/xvLuHtZD59bK4KlQ9m+4W5WhursrdUfSI2EuXNp7xYwNRVf
+elApmsOOWqONqWg4leirxkWUMz7XDArDPuei4Qk8VF4/0yfGOVSh8VHQrIauzqrN
+p4LbYC9sii1fqxQTFVGPPhv6Wujd/eUuUeURZbKgpHIfniDXLiaTUyc=
+=aMmv
+-----END PGP PUBLIC KEY BLOCK-----
+
pub EB380DC13C39F675
uid Mark Vedder <[email protected]>
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 5f5b0c8..c5a4c74 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -316,6 +316,7 @@
<trusted-key id="719F7C29985A8E95F58F47194D8159D6A1159B69" group="dev.zacsweers.moshix"/>
<trusted-key id="720746177725A89207A7075BFD5DEA07FCB690A8" group="org.codehaus.mojo"/>
<trusted-key id="73976C9C39C1479B84E2641A5A68A2249128E2C6" group="com.google.crypto.tink" name="tink-android"/>
+ <trusted-key id="7440F1F7D27BAC115F953D55EB095DA7D2F6AC0E" group="org.tensorflow"/>
<trusted-key id="748F15B2CF9BA8F024155E6ED7C92B70FA1C814D" group="org.apache.logging.log4j"/>
<trusted-key id="7615AD56144DF2376F49D98B1669C4BB543E0445" group="com.google.errorprone"/>
<trusted-key id="7616EB882DAF57A11477AAF559A252FB1199D873" group="com.google.code.findbugs"/>
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt
index 99d7e6f..1f9d6a8 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLManagerTest.kt
@@ -62,7 +62,6 @@
@RunWith(AndroidJUnit4::class)
@SmallTest
-@Suppress("AcronymName")
class EGLManagerTest {
@Test
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLTestActivity.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLTestActivity.kt
index 622f973..ce80fb8 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLTestActivity.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/egl/EGLTestActivity.kt
@@ -33,7 +33,6 @@
const val TAG: String = "EGLTestActivity"
-@Suppress("AcronymName")
class EGLTestActivity : Activity() {
private val mGLRenderer = GLRenderer()
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
index 2fd880c..659b5a7 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
@@ -74,7 +74,6 @@
* https://developer.android.com/reference/android/hardware/HardwareBuffer
*/
@RequiresApi(Build.VERSION_CODES.Q)
-@Suppress("AcronymName")
class GLFrontBufferedRenderer<T>
@JvmOverloads
constructor(
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLFrameBufferRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLFrameBufferRenderer.kt
index 2a1683a..bad5d25 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLFrameBufferRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLFrameBufferRenderer.kt
@@ -48,7 +48,6 @@
* buffers as well as fine grained control over synchronization of buffer content.
*/
@RequiresApi(Build.VERSION_CODES.Q)
-@Suppress("AcronymName")
class GLFrameBufferRenderer
internal constructor(
private val surfaceControlProvider: SurfaceControlProvider,
@@ -195,7 +194,6 @@
* thread
* @return The builder instance
*/
- @Suppress("AcronymName")
fun setGLRenderer(glRenderer: GLRenderer?): Builder {
mGLRenderer = glRenderer
return this
@@ -339,7 +337,7 @@
* OpenGL.
*/
val glRenderer: GLRenderer
- @Suppress("AcronymName") @JvmName("getGLRenderer") get() = mGLRenderer
+ @JvmName("getGLRenderer") get() = mGLRenderer
/**
* Returns the [SyncStrategy] used for determining when to create [SyncFenceCompat] objects in
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLRenderer.kt
index 40ec7af..a595864 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/GLRenderer.kt
@@ -43,7 +43,6 @@
* the EGL context. This is invoked on the GL Thread
*/
// GL is the industry standard for referencing OpenGL vs Gl (lowercase l)
-@Suppress("AcronymName")
class GLRenderer(
eglSpecFactory: () -> EGLSpec = { EGLSpec.V14 },
eglConfigFactory: EGLManager.() -> EGLConfig = {
@@ -265,7 +264,6 @@
*
* These callbacks are invoked on the backing thread.
*/
- @Suppress("AcronymName")
fun registerEGLContextCallback(callback: EGLContextCallback) {
mEglContextCallback.add(callback)
mGLThread?.addEGLCallback(callback)
@@ -277,7 +275,6 @@
*
* These callbacks are invoked on the backing thread
*/
- @Suppress("AcronymName")
fun unregisterEGLContextCallback(callback: EGLContextCallback) {
mEglContextCallback.remove(callback)
mGLThread?.removeEGLCallback(callback)
@@ -288,7 +285,6 @@
* places to setup and tear down any dependencies that are used for drawing content within a
* frame (ex. compiling shaders)
*/
- @Suppress("AcronymName")
interface EGLContextCallback {
/**
@@ -297,7 +293,7 @@
* called. This will be invoked after [GLRenderer.start].
*/
// Suppressing CallbackMethodName due to b/238939160
- @Suppress("AcronymName", "CallbackMethodName")
+ @Suppress("CallbackMethodName")
@WorkerThread
fun onEGLContextCreated(eglManager: EGLManager)
@@ -306,7 +302,7 @@
* This is invoked after [GLRenderer.stop] is processed.
*/
// Suppressing CallbackMethodName due to b/238939160
- @Suppress("AcronymName", "CallbackMethodName")
+ @Suppress("CallbackMethodName")
@WorkerThread
fun onEGLContextDestroyed(eglManager: EGLManager)
}
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLConfigAttributes.kt b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLConfigAttributes.kt
index d609721..86f1b5c 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLConfigAttributes.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLConfigAttributes.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:Suppress("AcronymName")
-
package androidx.graphics.opengl.egl
import android.opengl.EGL14
@@ -89,7 +87,6 @@
* }
* ```
*/
-@Suppress("AcronymName")
class EGLConfigAttributes internal constructor(@PublishedApi internal val attrs: IntArray) {
/**
@@ -197,7 +194,6 @@
* EGL Attributes to create an 8 bit EGL config for red, green, blue, and alpha channels as
* well as an 8 bit stencil size
*/
- @Suppress("AcronymName")
@JvmField
val RGBA_8888 = EGLConfigAttributes {
EGL14.EGL_RENDERABLE_TYPE to EGL14.EGL_OPENGL_ES2_BIT
@@ -215,7 +211,6 @@
* EGL Attributes to create a 10 bit EGL config for red, green, blue, channels and a 2 bit
* alpha channels. This does not include any bits for depth and stencil buffers.
*/
- @Suppress("AcronymName")
@JvmField
val RGBA_1010102 = EGLConfigAttributes {
EGL14.EGL_RENDERABLE_TYPE to EGL14.EGL_OPENGL_ES2_BIT
@@ -232,7 +227,6 @@
* EGL Attributes to create a 16 bit floating point EGL config for red, green, blue and
* alpha channels without a depth or stencil channel.
*/
- @Suppress("AcronymName")
@JvmField
val RGBA_F16 = EGLConfigAttributes {
EGL14.EGL_RENDERABLE_TYPE to EGL14.EGL_OPENGL_ES2_BIT
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLManager.kt b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLManager.kt
index 7540cf3..68afce4e 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLManager.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLManager.kt
@@ -28,7 +28,6 @@
* Class responsible for configuration of EGL related resources. This includes initialization of the
* corresponding EGL Display as well as EGL Context, among other EGL related facilities.
*/
-@Suppress("AcronymName")
class EGLManager(eglSpec: EGLSpec = EGLSpec.V14) {
private var mEglConfig: EGLConfig? = null
@@ -124,27 +123,27 @@
}
val eglSpec: EGLSpec
- @Suppress("AcronymName") @JvmName("getEGLSpec") get() = mEglSpec
+ @JvmName("getEGLSpec") get() = mEglSpec
/**
* Returns the EGL version that is supported. This parameter is configured after [initialize] is
* invoked.
*/
val eglVersion: EGLVersion
- @Suppress("AcronymName") @JvmName("getEGLVersion") get() = mEglVersion
+ @JvmName("getEGLVersion") get() = mEglVersion
/**
* Returns the current EGLContext. This parameter is configured after [initialize] is invoked
*/
val eglContext: EGLContext?
- @Suppress("AcronymName") @JvmName("getEGLContext") get() = mEglContext
+ @JvmName("getEGLContext") get() = mEglContext
/**
* Returns the [EGLConfig] used to load the current [EGLContext]. This is configured after
* [createContext] is invoked.
*/
val eglConfig: EGLConfig?
- @Suppress("AcronymName") @JvmName("getEGLConfig") get() = mEglConfig
+ @JvmName("getEGLConfig") get() = mEglConfig
/**
* Determines whether the extension with the provided name is supported. The string provided is
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLSpec.kt b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLSpec.kt
index a233503..fdc7e4f 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLSpec.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/egl/EGLSpec.kt
@@ -45,7 +45,6 @@
*
* EGLSpec is not thread safe and is up to the caller of these methods to guarantee thread safety.
*/
-@Suppress("AcronymName")
interface EGLSpec {
/**
@@ -224,7 +223,6 @@
*
* See www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_get_native_client_buffer.txt
*/
- @Suppress("AcronymName")
@RequiresApi(Build.VERSION_CODES.O)
fun eglCreateImageFromHardwareBuffer(hardwareBuffer: HardwareBuffer): EGLImageKHR?
@@ -240,7 +238,7 @@
* @param image EGLImageKHR to be destroyed
* @return `true` if the destruction of the EGLImageKHR object was successful, `false` otherwise
*/
- @Suppress("AcronymName") fun eglDestroyImageKHR(image: EGLImageKHR): Boolean
+ fun eglDestroyImageKHR(image: EGLImageKHR): Boolean
/**
* Creates a sync object of the specified type associated with the specified display, and
@@ -260,7 +258,6 @@
* @return the [EGLSyncKHR] object to be used as a fence or null if this extension is not
* supported
*/
- @Suppress("AcronymName")
fun eglCreateSyncKHR(type: Int, attributes: EGLConfigAttributes?): EGLSyncKHR?
/**
@@ -280,7 +277,6 @@
* not matching the display that was used to create this sync object. Additionally if the
* queried attribute is not supported for the sync object, false is returned.
*/
- @Suppress("AcronymName")
fun eglGetSyncAttribKHR(
sync: EGLSyncKHR,
@EGLSyncAttribute attribute: Int,
@@ -301,7 +297,7 @@
* or if the display provided in this method does not match the display used to create this
* sync in [eglCreateSyncKHR].
*/
- @Suppress("AcronymName") fun eglDestroySyncKHR(sync: EGLSyncKHR): Boolean
+ fun eglDestroySyncKHR(sync: EGLSyncKHR): Boolean
/**
* Blocks the calling thread until the specified sync object is signalled or until
@@ -342,7 +338,6 @@
* [EGL_TIMEOUT_EXPIRED_KHR] if the sync did not signal within the specified timeout, or
* [EGL_FALSE] if an error occurs.
*/
- @Suppress("AcronymName")
fun eglClientWaitSyncKHR(
sync: EGLSyncKHR,
flags: Int,
@@ -550,7 +545,6 @@
* @param error Error code reported via eglGetError
* @param msg Optional message describing the exception being thrown
*/
-@Suppress("AcronymName")
class EGLException(val error: Int, val msg: String = "") : RuntimeException() {
override val message: String
@@ -563,7 +557,6 @@
* @param major Major version of the EGL implementation
* @param minor Minor version of the EGL implementation
*/
-@Suppress("AcronymName")
data class EGLVersion(val major: Int, val minor: Int) {
override fun toString(): String {
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/surface/SurfaceControlCompat.kt b/graphics/graphics-core/src/main/java/androidx/graphics/surface/SurfaceControlCompat.kt
index 182f845..0cc0d41 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/surface/SurfaceControlCompat.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/surface/SurfaceControlCompat.kt
@@ -58,7 +58,6 @@
*
* Various transformations that can be applied to a buffer.
*/
- @Suppress("AcronymName")
@IntDef(
value =
[
diff --git a/graphics/graphics-core/src/main/java/androidx/opengl/EGLExt.kt b/graphics/graphics-core/src/main/java/androidx/opengl/EGLExt.kt
index 299c046..757b98b 100644
--- a/graphics/graphics-core/src/main/java/androidx/opengl/EGLExt.kt
+++ b/graphics/graphics-core/src/main/java/androidx/opengl/EGLExt.kt
@@ -28,7 +28,6 @@
import androidx.opengl.EGLExt.Companion.eglCreateSyncKHR
/** Utility class that provides some helper methods for interacting EGL Extension APIs */
-@Suppress("AcronymName")
class EGLExt private constructor() {
companion object {
@@ -191,7 +190,6 @@
/** Specifies the types of attributes that can be queried in [eglGetSyncAttribKHR] */
@RestrictTo(RestrictTo.Scope.LIBRARY)
- @Suppress("AcronymName")
@IntDef(value = [EGL_SYNC_TYPE_KHR, EGL_SYNC_STATUS_KHR, EGL_SYNC_CONDITION_KHR])
annotation class EGLSyncAttribute
@@ -246,7 +244,6 @@
/** Specifies the type of fence to create in [eglCreateSyncKHR] */
@RestrictTo(RestrictTo.Scope.LIBRARY)
- @Suppress("AcronymName")
@IntDef(value = [EGL_SYNC_FENCE_KHR, EGL_SYNC_NATIVE_FENCE_ANDROID])
annotation class EGLFenceType
@@ -290,7 +287,6 @@
/** Specifies various return values for the [eglClientWaitSyncKHR] method */
@RestrictTo(RestrictTo.Scope.LIBRARY)
@Target(AnnotationTarget.TYPE)
- @Suppress("AcronymName")
@IntDef(value = [EGL_CONDITION_SATISFIED_KHR, EGL_TIMEOUT_EXPIRED_KHR, EGL_FALSE])
annotation class EGLClientWaitResult
@@ -368,7 +364,6 @@
* @return True if the destruction of the EGLImageKHR object was successful, false otherwise
*/
@JvmStatic
- @Suppress("AcronymName")
fun eglDestroyImageKHR(eglDisplay: EGLDisplay, image: EGLImageKHR): Boolean =
EGLBindings.nDestroyImageKHR(eglDisplay.nativeHandle, image.nativeHandle)
@@ -406,7 +401,6 @@
* supported
*/
@JvmStatic
- @Suppress("AcronymName")
fun eglCreateSyncKHR(
eglDisplay: EGLDisplay,
@EGLFenceType type: Int,
@@ -441,7 +435,6 @@
* returned.
*/
@JvmStatic
- @Suppress("AcronymName")
fun eglGetSyncAttribKHR(
eglDisplay: EGLDisplay,
sync: EGLSyncKHR,
@@ -498,7 +491,6 @@
* [EGL_FALSE] if an error occurs.
*/
@JvmStatic
- @Suppress("AcronymName")
fun eglClientWaitSyncKHR(
eglDisplay: EGLDisplay,
sync: EGLSyncKHR,
@@ -557,7 +549,6 @@
* this sync in eglCreateSyncKHR.
*/
@JvmStatic
- @Suppress("AcronymName")
fun eglDestroySyncKHR(eglDisplay: EGLDisplay, eglSync: EGLSyncKHR): Boolean =
EGLBindings.nDestroySyncKHR(eglDisplay.nativeHandle, eglSync.nativeHandle)
diff --git a/graphics/graphics-core/src/main/java/androidx/opengl/EGLHandle.kt b/graphics/graphics-core/src/main/java/androidx/opengl/EGLHandle.kt
index 6c66383..8b30e32 100644
--- a/graphics/graphics-core/src/main/java/androidx/opengl/EGLHandle.kt
+++ b/graphics/graphics-core/src/main/java/androidx/opengl/EGLHandle.kt
@@ -17,7 +17,6 @@
package androidx.opengl
/** Interface used to wrap native EGL objects to create type safe objects */
-@Suppress("AcronymName")
interface EGLHandle {
/**
* Returns the native handle of the wrapped EGL object. This handle can be cast to the
diff --git a/graphics/graphics-core/src/main/java/androidx/opengl/EGLImageKHR.kt b/graphics/graphics-core/src/main/java/androidx/opengl/EGLImageKHR.kt
index 84ea358..eaea90d 100644
--- a/graphics/graphics-core/src/main/java/androidx/opengl/EGLImageKHR.kt
+++ b/graphics/graphics-core/src/main/java/androidx/opengl/EGLImageKHR.kt
@@ -21,7 +21,6 @@
* APIs). This is similar to EGL's EGLImage API except the KHR suffix indicates it is generated as
* part of the extension APIs namely through [EGLExt.eglCreateImageFromHardwareBuffer]
*/
-@Suppress("AcronymName")
class EGLImageKHR(override val nativeHandle: Long) : EGLHandle {
override fun equals(other: Any?): Boolean {
diff --git a/graphics/graphics-core/src/main/java/androidx/opengl/EGLSyncKHR.kt b/graphics/graphics-core/src/main/java/androidx/opengl/EGLSyncKHR.kt
index 3b20756..fc90ac4 100644
--- a/graphics/graphics-core/src/main/java/androidx/opengl/EGLSyncKHR.kt
+++ b/graphics/graphics-core/src/main/java/androidx/opengl/EGLSyncKHR.kt
@@ -21,7 +21,6 @@
* suffix indicates it is generated as part of the extension APIs namely through
* [EGLExt.eglCreateSyncKHR].
*/
-@Suppress("AcronymName")
class EGLSyncKHR(override val nativeHandle: Long) : EGLHandle {
override fun equals(other: Any?): Boolean {
if (this === other) return true
diff --git a/lifecycle/lifecycle-viewmodel-navigation3/api/current.txt b/lifecycle/lifecycle-viewmodel-navigation3/api/current.txt
index 927612c..170aefd 100644
--- a/lifecycle/lifecycle-viewmodel-navigation3/api/current.txt
+++ b/lifecycle/lifecycle-viewmodel-navigation3/api/current.txt
@@ -2,7 +2,7 @@
package androidx.lifecycle.viewmodel.navigation3 {
public final class ViewModelStoreNavLocalProvider implements androidx.navigation3.NavLocalProvider {
- method @androidx.compose.runtime.Composable public void ProvideToBackStack(java.util.List<?> backStack);
+ method @androidx.compose.runtime.Composable public void ProvideToBackStack(java.util.List<?> backStack, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @androidx.compose.runtime.Composable public <T> void ProvideToEntry(androidx.navigation3.NavEntry<T> entry);
field public static final androidx.lifecycle.viewmodel.navigation3.ViewModelStoreNavLocalProvider INSTANCE;
}
diff --git a/lifecycle/lifecycle-viewmodel-navigation3/api/restricted_current.txt b/lifecycle/lifecycle-viewmodel-navigation3/api/restricted_current.txt
index 927612c..170aefd 100644
--- a/lifecycle/lifecycle-viewmodel-navigation3/api/restricted_current.txt
+++ b/lifecycle/lifecycle-viewmodel-navigation3/api/restricted_current.txt
@@ -2,7 +2,7 @@
package androidx.lifecycle.viewmodel.navigation3 {
public final class ViewModelStoreNavLocalProvider implements androidx.navigation3.NavLocalProvider {
- method @androidx.compose.runtime.Composable public void ProvideToBackStack(java.util.List<?> backStack);
+ method @androidx.compose.runtime.Composable public void ProvideToBackStack(java.util.List<?> backStack, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @androidx.compose.runtime.Composable public <T> void ProvideToEntry(androidx.navigation3.NavEntry<T> entry);
field public static final androidx.lifecycle.viewmodel.navigation3.ViewModelStoreNavLocalProvider INSTANCE;
}
diff --git a/lifecycle/lifecycle-viewmodel-navigation3/src/androidMain/kotlin/androidx/lifecycle/viewmodel/navigation3/ViewModelStoreNavLocalProvider.android.kt b/lifecycle/lifecycle-viewmodel-navigation3/src/androidMain/kotlin/androidx/lifecycle/viewmodel/navigation3/ViewModelStoreNavLocalProvider.android.kt
index 37b32ac..aed0618 100644
--- a/lifecycle/lifecycle-viewmodel-navigation3/src/androidMain/kotlin/androidx/lifecycle/viewmodel/navigation3/ViewModelStoreNavLocalProvider.android.kt
+++ b/lifecycle/lifecycle-viewmodel-navigation3/src/androidMain/kotlin/androidx/lifecycle/viewmodel/navigation3/ViewModelStoreNavLocalProvider.android.kt
@@ -50,10 +50,11 @@
public object ViewModelStoreNavLocalProvider : NavLocalProvider {
@Composable
- override fun ProvideToBackStack(backStack: List<Any>) {
+ override fun ProvideToBackStack(backStack: List<Any>, content: @Composable () -> Unit) {
val entryViewModelStoreProvider = viewModel { EntryViewModel() }
entryViewModelStoreProvider.ownerInBackStack.clear()
entryViewModelStoreProvider.ownerInBackStack.addAll(backStack)
+ content.invoke()
}
@Composable
@@ -88,36 +89,36 @@
}
val savedStateRegistryOwner = LocalSavedStateRegistryOwner.current
- CompositionLocalProvider(
- LocalViewModelStoreOwner provides
- object :
- ViewModelStoreOwner,
- SavedStateRegistryOwner by savedStateRegistryOwner,
- HasDefaultViewModelProviderFactory {
- override val viewModelStore: ViewModelStore
- get() = viewModelStore
+ val childViewModelOwner = remember {
+ object :
+ ViewModelStoreOwner,
+ SavedStateRegistryOwner by savedStateRegistryOwner,
+ HasDefaultViewModelProviderFactory {
+ override val viewModelStore: ViewModelStore
+ get() = viewModelStore
- override val defaultViewModelProviderFactory: ViewModelProvider.Factory
- get() = SavedStateViewModelFactory(null, savedStateRegistryOwner)
+ override val defaultViewModelProviderFactory: ViewModelProvider.Factory
+ get() = SavedStateViewModelFactory(null, savedStateRegistryOwner)
- override val defaultViewModelCreationExtras: CreationExtras
- get() =
- MutableCreationExtras().also {
- it[SAVED_STATE_REGISTRY_OWNER_KEY] = savedStateRegistryOwner
- it[VIEW_MODEL_STORE_OWNER_KEY] = this
- }
-
- init {
- require(this.lifecycle.currentState == Lifecycle.State.INITIALIZED) {
- "The Lifecycle state is already beyond INITIALIZED. The " +
- "ViewModelStoreNavLocalProvider requires adding the " +
- "SavedStateNavLocalProvider to ensure support for " +
- "SavedStateHandles."
+ override val defaultViewModelCreationExtras: CreationExtras
+ get() =
+ MutableCreationExtras().also {
+ it[SAVED_STATE_REGISTRY_OWNER_KEY] = savedStateRegistryOwner
+ it[VIEW_MODEL_STORE_OWNER_KEY] = this
}
- enableSavedStateHandles()
+
+ init {
+ require(this.lifecycle.currentState == Lifecycle.State.INITIALIZED) {
+ "The Lifecycle state is already beyond INITIALIZED. The " +
+ "ViewModelStoreNavLocalProvider requires adding the " +
+ "SavedStateNavLocalProvider to ensure support for " +
+ "SavedStateHandles."
}
+ enableSavedStateHandles()
}
- ) {
+ }
+ }
+ CompositionLocalProvider(LocalViewModelStoreOwner provides childViewModelOwner) {
entry.content.invoke(key)
}
}
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/api/current.txt b/lifecycle/lifecycle-viewmodel-savedstate/api/current.txt
index 74041ee..e9b8ced 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/api/current.txt
+++ b/lifecycle/lifecycle-viewmodel-savedstate/api/current.txt
@@ -50,10 +50,8 @@
package androidx.lifecycle.serialization {
public final class SavedStateHandleDelegatesKt {
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, String key, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, String key, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, kotlinx.serialization.KSerializer<T> serializer, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
}
}
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/api/restricted_current.txt b/lifecycle/lifecycle-viewmodel-savedstate/api/restricted_current.txt
index 74041ee..e9b8ced 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/api/restricted_current.txt
+++ b/lifecycle/lifecycle-viewmodel-savedstate/api/restricted_current.txt
@@ -50,10 +50,8 @@
package androidx.lifecycle.serialization {
public final class SavedStateHandleDelegatesKt {
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, String key, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, String key, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.lifecycle.SavedStateHandle, kotlinx.serialization.KSerializer<T> serializer, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
}
}
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/bcv/native/current.txt b/lifecycle/lifecycle-viewmodel-savedstate/bcv/native/current.txt
index 7a78cde..3b9bf81 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/bcv/native/current.txt
+++ b/lifecycle/lifecycle-viewmodel-savedstate/bcv/native/current.txt
@@ -42,7 +42,5 @@
final fun (androidx.lifecycle.viewmodel/CreationExtras).androidx.lifecycle/createSavedStateHandle(): androidx.lifecycle/SavedStateHandle // androidx.lifecycle/createSavedStateHandle|createSavedStateHandle@androidx.lifecycle.viewmodel.CreationExtras(){}[0]
final fun <#A: androidx.lifecycle/ViewModelStoreOwner & androidx.savedstate/SavedStateRegistryOwner> (#A).androidx.lifecycle/enableSavedStateHandles() // androidx.lifecycle/enableSavedStateHandles|enableSavedStateHandles@0:0(){0§<androidx.savedstate.SavedStateRegistryOwner&androidx.lifecycle.ViewModelStoreOwner>}[0]
-final fun <#A: kotlin/Any> (androidx.lifecycle/SavedStateHandle).androidx.lifecycle.serialization/saved(kotlin/String, kotlinx.serialization/KSerializer<#A>, kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.lifecycle.serialization/saved|[email protected](kotlin.String;kotlinx.serialization.KSerializer<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
-final fun <#A: kotlin/Any> (androidx.lifecycle/SavedStateHandle).androidx.lifecycle.serialization/saved(kotlinx.serialization/KSerializer<#A>, kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.lifecycle.serialization/saved|[email protected](kotlinx.serialization.KSerializer<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
-final inline fun <#A: reified kotlin/Any> (androidx.lifecycle/SavedStateHandle).androidx.lifecycle.serialization/saved(kotlin/String, noinline kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.lifecycle.serialization/saved|[email protected](kotlin.String;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
-final inline fun <#A: reified kotlin/Any> (androidx.lifecycle/SavedStateHandle).androidx.lifecycle.serialization/saved(noinline kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.lifecycle.serialization/saved|[email protected](kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
+final fun <#A: kotlin/Any> (androidx.lifecycle/SavedStateHandle).androidx.lifecycle.serialization/saved(kotlinx.serialization/KSerializer<#A>, kotlin/String? = ..., kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.lifecycle.serialization/saved|[email protected](kotlinx.serialization.KSerializer<0:0>;kotlin.String?;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
+final inline fun <#A: reified kotlin/Any> (androidx.lifecycle/SavedStateHandle).androidx.lifecycle.serialization/saved(kotlin/String? = ..., noinline kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.lifecycle.serialization/saved|[email protected](kotlin.String?;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/src/commonMain/kotlin/androidx/lifecycle/serialization/SavedStateHandleDelegates.kt b/lifecycle/lifecycle-viewmodel-savedstate/src/commonMain/kotlin/androidx/lifecycle/serialization/SavedStateHandleDelegates.kt
index a964d34..edd1bc10 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/src/commonMain/kotlin/androidx/lifecycle/serialization/SavedStateHandleDelegates.kt
+++ b/lifecycle/lifecycle-viewmodel-savedstate/src/commonMain/kotlin/androidx/lifecycle/serialization/SavedStateHandleDelegates.kt
@@ -27,67 +27,34 @@
/**
* Returns a property delegate that uses [SavedStateHandle] to save and restore a value of type [T]
- * with fully qualified property or variable name as key and the default serializer.
- *
- * @sample androidx.lifecycle.delegate
- * @param init The function to provide the initial value of the property.
- * @return A property delegate that manages the saving and restoring of the value.
- */
-public inline fun <reified T : Any> SavedStateHandle.saved(
- noinline init: () -> T,
-): ReadWriteProperty<Any?, T> {
- return saved(serializer(), init)
-}
-
-/**
- * Returns a property delegate that uses [SavedStateHandle] to save and restore a value of type [T]
* with the default serializer.
*
* @sample androidx.lifecycle.delegateExplicitKey
- * @param key The [String] key to use for storing the value in the [SavedStateHandle].
+ * @param key An optional [String] key to use for storing the value in the [SavedStateHandle]. A
+ * default key will be generated if it's omitted or when 'null' is passed.
* @param init The function to provide the initial value of the property.
* @return A property delegate that manages the saving and restoring of the value.
*/
public inline fun <reified T : Any> SavedStateHandle.saved(
- key: String,
+ key: String? = null,
noinline init: () -> T,
): ReadWriteProperty<Any?, T> {
- return saved(key, serializer(), init)
-}
-
-/**
- * Returns a property delegate that uses [SavedStateHandle] to save and restore a value of type [T]
- * with fully qualified property or variable name as key.
- *
- * @sample androidx.lifecycle.delegateExplicitSerializer
- * @param serializer The [KSerializer] to use for serializing and deserializing the value.
- * @param init The function to provide the initial value of the property.
- * @return A property delegate that manages the saving and restoring of the value.
- */
-public fun <T : Any> SavedStateHandle.saved(
- serializer: KSerializer<T>,
- init: () -> T,
-): ReadWriteProperty<Any?, T> {
- return SavedStateHandleDelegate(
- savedStateHandle = this,
- key = null,
- serializer = serializer,
- init = init
- )
+ return saved(serializer(), key, init)
}
/**
* Returns a property delegate that uses [SavedStateHandle] to save and restore a value of type [T].
*
* @sample androidx.lifecycle.delegateExplicitKeyAndSerializer
- * @param key The [String] key to use for storing the value in the [SavedStateHandle].
* @param serializer The [KSerializer] to use for serializing and deserializing the value.
+ * @param key An optional [String] key to use for storing the value in the [SavedStateHandle]. A
+ * default key will be generated if it's omitted or when 'null' is passed.
* @param init The function to provide the initial value of the property.
* @return A property delegate that manages the saving and restoring of the value.
*/
public fun <T : Any> SavedStateHandle.saved(
- key: String,
serializer: KSerializer<T>,
+ key: String? = null,
init: () -> T,
): ReadWriteProperty<Any?, T> {
return SavedStateHandleDelegate(
diff --git a/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorImportsTest.kt b/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorImportsTest.kt
index 1be5a54..6c38fa8 100644
--- a/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorImportsTest.kt
+++ b/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorImportsTest.kt
@@ -16,6 +16,8 @@
package androidx.build.lint.replacewith
+import androidx.build.lint.ReplaceWithDetector
+import com.android.tools.lint.checks.infrastructure.TestLintTask
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -217,6 +219,13 @@
"""
.trimIndent()
- check(*input).expect(expected).expectFixDiffs(expectedFixDiffs)
+ // Move to check(*input) when b/391690668 is fixed and verifyFixedFileSyntax is removed.
+ TestLintTask.lint()
+ .files(ANDROIDX_REPLACE_WITH_KT, ANDROIDX_ANY_THREAD_KT, *input)
+ .issues(ReplaceWithDetector.ISSUE)
+ .verifyFixedFileSyntax(false)
+ .run()
+ .expect(expected)
+ .expectFixDiffs(expectedFixDiffs)
}
}
diff --git a/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorPropertyTest.kt b/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorPropertyTest.kt
index 407c0b7..fb2cf44 100644
--- a/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorPropertyTest.kt
+++ b/lint-checks/src/test/java/androidx/build/lint/replacewith/ReplaceWithDetectorPropertyTest.kt
@@ -16,6 +16,8 @@
package androidx.build.lint.replacewith
+import androidx.build.lint.ReplaceWithDetector
+import com.android.tools.lint.checks.infrastructure.TestLintTask
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -60,6 +62,13 @@
"""
.trimIndent()
- check(*input).expect(expected).expectFixDiffs(expectedFixDiffs)
+ // Move to check(*input) when b/391690668 is fixed and verifyFixedFileSyntax is removed.
+ TestLintTask.lint()
+ .files(ANDROIDX_REPLACE_WITH_KT, ANDROIDX_ANY_THREAD_KT, *input)
+ .issues(ReplaceWithDetector.ISSUE)
+ .verifyFixedFileSyntax(false)
+ .run()
+ .expect(expected)
+ .expectFixDiffs(expectedFixDiffs)
}
}
diff --git a/navigation/navigation-runtime/bcv/native/current.txt b/navigation/navigation-runtime/bcv/native/current.txt
new file mode 100644
index 0000000..47e0dc0
--- /dev/null
+++ b/navigation/navigation-runtime/bcv/native/current.txt
@@ -0,0 +1,11 @@
+// Klib ABI Dump
+// Targets: [iosArm64, iosSimulatorArm64, iosX64, linuxArm64, linuxX64, macosArm64, macosX64]
+// Rendering settings:
+// - Signature version: 2
+// - Show manifest properties: true
+// - Show declarations: true
+
+// Library unique name: <androidx.navigation:navigation-runtime>
+open annotation class androidx.navigation/NavDeepLinkSaveStateControl : kotlin/Annotation { // androidx.navigation/NavDeepLinkSaveStateControl|null[0]
+ constructor <init>() // androidx.navigation/NavDeepLinkSaveStateControl.<init>|<init>(){}[0]
+}
diff --git a/navigation/navigation-runtime/build.gradle b/navigation/navigation-runtime/build.gradle
index 1ad4631..c71a4c0 100644
--- a/navigation/navigation-runtime/build.gradle
+++ b/navigation/navigation-runtime/build.gradle
@@ -24,49 +24,132 @@
import androidx.build.KotlinTarget
import androidx.build.LibraryType
+import androidx.build.PlatformIdentifier
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
plugins {
id("AndroidXPlugin")
id("com.android.library")
- id("kotlin-android")
alias(libs.plugins.kotlinSerialization)
}
+androidXMultiplatform {
+ android()
+ desktop()
+ mac()
+ linux()
+ ios()
+
+ defaultPlatform(PlatformIdentifier.ANDROID)
+
+ sourceSets {
+ commonMain {
+ dependencies {
+ api(libs.kotlinStdlib)
+ api(libs.kotlinCoroutinesCore)
+ api(project(":navigation:navigation-common"))
+ api("androidx.lifecycle:lifecycle-common:2.6.2")
+ api("androidx.lifecycle:lifecycle-runtime:2.6.2")
+ api("androidx.lifecycle:lifecycle-viewmodel:2.6.2")
+
+ implementation(libs.kotlinSerializationCore)
+ implementation("androidx.collection:collection:1.4.2")
+ }
+ }
+ commonTest {
+ dependencies {
+ implementation(libs.kotlinTest)
+ }
+ }
+ nonAndroidMain {
+ dependsOn(commonMain)
+ }
+ nonAndroidTest {
+ dependsOn(commonTest)
+ }
+ jvmCommonMain {
+ dependsOn(commonMain)
+ }
+ jvmCommonTest {
+ dependsOn(commonTest)
+ }
+ desktopMain {
+ dependsOn(jvmCommonMain)
+ dependsOn(nonAndroidMain)
+ }
+ desktopTest {
+ dependsOn(jvmCommonTest)
+ dependsOn(nonAndroidTest)
+ }
+ androidMain {
+ dependsOn(jvmCommonMain)
+ dependencies {
+ api("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
+ api("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
+ api("androidx.activity:activity-ktx:1.7.1")
+ api("androidx.core:core-ktx:1.8.0")
+ api("androidx.annotation:annotation-experimental:1.4.1")
+ }
+ }
+ androidUnitTest {
+ dependsOn(commonTest)
+ }
+ androidInstrumentedTest {
+ dependsOn(commonTest)
+ dependencies {
+ implementation("androidx.annotation:annotation:1.8.0")
+ implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.2")
+ implementation("androidx.lifecycle:lifecycle-common:2.6.2")
+ implementation("androidx.lifecycle:lifecycle-runtime:2.6.2")
+ implementation("androidx.lifecycle:lifecycle-runtime-testing:2.6.2")
+ implementation(project(":internal-testutils-navigation"))
+ implementation(project(":internal-testutils-runtime"))
+ implementation(libs.hamcrestCore)
+ implementation(libs.junit)
+ implementation(libs.kotlinTest)
+ implementation(libs.testCore)
+ implementation(libs.testExtJunit)
+ implementation(libs.testExtTruth)
+ implementation(libs.testMonitor)
+ implementation(libs.testRunner)
+ implementation(libs.testRules)
+ implementation(libs.espressoIntents)
+ implementation(libs.truth)
+ implementation(libs.dexmakerMockito)
+ implementation(libs.mockitoCore)
+ }
+ }
+ nonJvmCommonMain {
+ dependsOn(nonAndroidMain)
+ }
+ nonJvmCommonTest {
+ dependsOn(nonAndroidTest)
+ }
+ nativeMain {
+ dependsOn(nonJvmCommonMain)
+ }
+ linuxMain.dependsOn(nativeMain)
+ darwinMain.dependsOn(nativeMain)
+ nativeTest {
+ dependsOn(nonJvmCommonTest)
+ }
+ linuxTest.dependsOn(nativeTest)
+ darwinTest.dependsOn(nativeTest)
+ targets.configureEach { target ->
+ if (target.platformType == KotlinPlatformType.native) {
+ if (target.konanTarget.family.appleFamily) {
+ target.compilations["main"].defaultSourceSet.dependsOn(darwinMain)
+ target.compilations["test"].defaultSourceSet.dependsOn(darwinTest)
+ } else if (target.konanTarget.family == org.jetbrains.kotlin.konan.target.Family.LINUX) {
+ target.compilations["main"].defaultSourceSet.dependsOn(linuxMain)
+ target.compilations["test"].defaultSourceSet.dependsOn(linuxTest)
+ }
+ }
+ }
+ }
+}
+
dependencies {
- api(libs.kotlinStdlib)
- api(libs.kotlinCoroutinesCore)
- api(project(":navigation:navigation-common"))
- api("androidx.activity:activity-ktx:1.7.1")
- api("androidx.core:core-ktx:1.8.0")
- api("androidx.lifecycle:lifecycle-common:2.6.2")
- api("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
- api("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
- api("androidx.annotation:annotation-experimental:1.4.1")
-
- implementation(libs.kotlinSerializationCore)
- implementation("androidx.collection:collection:1.4.2")
-
- androidTestImplementation("androidx.annotation:annotation:1.8.0")
- androidTestImplementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.2")
- androidTestImplementation("androidx.lifecycle:lifecycle-common:2.6.2")
- androidTestImplementation("androidx.lifecycle:lifecycle-runtime:2.6.2")
- androidTestImplementation("androidx.lifecycle:lifecycle-runtime-testing:2.6.2")
- androidTestImplementation(project(":internal-testutils-navigation"))
- androidTestImplementation(project(":internal-testutils-runtime"))
- androidTestImplementation(libs.hamcrestCore)
- androidTestImplementation(libs.junit)
- androidTestImplementation(libs.kotlinTest)
- androidTestImplementation(libs.testCore)
- androidTestImplementation(libs.testExtJunit)
- androidTestImplementation(libs.testExtTruth)
- androidTestImplementation(libs.testMonitor)
- androidTestImplementation(libs.testRunner)
- androidTestImplementation(libs.testRules)
- androidTestImplementation(libs.espressoIntents)
- androidTestImplementation(libs.truth)
- androidTestImplementation(libs.dexmakerMockito)
- androidTestImplementation(libs.mockitoCore)
-
lintPublish(project(":navigation:navigation-runtime-lint"))
}
diff --git a/navigation/navigation-runtime/src/androidTest/AndroidManifest.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/AndroidManifest.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/AndroidManifest.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/AndroidManifest.xml
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityNavigatorDestinationBuilderTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorExtrasTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityNavigatorExtrasTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorExtrasTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityNavigatorExtrasTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityNavigatorTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityNavigatorTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ActivityTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/FloatingWindowTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/FloatingWindowTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/FloatingWindowTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/FloatingWindowTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavBackStackEntryLifecycleTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavBackStackEntryLifecycleTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavBackStackEntryTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavBackStackEntryTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerActivityTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerActivityTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerActivityTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerRouteTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerRouteTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerViewModelTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerViewModelTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerViewModelTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavControllerViewModelTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavDeepLinkBuilderTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavDeepLinkBuilderTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavDeepLinkBuilderTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavDeepLinkBuilderTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavHostTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavHostTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavHostTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavHostTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavInflaterTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/NavInflaterTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ViewTest.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ViewTest.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ViewTest.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/ViewTest.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/FloatingTestNavigator.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/FloatingTestNavigator.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/FloatingTestNavigator.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/FloatingTestNavigator.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/SupportingFloatingTestNavigator.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/SupportingFloatingTestNavigator.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/SupportingFloatingTestNavigator.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/SupportingFloatingTestNavigator.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/SupportingTestNavigator.kt b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/SupportingTestNavigator.kt
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/SupportingTestNavigator.kt
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/SupportingTestNavigator.kt
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/TestEnum.java b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/TestEnum.kt
similarity index 86%
rename from navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/TestEnum.java
rename to navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/TestEnum.kt
index f3a5276..11e2eb167 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/test/TestEnum.java
+++ b/navigation/navigation-runtime/src/androidInstrumentedTest/kotlin/androidx/navigation/test/TestEnum.kt
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package androidx.navigation.test;
+package androidx.navigation.test
-public enum TestEnum {
- VALUE_ONE, VALUE_TWO
+public enum class TestEnum {
+ VALUE_ONE,
+ VALUE_TWO
}
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_applicationid_arg.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_applicationid_arg.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_applicationid_arg.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_applicationid_arg.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_arguments.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_arguments.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_arguments.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_arguments.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_deeplink.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_deeplink.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_deeplink.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_deeplink.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_default_arguments.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_default_arguments.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_default_arguments.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_default_arguments.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_first.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_first.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_first.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_first.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_floating.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_floating.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_floating.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_floating.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_invalid_argument_arg_type.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_invalid_argument_arg_type.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_invalid_argument_arg_type.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_invalid_argument_arg_type.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_invalid_argument_default_value.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_invalid_argument_default_value.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_invalid_argument_default_value.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_invalid_argument_default_value.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_invalid_start_destination.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_invalid_start_destination.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_invalid_start_destination.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_invalid_start_destination.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_missing_start_destination.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_missing_start_destination.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_missing_start_destination.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_missing_start_destination.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_multiple_navigation.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_multiple_navigation.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_multiple_navigation.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_multiple_navigation.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_nested_start_destination.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_nested_start_destination.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_nested_start_destination.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_nested_start_destination.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_non_start_nest.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_non_start_nest.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_non_start_nest.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_non_start_nest.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_root.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_root.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_root.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_root.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_second.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_second.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_second.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_second.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_simple.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_simple.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_simple.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_simple.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_start_destination.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_start_destination.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/navigation/nav_start_destination.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/navigation/nav_start_destination.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/values/styles.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/values/styles.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/values/styles.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/values/styles.xml
diff --git a/navigation/navigation-runtime/src/androidTest/res/values/values.xml b/navigation/navigation-runtime/src/androidInstrumentedTest/res/values/values.xml
similarity index 100%
rename from navigation/navigation-runtime/src/androidTest/res/values/values.xml
rename to navigation/navigation-runtime/src/androidInstrumentedTest/res/values/values.xml
diff --git a/navigation/navigation-runtime/src/main/AndroidManifest.xml b/navigation/navigation-runtime/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from navigation/navigation-runtime/src/main/AndroidManifest.xml
rename to navigation/navigation-runtime/src/androidMain/AndroidManifest.xml
diff --git a/navigation/navigation-runtime/src/main/baseline-prof.txt b/navigation/navigation-runtime/src/androidMain/baseline-prof.txt
similarity index 100%
rename from navigation/navigation-runtime/src/main/baseline-prof.txt
rename to navigation/navigation-runtime/src/androidMain/baseline-prof.txt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/package-info.java b/navigation/navigation-runtime/src/androidMain/java/androidx/navigation/package-info.java
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/package-info.java
rename to navigation/navigation-runtime/src/androidMain/java/androidx/navigation/package-info.java
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/Activity.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/Activity.android.kt
similarity index 94%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/Activity.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/Activity.android.kt
index 8bf71cd..a0f3b6b 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/Activity.kt
+++ b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/Activity.android.kt
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+@file:JvmName("ActivityKt")
+@file:JvmMultifileClass
+
package androidx.navigation
import android.app.Activity
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavArgsLazy.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavArgsLazy.android.kt
similarity index 95%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavArgsLazy.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavArgsLazy.android.kt
index f1d9052..bf50861 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavArgsLazy.kt
+++ b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavArgsLazy.android.kt
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+@file:JvmName("ActivityNavArgsLazyKt")
+@file:JvmMultifileClass
+
package androidx.navigation
import android.app.Activity
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigator.android.kt
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigator.android.kt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigatorDestinationBuilder.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigatorDestinationBuilder.android.kt
similarity index 97%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigatorDestinationBuilder.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigatorDestinationBuilder.android.kt
index 8fdb188..9be7470 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigatorDestinationBuilder.android.kt
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-@file:Suppress("NOTHING_TO_INLINE")
+@file:JvmName("ActivityNavigatorDestinationBuilderKt")
+@file:JvmMultifileClass
package androidx.navigation
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigatorExtras.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigatorExtras.android.kt
similarity index 94%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigatorExtras.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigatorExtras.android.kt
index f280a1a..1611117 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigatorExtras.kt
+++ b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/ActivityNavigatorExtras.android.kt
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+@file:JvmName("ActivityNavigatorExtrasKt")
+@file:JvmMultifileClass
+
package androidx.navigation
import androidx.core.app.ActivityOptionsCompat
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntryState.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavBackStackEntryState.android.kt
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntryState.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavBackStackEntryState.android.kt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavController.android.kt
similarity index 99%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavController.android.kt
index 4eed05f..145193d 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
+++ b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavController.android.kt
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+@file:JvmName("NavControllerKt")
+@file:JvmMultifileClass
+
package androidx.navigation
import android.app.Activity
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavControllerViewModel.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavControllerViewModel.android.kt
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavControllerViewModel.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavControllerViewModel.android.kt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkBuilder.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavDeepLinkBuilder.android.kt
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkBuilder.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavDeepLinkBuilder.android.kt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavHost.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavHost.android.kt
similarity index 98%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavHost.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavHost.android.kt
index 30024a2..b21b710 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavHost.kt
+++ b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavHost.android.kt
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+@file:JvmName("NavHostKt")
+@file:JvmMultifileClass
+
package androidx.navigation
import androidx.annotation.IdRes
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavHostController.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavHostController.android.kt
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavHostController.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavHostController.android.kt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavInflater.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavInflater.android.kt
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavInflater.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/NavInflater.android.kt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/Navigation.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/Navigation.android.kt
similarity index 100%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/Navigation.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/Navigation.android.kt
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/View.kt b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/View.android.kt
similarity index 94%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/View.kt
rename to navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/View.android.kt
index 55db610..c5db4bc 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/View.kt
+++ b/navigation/navigation-runtime/src/androidMain/kotlin/androidx/navigation/View.android.kt
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+@file:JvmName("ViewKt")
+@file:JvmMultifileClass
+
package androidx.navigation
import android.view.View
diff --git a/navigation/navigation-runtime/src/main/res-public/values/public_attrs.xml b/navigation/navigation-runtime/src/androidMain/res-public/values/public_attrs.xml
similarity index 100%
rename from navigation/navigation-runtime/src/main/res-public/values/public_attrs.xml
rename to navigation/navigation-runtime/src/androidMain/res-public/values/public_attrs.xml
diff --git a/navigation/navigation-runtime/src/main/res/values/attrs.xml b/navigation/navigation-runtime/src/androidMain/res/values/attrs.xml
similarity index 100%
rename from navigation/navigation-runtime/src/main/res/values/attrs.xml
rename to navigation/navigation-runtime/src/androidMain/res/values/attrs.xml
diff --git a/navigation/navigation-runtime/src/main/res/values/ids.xml b/navigation/navigation-runtime/src/androidMain/res/values/ids.xml
similarity index 100%
rename from navigation/navigation-runtime/src/main/res/values/ids.xml
rename to navigation/navigation-runtime/src/androidMain/res/values/ids.xml
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkSaveStateControl.kt b/navigation/navigation-runtime/src/commonMain/kotlin/androidx/navigation/NavDeepLinkSaveStateControl.kt
similarity index 94%
rename from navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkSaveStateControl.kt
rename to navigation/navigation-runtime/src/commonMain/kotlin/androidx/navigation/NavDeepLinkSaveStateControl.kt
index 469b038..5e7015f 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavDeepLinkSaveStateControl.kt
+++ b/navigation/navigation-runtime/src/commonMain/kotlin/androidx/navigation/NavDeepLinkSaveStateControl.kt
@@ -16,7 +16,6 @@
package androidx.navigation
-/** @see NavController.enableDeepLinkSaveState */
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FUNCTION)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
diff --git a/navigation3/navigation3/api/current.txt b/navigation3/navigation3/api/current.txt
index 1fe0724..587a03d 100644
--- a/navigation3/navigation3/api/current.txt
+++ b/navigation3/navigation3/api/current.txt
@@ -45,42 +45,44 @@
method public static inline kotlin.jvm.functions.Function1<java.lang.Object,androidx.navigation3.NavEntry<? extends java.lang.Object?>> entryProvider(optional kotlin.jvm.functions.Function1<java.lang.Object,? extends androidx.navigation3.NavEntry<? extends java.lang.Object?>> fallback, kotlin.jvm.functions.Function1<? super androidx.navigation3.EntryProviderBuilder,kotlin.Unit> builder);
}
+ public final class NavBackStackProviderKt {
+ method @androidx.compose.runtime.Composable public static <T> void NavBackStackProvider(java.util.List<? extends T> backStack, java.util.List<? extends androidx.navigation3.NavLocalProvider> localProviders, kotlin.jvm.functions.Function1<? super T,? extends androidx.navigation3.NavEntry<T>> entryProvider, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.navigation3.NavEntry<T>>,kotlin.Unit> content);
+ }
+
public final class NavDisplay {
- method public java.util.Map<java.lang.String,java.lang.Object> isDialog(boolean boolean);
+ method public java.util.Map<java.lang.String,java.lang.Object> popTransition(androidx.compose.animation.EnterTransition? enter, androidx.compose.animation.ExitTransition? exit);
method public java.util.Map<java.lang.String,java.lang.Object> transition(androidx.compose.animation.EnterTransition? enter, androidx.compose.animation.ExitTransition? exit);
field public static final androidx.navigation3.NavDisplay INSTANCE;
}
public final class NavDisplay_androidKt {
- method @androidx.compose.runtime.Composable public static <T> void NavDisplay(java.util.List<? extends T> backstack, optional androidx.compose.ui.Modifier modifier, optional java.util.List<? extends androidx.navigation3.NavLocalProvider> localProviders, optional androidx.compose.ui.Alignment contentAlignment, optional androidx.compose.animation.SizeTransform? sizeTransform, optional androidx.compose.animation.EnterTransition enterTransition, optional androidx.compose.animation.ExitTransition exitTransition, optional kotlin.jvm.functions.Function0<kotlin.Unit> onBack, kotlin.jvm.functions.Function1<? super T,? extends androidx.navigation3.NavEntry<? extends T>> entryProvider);
+ method @androidx.compose.runtime.Composable public static <T> void NavDisplay(java.util.List<? extends T> backstack, optional androidx.compose.ui.Modifier modifier, optional java.util.List<? extends androidx.navigation3.NavLocalProvider> localProviders, optional androidx.compose.ui.Alignment contentAlignment, optional androidx.compose.animation.SizeTransform? sizeTransform, optional androidx.compose.animation.EnterTransition enterTransition, optional androidx.compose.animation.ExitTransition exitTransition, optional androidx.compose.animation.EnterTransition popEnterTransition, optional androidx.compose.animation.ExitTransition popExitTransition, optional kotlin.jvm.functions.Function0<kotlin.Unit> onBack, kotlin.jvm.functions.Function1<? super T,? extends androidx.navigation3.NavEntry<? extends T>> entryProvider);
}
public class NavEntry<T> {
ctor public NavEntry(T key, optional java.util.Map<java.lang.String,?> featureMap, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> content);
- method public final kotlin.jvm.functions.Function1<T,kotlin.Unit> getContent();
- method public final java.util.Map<java.lang.String,java.lang.Object> getFeatureMap();
- method public final T getKey();
- property public final kotlin.jvm.functions.Function1<T,kotlin.Unit> content;
- property public final java.util.Map<java.lang.String,java.lang.Object> featureMap;
- property public final T key;
+ method public kotlin.jvm.functions.Function1<T,kotlin.Unit> getContent();
+ method public java.util.Map<java.lang.String,java.lang.Object> getFeatureMap();
+ method public T getKey();
+ property public kotlin.jvm.functions.Function1<T,kotlin.Unit> content;
+ property public java.util.Map<java.lang.String,java.lang.Object> featureMap;
+ property public T key;
+ }
+
+ public class NavEntryWrapper<T> extends androidx.navigation3.NavEntry<T> {
+ ctor public NavEntryWrapper(androidx.navigation3.NavEntry<T> navEntry);
+ method public final androidx.navigation3.NavEntry<T> getNavEntry();
+ property public kotlin.jvm.functions.Function1<T,kotlin.Unit> content;
+ property public java.util.Map<java.lang.String,java.lang.Object> featureMap;
+ property public T key;
+ property public final androidx.navigation3.NavEntry<T> navEntry;
}
public interface NavLocalProvider {
- method @androidx.compose.runtime.Composable public default void ProvideToBackStack(java.util.List<?> backStack);
+ method @androidx.compose.runtime.Composable public default void ProvideToBackStack(java.util.List<?> backStack, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @androidx.compose.runtime.Composable public <T> void ProvideToEntry(androidx.navigation3.NavEntry<T> entry);
}
- public final class NavWrapperManager {
- ctor public NavWrapperManager();
- ctor public NavWrapperManager(optional java.util.List<? extends androidx.navigation3.NavLocalProvider> navLocalProviders);
- method @androidx.compose.runtime.Composable public <T> void ContentForEntry(androidx.navigation3.NavEntry<T> entry);
- method @androidx.compose.runtime.Composable public void PrepareBackStack(java.util.List<?> backStack);
- }
-
- public final class NavWrapperManagerKt {
- method @androidx.compose.runtime.Composable public static androidx.navigation3.NavWrapperManager rememberNavWrapperManager(java.util.List<? extends androidx.navigation3.NavLocalProvider> navLocalProviders);
- }
-
public final class SaveableStateNavLocalProvider implements androidx.navigation3.NavLocalProvider {
ctor public SaveableStateNavLocalProvider();
method @androidx.compose.runtime.Composable public <T> void ProvideToEntry(androidx.navigation3.NavEntry<T> entry);
diff --git a/navigation3/navigation3/api/restricted_current.txt b/navigation3/navigation3/api/restricted_current.txt
index 1fe0724..587a03d 100644
--- a/navigation3/navigation3/api/restricted_current.txt
+++ b/navigation3/navigation3/api/restricted_current.txt
@@ -45,42 +45,44 @@
method public static inline kotlin.jvm.functions.Function1<java.lang.Object,androidx.navigation3.NavEntry<? extends java.lang.Object?>> entryProvider(optional kotlin.jvm.functions.Function1<java.lang.Object,? extends androidx.navigation3.NavEntry<? extends java.lang.Object?>> fallback, kotlin.jvm.functions.Function1<? super androidx.navigation3.EntryProviderBuilder,kotlin.Unit> builder);
}
+ public final class NavBackStackProviderKt {
+ method @androidx.compose.runtime.Composable public static <T> void NavBackStackProvider(java.util.List<? extends T> backStack, java.util.List<? extends androidx.navigation3.NavLocalProvider> localProviders, kotlin.jvm.functions.Function1<? super T,? extends androidx.navigation3.NavEntry<T>> entryProvider, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.navigation3.NavEntry<T>>,kotlin.Unit> content);
+ }
+
public final class NavDisplay {
- method public java.util.Map<java.lang.String,java.lang.Object> isDialog(boolean boolean);
+ method public java.util.Map<java.lang.String,java.lang.Object> popTransition(androidx.compose.animation.EnterTransition? enter, androidx.compose.animation.ExitTransition? exit);
method public java.util.Map<java.lang.String,java.lang.Object> transition(androidx.compose.animation.EnterTransition? enter, androidx.compose.animation.ExitTransition? exit);
field public static final androidx.navigation3.NavDisplay INSTANCE;
}
public final class NavDisplay_androidKt {
- method @androidx.compose.runtime.Composable public static <T> void NavDisplay(java.util.List<? extends T> backstack, optional androidx.compose.ui.Modifier modifier, optional java.util.List<? extends androidx.navigation3.NavLocalProvider> localProviders, optional androidx.compose.ui.Alignment contentAlignment, optional androidx.compose.animation.SizeTransform? sizeTransform, optional androidx.compose.animation.EnterTransition enterTransition, optional androidx.compose.animation.ExitTransition exitTransition, optional kotlin.jvm.functions.Function0<kotlin.Unit> onBack, kotlin.jvm.functions.Function1<? super T,? extends androidx.navigation3.NavEntry<? extends T>> entryProvider);
+ method @androidx.compose.runtime.Composable public static <T> void NavDisplay(java.util.List<? extends T> backstack, optional androidx.compose.ui.Modifier modifier, optional java.util.List<? extends androidx.navigation3.NavLocalProvider> localProviders, optional androidx.compose.ui.Alignment contentAlignment, optional androidx.compose.animation.SizeTransform? sizeTransform, optional androidx.compose.animation.EnterTransition enterTransition, optional androidx.compose.animation.ExitTransition exitTransition, optional androidx.compose.animation.EnterTransition popEnterTransition, optional androidx.compose.animation.ExitTransition popExitTransition, optional kotlin.jvm.functions.Function0<kotlin.Unit> onBack, kotlin.jvm.functions.Function1<? super T,? extends androidx.navigation3.NavEntry<? extends T>> entryProvider);
}
public class NavEntry<T> {
ctor public NavEntry(T key, optional java.util.Map<java.lang.String,?> featureMap, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> content);
- method public final kotlin.jvm.functions.Function1<T,kotlin.Unit> getContent();
- method public final java.util.Map<java.lang.String,java.lang.Object> getFeatureMap();
- method public final T getKey();
- property public final kotlin.jvm.functions.Function1<T,kotlin.Unit> content;
- property public final java.util.Map<java.lang.String,java.lang.Object> featureMap;
- property public final T key;
+ method public kotlin.jvm.functions.Function1<T,kotlin.Unit> getContent();
+ method public java.util.Map<java.lang.String,java.lang.Object> getFeatureMap();
+ method public T getKey();
+ property public kotlin.jvm.functions.Function1<T,kotlin.Unit> content;
+ property public java.util.Map<java.lang.String,java.lang.Object> featureMap;
+ property public T key;
+ }
+
+ public class NavEntryWrapper<T> extends androidx.navigation3.NavEntry<T> {
+ ctor public NavEntryWrapper(androidx.navigation3.NavEntry<T> navEntry);
+ method public final androidx.navigation3.NavEntry<T> getNavEntry();
+ property public kotlin.jvm.functions.Function1<T,kotlin.Unit> content;
+ property public java.util.Map<java.lang.String,java.lang.Object> featureMap;
+ property public T key;
+ property public final androidx.navigation3.NavEntry<T> navEntry;
}
public interface NavLocalProvider {
- method @androidx.compose.runtime.Composable public default void ProvideToBackStack(java.util.List<?> backStack);
+ method @androidx.compose.runtime.Composable public default void ProvideToBackStack(java.util.List<?> backStack, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @androidx.compose.runtime.Composable public <T> void ProvideToEntry(androidx.navigation3.NavEntry<T> entry);
}
- public final class NavWrapperManager {
- ctor public NavWrapperManager();
- ctor public NavWrapperManager(optional java.util.List<? extends androidx.navigation3.NavLocalProvider> navLocalProviders);
- method @androidx.compose.runtime.Composable public <T> void ContentForEntry(androidx.navigation3.NavEntry<T> entry);
- method @androidx.compose.runtime.Composable public void PrepareBackStack(java.util.List<?> backStack);
- }
-
- public final class NavWrapperManagerKt {
- method @androidx.compose.runtime.Composable public static androidx.navigation3.NavWrapperManager rememberNavWrapperManager(java.util.List<? extends androidx.navigation3.NavLocalProvider> navLocalProviders);
- }
-
public final class SaveableStateNavLocalProvider implements androidx.navigation3.NavLocalProvider {
ctor public SaveableStateNavLocalProvider();
method @androidx.compose.runtime.Composable public <T> void ProvideToEntry(androidx.navigation3.NavEntry<T> entry);
diff --git a/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavDisplaySamples.kt b/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavDisplaySamples.kt
index d4728e8..64c39b0 100644
--- a/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavDisplaySamples.kt
+++ b/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavDisplaySamples.kt
@@ -21,6 +21,8 @@
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.viewmodel.navigation3.ViewModelStoreNavLocalProvider
@@ -38,6 +40,7 @@
@Composable
fun BaseNav() {
val backStack = rememberMutableStateListOf(Profile)
+ val showDialog = remember { mutableStateOf(false) }
NavDisplay(
backstack = backStack,
localProviders = listOf(SavedStateNavLocalProvider, ViewModelStoreNavLocalProvider),
@@ -55,8 +58,8 @@
) {
Scrollable({ backStack.add(it) }) { backStack.removeLast() }
}
- entry<Dialog>(featureMap = NavDisplay.isDialog(true)) {
- DialogContent { backStack.removeLast() }
+ entry<DialogBase> {
+ DialogBase(onClick = { showDialog.value = true }) { backStack.removeLast() }
}
entry<Dashboard>(
NavDisplay.transition(slideInHorizontally { it }, slideOutHorizontally { it })
@@ -66,4 +69,7 @@
}
}
)
+ if (showDialog.value) {
+ DialogContent(onDismissRequest = { showDialog.value = false })
+ }
}
diff --git a/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavigationSamples.kt b/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavigationSamples.kt
index 3702017..6a5ec92 100644
--- a/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavigationSamples.kt
+++ b/navigation3/navigation3/samples/src/main/kotlin/androidx/navigation3/samples/NavigationSamples.kt
@@ -42,6 +42,7 @@
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.Dialog
import androidx.savedstate.serialization.decodeFromSavedState
import androidx.savedstate.serialization.encodeToSavedState
import kotlinx.serialization.InternalSerializationApi
@@ -66,7 +67,7 @@
}
@Serializable
-object Dialog {
+object DialogBase {
val resourceId: Int = R.string.dialog
}
@@ -85,7 +86,7 @@
Divider(color = Color.Black)
NavigateButton(stringResource(Scrollable.resourceId)) { navigateTo(Scrollable) }
Divider(color = Color.Black)
- NavigateButton(stringResource(Dialog.resourceId)) { navigateTo(Dialog) }
+ NavigateButton(stringResource(DialogBase.resourceId)) { navigateTo(DialogBase) }
Spacer(Modifier.weight(1f))
NavigateBackButton(onBack)
}
@@ -112,13 +113,24 @@
}
@Composable
-fun DialogContent(onBack: () -> Unit) {
- val dialogWidth = 300.dp
- val dialogHeight = 300.dp
- Column(Modifier.size(dialogWidth, dialogHeight).background(Color.White).padding(8.dp)) {
+fun DialogBase(onClick: () -> Unit, onBack: () -> Unit) {
+ Column(Modifier.fillMaxSize()) {
+ Text(stringResource(R.string.dialog))
+ Button(onClick = onClick) { Text("Show Dialog") }
+ Spacer(Modifier.weight(1f))
NavigateBackButton(onBack)
- LazyColumn(modifier = Modifier.weight(1f)) {
- items(phrases) { phrase -> Text(phrase, fontSize = 16.sp) }
+ }
+}
+
+@Composable
+fun DialogContent(onDismissRequest: () -> Unit) {
+ Dialog(onDismissRequest = onDismissRequest) {
+ val dialogWidth = 300.dp
+ val dialogHeight = 300.dp
+ Column(Modifier.size(dialogWidth, dialogHeight).background(Color.White).padding(8.dp)) {
+ LazyColumn(modifier = Modifier.weight(1f)) {
+ items(phrases) { phrase -> Text(phrase, fontSize = 16.sp) }
+ }
}
}
}
diff --git a/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/AnimatedTest.kt b/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/AnimatedTest.kt
index 6fb5955..be69875 100644
--- a/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/AnimatedTest.kt
+++ b/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/AnimatedTest.kt
@@ -138,7 +138,637 @@
composeTestRule.onNodeWithText(first).assertDoesNotExist()
composeTestRule.onNodeWithText(second).assertExists()
}
+
+ @Test
+ fun testPop() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ featureMap =
+ NavDisplay.popTransition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(second).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle { backstack.removeAt(1) }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+
+ composeTestRule.waitForIdle()
+ // pop to first
+ assertThat(backstack).containsExactly(first)
+ composeTestRule.onNodeWithText(first).assertIsDisplayed()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ }
+
+ @Test
+ fun testPopMultiple() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second, third) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ featureMap =
+ NavDisplay.popTransition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ ) {
+ Text(third)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second, third)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle {
+ backstack.removeAt(2)
+ backstack.removeAt(1)
+ }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+
+ composeTestRule.waitForIdle()
+ // pop to first
+ assertThat(backstack).containsExactly(first)
+ composeTestRule.onNodeWithText(first).assertIsDisplayed()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertDoesNotExist()
+ }
+
+ @Test
+ fun testPopNavigate() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ featureMap =
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(third)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(second).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle {
+ backstack.removeAt(1)
+ backstack.add(third)
+ }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, third)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ }
+
+ @Test
+ fun testCentrePop() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second, third) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ featureMap =
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(third)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second, third)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle { backstack.removeAt(1) }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, third)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ }
+
+ @Test
+ fun testCentreNavigate() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, third) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ featureMap =
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(third)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, third)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle { backstack.add(1, second) }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, second, third)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ }
+
+ @Test
+ fun testCentrePopAndEndPop() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second, third, fourth) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(third)
+ }
+ fourth ->
+ NavEntry(
+ fourth,
+ ) {
+ Text(fourth)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(fourth).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second, third, fourth)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle {
+ backstack.removeAt(3)
+ backstack.removeAt(1)
+ }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, third)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ composeTestRule.onNodeWithText(fourth).assertDoesNotExist()
+ }
+
+ @Test
+ fun testCentrePopAndEndNavigate() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second, third) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ ) {
+ Text(third)
+ }
+ fourth ->
+ NavEntry(
+ fourth,
+ featureMap =
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(fourth)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second, third)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle {
+ backstack.removeAt(1)
+ backstack.add(fourth)
+ }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, third, fourth)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertDoesNotExist()
+ composeTestRule.onNodeWithText(fourth).assertIsDisplayed()
+ }
+
+ @Test
+ fun testCentreNavigateAndEndPop() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, third, fourth) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ featureMap =
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(third)
+ }
+ fourth ->
+ NavEntry(
+ fourth,
+ ) {
+ Text(fourth)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(fourth).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, third, fourth)
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle {
+ backstack.removeAt(2)
+ backstack.add(1, second)
+ }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, second, third)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ composeTestRule.onNodeWithText(fourth).assertDoesNotExist()
+ }
+
+ @Test
+ fun testCentreNavigateAndEndNavigate() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, third) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ ) {
+ Text(third)
+ }
+ fourth ->
+ NavEntry(
+ fourth,
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(fourth)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, third)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle {
+ backstack.add(1, second)
+ backstack.add(fourth)
+ }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, second, third, fourth)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertDoesNotExist()
+ composeTestRule.onNodeWithText(fourth).assertIsDisplayed()
+ }
+
+ @Test
+ fun testSameStack() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(second)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(second).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle {
+ backstack.removeAt(1)
+ backstack.add(second)
+ }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, second)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertIsDisplayed()
+ }
+
+ @Test
+ fun testDuplicateLastEntry() {
+ lateinit var backstack: MutableList<Any>
+ val testDuration = DEFAULT_TRANSITION_DURATION_MILLISECOND / 5
+ composeTestRule.setContent {
+ backstack = remember { mutableStateListOf(first, second, third) }
+ NavDisplay(backstack) {
+ when (it) {
+ first ->
+ NavEntry(
+ first,
+ ) {
+ Text(first)
+ }
+ second ->
+ NavEntry(
+ second,
+ featureMap =
+ NavDisplay.transition(
+ enter = fadeIn(tween(testDuration)),
+ exit = fadeOut(tween(testDuration))
+ )
+ ) {
+ Text(second)
+ }
+ third ->
+ NavEntry(
+ third,
+ ) {
+ Text(third)
+ }
+ else -> error("Invalid key passed")
+ }
+ }
+ }
+
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertIsDisplayed()
+ assertThat(backstack).containsExactly(first, second, third)
+
+ composeTestRule.mainClock.autoAdvance = false
+ composeTestRule.runOnIdle { backstack.add(second) }
+
+ // advance by a duration that is much shorter than the default duration
+ // to ensure that the custom animation is used and has completed after this
+ composeTestRule.mainClock.advanceTimeBy((testDuration * 1.5).toLong())
+ // not pop
+ composeTestRule.waitForIdle()
+ assertThat(backstack).containsExactly(first, second, third, second)
+ composeTestRule.onNodeWithText(first).assertDoesNotExist()
+ composeTestRule.onNodeWithText(third).assertDoesNotExist()
+ composeTestRule.onNodeWithText(second).assertIsDisplayed()
+ }
}
private const val first = "first"
private const val second = "second"
+private const val third = "third"
+private const val fourth = "fourth"
diff --git a/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavWrapperManagerTest.kt b/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavBackStackProviderTest.kt
similarity index 67%
rename from navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavWrapperManagerTest.kt
rename to navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavBackStackProviderTest.kt
index 646df38..6d199e3 100644
--- a/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavWrapperManagerTest.kt
+++ b/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavBackStackProviderTest.kt
@@ -27,18 +27,22 @@
@LargeTest
@RunWith(AndroidJUnit4::class)
-class NavWrapperManagerTest {
+class NavBackStackProviderTest {
@get:Rule val composeTestRule = createComposeRule()
@Test
fun callWrapperFunctions() {
var calledWrapBackStack = false
var calledWrapContent = false
- val wrapper =
+ val provider =
object : NavLocalProvider {
@Composable
- override fun ProvideToBackStack(backStack: List<Any>) {
+ override fun ProvideToBackStack(
+ backStack: List<Any>,
+ content: @Composable () -> Unit
+ ) {
calledWrapBackStack = true
+ content.invoke()
}
@Composable
@@ -47,11 +51,14 @@
}
}
- val manager = NavWrapperManager(listOf(wrapper))
-
composeTestRule.setContent {
- manager.PrepareBackStack(listOf("something"))
- manager.ContentForEntry(NavEntry("myKey") {})
+ NavBackStackProvider(
+ backStack = listOf("something"),
+ localProviders = listOf(provider),
+ entryProvider = { NavEntry("something") {} }
+ ) { records ->
+ records.last().content.invoke("something")
+ }
}
assertThat(calledWrapBackStack).isTrue()
@@ -62,11 +69,15 @@
fun callWrapperFunctionsOnce() {
var calledWrapBackStackCount = 0
var calledWrapContentCount = 0
- val wrapper =
+ val provider =
object : NavLocalProvider {
@Composable
- override fun ProvideToBackStack(backStack: List<Any>) {
+ override fun ProvideToBackStack(
+ backStack: List<Any>,
+ content: @Composable () -> Unit
+ ) {
calledWrapBackStackCount++
+ content.invoke()
}
@Composable
@@ -75,11 +86,14 @@
}
}
- val manager = NavWrapperManager(listOf(wrapper, wrapper))
-
composeTestRule.setContent {
- manager.PrepareBackStack(listOf("something"))
- manager.ContentForEntry(NavEntry("myKey") {})
+ NavBackStackProvider(
+ backStack = listOf("something"),
+ localProviders = listOf(provider, provider),
+ entryProvider = { NavEntry("something") {} }
+ ) { records ->
+ records.last().content.invoke("something")
+ }
}
assertThat(calledWrapBackStackCount).isEqualTo(1)
diff --git a/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavDisplayTest.kt b/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavDisplayTest.kt
index 614eb88..3342fbf 100644
--- a/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavDisplayTest.kt
+++ b/navigation3/navigation3/src/androidInstrumentedTest/kotlin/androidx/navigation3/NavDisplayTest.kt
@@ -18,6 +18,7 @@
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
+import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateListOf
@@ -28,6 +29,8 @@
import androidx.compose.ui.test.isDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.window.Dialog
import androidx.kruth.assertThat
import androidx.savedstate.SavedStateRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -78,20 +81,28 @@
fun testDialog() {
lateinit var backstack: MutableList<Any>
composeTestRule.setContent {
+ var showDialog = remember { mutableStateOf(false) }
backstack = remember { mutableStateListOf(first) }
NavDisplay(backstack = backstack) {
when (it) {
- first -> NavEntry(first) { Text(first) }
- second -> NavEntry(second, NavDisplay.isDialog(true)) { Text(second) }
+ first ->
+ NavEntry(first) {
+ Button(onClick = { showDialog.value = true }) { Text(first) }
+ }
else -> error("Invalid key passed")
}
}
+ if (showDialog.value) {
+ Dialog(onDismissRequest = {}) { Text(second) }
+ }
}
assertThat(composeTestRule.onNodeWithText(first).isDisplayed()).isTrue()
- composeTestRule.runOnIdle { backstack.add(second) }
+ composeTestRule.waitForIdle()
+ composeTestRule.onNodeWithText(first).performClick()
+ composeTestRule.waitForIdle()
// Both first and second should be showing if we are on a dialog.
assertThat(composeTestRule.onNodeWithText(first).isDisplayed()).isTrue()
assertThat(composeTestRule.onNodeWithText(second).isDisplayed()).isTrue()
diff --git a/navigation3/navigation3/src/androidMain/kotlin/androidx/navigation3/NavDisplay.android.kt b/navigation3/navigation3/src/androidMain/kotlin/androidx/navigation3/NavDisplay.android.kt
index fdc1e24..7f693f6 100644
--- a/navigation3/navigation3/src/androidMain/kotlin/androidx/navigation3/NavDisplay.android.kt
+++ b/navigation3/navigation3/src/androidMain/kotlin/androidx/navigation3/NavDisplay.android.kt
@@ -28,8 +28,11 @@
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.window.Dialog
import androidx.navigation3.NavDisplay.DEFAULT_TRANSITION_DURATION_MILLISECOND
+import androidx.navigation3.NavDisplay.ENTER_TRANSITION_KEY
+import androidx.navigation3.NavDisplay.EXIT_TRANSITION_KEY
+import androidx.navigation3.NavDisplay.POP_ENTER_TRANSITION_KEY
+import androidx.navigation3.NavDisplay.POP_EXIT_TRANSITION_KEY
/** Object that indicates the features that can be handled by the [NavDisplay] */
public object NavDisplay {
@@ -42,15 +45,17 @@
else mapOf(ENTER_TRANSITION_KEY to enter, EXIT_TRANSITION_KEY to exit)
/**
- * Function to be called on the [NavEntry.featureMap] to notify the [NavDisplay] that the
- * content should be displayed inside of a [Dialog]
+ * Function to be called on the [NavEntry.featureMap] to notify the [NavDisplay] that, when
+ * popping from backstack, the content should be animated using the provided transitions.
*/
- public fun isDialog(boolean: Boolean): Map<String, Any> =
- if (!boolean) emptyMap() else mapOf(DIALOG_KEY to true)
+ public fun popTransition(enter: EnterTransition?, exit: ExitTransition?): Map<String, Any> =
+ if (enter == null || exit == null) emptyMap()
+ else mapOf(POP_ENTER_TRANSITION_KEY to enter, POP_EXIT_TRANSITION_KEY to exit)
internal const val ENTER_TRANSITION_KEY = "enterTransition"
internal const val EXIT_TRANSITION_KEY = "exitTransition"
- internal const val DIALOG_KEY = "dialog"
+ internal const val POP_ENTER_TRANSITION_KEY = "popEnterTransition"
+ internal const val POP_EXIT_TRANSITION_KEY = "popExitTransition"
internal const val DEFAULT_TRANSITION_DURATION_MILLISECOND = 700
}
@@ -58,19 +63,22 @@
* Display for Composable content that displays a single pane of content at a time, but can move
* that content in and out with customized transitions.
*
- * The NavDisplay displays the content associated with the last key on the back stack in most
- * circumstances. If that content wants to be displayed as a dialog, as communicated by adding
- * [NavDisplay.isDialog] to a [NavEntry.featureMap], then the last key's content is a dialog and the
- * second to last key is a displayed in the background.
+ * The NavDisplay displays the content associated with the last key on the back stack.
*
* @param backstack the collection of keys that represents the state that needs to be handled
* @param localProviders list of [NavLocalProvider] to add information to the provided entriess
* @param modifier the modifier to be applied to the layout.
* @param contentAlignment The [Alignment] of the [AnimatedContent]
- * @param enterTransition Default [EnterTransition] for all [NavEntry]s. Can be overridden
+ * @param enterTransition Default [EnterTransition] when navigating to [NavEntry]s. Can be
+ * overridden individually for each [NavEntry] by passing in the entry's transitions through
+ * [NavEntry.featureMap].
+ * @param exitTransition Default [ExitTransition] when navigating to [NavEntry]s. Can be overridden
* individually for each [NavEntry] by passing in the entry's transitions through
* [NavEntry.featureMap].
- * @param exitTransition Default [ExitTransition] for all [NavEntry]s. Can be overridden
+ * @param popEnterTransition Default [EnterTransition] when popping [NavEntry]s. Can be overridden
+ * individually for each [NavEntry] by passing in the entry's transitions through
+ * [NavEntry.featureMap].
+ * @param popExitTransition Default [ExitTransition] when popping [NavEntry]s. Can be overridden
* individually for each [NavEntry] by passing in the entry's transitions through
* [NavEntry.featureMap].
* @param onBack a callback for handling system back presses
@@ -98,55 +106,79 @@
DEFAULT_TRANSITION_DURATION_MILLISECOND,
)
),
+ popEnterTransition: EnterTransition =
+ fadeIn(
+ animationSpec =
+ tween(
+ DEFAULT_TRANSITION_DURATION_MILLISECOND,
+ )
+ ),
+ popExitTransition: ExitTransition =
+ fadeOut(
+ animationSpec =
+ tween(
+ DEFAULT_TRANSITION_DURATION_MILLISECOND,
+ )
+ ),
onBack: () -> Unit = { if (backstack is MutableList) backstack.removeAt(backstack.size - 1) },
entryProvider: (key: T) -> NavEntry<out T>
) {
require(backstack.isNotEmpty()) { "NavDisplay backstack cannot be empty" }
- val wrapperManager: NavWrapperManager = rememberNavWrapperManager(localProviders)
BackHandler(backstack.size > 1, onBack)
- wrapperManager.PrepareBackStack(backStack = backstack)
- val key = backstack.last()
- val entry = entryProvider.invoke(key)
+ @Suppress("UNCHECKED_CAST")
+ NavBackStackProvider(backstack, localProviders, entryProvider as (T) -> NavEntry<T>) { entries
+ ->
- // Incoming entry defines transitions, otherwise it uses default transitions from NavDisplay
- val finalEnterTransition =
- entry.featureMap[NavDisplay.ENTER_TRANSITION_KEY] as? EnterTransition ?: enterTransition
- val finalExitTransition =
- entry.featureMap[NavDisplay.EXIT_TRANSITION_KEY] as? ExitTransition ?: exitTransition
+ // Make a copy shallow copy so that transition.currentState and transition.targetState are
+ // different backstack instances. This ensures currentState reflects the old backstack when
+ // the backstack (targetState) is updated.
+ val newStack = backstack.toList()
+ val entry = entries.last()
- val isDialog = entry.featureMap[NavDisplay.DIALOG_KEY] == true
-
- // if there is a dialog, we should create a transition with the next to last entry instead.
- val transition =
- if (isDialog) {
- if (backstack.size > 1) {
- val previousKey = backstack[backstack.size - 2]
- val previousEntry = entryProvider.invoke(previousKey)
- updateTransition(targetState = previousEntry, label = previousKey.toString())
+ val transition = updateTransition(targetState = newStack, label = newStack.toString())
+ val isPop = isPop(transition.currentState, newStack)
+ // Incoming entry defines transitions, otherwise it uses default transitions from
+ // NavDisplay
+ val finalEnterTransition =
+ if (isPop) {
+ entry.featureMap[POP_ENTER_TRANSITION_KEY] as? EnterTransition ?: popEnterTransition
} else {
- null
+ entry.featureMap[ENTER_TRANSITION_KEY] as? EnterTransition ?: enterTransition
}
- } else {
- updateTransition(targetState = entry, label = key.toString())
+ val finalExitTransition =
+ if (isPop) {
+ entry.featureMap[POP_EXIT_TRANSITION_KEY] as? ExitTransition ?: popExitTransition
+ } else {
+ entry.featureMap[EXIT_TRANSITION_KEY] as? ExitTransition ?: exitTransition
+ }
+ transition.AnimatedContent(
+ modifier = modifier,
+ transitionSpec = {
+ ContentTransform(
+ targetContentEnter = finalEnterTransition,
+ initialContentExit = finalExitTransition,
+ sizeTransform = sizeTransform
+ )
+ },
+ contentAlignment = contentAlignment,
+ contentKey = { it.last() }
+ ) { innerStack ->
+ val lastKey = innerStack.last()
+ entries.findLast { entry -> entry.key == lastKey }?.content?.invoke(lastKey)
}
-
- transition?.AnimatedContent(
- modifier = modifier,
- transitionSpec = {
- ContentTransform(
- targetContentEnter = finalEnterTransition,
- initialContentExit = finalExitTransition,
- sizeTransform = sizeTransform
- )
- },
- contentAlignment = contentAlignment,
- contentKey = { it.key }
- ) { innerEntry ->
- wrapperManager.ContentForEntry(innerEntry)
}
+}
- if (isDialog) {
- Dialog(onBack) { wrapperManager.ContentForEntry(entry) }
- }
+private fun <T : Any> isPop(oldBackStack: List<T>, newBackStack: List<T>): Boolean {
+ // entire stack replaced
+ if (oldBackStack.first() != newBackStack.first()) return false
+ // navigated
+ if (newBackStack.size > oldBackStack.size) return false
+
+ val divergingIndex =
+ newBackStack.indices.firstOrNull { index -> newBackStack[index] != oldBackStack[index] }
+ // if newBackStack never diverged from oldBackStack, then it is a clean subset of the oldStack
+ // and is a pop
+ return divergingIndex == null
}
diff --git a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavBackStackProvider.kt b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavBackStackProvider.kt
new file mode 100644
index 0000000..5c048b5
--- /dev/null
+++ b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavBackStackProvider.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.navigation3
+
+import androidx.compose.runtime.Composable
+import kotlin.collections.plus
+
+/**
+ * Function that provides all of the [NavEntry]s wrapped with the given [NavLocalProvider]s. It is
+ * responsible for executing the functions provided by each [NavLocalProvider] appropriately.
+ *
+ * Note: the order in which the [NavLocalProvider]s are added to the list determines their scope,
+ * i.e. a [NavLocalProvider] added earlier in a list has its data available to those added later.
+ *
+ * @param backStack the list of keys that represent the backstack
+ * @param localProviders the [NavLocalProvider]s that are providing data to the content
+ * @param entryProvider a function that returns the [NavEntry] for a given key
+ * @param content the content to be displayed
+ */
+@Composable
+public fun <T : Any> NavBackStackProvider(
+ backStack: List<T>,
+ localProviders: List<NavLocalProvider>,
+ entryProvider: (key: T) -> NavEntry<T>,
+ content: @Composable (List<NavEntry<T>>) -> Unit
+) {
+ val finalProviders = (listOf(SaveableStateNavLocalProvider()) + localProviders).distinct()
+
+ // Generates a list of entries that are wrapped with the given providers
+ val entries =
+ backStack.map {
+ val entry = entryProvider.invoke(it)
+ finalProviders.distinct().foldRight(entry) { provider: NavLocalProvider, wrappedEntry ->
+ object : NavEntryWrapper<T>(wrappedEntry) {
+ override val content: @Composable ((T) -> Unit)
+ get() = { provider.ProvideToEntry(wrappedEntry) }
+ }
+ }
+ }
+
+ // Provides the entire backstack to the previously wrapped entries
+ finalProviders
+ .distinct()
+ .foldRight<NavLocalProvider, @Composable () -> Unit>({ content(entries) }) {
+ provider: NavLocalProvider,
+ wrappedContent ->
+ { provider.ProvideToBackStack(backStack = backStack, wrappedContent) }
+ }
+ .invoke()
+}
diff --git a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavEntry.kt b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavEntry.kt
index e8fc674..727f809 100644
--- a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavEntry.kt
+++ b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavEntry.kt
@@ -27,7 +27,7 @@
* @param content content for this entry to be displayed when this entry is active
*/
public open class NavEntry<T : Any>(
- public val key: T,
- public val featureMap: Map<String, Any> = emptyMap(),
- public val content: @Composable (T) -> Unit,
+ public open val key: T,
+ public open val featureMap: Map<String, Any> = emptyMap(),
+ public open val content: @Composable (T) -> Unit
)
diff --git a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavEntryWrapper.kt b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavEntryWrapper.kt
new file mode 100644
index 0000000..c24a68e
--- /dev/null
+++ b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavEntryWrapper.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.navigation3
+
+import androidx.compose.runtime.Composable
+
+/**
+ * Class that wraps a [NavEntry] within another [NavEntry].
+ *
+ * This provides a nesting mechanism for [NavEntry]s that allows properly nested content.
+ *
+ * @param navEntry the [NavEntry] to wrap
+ */
+public open class NavEntryWrapper<T : Any>(public val navEntry: NavEntry<T>) :
+ NavEntry<T>(navEntry.key, navEntry.featureMap, navEntry.content) {
+ override val key: T
+ get() = navEntry.key
+
+ override val featureMap: Map<String, Any>
+ get() = navEntry.featureMap
+
+ override val content: @Composable (T) -> Unit
+ get() = navEntry.content
+}
diff --git a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavLocalProvider.kt b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavLocalProvider.kt
index b3fbeb2..f40365d 100644
--- a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavLocalProvider.kt
+++ b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavLocalProvider.kt
@@ -32,7 +32,9 @@
*
* This function is called by the [NavWrapperManager] and should not be called directly.
*/
- @Composable public fun ProvideToBackStack(backStack: List<Any>): Unit = Unit
+ @Composable
+ public fun ProvideToBackStack(backStack: List<Any>, content: @Composable () -> Unit): Unit =
+ content.invoke()
/**
* Allows a [NavLocalProvider] to provide information to a single entry.
diff --git a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavWrapperManager.kt b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavWrapperManager.kt
deleted file mode 100644
index a994b16..0000000
--- a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/NavWrapperManager.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.navigation3
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-
-/** Creates a [NavLocalProvider]. */
-@Composable
-public fun rememberNavWrapperManager(navLocalProviders: List<NavLocalProvider>): NavWrapperManager {
- return remember { NavWrapperManager(navLocalProviders) }
-}
-
-/**
- * Class that manages all of the provided [NavLocalProvider]. It is responsible for executing the
- * functions provided by each [NavLocalProvider] appropriately.
- *
- * Note: the order in which the [NavLocalProvider]s are added to the list determines their scope,
- * i.e. a [NavLocalProvider] added earlier in a list has its data available to those added later.
- *
- * @param navLocalProviders the [NavLocalProvider]s that are providing data to the content
- */
-public class NavWrapperManager(navLocalProviders: List<NavLocalProvider> = emptyList()) {
- /**
- * Final list of wrappers. This always adds a [SaveableStateNavLocalProvider] by default, as it
- * is required. It then filters out any duplicates to ensure there is always one instance of any
- * wrapper at a given time.
- */
- private val finalWrappers =
- (navLocalProviders + listOf(SaveableStateNavLocalProvider())).distinct()
-
- /**
- * Calls the [NavLocalProvider.ProvideToBackStack] functions on each wrapper
- *
- * This function is called by the [NavDisplay](reference/androidx/navigation/NavDisplay) and
- * should not be called directly.
- */
- @Composable
- public fun PrepareBackStack(backStack: List<Any>) {
- finalWrappers.distinct().forEach { it.ProvideToBackStack(backStack = backStack) }
- }
-
- /**
- * Calls the [NavLocalProvider.ProvideToEntry] functions on each wrapper.
- *
- * This function is called by the [NavDisplay](reference/androidx/navigation/NavDisplay) and
- * should not be called directly.
- */
- @Composable
- public fun <T : Any> ContentForEntry(entry: NavEntry<T>) {
- val key = entry.key
- finalWrappers
- .distinct()
- .foldRight(entry.content) { wrapper, contentLambda ->
- { wrapper.ProvideToEntry(NavEntry(key, entry.featureMap, content = contentLambda)) }
- }
- .invoke(key)
- }
-}
diff --git a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/SaveableStateNavLocalProvider.kt b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/SaveableStateNavLocalProvider.kt
index 69451da..76d4238 100644
--- a/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/SaveableStateNavLocalProvider.kt
+++ b/navigation3/navigation3/src/commonMain/kotlin/androidx/navigation3/SaveableStateNavLocalProvider.kt
@@ -36,7 +36,7 @@
private var backstackSize = 0
@Composable
- override fun ProvideToBackStack(backStack: List<Any>) {
+ override fun ProvideToBackStack(backStack: List<Any>, content: @Composable () -> Unit) {
DisposableEffect(key1 = backStack) {
refCount.clear()
onDispose {}
@@ -64,6 +64,7 @@
}
}
}
+ content.invoke()
}
@Composable
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/BitmapFetcher.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/BitmapFetcher.kt
index 8b223f0..f8c0f61 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/BitmapFetcher.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/BitmapFetcher.kt
@@ -24,12 +24,11 @@
import androidx.annotation.MainThread
import androidx.annotation.VisibleForTesting
import androidx.pdf.PdfDocument
+import androidx.pdf.util.RectUtils
import kotlin.math.roundToInt
-import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.ensureActive
-import kotlinx.coroutines.job
import kotlinx.coroutines.launch
/**
@@ -56,6 +55,7 @@
*/
private val maxTileBackgroundSizePx = Point(maxBitmapSizePx.x / 2, maxBitmapSizePx.y / 2)
+ /** True if this fetcher is ready to fetch bitmaps for the page */
var isActive: Boolean = false
set(value) {
// Debounce setting the field to the same value
@@ -64,41 +64,102 @@
if (field) onActive() else onInactive()
}
+ /** The bitmaps to draw for this page, as [PageContents] */
@get:MainThread var pageContents: PageContents? = null
+ /** The [PdfDocument.BitmapSource] from which to obtain [Bitmap]s, only used while [isActive] */
private var bitmapSource: PdfDocument.BitmapSource? = null
- @VisibleForTesting var currentRenderingScale: Float? = null
- @VisibleForTesting var renderingJob: Job? = null
- /**
- * Notify this fetcher that the zoom level / scale factor of the UI has changed, and that it
- * ought to consider fetching new bitmaps
- */
- fun onScaleChanged(scale: Float) {
- if (!shouldRenderNewBitmaps(scale)) return
+ /** The scale, i.e. zoom level for which we're actively fetching [Bitmap]s */
+ @VisibleForTesting var currentFetchingScale: Float? = null
- currentRenderingScale = scale
- renderingJob?.cancel()
- renderingJob =
- if (needsTiling(scale)) {
- fetchTiles(scale)
- } else {
- fetchNewBitmap(scale)
- }
- renderingJob?.invokeOnCompletion { cause ->
- // We only want to reset these states when we completed naturally
- if (cause is CancellationException) return@invokeOnCompletion
- renderingJob = null
- currentRenderingScale = null
+ /** The [BitmapRequestHandle] for any ongoing fetch */
+ @VisibleForTesting var fetchingWorkHandle: BitmapRequestHandle? = null
+
+ /** Update the view area and scale for which we should be fetching bitmaps */
+ fun updateViewProperties(scale: Float, viewArea: Rect) {
+ // Scale the provided viewArea, and clip it to the scaled bounds of the page
+ // Carefully avoid mutating the provided Rect
+ val scaledViewArea = Rect(viewArea)
+ RectUtils.scale(scaledViewArea, scale)
+ scaledViewArea.intersect(0, 0, (pageSize.x * scale).toInt(), (pageSize.y * scale).toInt())
+ if (shouldFetchNewContents(scale)) {
+ // Scale has changed, fetch entirely new PageContents
+ fetchNewContents(scale, scaledViewArea)
+ } else {
+ // View area has changed, fetch new tiles and discard obsolete ones IFF we're tiling
+ maybeUpdateTiling(scale, scaledViewArea)
}
}
- private fun shouldRenderNewBitmaps(scale: Float): Boolean {
- val renderingAtCurrentScale =
- currentRenderingScale == scale && renderingJob?.isActive == true
- val renderedAtCurrentScale = pageContents?.let { it.renderedScale == scale } ?: false
+ /** Discard all bitmaps in the current tiling */
+ fun discardTileBitmaps() {
+ (pageContents as? TileBoard)?.let { for (tile in it.tiles) tile.bitmap = null }
+ }
- return !renderedAtCurrentScale && !renderingAtCurrentScale
+ private fun maybeUpdateTiling(scale: Float, scaledViewArea: Rect) {
+ // Exit early if we're not tiling
+ val currentTileBoard = pageContents as? TileBoard ?: return
+ val currentTilingWork = fetchingWorkHandle as? TileBoardRequestHandle
+ val tileRequests = mutableMapOf<Int, SingleBitmapRequestHandle>()
+ var tileJob: Job? = null
+ for (tile in currentTileBoard.tiles) {
+ val ongoingRequest = currentTilingWork?.tileRequestHandles?.get(tile.index)
+ if (
+ tile.rectPx.intersects(
+ scaledViewArea.left,
+ scaledViewArea.top,
+ scaledViewArea.right,
+ scaledViewArea.bottom
+ )
+ ) {
+ // Tile is visible, make sure we have, or have requested, a Bitmap for it
+ if (ongoingRequest?.isActive == true) {
+ // Continue tracking the active request for this tile
+ tileRequests[tile.index] = ongoingRequest
+ } else if (tile.bitmap == null) {
+ // Make a new request for this tile
+ tileJob = fetchBitmap(tile, scale, tileJob)
+ tileRequests[tile.index] = SingleBitmapRequestHandle(tileJob)
+ }
+ } else {
+ // Tile is no longer visible, cancel any active request and clean up the Bitmap
+ ongoingRequest?.cancel()
+ tile.bitmap = null
+ }
+ }
+ if (tileRequests.isNotEmpty()) {
+ fetchingWorkHandle =
+ TileBoardRequestHandle(tileRequests, currentTilingWork?.backgroundRequestHandle)
+ currentFetchingScale = scale
+ }
+ }
+
+ /**
+ * Notify this fetcher that the zoom level / scale factor of the UI has changed, and that it
+ * ought to fetch new bitmaps
+ */
+ private fun fetchNewContents(scale: Float, scaledViewArea: Rect) {
+ fetchingWorkHandle?.cancel()
+ fetchingWorkHandle =
+ if (needsTiling(scale)) {
+ fetchTiles(scale, scaledViewArea)
+ } else {
+ fetchNewBitmap(scale)
+ }
+ currentFetchingScale = scale
+ }
+
+ /**
+ * Returns true if this fetcher should start fetching a net-new [PageContents], i.e. if the
+ * scaled has changed since we started or finished fetching the previous set of Bitmaps
+ */
+ private fun shouldFetchNewContents(scale: Float): Boolean {
+ val fetchingAtCurrentScale =
+ currentFetchingScale == scale && fetchingWorkHandle?.isActive == true
+ val fetchedAtCurrentScale = pageContents?.let { it.bitmapScale == scale } == true
+
+ return !fetchedAtCurrentScale && !fetchingAtCurrentScale
}
/** Prepare to start fetching bitmaps */
@@ -111,73 +172,102 @@
* this fetcher
*/
private fun onInactive() {
- currentRenderingScale = null
+ currentFetchingScale = null
pageContents = null
- renderingJob?.cancel()
- renderingJob = null
+ fetchingWorkHandle?.cancel()
+ fetchingWorkHandle = null
bitmapSource?.close()
bitmapSource = null
}
/** Fetch a [FullPageBitmap] */
- private fun fetchNewBitmap(scale: Float): Job {
- return backgroundScope.launch {
- val size = limitBitmapSize(scale, maxBitmapSizePx)
- // If our BitmapSource is null that means this fetcher is inactive and we should
- // stop what we're doing
- val bitmap = bitmapSource?.getBitmap(size) ?: return@launch
- ensureActive()
- pageContents = FullPageBitmap(bitmap, scale)
- onPageUpdate()
- }
+ private fun fetchNewBitmap(scale: Float): SingleBitmapRequestHandle {
+ val job =
+ backgroundScope.launch {
+ val size = limitBitmapSize(scale, maxBitmapSizePx)
+ // If our BitmapSource is null that means this fetcher is inactive and we should
+ // stop what we're doing
+ val bitmap = bitmapSource?.getBitmap(size) ?: return@launch
+ ensureActive()
+ pageContents = FullPageBitmap(bitmap, scale)
+ onPageUpdate()
+ }
+ return SingleBitmapRequestHandle(job)
}
/** Fetch a [TileBoard] */
- private fun fetchTiles(scale: Float): Job {
+ private fun fetchTiles(scale: Float, scaledViewArea: Rect): TileBoardRequestHandle {
val pageSizePx = Point((pageSize.x * scale).roundToInt(), (pageSize.y * scale).roundToInt())
val tileBoard = TileBoard(tileSizePx, pageSizePx, scale)
- // Re-use an existing background bitmap if we have one to avoid unnecessary re-rendering
+ // Re-use an existing background bitmap if we have one to avoid unnecessary re-fetching
// and jank
- val prevBackground = (tileBoard as? TileBoard)?.backgroundBitmap
+ val prevBackground = tileBoard.backgroundBitmap
if (prevBackground != null) {
tileBoard.backgroundBitmap = prevBackground
pageContents = tileBoard
onPageUpdate()
}
- return backgroundScope.launch {
- // Render a new background bitmap if we must
+ val backgroundRequest =
if (prevBackground == null) {
- // If our BitmapSource is null that means this fetcher is inactive and we should
- // stop what we're doing
- val backgroundSize = limitBitmapSize(scale, maxTileBackgroundSizePx)
- val bitmap = bitmapSource?.getBitmap(backgroundSize) ?: return@launch
- pageContents = tileBoard
- ensureActive()
- tileBoard.backgroundBitmap = bitmap
- onPageUpdate()
+ val job =
+ backgroundScope.launch {
+ ensureActive()
+ val backgroundSize = limitBitmapSize(scale, maxTileBackgroundSizePx)
+ val bitmap = bitmapSource?.getBitmap(backgroundSize) ?: return@launch
+ pageContents = tileBoard
+ ensureActive()
+ tileBoard.backgroundBitmap = bitmap
+ onPageUpdate()
+ }
+ SingleBitmapRequestHandle(job)
+ } else {
+ null
}
- for (tile in tileBoard.tiles) {
- renderBitmap(tile, coroutineContext.job, scale)
+ val tileRequests = mutableMapOf<Int, SingleBitmapRequestHandle>()
+ // Used to sequence requests so tiles are loaded left-to-right and top-to-bottom
+ var tileJob: Job? = null
+ for (tile in tileBoard.tiles) {
+ val tileRect = tile.rectPx
+ if (
+ scaledViewArea.intersects(
+ tileRect.left,
+ tileRect.top,
+ tileRect.right,
+ tileRect.bottom
+ )
+ ) {
+ tileJob = fetchBitmap(tile, scale, tileJob)
+ tileRequests[tile.index] = SingleBitmapRequestHandle(tileJob)
}
}
+ return TileBoardRequestHandle(tileRequests.toMap(), backgroundRequest)
}
- /** Render a [Bitmap] for this [TileBoard.Tile] */
- private suspend fun renderBitmap(tile: TileBoard.Tile, thisJob: Job, scale: Float) {
- thisJob.ensureActive()
- val left = tile.offsetPx.x
- val top = tile.offsetPx.y
- val tileRect = Rect(left, top, left + tile.exactSizePx.x, top + tile.exactSizePx.y)
- // If our BitmapSource is null that means this fetcher is inactive and we should
- // stop what we're doing
- val bitmap =
- bitmapSource?.getBitmap(
- Size((pageSize.x * scale).roundToInt(), (pageSize.y * scale).roundToInt()),
- tileRect
- ) ?: return
- thisJob.ensureActive()
- tile.bitmap = bitmap
- onPageUpdate()
+ /**
+ * Fetch a [Bitmap] for this [TileBoard.Tile]
+ *
+ * @param tile the [TileBoard.Tile] to fetch a bitmap for
+ * @param scale the scale factor of the bitmap
+ * @param prevJob the [Job] that is fetching a bitmap for the tile left or above [tile], i.e. to
+ * guarantee tiles are loaded left-to-right and top-to-bottom
+ */
+ private fun fetchBitmap(tile: TileBoard.Tile, scale: Float, prevJob: Job?): Job {
+ val job =
+ backgroundScope.launch {
+ prevJob?.join()
+ ensureActive()
+ // If our BitmapSource is null that means this fetcher is inactive and we should
+ // stop what we're doing
+ val bitmap =
+ bitmapSource?.getBitmap(
+ Size((pageSize.x * scale).roundToInt(), (pageSize.y * scale).roundToInt()),
+ tile.rectPx
+ ) ?: return@launch
+ ensureActive()
+ tile.bitmap = bitmap
+ onPageUpdate()
+ }
+ return job
}
/** True if the [pageSize] * [scale] exceeds [maxBitmapSizePx] */
@@ -206,13 +296,56 @@
}
}
+/** Represents a cancellable handle to a request for one or more [Bitmap]s */
+internal sealed interface BitmapRequestHandle {
+ /** True if this request is active */
+ val isActive: Boolean
+
+ /** Cancel this request completely */
+ fun cancel()
+}
+
+/** Cancellable [BitmapRequestHandle] for a single [Bitmap] */
+internal class SingleBitmapRequestHandle(private val job: Job) : BitmapRequestHandle {
+ override val isActive: Boolean
+ get() = job.isActive
+
+ override fun cancel() {
+ job.cancel()
+ }
+}
+
+/**
+ * Cancellable [BitmapRequestHandle] for a full [TileBoard], composing multiple
+ * [SingleBitmapRequestHandle] for the low-res background and each high-res tile
+ */
+internal class TileBoardRequestHandle(
+ /** Map of [TileBoard.Tile.index] to a [BitmapRequestHandle] to fetch that tile's bitmap */
+ val tileRequestHandles: Map<Int, SingleBitmapRequestHandle>,
+ /**
+ * [SingleBitmapRequestHandle] to fetch a low-res background for this tiling, or null if we
+ * re-used the background from a previous tiling
+ */
+ val backgroundRequestHandle: SingleBitmapRequestHandle? = null
+) : BitmapRequestHandle {
+ override val isActive: Boolean
+ get() =
+ tileRequestHandles.values.any { it.isActive } ||
+ backgroundRequestHandle?.isActive == true
+
+ override fun cancel() {
+ tileRequestHandles.values.forEach { it.cancel() }
+ backgroundRequestHandle?.cancel()
+ }
+}
+
/** Represents the [Bitmap] or [Bitmap]s used to render this page */
internal sealed interface PageContents {
- val renderedScale: Float
+ val bitmapScale: Float
}
/** A singular [Bitmap] depicting the full page, when full page rendering is used */
-internal class FullPageBitmap(val bitmap: Bitmap, override val renderedScale: Float) : PageContents
+internal class FullPageBitmap(val bitmap: Bitmap, override val bitmapScale: Float) : PageContents
/**
* A set of [Bitmap]s that depict the full page as a rectangular grid of individual bitmap tiles.
@@ -221,7 +354,7 @@
internal class TileBoard(
val tileSizePx: Point,
val pageSizePx: Point,
- override val renderedScale: Float
+ override val bitmapScale: Float
) : PageContents {
/** The low res background [Bitmap] for this [TileBoard] */
@@ -239,7 +372,7 @@
val tiles = Array(numRows * numCols) { index -> Tile(index) }
/** An individual [Tile] in this [TileBoard] */
- inner class Tile(index: Int) {
+ inner class Tile(val index: Int) {
/** The x position of this tile in the tile board */
private val rowIdx = index / numCols
@@ -248,7 +381,7 @@
/**
* The offset of this [Tile] from the origin of the page in pixels, used in computations
- * where an exact pixel size is expected, e.g. rendering bitmaps
+ * where an exact pixel size is expected, e.g. fetching bitmaps
*/
val offsetPx = Point(colIdx * tileSizePx.x, rowIdx * tileSizePx.y)
@@ -259,6 +392,10 @@
minOf(tileSizePx.y, pageSizePx.y - offsetPx.y),
)
+ /** The exact pixel location of this tile in the scaled page */
+ val rectPx =
+ Rect(offsetPx.x, offsetPx.y, offsetPx.x + exactSizePx.x, offsetPx.y + exactSizePx.y)
+
/** The high res [Bitmap] for this [Tile] */
var bitmap: Bitmap? = null
}
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/Page.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/Page.kt
index 48d9f6f..5cfabbc 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/Page.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/Page.kt
@@ -39,7 +39,7 @@
/** The 0-based index of this page in the PDF */
private val pageNum: Int,
/** The size of this PDF page, in content coordinates */
- pageSizePx: Point,
+ pageSize: Point,
/** The [PdfDocument] this [Page] belongs to */
private val pdfDocument: PdfDocument,
/** The [CoroutineScope] to use for background work */
@@ -64,7 +64,7 @@
private val bitmapFetcher =
BitmapFetcher(
pageNum,
- pageSizePx,
+ pageSize,
pdfDocument,
backgroundScope,
maxBitmapSizePx,
@@ -91,17 +91,34 @@
internal var links: PdfDocument.PdfPageLinks? = null
private set
- fun updateState(zoom: Float, isFlinging: Boolean = false) {
+ /**
+ * Puts this page into a "visible" state, and / or updates various properties related to the
+ * page's visible state
+ *
+ * @param zoom the current scale
+ * @param viewArea the portion of the page that's visible, in content coordinates
+ * @param stablePosition true if position is not actively changing, e.g. during a fling
+ */
+ fun setVisible(zoom: Float, viewArea: Rect, stablePosition: Boolean = true) {
bitmapFetcher.isActive = true
- bitmapFetcher.onScaleChanged(zoom)
- if (!isFlinging) {
+ bitmapFetcher.updateViewProperties(zoom, viewArea)
+ if (stablePosition) {
maybeFetchLinks()
if (isTouchExplorationEnabled) {
- fetchPageText()
+ maybeFetchPageText()
}
}
}
+ /**
+ * Puts this page into a "nearly visible" state, discarding only high res bitmaps and retaining
+ * lighter weight data in case the page becomes visible again
+ */
+ fun setNearlyVisible() {
+ bitmapFetcher.discardTileBitmaps()
+ }
+
+ /** Puts this page into an "invisible" state, i.e. retaining only the minimum data required */
fun setInvisible() {
bitmapFetcher.isActive = false
pageText = null
@@ -112,7 +129,7 @@
fetchLinksJob = null
}
- private fun fetchPageText() {
+ private fun maybeFetchPageText() {
if (fetchPageTextJob?.isActive == true || pageText != null) return
fetchPageTextJob =
@@ -171,7 +188,7 @@
canvas.drawBitmap(
bitmap, /* src */
null,
- locationForTile(tile, tileBoard.renderedScale, locationInView),
+ locationForTile(tile, tileBoard.bitmapScale, locationInView),
BMP_PAINT
)
}
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt
index 2844056..90156e5 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt
@@ -21,6 +21,7 @@
import android.graphics.Rect
import android.graphics.RectF
import android.util.Range
+import android.util.SparseArray
import androidx.pdf.PdfDocument
import kotlin.math.ceil
import kotlin.math.floor
@@ -107,6 +108,30 @@
}
/**
+ * Returns a [SparseArray] containing [Rect]s indicating the visible region of each visible
+ * page, in page coordinates.
+ */
+ fun getVisiblePageAreas(pages: Range<Int>, viewport: Rect): SparseArray<Rect> {
+ val ret = SparseArray<Rect>(pages.upper - pages.lower + 1)
+ for (i in pages.lower..pages.upper) {
+ ret.put(i, getPageVisibleArea(i, viewport))
+ }
+ return ret
+ }
+
+ private fun getPageVisibleArea(pageNum: Int, viewport: Rect): Rect {
+ val pageLocation = getPageLocation(pageNum, viewport)
+ val pageWidth = pageLocation.right - pageLocation.left
+ val pageHeight = pageLocation.bottom - pageLocation.top
+ return Rect(
+ maxOf(viewport.left - pageLocation.left, 0),
+ maxOf(viewport.top - pageLocation.top, 0),
+ minOf(viewport.right - pageLocation.left, pageWidth),
+ minOf(viewport.bottom - pageLocation.top, pageHeight),
+ )
+ }
+
+ /**
* Returns the current View-coordinate location of a 0-indexed [pageNum] given the [viewport]
*/
fun getPageLocation(pageNum: Int, viewport: Rect): Rect {
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageManager.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageManager.kt
index 322ee54..e32dbae 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageManager.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageManager.kt
@@ -78,29 +78,41 @@
private val highlights: MutableMap<Int, MutableList<Highlight>> = mutableMapOf()
/**
- * Updates the internal state of [Page]s owned by this manager in response to a viewport change
+ * Updates the visibility state of [Page]s owned by this manager.
+ *
+ * @param visiblePageAreas the visible area of each visible page, in page coordinates
+ * @param currentZoomLevel the current zoom level
+ * @param stablePosition true if we don't believe our position is actively changing
*/
- fun maybeUpdatePageState(
- visiblePages: Range<Int>,
+ fun updatePageVisibilities(
+ visiblePageAreas: SparseArray<Rect>,
currentZoomLevel: Float,
- isFlinging: Boolean
+ stablePosition: Boolean
) {
// Start preparing UI for visible pages
- for (i in visiblePages.lower..visiblePages.upper) {
- pages[i]?.updateState(currentZoomLevel, isFlinging)
+ visiblePageAreas.keyIterator().forEach { pageNum ->
+ pages[pageNum]?.setVisible(
+ currentZoomLevel,
+ visiblePageAreas.get(pageNum),
+ stablePosition
+ )
}
- // Hide pages that are well outside the viewport. We deliberately don't set pages that
- // are within nearPages, but outside visible pages to invisible to avoid rendering churn
- // for pages likely to return to the viewport.
+ // We put pages that are near the viewport in a "nearly visible" state where some data is
+ // retained. We release all data from pages well outside the viewport
val nearPages =
Range(
- maxOf(0, visiblePages.lower - pagePrefetchRadius),
- minOf(visiblePages.upper + pagePrefetchRadius, pdfDocument.pageCount - 1),
+ maxOf(0, visiblePageAreas.keyAt(0) - pagePrefetchRadius),
+ minOf(
+ visiblePageAreas.keyAt(visiblePageAreas.size() - 1) + pagePrefetchRadius,
+ pdfDocument.pageCount - 1
+ ),
)
for (pageNum in pages.keyIterator()) {
if (pageNum < nearPages.lower || pageNum > nearPages.upper) {
pages[pageNum]?.setInvisible()
+ } else if (!visiblePageAreas.contains(pageNum)) {
+ pages[pageNum]?.setNearlyVisible()
}
}
}
@@ -109,12 +121,12 @@
* Updates the set of [Page]s owned by this manager when a new Page's dimensions are loaded.
* Dimensions are the minimum data required to instantiate a page.
*/
- fun onPageSizeReceived(
+ fun addPage(
pageNum: Int,
size: Point,
- isVisible: Boolean,
currentZoomLevel: Float,
- isFlinging: Boolean
+ stablePosition: Boolean,
+ viewArea: Rect? = null
) {
if (pages.contains(pageNum)) return
val page =
@@ -128,7 +140,12 @@
onPageUpdate = { _invalidationSignalFlow.tryEmit(Unit) },
onPageTextReady = { pageNumber -> _pageTextReadyFlow.tryEmit(pageNumber) }
)
- .apply { if (isVisible) updateState(currentZoomLevel, isFlinging) }
+ .apply {
+ // If the page is visible, let it know
+ if (viewArea != null) {
+ setVisible(currentZoomLevel, viewArea, stablePosition)
+ }
+ }
pages.put(pageNum, page)
}
@@ -151,7 +168,7 @@
* Sets all [Page]s owned by this manager to invisible, i.e. to reduce memory when the host
* [PdfView] is not in an interactive state.
*/
- fun onDetached() {
+ fun cleanup() {
for (page in pages.valueIterator()) {
page.setInvisible()
}
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt
index 2621d74..8885cb3 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt
@@ -40,6 +40,7 @@
import android.view.ScaleGestureDetector
import android.view.View
import androidx.annotation.CallSuper
+import androidx.annotation.MainThread
import androidx.annotation.RestrictTo
import androidx.annotation.VisibleForTesting
import androidx.core.graphics.toRectF
@@ -105,9 +106,9 @@
set(value) {
checkMainThread()
value?.let {
- val reset = field != null && field?.uri != value.uri
+ if (field == value) return
field = it
- if (reset) reset()
+ reset()
onDocumentSet()
}
}
@@ -232,6 +233,22 @@
/** Whether we are in a fling movement. This is used to detect the end of that movement */
private var isFling = false
+ /**
+ * Returns true if neither zoom nor scroll are actively changing. Does not account for
+ * externally-driven changes in position (e.g. a animating scrollY or zoom)
+ */
+ private val positionIsStable: Boolean
+ get() {
+ val zoomIsChanging = gestureTracker.matches(GestureTracker.Gesture.ZOOM)
+ val scrollIsChanging =
+ gestureTracker.matches(
+ GestureTracker.Gesture.DRAG,
+ GestureTracker.Gesture.DRAG_X,
+ GestureTracker.Gesture.DRAG_Y
+ ) || isFling
+ return !zoomIsChanging && !scrollIsChanging
+ }
+
// To avoid allocations during drawing
private val visibleAreaRect = Rect()
@@ -251,9 +268,6 @@
@VisibleForTesting
internal var isTouchExplorationEnabled: Boolean =
Accessibility.get().isTouchExplorationEnabled(context)
- set(value) {
- field = value
- }
private var selectionStateManager: SelectionStateManager? = null
private val selectionRenderer = SelectionRenderer(context)
@@ -515,7 +529,7 @@
super.onDetachedFromWindow()
stopCollectingData()
awaitingFirstLayout = true
- pageManager?.onDetached()
+ pageManager?.cleanup()
}
override fun onSaveInstanceState(): Parcelable? {
@@ -555,11 +569,11 @@
postInvalidateOnAnimation()
} else if (isFling) {
isFling = false
- // Once the fling has ended, prompt the page manager to start fetching data for pages
- // that we don't fetch during a fling
- pageManager?.maybeUpdatePageState(visiblePages, zoom, isFling)
// We hide the action mode during a fling, so reveal it when the fling is over
updateSelectionActionModeVisibility()
+ // Once the fling has ended, prompt the page manager to start fetching data for pages
+ // that we don't fetch during a fling
+ maybeUpdatePageVisibility()
}
}
@@ -675,6 +689,7 @@
* Launches a tree of coroutines to collect data from helper classes while we're attached to a
* visible window
*/
+ @MainThread
private fun startCollectingData() {
val mainScope =
CoroutineScope(HandlerCompat.createAsync(handler.looper).asCoroutineDispatcher())
@@ -688,7 +703,17 @@
launch {
manager.dimensions.collect { onPageDimensionsReceived(it.first, it.second) }
}
- launch { manager.visiblePages.collect { onVisiblePagesChanged() } }
+ launch { manager.visiblePages.collect { maybeUpdatePageVisibility() } }
+ }
+ // Don't let two copies of this run concurrently
+ val visiblePagesToJoin = visiblePagesCollector?.apply { cancel() }
+ visiblePagesCollector =
+ mainScope.launch(start = CoroutineStart.UNDISPATCHED) {
+ manager.visiblePages.collect {
+ // Prevent 2 copies from running concurrently
+ visiblePagesToJoin?.join()
+ maybeUpdatePageVisibility()
+ }
}
}
pageManager?.let { manager ->
@@ -825,13 +850,12 @@
onViewportChanged()
// Don't fetch new Bitmaps while the user is actively zooming, to avoid jank and rendering
// churn
- if (!gestureTracker.matches(GestureTracker.Gesture.ZOOM)) {
- pageManager?.maybeUpdatePageState(visiblePages, zoom, isFling)
- }
+ if (positionIsStable) maybeUpdatePageVisibility()
}
private fun onViewportChanged() {
pageLayoutManager?.onViewportChanged(scrollY, height, zoom)
+ if (positionIsStable) maybeUpdatePageVisibility()
accessibilityPageHelper?.invalidateRoot()
updateSelectionActionModeVisibility()
}
@@ -890,18 +914,11 @@
return RectF(viewport).intersects(leftEdge, topEdge, rightEdge, bottomEdge)
}
- /**
- * Invoked by gesture handlers to let this view know that its position has stabilized, i.e. it's
- * not actively changing due to user input
- */
- internal fun onStableZoom() {
- pageManager?.maybeUpdatePageState(visiblePages, zoom, isFling)
- }
-
private fun reset() {
// Stop any in progress fling when we open a new document
scroller.forceFinished(true)
scrollTo(0, 0)
+ pageManager?.cleanup()
zoom = DEFAULT_INIT_ZOOM
pageManager = null
pageLayoutManager = null
@@ -909,20 +926,22 @@
stopCollectingData()
}
- /** React to a change in visible pages (load new pages and clean up old ones) */
- private fun onVisiblePagesChanged() {
- pageManager?.maybeUpdatePageState(visiblePages, zoom, isFling)
+ private fun maybeUpdatePageVisibility() {
+ val visiblePageAreas =
+ pageLayoutManager?.getVisiblePageAreas(visiblePages, getVisibleAreaInContentCoords())
+ ?: return
+ pageManager?.updatePageVisibilities(visiblePageAreas, zoom, positionIsStable)
}
/** React to a page's dimensions being made available */
private fun onPageDimensionsReceived(pageNum: Int, size: Point) {
- pageManager?.onPageSizeReceived(
- pageNum,
- size,
- visiblePages.contains(pageNum),
- zoom,
- isFling
- )
+ val pageLocation =
+ if (visiblePages.contains(pageNum)) {
+ pageLayoutManager?.getPageLocation(pageNum, getVisibleAreaInContentCoords())
+ } else {
+ null
+ }
+ pageManager?.addPage(pageNum, size, zoom, isFling, pageLocation)
// Learning the dimensions of a page can change our understanding of the content that's in
// the viewport
pageLayoutManager?.onViewportChanged(scrollY, height, zoom)
@@ -1182,7 +1201,9 @@
}
override fun onGestureEnd(gesture: GestureTracker.Gesture?) {
- if (gesture == GestureTracker.Gesture.ZOOM) onStableZoom()
+ // Update page visibility after scroll / zoom gestures end, because we avoid fetching
+ // certain data while those gestures are in progress
+ if (gesture in ZOOM_OR_SCROLL_GESTURES) maybeUpdatePageVisibility()
totalX = 0f
totalY = 0f
straightenCurrentVerticalScroll = true
@@ -1390,6 +1411,14 @@
private const val DEFAULT_PAGE_PREFETCH_RADIUS: Int = 2
+ private val ZOOM_OR_SCROLL_GESTURES =
+ setOf(
+ GestureTracker.Gesture.ZOOM,
+ GestureTracker.Gesture.DRAG,
+ GestureTracker.Gesture.DRAG_X,
+ GestureTracker.Gesture.DRAG_Y
+ )
+
private fun checkMainThread() {
check(Looper.myLooper() == Looper.getMainLooper()) {
"Property must be set on the main thread"
diff --git a/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/BitmapFetcherTest.kt b/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/BitmapFetcherTest.kt
index fc60503..048f51b 100644
--- a/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/BitmapFetcherTest.kt
+++ b/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/BitmapFetcherTest.kt
@@ -16,7 +16,9 @@
package androidx.pdf.view
+import android.graphics.Bitmap
import android.graphics.Point
+import android.graphics.Rect
import androidx.pdf.PdfDocument
import com.google.common.truth.Truth.assertThat
import kotlin.math.roundToInt
@@ -48,6 +50,7 @@
private val maxBitmapSizePx = Point(2048, 2048)
private val pageSize = Point(512, 512)
+ private val fullPageViewArea = Rect(0, 0, pageSize.x, pageSize.y)
private lateinit var bitmapFetcher: BitmapFetcher
private lateinit var tileSizePx: Point
@@ -72,23 +75,23 @@
@Test
fun setInactive_cancelsWorkAndFreesBitmaps() {
- bitmapFetcher.onScaleChanged(1.5f)
- assertThat(bitmapFetcher.renderingJob?.isActive).isTrue()
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
+ assertThat(bitmapFetcher.fetchingWorkHandle?.isActive).isTrue()
bitmapFetcher.isActive = false
- assertThat(bitmapFetcher.renderingJob).isNull()
+ assertThat(bitmapFetcher.fetchingWorkHandle).isNull()
assertThat(bitmapFetcher.pageContents).isNull()
}
@Test
- fun setScale_rendersFullPageBitmap() {
- bitmapFetcher.onScaleChanged(1.5f)
+ fun lowScale_fullPageViewArea_fetchesFullPageBitmap() {
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
val pageBitmaps = bitmapFetcher.pageContents
assertThat(pageBitmaps).isInstanceOf(FullPageBitmap::class.java)
- assertThat(pageBitmaps?.renderedScale).isEqualTo(1.5f)
+ assertThat(pageBitmaps?.bitmapScale).isEqualTo(1.5f)
pageBitmaps as FullPageBitmap // Make smartcast work nicely below
assertThat(pageBitmaps.bitmap.width).isEqualTo((pageSize.x * 1.5f).roundToInt())
assertThat(pageBitmaps.bitmap.height).isEqualTo((pageSize.y * 1.5f).roundToInt())
@@ -96,14 +99,33 @@
}
@Test
- fun setScale_rendersTileBoard() {
- bitmapFetcher.onScaleChanged(5.0f)
+ fun lowScale_partialPageViewArea_fetchesFullPageBitmap() {
+ // 1.5 scale, viewing the lower right half of the page
+ bitmapFetcher.updateViewProperties(
+ 1.5f,
+ viewArea = Rect(pageSize.x / 2, pageSize.y / 2, pageSize.x, pageSize.y)
+ )
+
+ testDispatcher.scheduler.runCurrent()
+
+ val pageBitmaps = bitmapFetcher.pageContents
+ assertThat(pageBitmaps).isInstanceOf(FullPageBitmap::class.java)
+ assertThat(pageBitmaps?.bitmapScale).isEqualTo(1.5f)
+ pageBitmaps as FullPageBitmap // Make smartcast work nicely below
+ assertThat(pageBitmaps.bitmap.width).isEqualTo((pageSize.x * 1.5f).roundToInt())
+ assertThat(pageBitmaps.bitmap.height).isEqualTo((pageSize.y * 1.5f).roundToInt())
+ assertThat(invalidationCounter).isEqualTo(1)
+ }
+
+ @Test
+ fun highScale_fullPageViewArea_fetchesTileBoard() {
+ bitmapFetcher.updateViewProperties(5.0f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
val pageBitmaps = bitmapFetcher.pageContents
assertThat(pageBitmaps).isInstanceOf(TileBoard::class.java)
- assertThat(pageBitmaps?.renderedScale).isEqualTo(5.0f)
+ assertThat(pageBitmaps?.bitmapScale).isEqualTo(5.0f)
pageBitmaps as TileBoard // Make smartcast work nicely below
// Check the properties of an arbitrary full-size tile
@@ -123,21 +145,54 @@
assertThat(row3Col3.offsetPx).isEqualTo(Point(tileSizePx.x * 3, tileSizePx.y * 3))
assertThat(row3Col3.exactSizePx).isEqualTo(row3Col3Size)
+ for (tile in pageBitmaps.tiles) {
+ assertThat(tile.bitmap).isNotNull()
+ }
+
// 1 invalidation for the low-res background, 1 for each tile * 16 tiles
assertThat(invalidationCounter).isEqualTo(17)
}
@Test
- fun setScale_toRenderedValue_noNewWork() {
+ fun highScale_partialPageViewArea_fetchesPartialTileBoard() {
+ // 1.5 scale, viewing the lower right half of the page
+ bitmapFetcher.updateViewProperties(
+ 5.0f,
+ viewArea = Rect(pageSize.x / 2, pageSize.y / 2, pageSize.x, pageSize.y)
+ )
+
+ testDispatcher.scheduler.runCurrent()
+
+ val pageBitmaps = bitmapFetcher.pageContents
+ assertThat(pageBitmaps).isInstanceOf(TileBoard::class.java)
+ assertThat(pageBitmaps?.bitmapScale).isEqualTo(5.0f)
+ pageBitmaps as TileBoard // Make smartcast work nicely below
+ // This is all tiles in row >= 0 && col >= 0 (row 1 and col 1 are partially visible)
+ val expectedVisibleIndices = setOf(5, 6, 7, 9, 10, 11, 13, 14, 15)
+
+ for (tile in pageBitmaps.tiles) {
+ if (tile.index in expectedVisibleIndices) {
+ assertThat(tile.bitmap).isNotNull()
+ } else {
+ assertThat(tile.bitmap).isNull()
+ }
+ }
+
+ // 1 invalidation for the low-res background, 1 for each visible tile * 9 visible tiles
+ assertThat(invalidationCounter).isEqualTo(10)
+ }
+
+ @Test
+ fun changeScale_toFetchedValue_noNewWork() {
bitmapFetcher.isActive = true
- bitmapFetcher.onScaleChanged(1.5f)
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
val firstBitmaps = bitmapFetcher.pageContents
- bitmapFetcher.onScaleChanged(1.5f)
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
// We shouldn't have started a new Job the second time onScaleChanged to the same value
- assertThat(bitmapFetcher.renderingJob).isNull()
+ assertThat(bitmapFetcher.fetchingWorkHandle?.isActive).isFalse()
// And we should still have the same bitmaps
assertThat(bitmapFetcher.pageContents).isEqualTo(firstBitmaps)
// 1 total invalidation
@@ -145,20 +200,20 @@
}
@Test
- fun setScale_toRenderingValue_noNewWork() {
- bitmapFetcher.onScaleChanged(1.5f)
- val firstJob = bitmapFetcher.renderingJob
- bitmapFetcher.onScaleChanged(1.5f)
+ fun changeScale_toFetchingValue_noNewWork() {
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
+ val firstJob = bitmapFetcher.fetchingWorkHandle
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
// This should be the same Job we started the first time onScaleChanged
- assertThat(bitmapFetcher.renderingJob).isEqualTo(firstJob)
+ assertThat(bitmapFetcher.fetchingWorkHandle).isEqualTo(firstJob)
// 0 invalidations because we're still rendering
assertThat(invalidationCounter).isEqualTo(0)
}
@Test
- fun setScale_afterInactive_rendersNewBitmaps() {
- bitmapFetcher.onScaleChanged(1.5f)
+ fun changeScale_afterInactive_fetchesNewBitmaps() {
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
assertThat(bitmapFetcher.pageContents).isNotNull()
assertThat(invalidationCounter).isEqualTo(1)
@@ -167,47 +222,106 @@
assertThat(bitmapFetcher.pageContents).isNull()
bitmapFetcher.isActive = true
- bitmapFetcher.onScaleChanged(1.5f)
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
assertThat(bitmapFetcher.pageContents).isNotNull()
assertThat(invalidationCounter).isEqualTo(2)
}
@Test
- fun setScale_fromFullPage_toTiled() {
- bitmapFetcher.onScaleChanged(1.5f)
+ fun changeScale_lowToHigh_fullPageToTiling() {
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
val fullPageBitmap = bitmapFetcher.pageContents
assertThat(fullPageBitmap).isInstanceOf(FullPageBitmap::class.java)
- assertThat(fullPageBitmap?.renderedScale).isEqualTo(1.5f)
+ assertThat(fullPageBitmap?.bitmapScale).isEqualTo(1.5f)
assertThat(invalidationCounter).isEqualTo(1)
- bitmapFetcher.onScaleChanged(5.0f)
+ bitmapFetcher.updateViewProperties(5.0f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
val tileBoard = bitmapFetcher.pageContents
assertThat(tileBoard).isInstanceOf(TileBoard::class.java)
- assertThat(tileBoard?.renderedScale).isEqualTo(5.0f)
+ assertThat(tileBoard?.bitmapScale).isEqualTo(5.0f)
// 1 invalidation for the previous full page bitmap + 1 for the low res background
// + (1 for each tile * 16 tiles)
assertThat(invalidationCounter).isEqualTo(18)
}
@Test
- fun setScale_fromTiled_toFullPage() {
- bitmapFetcher.onScaleChanged(5.0f)
+ fun changeScale_highToLow_tilingToFullPage() {
+ bitmapFetcher.updateViewProperties(5.0f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
val tileBoard = bitmapFetcher.pageContents
assertThat(tileBoard).isInstanceOf(TileBoard::class.java)
- assertThat(tileBoard?.renderedScale).isEqualTo(5.0f)
+ assertThat(tileBoard?.bitmapScale).isEqualTo(5.0f)
// 1 invalidation for the low res background + (1 for each tile * 16 tiles)
assertThat(invalidationCounter).isEqualTo(17)
- bitmapFetcher.onScaleChanged(1.5f)
+ bitmapFetcher.updateViewProperties(1.5f, fullPageViewArea)
testDispatcher.scheduler.runCurrent()
val fullPageBitmap = bitmapFetcher.pageContents
assertThat(fullPageBitmap).isInstanceOf(FullPageBitmap::class.java)
- assertThat(fullPageBitmap?.renderedScale).isEqualTo(1.5f)
+ assertThat(fullPageBitmap?.bitmapScale).isEqualTo(1.5f)
// 1 additional invalidation for the new full page bitmap
assertThat(invalidationCounter).isEqualTo(18)
}
+
+ @Test
+ fun changeViewArea_overlapWithPrevious() {
+ // 5.0 scale, viewing the lower right half of the page
+ bitmapFetcher.updateViewProperties(
+ 5.0f,
+ Rect(pageSize.x / 2, pageSize.y / 2, pageSize.x, pageSize.y)
+ )
+ testDispatcher.scheduler.runCurrent()
+ val originalTileBoard = bitmapFetcher.pageContents
+ assertThat(originalTileBoard).isInstanceOf(TileBoard::class.java)
+ // This is all tiles in row > 0 && col > 0 (row 1 and col 1 are partially visible)
+ val originalVisibleIndices = setOf(5, 6, 7, 9, 10, 11, 13, 14, 15)
+ val originalBitmaps = mutableMapOf<Int, Bitmap>()
+ for (tile in (originalTileBoard as TileBoard).tiles) {
+ if (tile.index in originalVisibleIndices) {
+ assertThat(tile.bitmap).isNotNull()
+ originalBitmaps[tile.index] = requireNotNull(tile.bitmap)
+ } else {
+ assertThat(tile.bitmap).isNull()
+ }
+ }
+ // 1 invalidation for the low-res background, 1 for each visible tile
+ val originalInvalidations = invalidationCounter
+ assertThat(originalInvalidations).isEqualTo(originalVisibleIndices.size + 1)
+
+ // 5.0 scale, viewing the middle of the page offset by 1/4 of the page's dimensions
+ bitmapFetcher.updateViewProperties(
+ 5.0f,
+ Rect(pageSize.x / 4, pageSize.y / 4, pageSize.x * 3 / 4, pageSize.y * 3 / 4)
+ )
+ testDispatcher.scheduler.runCurrent()
+ val newTileBoard = bitmapFetcher.pageContents
+ // We should re-use the previous tile board
+ assertThat(newTileBoard).isEqualTo(originalTileBoard)
+ // This is all tiles in row < 3 and col < 3 (row 0 and 2, col 0 and 2 are partially visible)
+ val newVisibleIndices = setOf(0, 1, 2, 4, 5, 6, 8, 9, 10)
+ // This is all tiles that are visible in both view areas (original and new)
+ val expectedRetainedIndices = originalVisibleIndices.intersect(newVisibleIndices)
+ for (tile in (newTileBoard as TileBoard).tiles) {
+ if (tile.index in expectedRetainedIndices) {
+ // We should have re-used the previous tile Bitmap
+ assertThat(tile.bitmap).isNotNull()
+ assertThat(tile.bitmap).isEqualTo(originalBitmaps[tile.index])
+ } else if (tile.index in newVisibleIndices) {
+ // We should have fetched a new tile Bitmap
+ assertThat(tile.bitmap).isNotNull()
+ } else {
+ // We should have cleaned up the Bitmap
+ assertThat(tile.bitmap).isNull()
+ }
+ }
+
+ // Invalidations before the view area changed + 1 for each *newly* visible tile
+ assertThat(invalidationCounter)
+ .isEqualTo(
+ originalInvalidations + (newVisibleIndices.size - expectedRetainedIndices.size)
+ )
+ }
}
diff --git a/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/PageTest.kt b/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/PageTest.kt
index f360178..ad18636 100644
--- a/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/PageTest.kt
+++ b/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/PageTest.kt
@@ -73,7 +73,7 @@
private fun createPage(isTouchExplorationEnabled: Boolean): Page {
return Page(
0,
- pageSizePx = PAGE_SIZE,
+ pageSize = PAGE_SIZE,
pdfDocument,
testScope,
MAX_BITMAP_SIZE,
@@ -97,7 +97,7 @@
fun draw_withoutBitmap() {
// Notably we don't call testDispatcher.scheduler.runCurrent(), so we start, but do not
// finish, fetching a Bitmap
- page.updateState(zoom = 1.5F)
+ page.setVisible(zoom = 1.5F, FULL_PAGE_RECT)
val locationInView = Rect(-60, 125, -60 + PAGE_SIZE.x, 125 + PAGE_SIZE.y)
page.draw(canvasSpy, locationInView, listOf())
@@ -107,7 +107,7 @@
@Test
fun draw_withBitmap() {
- page.updateState(zoom = 1.5F)
+ page.setVisible(zoom = 1.5F, FULL_PAGE_RECT)
testDispatcher.scheduler.runCurrent()
val locationInView = Rect(50, -100, 50 + PAGE_SIZE.x, -100 + PAGE_SIZE.y)
@@ -127,7 +127,7 @@
@Test
fun draw_withHighlight() {
- page.updateState(zoom = 1.5F)
+ page.setVisible(zoom = 1.5F, FULL_PAGE_RECT)
testDispatcher.scheduler.runCurrent()
val leftEdgeInView = 650
val topEdgeInView = -320
@@ -158,7 +158,7 @@
@Test
fun updateState_withTouchExplorationEnabled_fetchesPageText() {
- page.updateState(zoom = 1.0f)
+ page.setVisible(zoom = 1.0f, FULL_PAGE_RECT)
testDispatcher.scheduler.runCurrent()
assertThat(page.pageText).isEqualTo("SampleText")
assertThat(pageTextReadyCounter).isEqualTo(1)
@@ -167,7 +167,7 @@
@Test
fun setVisible_withTouchExplorationDisabled_doesNotFetchPageText() {
page = createPage(isTouchExplorationEnabled = false)
- page.updateState(zoom = 1.0f)
+ page.setVisible(zoom = 1.0f, FULL_PAGE_RECT)
testDispatcher.scheduler.runCurrent()
assertThat(page.pageText).isEqualTo(null)
@@ -176,20 +176,20 @@
@Test
fun updateState_doesNotFetchPageTextIfAlreadyFetched() {
- page.updateState(zoom = 1.0f)
+ page.setVisible(zoom = 1.0f, FULL_PAGE_RECT)
testDispatcher.scheduler.runCurrent()
assertThat(page.pageText).isEqualTo("SampleText")
assertThat(pageTextReadyCounter).isEqualTo(1)
- page.updateState(zoom = 1.0f)
+ page.setVisible(zoom = 1.0f, FULL_PAGE_RECT)
testDispatcher.scheduler.runCurrent()
assertThat(page.pageText).isEqualTo("SampleText")
assertThat(pageTextReadyCounter).isEqualTo(1)
}
@Test
- fun setInvisible_cancelsPageTextFetch() {
- page.updateState(zoom = 1.0f)
+ fun setPageInvisible_cancelsTextFetch() {
+ page.setVisible(zoom = 1.0f, FULL_PAGE_RECT)
page.setInvisible()
testDispatcher.scheduler.runCurrent()
assertThat(page.pageText).isNull()
@@ -198,4 +198,5 @@
}
val PAGE_SIZE = Point(100, 150)
+val FULL_PAGE_RECT = Rect(0, 0, PAGE_SIZE.x, PAGE_SIZE.y)
val MAX_BITMAP_SIZE = Point(500, 500)
diff --git a/room/room-common/api/api_lint.ignore b/room/room-common/api/api_lint.ignore
index 0f16720..934672f 100644
--- a/room/room-common/api/api_lint.ignore
+++ b/room/room-common/api/api_lint.ignore
@@ -1,8 +1,4 @@
// Baseline format: 1.0
-AcronymName: androidx.room.ColumnInfo.SQLiteTypeAffinity:
- Acronyms should not be capitalized in class names: was `SQLiteTypeAffinity`, should this be `SqLiteTypeAffinity`?
-
-
GetterSetterNames: androidx.room.ColumnInfo#index:
Invalid name for boolean property `index`. Should start with one of `has`, `can`, `should`, `is`.
GetterSetterNames: androidx.room.Database#exportSchema:
diff --git a/room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/RoomPagingUtil.android.kt b/room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/RoomPagingUtil.android.kt
index 35104e8..cd0fa67 100644
--- a/room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/RoomPagingUtil.android.kt
+++ b/room/room-paging/src/androidMain/kotlin/androidx/room/paging/util/RoomPagingUtil.android.kt
@@ -31,7 +31,6 @@
*
* Any loaded data or queued loads prior to returning INVALID will be discarded
*/
-@get:Suppress("AcronymName")
@get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public val INVALID: LoadResult<Any, Any> = LoadResult.Invalid<Any, Any>()
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/support/QueryInterceptorDatabase.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/support/QueryInterceptorDatabase.android.kt
index 58dce9f..01dc16b 100644
--- a/room/room-runtime/src/androidMain/kotlin/androidx/room/support/QueryInterceptorDatabase.android.kt
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/support/QueryInterceptorDatabase.android.kt
@@ -111,17 +111,11 @@
return delegate.query(query)
}
- // Suppress warning about `SQL` in execSQL not being camel case. This is an override function
- // and it can't be renamed.
- @Suppress("AcronymName")
override fun execSQL(sql: String) {
queryCallbackScope.launch { queryCallback.onQuery(sql, emptyList()) }
delegate.execSQL(sql)
}
- // Suppress warning about `SQL` in execSQL not being camel case. This is an override function
- // and it can't be renamed.
- @Suppress("AcronymName")
override fun execSQL(sql: String, bindArgs: Array<out Any?>) {
val argsCopy = bindArgs.toList()
queryCallbackScope.launch { queryCallback.onQuery(sql, argsCopy) }
diff --git a/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt b/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt
index 105f220..7ba38d0 100644
--- a/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt
+++ b/room/room-runtime/src/commonMain/kotlin/androidx/room/Transactor.kt
@@ -42,7 +42,6 @@
}
/** Executes a single SQL statement that returns no values. */
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
suspend fun PooledConnection.execSQL(sql: String) {
usePrepared(sql) { it.step() }
}
@@ -78,7 +77,6 @@
*
* @see Transactor.withTransaction
*/
- @Suppress("AcronymName") // SQL is a known term and should remain capitalized
enum class SQLiteTransactionType {
/**
* The transaction mode that does not start the actual transaction until the database is
diff --git a/savedstate/savedstate/api/current.txt b/savedstate/savedstate/api/current.txt
index 7249870..2c7e9e3d 100644
--- a/savedstate/savedstate/api/current.txt
+++ b/savedstate/savedstate/api/current.txt
@@ -169,10 +169,8 @@
}
public final class SavedStateRegistryOwnerDelegatesKt {
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, String key, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, String key, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, kotlinx.serialization.KSerializer<T> serializer, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
}
}
diff --git a/savedstate/savedstate/api/restricted_current.txt b/savedstate/savedstate/api/restricted_current.txt
index c5c3df3..f87e8a6 100644
--- a/savedstate/savedstate/api/restricted_current.txt
+++ b/savedstate/savedstate/api/restricted_current.txt
@@ -194,10 +194,8 @@
}
public final class SavedStateRegistryOwnerDelegatesKt {
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, String key, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, String key, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
- method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, kotlin.jvm.functions.Function0<? extends T> init);
- method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, kotlinx.serialization.KSerializer<T> serializer, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static inline <reified T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
+ method public static <T> kotlin.properties.ReadWriteProperty<java.lang.Object?,T> saved(androidx.savedstate.SavedStateRegistryOwner, kotlinx.serialization.KSerializer<T> serializer, optional String? key, kotlin.jvm.functions.Function0<? extends T> init);
}
}
diff --git a/savedstate/savedstate/bcv/native/current.txt b/savedstate/savedstate/bcv/native/current.txt
index e96770a..9b72797 100644
--- a/savedstate/savedstate/bcv/native/current.txt
+++ b/savedstate/savedstate/bcv/native/current.txt
@@ -161,15 +161,13 @@
final const val androidx.savedstate/DEFAULT_LONG // androidx.savedstate/DEFAULT_LONG|{}DEFAULT_LONG[0]
final fun <get-DEFAULT_LONG>(): kotlin/Long // androidx.savedstate/DEFAULT_LONG.<get-DEFAULT_LONG>|<get-DEFAULT_LONG>(){}[0]
-final fun <#A: kotlin/Any> (androidx.savedstate/SavedStateRegistryOwner).androidx.savedstate.serialization/saved(kotlin/String, kotlinx.serialization/KSerializer<#A>, kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.savedstate.serialization/saved|[email protected](kotlin.String;kotlinx.serialization.KSerializer<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
-final fun <#A: kotlin/Any> (androidx.savedstate/SavedStateRegistryOwner).androidx.savedstate.serialization/saved(kotlinx.serialization/KSerializer<#A>, kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.savedstate.serialization/saved|[email protected](kotlinx.serialization.KSerializer<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
+final fun <#A: kotlin/Any> (androidx.savedstate/SavedStateRegistryOwner).androidx.savedstate.serialization/saved(kotlinx.serialization/KSerializer<#A>, kotlin/String? = ..., kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.savedstate.serialization/saved|[email protected](kotlinx.serialization.KSerializer<0:0>;kotlin.String?;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
final fun <#A: kotlin/Any> androidx.savedstate.serialization/decodeFromSavedState(kotlinx.serialization/DeserializationStrategy<#A>, androidx.savedstate/SavedState): #A // androidx.savedstate.serialization/decodeFromSavedState|decodeFromSavedState(kotlinx.serialization.DeserializationStrategy<0:0>;androidx.savedstate.SavedState){0§<kotlin.Any>}[0]
final fun <#A: kotlin/Any> androidx.savedstate.serialization/encodeToSavedState(kotlinx.serialization/SerializationStrategy<#A>, #A): androidx.savedstate/SavedState // androidx.savedstate.serialization/encodeToSavedState|encodeToSavedState(kotlinx.serialization.SerializationStrategy<0:0>;0:0){0§<kotlin.Any>}[0]
final fun <#A: kotlin/Any?> androidx.savedstate.serialization.serializers/MutableStateFlowSerializer(kotlinx.serialization/KSerializer<#A>): kotlinx.serialization/KSerializer<kotlinx.coroutines.flow/MutableStateFlow<#A>> // androidx.savedstate.serialization.serializers/MutableStateFlowSerializer|MutableStateFlowSerializer(kotlinx.serialization.KSerializer<0:0>){0§<kotlin.Any?>}[0]
final inline fun <#A: kotlin/Any?> (androidx.savedstate/SavedState).androidx.savedstate/read(kotlin/Function1<androidx.savedstate/SavedStateReader, #A>): #A // androidx.savedstate/read|[email protected](kotlin.Function1<androidx.savedstate.SavedStateReader,0:0>){0§<kotlin.Any?>}[0]
final inline fun <#A: kotlin/Any?> (androidx.savedstate/SavedState).androidx.savedstate/write(kotlin/Function1<androidx.savedstate/SavedStateWriter, #A>): #A // androidx.savedstate/write|[email protected](kotlin.Function1<androidx.savedstate.SavedStateWriter,0:0>){0§<kotlin.Any?>}[0]
-final inline fun <#A: reified kotlin/Any> (androidx.savedstate/SavedStateRegistryOwner).androidx.savedstate.serialization/saved(kotlin/String, noinline kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.savedstate.serialization/saved|[email protected](kotlin.String;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
-final inline fun <#A: reified kotlin/Any> (androidx.savedstate/SavedStateRegistryOwner).androidx.savedstate.serialization/saved(noinline kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.savedstate.serialization/saved|[email protected](kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
+final inline fun <#A: reified kotlin/Any> (androidx.savedstate/SavedStateRegistryOwner).androidx.savedstate.serialization/saved(kotlin/String? = ..., noinline kotlin/Function0<#A>): kotlin.properties/ReadWriteProperty<kotlin/Any?, #A> // androidx.savedstate.serialization/saved|[email protected](kotlin.String?;kotlin.Function0<0:0>){0§<kotlin.Any>}[0]
final inline fun <#A: reified kotlin/Any> androidx.savedstate.serialization/decodeFromSavedState(androidx.savedstate/SavedState): #A // androidx.savedstate.serialization/decodeFromSavedState|decodeFromSavedState(androidx.savedstate.SavedState){0§<kotlin.Any>}[0]
final inline fun <#A: reified kotlin/Any> androidx.savedstate.serialization/encodeToSavedState(#A): androidx.savedstate/SavedState // androidx.savedstate.serialization/encodeToSavedState|encodeToSavedState(0:0){0§<kotlin.Any>}[0]
final inline fun <#A: reified kotlin/Any?> androidx.savedstate.serialization.serializers/MutableStateFlowSerializer(): kotlinx.serialization/KSerializer<kotlinx.coroutines.flow/MutableStateFlow<#A>> // androidx.savedstate.serialization.serializers/MutableStateFlowSerializer|MutableStateFlowSerializer(){0§<kotlin.Any?>}[0]
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/serialization/SavedStateRegistryOwnerDelegates.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/serialization/SavedStateRegistryOwnerDelegates.kt
index a890db3..c11359f 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/serialization/SavedStateRegistryOwnerDelegates.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/serialization/SavedStateRegistryOwnerDelegates.kt
@@ -28,16 +28,17 @@
* within the [SavedStateRegistry] of this [SavedStateRegistryOwner].
*
* @sample androidx.savedstate.serialization.savedStateRegistryOwner_saved_withKey_withSerializer
- * @param key The [String] key to use for storing the value in the [SavedStateRegistry].
* @param serializer The [KSerializer] to use for serializing and deserializing the value.
+ * @param key An optional [String] key to use for storing the value in the [SavedStateRegistry]. A
+ * default key will be generated if it's omitted or when 'null' is passed.
* @param init The function to provide the initial value of the property.
* @return A property delegate provider that manages the saving and restoring of the value.
* @see encodeToSavedState
* @see decodeFromSavedState
*/
public fun <T : Any> SavedStateRegistryOwner.saved(
- key: String,
serializer: KSerializer<T>,
+ key: String? = null,
init: () -> T,
): ReadWriteProperty<Any?, T> {
return SavedStateRegistryOwnerDelegate(
@@ -52,34 +53,9 @@
* Returns a property delegate provider that manages the saving and restoring of a value of type [T]
* within the [SavedStateRegistry] of this [SavedStateRegistryOwner].
*
- * This is a convenience overload that uses the name of the property as the key for storing the
- * value in the [SavedStateRegistry]
- *
- * @sample androidx.savedstate.serialization.savedStateRegistryOwner_saved_withSerializer
- * @param serializer The [KSerializer] to use for serializing and deserializing the value.
- * @param init The function to provide the initial value of the property.
- * @return A property delegate provider that manages the saving and restoring of the value.
- * @see encodeToSavedState
- * @see decodeFromSavedState
- */
-public fun <T : Any> SavedStateRegistryOwner.saved(
- serializer: KSerializer<T>,
- init: () -> T,
-): ReadWriteProperty<Any?, T> {
- return SavedStateRegistryOwnerDelegate(
- registry = savedStateRegistry,
- key = null,
- serializer = serializer,
- init = init
- )
-}
-
-/**
- * Returns a property delegate provider that manages the saving and restoring of a value of type [T]
- * within the [SavedStateRegistry] of this [SavedStateRegistryOwner].
- *
* @sample androidx.savedstate.serialization.savedStateRegistryOwner_saved_withKey
- * @param key The [String] key to use for storing the value in the [SavedStateRegistry].
+ * @param key An optional [String] key to use for storing the value in the [SavedStateRegistry]. A
+ * default key will be generated if it's omitted or when 'null' is passed.
* @param init The function to provide the initial value of the property.
* @return A property delegate provider that manages the saving and restoring of the value.
* @see encodeToSavedState
@@ -87,30 +63,9 @@
* @see serializer
*/
public inline fun <reified T : Any> SavedStateRegistryOwner.saved(
- key: String,
+ key: String? = null,
noinline init: () -> T,
-): ReadWriteProperty<Any?, T> = saved(key = key, serializer = serializer(), init = init)
-
-/**
- * Returns a property delegate provider that manages the saving and restoring of a value of type [T]
- * within the [SavedStateRegistry] of this [SavedStateRegistryOwner].
- *
- * This is a convenience overload that uses the [serializer] function to obtain the serializer for
- * the reified type [T].
- *
- * The name of the property will be used as the key for storing the value in the
- * [SavedStateRegistry].
- *
- * @sample androidx.savedstate.serialization.savedStateRegistryOwner_saved
- * @param init The function to provide the initial value of the property.
- * @return A property delegate provider that manages the saving and restoring of the value.
- * @see encodeToSavedState
- * @see decodeFromSavedState
- * @see serializer
- */
-public inline fun <reified T : Any> SavedStateRegistryOwner.saved(
- noinline init: () -> T,
-): ReadWriteProperty<Any?, T> = saved(serializer = serializer(), init = init)
+): ReadWriteProperty<Any?, T> = saved(serializer = serializer(), key = key, init = init)
private class SavedStateRegistryOwnerDelegate<T : Any>(
private val registry: SavedStateRegistry,
diff --git a/settings.gradle b/settings.gradle
index cf922fc..6597c4d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -33,7 +33,7 @@
if (agpOverride != null) {
classpath("com.android.settings:com.android.settings.gradle.plugin:$agpOverride")
} else {
- classpath("com.android.settings:com.android.settings.gradle.plugin:8.9.0-alpha01")
+ classpath("com.android.settings:com.android.settings.gradle.plugin:8.9.0-beta01")
}
// set guava version to be compatible with Depdendency analysis gradle plugin
classpath("com.google.guava:guava:33.3.1-jre")
diff --git a/slidingpanelayout/slidingpanelayout/api/current.txt b/slidingpanelayout/slidingpanelayout/api/current.txt
index 072d9d3..6090e13 100644
--- a/slidingpanelayout/slidingpanelayout/api/current.txt
+++ b/slidingpanelayout/slidingpanelayout/api/current.txt
@@ -13,6 +13,7 @@
method public boolean closePane();
method @Deprecated @ColorInt public int getCoveredFadeColor();
method public final int getLockMode();
+ method @Px public final int getPaneSpacing();
method @Px public int getParallaxDistance();
method @Deprecated @ColorInt public int getSliderFadeColor();
method public final int getSplitDividerPosition();
@@ -33,6 +34,7 @@
method public final void setLockMode(int);
method public final void setOnUserResizingDividerClickListener(android.view.View.OnClickListener? listener);
method public final void setOverlappingEnabled(boolean);
+ method public final void setPaneSpacing(int);
method @Deprecated public void setPanelSlideListener(androidx.slidingpanelayout.widget.SlidingPaneLayout.PanelSlideListener? listener);
method public void setParallaxDistance(@Px int);
method @Deprecated public void setShadowDrawable(android.graphics.drawable.Drawable? drawable);
@@ -58,6 +60,7 @@
property public final boolean isUserResizable;
property public final boolean isUserResizingEnabled;
property public final int lockMode;
+ property @Px public final int paneSpacing;
property @Px public int parallaxDistance;
property @Deprecated @ColorInt public int sliderFadeColor;
property public final int splitDividerPosition;
diff --git a/slidingpanelayout/slidingpanelayout/api/res-current.txt b/slidingpanelayout/slidingpanelayout/api/res-current.txt
index 88c866a..6da1d9a 100644
--- a/slidingpanelayout/slidingpanelayout/api/res-current.txt
+++ b/slidingpanelayout/slidingpanelayout/api/res-current.txt
@@ -1,6 +1,7 @@
attr isChildClippingToResizeDividerEnabled
attr isOverlappingEnabled
attr isUserResizingEnabled
+attr paneSpacing
attr userResizeBehavior
attr userResizingDividerDrawable
attr userResizingDividerTint
diff --git a/slidingpanelayout/slidingpanelayout/api/restricted_current.txt b/slidingpanelayout/slidingpanelayout/api/restricted_current.txt
index 072d9d3..6090e13 100644
--- a/slidingpanelayout/slidingpanelayout/api/restricted_current.txt
+++ b/slidingpanelayout/slidingpanelayout/api/restricted_current.txt
@@ -13,6 +13,7 @@
method public boolean closePane();
method @Deprecated @ColorInt public int getCoveredFadeColor();
method public final int getLockMode();
+ method @Px public final int getPaneSpacing();
method @Px public int getParallaxDistance();
method @Deprecated @ColorInt public int getSliderFadeColor();
method public final int getSplitDividerPosition();
@@ -33,6 +34,7 @@
method public final void setLockMode(int);
method public final void setOnUserResizingDividerClickListener(android.view.View.OnClickListener? listener);
method public final void setOverlappingEnabled(boolean);
+ method public final void setPaneSpacing(int);
method @Deprecated public void setPanelSlideListener(androidx.slidingpanelayout.widget.SlidingPaneLayout.PanelSlideListener? listener);
method public void setParallaxDistance(@Px int);
method @Deprecated public void setShadowDrawable(android.graphics.drawable.Drawable? drawable);
@@ -58,6 +60,7 @@
property public final boolean isUserResizable;
property public final boolean isUserResizingEnabled;
property public final int lockMode;
+ property @Px public final int paneSpacing;
property @Px public int parallaxDistance;
property @Deprecated @ColorInt public int sliderFadeColor;
property public final int splitDividerPosition;
diff --git a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt
index da4b909..c200c3d 100644
--- a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt
+++ b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt
@@ -137,4 +137,36 @@
assertThat(findViewX(R.id.list_pane)).isLessThan(findViewX(R.id.detail_pane))
}
}
+
+ @Test
+ fun testFold_hasPaneSpacing() {
+ val foldWidth = 10
+ val paneSpacing = 20
+
+ TestActivity.onActivityCreated = { activity ->
+ val spl =
+ activity.layoutInflater.inflate(R.layout.activity_test_fold_layout, null, false)
+ as SlidingPaneLayout
+ spl.paneSpacing = paneSpacing
+ activity.setContentView(spl)
+ }
+
+ with(ActivityScenario.launch(TestActivity::class.java)) {
+ withActivity {
+ val testFeature =
+ FoldingFeature(activity = this, orientation = VERTICAL, size = foldWidth)
+ val info = WindowLayoutInfo(listOf(testFeature))
+ rule.overrideWindowLayoutInfo(info)
+ }
+
+ val spl = findViewById(R.id.sliding_pane_fold_layout) as SlidingPaneLayout
+ val listPane = findViewById(R.id.list_pane)
+ val detailPane = findViewById(R.id.detail_pane)
+
+ assertThat(spl.isSlideable).isFalse()
+ val expectedWidth = (spl.width - foldWidth - paneSpacing) / 2
+ assertThat(listPane.width).isEqualTo(expectedWidth)
+ assertThat(detailPane.width).isEqualTo(expectedWidth)
+ }
+ }
}
diff --git a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/SlidingPaneLayoutTest.kt b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/SlidingPaneLayoutTest.kt
index 903261a..6093130 100644
--- a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/SlidingPaneLayoutTest.kt
+++ b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/SlidingPaneLayoutTest.kt
@@ -284,6 +284,14 @@
assertWithMessage("isUserResizingEnabled").that(view.isUserResizingEnabled).isTrue()
assertWithMessage("isUserResizable").that(view.isUserResizable).isTrue()
}
+
+ @Test
+ fun userResizingDividerWidthInflated() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val inflater = LayoutInflater.from(context)
+ val view = inflater.inflate(R.layout.pane_spacing, null) as SlidingPaneLayout
+ assertWithMessage("paneSpacing is inflated").that(view.paneSpacing).isEqualTo(24)
+ }
}
private fun View.measureAndLayout(width: Int, height: Int) {
diff --git a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/UserResizeModeTest.kt b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/UserResizeModeTest.kt
index dede582..cbbbc57 100644
--- a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/UserResizeModeTest.kt
+++ b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/UserResizeModeTest.kt
@@ -103,6 +103,28 @@
}
@Test
+ fun layoutWithPaneSpacing() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val spl = createTestSpl(context)
+ val leftPane = spl[0]
+ val rightPane = spl[1]
+
+ spl.paneSpacing = 20
+ spl.isUserResizingEnabled = true
+ spl.measureAndLayoutForTest(width = 100)
+
+ assertWithMessage("leftPane width").that(leftPane.width).isEqualTo(40)
+ assertWithMessage("rightPane width").that(rightPane.width).isEqualTo(40)
+
+ // userResizeMode is disabled, paneSpacing should still be the same.
+ spl.isUserResizingEnabled = false
+ spl.measureAndLayoutForTest(width = 100)
+
+ assertWithMessage("leftPane width").that(leftPane.width).isEqualTo(40)
+ assertWithMessage("rightPane width").that(rightPane.width).isEqualTo(40)
+ }
+
+ @Test
fun layoutTooSmallForPadding() {
val context = InstrumentationRegistry.getInstrumentation().context
val spl = createTestSpl(context)
@@ -133,6 +155,30 @@
}
@Test
+ fun layoutTooSmallForPaneSpacing() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val spl = createTestSpl(context)
+ val leftPane = spl[0]
+ val rightPane = spl[1]
+ val splWidth = 100
+
+ spl.paneSpacing = 200
+ spl.measureAndLayoutForTest(splWidth, 0)
+
+ assertWithMessage("SlidingPaneLayout width").that(spl.width).isEqualTo(splWidth)
+ assertWithMessage("leftPane width is zero").that(leftPane.width).isEqualTo(0)
+ assertWithMessage("rightPane width is zero").that(rightPane.width).isEqualTo(0)
+
+ assertWithMessage("leftPane left is zero").that(leftPane.left).isEqualTo(0)
+ assertWithMessage("rightPane left is width").that(rightPane.left).isEqualTo(splWidth)
+
+ // SlidingPaneLayout switch to overlapping mode if paneSpacing is too large.
+ spl.isOverlappingEnabled = true
+ spl.measureAndLayoutForTest(splWidth, 0)
+ assertWithMessage("SlidingPaneLayout is slideable").that(spl.isSlideable).isTrue()
+ }
+
+ @Test
fun dragDividerWithTouchCapturingPanes() {
val context = InstrumentationRegistry.getInstrumentation().context
val spl = createTestSpl(context, childPanesAcceptTouchEvents = true)
@@ -253,6 +299,23 @@
}
@Test
+ fun visualDividerPositionClipsChildren_hasPaneSpacing() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val spl = createTestSpl(context)
+ spl.splitDividerPosition = 35
+ spl.paneSpacing = 10
+ spl.drawToBitmap()
+ assertWithMessage("left child clip")
+ .that((spl[0] as TestPaneView).clipBoundsAtLastDraw)
+ .isEqualTo(Rect(0, 0, 30, 100))
+ spl.splitDividerPosition = 65
+ spl.drawToBitmap()
+ assertWithMessage("right child clip")
+ .that(((spl[1] as ViewGroup)[0] as TestPaneView).clipBoundsAtLastDraw)
+ .isEqualTo(Rect(20, 0, 50, 100))
+ }
+
+ @Test
fun disablingDividerClippingDoesNotClipChildren() {
val context = InstrumentationRegistry.getInstrumentation().context
val spl = createTestSpl(context)
@@ -294,6 +357,30 @@
}
@Test
+ fun paneSpacingAffectsLayout() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val spl = createTestSpl(context)
+ assertWithMessage("layout requested after SlidingPaneLayout creation")
+ .that(spl.isLayoutRequested)
+ .isFalse()
+ spl.splitDividerPosition = 35
+ assertWithMessage("layout requested by splitDividerPosition change")
+ .that(spl.isLayoutRequested)
+ .isTrue()
+ spl.measureAndLayoutForTest()
+ assertWithMessage("first child expected width").that(spl[0].width).isEqualTo(35)
+ assertWithMessage("second child expected width").that(spl[1].width).isEqualTo(65)
+
+ spl.paneSpacing = 10
+ assertWithMessage("layout requested by splitDividerPosition change (2)")
+ .that(spl.isLayoutRequested)
+ .isTrue()
+ spl.measureAndLayoutForTest()
+ assertWithMessage("first child expected width").that(spl[0].width).isEqualTo(30)
+ assertWithMessage("second child expected width").that(spl[1].width).isEqualTo(60)
+ }
+
+ @Test
fun splitDividerPositionDoesNotChangePadding() {
val context = InstrumentationRegistry.getInstrumentation().context
val spl = createTestSpl(context)
@@ -336,6 +423,39 @@
}
@Test
+ fun zeroSpaceForOnePane_paneSpacingTakeChildWidth() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val spl = createTestSpl(context)
+ val splWidth = 100
+ val paneSpacing = 20
+ spl.paneSpacing = 20
+ spl.splitDividerPosition = 10
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("left pane has zero width").that(spl[0].width).isEqualTo(0)
+
+ spl.splitDividerPosition = 5
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("left pane has zero width").that(spl[0].width).isEqualTo(0)
+ assertWithMessage("right pane takes remaining width")
+ .that(spl[1].width)
+ .isEqualTo(splWidth - paneSpacing)
+
+ spl.splitDividerPosition = 90
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("left pane takes remaining width")
+ .that(spl[0].width)
+ .isEqualTo(splWidth - paneSpacing)
+ assertWithMessage("right pane has zero width").that(spl[1].width).isEqualTo(0)
+
+ spl.splitDividerPosition = 95
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("left pane takes remaining width")
+ .that(spl[0].width)
+ .isEqualTo(splWidth - paneSpacing)
+ assertWithMessage("right pane has zero width").that(spl[1].width).isEqualTo(0)
+ }
+
+ @Test
fun zeroSpaceForOnePanePaddedLayout() {
val context = InstrumentationRegistry.getInstrumentation().context
val spl = createTestSpl(context)
@@ -349,6 +469,49 @@
}
@Test
+ fun visualDividerPositionRange() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val spl = createTestSpl(context)
+ val splWidth = 100
+ spl.splitDividerPosition = 0
+ spl.setPadding(4, 0, 8, 0)
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("visualDividerPosition is clamped to view left")
+ .that(spl.visualDividerPosition)
+ .isEqualTo(4)
+ spl.splitDividerPosition = spl.width
+
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("visualDividerPosition is clamped to view right")
+ .that(spl.visualDividerPosition)
+ .isEqualTo(splWidth - 8)
+ }
+
+ @Test
+ fun visualDividerPositionRange_hasPaneSpacing() {
+ val context = InstrumentationRegistry.getInstrumentation().context
+ val spl = createTestSpl(context)
+ val splWidth = 100
+ val paneSpacing = 19
+ val paneSpacingLeftHalf = 9
+ val paneSpacingRightHalf = 10
+ spl.splitDividerPosition = 0
+ spl.setPadding(4, 0, 8, 0)
+ spl.paneSpacing = paneSpacing
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("visualDividerPosition is clamped to view left")
+ .that(spl.visualDividerPosition)
+ .isEqualTo(4 + paneSpacingLeftHalf)
+
+ spl.splitDividerPosition = spl.width
+
+ spl.measureAndLayoutForTest(width = splWidth)
+ assertWithMessage("visualDividerPosition is clamped to view right")
+ .that(spl.visualDividerPosition)
+ .isEqualTo(splWidth - 8 - paneSpacingRightHalf)
+ }
+
+ @Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
fun gestureExclusionRectsUpdated() {
val context = InstrumentationRegistry.getInstrumentation().context
diff --git a/slidingpanelayout/slidingpanelayout/src/androidTest/res/layout/pane_spacing.xml b/slidingpanelayout/slidingpanelayout/src/androidTest/res/layout/pane_spacing.xml
new file mode 100644
index 0000000..0991f8b
--- /dev/null
+++ b/slidingpanelayout/slidingpanelayout/src/androidTest/res/layout/pane_spacing.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2025 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<androidx.slidingpanelayout.widget.SlidingPaneLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:paneSpacing="24px"/>
\ No newline at end of file
diff --git a/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt b/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt
index 6649789..cc8d907 100644
--- a/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt
+++ b/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt
@@ -133,7 +133,7 @@
*/
fun splitViewPositions(
foldingFeature: FoldingFeature?,
- parentView: View,
+ parentView: SlidingPaneLayout,
outLeftRect: Rect,
outRightRect: Rect,
): Boolean {
@@ -149,15 +149,16 @@
foldingFeature.bounds.top == 0 &&
getFoldBoundsInView(foldingFeature, parentView, splitPosition)
) {
+ val paneSpacing = parentView.paneSpacing
outLeftRect.set(
parentView.paddingLeft,
parentView.paddingTop,
- max(parentView.paddingLeft, splitPosition.left),
+ max(parentView.paddingLeft, splitPosition.left - paneSpacing / 2),
parentView.height - parentView.paddingBottom
)
val rightBound = parentView.width - parentView.paddingRight
outRightRect.set(
- min(rightBound, splitPosition.right),
+ min(rightBound, splitPosition.right + (paneSpacing + 1) / 2),
parentView.paddingTop,
rightBound,
parentView.height - parentView.paddingBottom
@@ -495,7 +496,15 @@
when {
!isUserResizable -> -1
isDividerDragging -> draggableDividerHandler.dragPositionX
- splitDividerPosition >= 0 -> splitDividerPosition
+ splitDividerPosition >= 0 -> {
+ val paneSpacing =
+ [email protected]
+ .coerceAtMost(width - paddingLeft - paddingRight)
+ .coerceAtLeast(0)
+ splitDividerPosition
+ .coerceAtMost(width - paddingRight - (paneSpacing + 1) / 2)
+ .coerceAtLeast(paddingLeft + paneSpacing / 2)
+ }
else -> {
val leftChild: View
val rightChild: View
@@ -564,6 +573,22 @@
}
}
+ /**
+ * Set the amount of space between two panes in the side by side mode, in the unit of pixel. The
+ * added space is centered at the [visualDividerPosition], and the half of the specified width
+ * will be added to the left of [visualDividerPosition] and half will be added to the right. Its
+ * default value is 0 pixel.
+ */
+ @get:Px
+ var paneSpacing: Int = 0
+ set(value) {
+ require(value >= 0) { "paneSpacing can't be negative, but the given value is: $value" }
+ if (value != field) {
+ field = value
+ requestLayout()
+ }
+ }
+
private var onUserResizingDividerClickListener: OnClickListener? = null
/**
@@ -631,6 +656,8 @@
1 -> USER_RESIZE_RELAYOUT_WHEN_MOVED
else -> error("$behaviorConstant is not a valid userResizeBehavior value")
}
+
+ paneSpacing = getDimensionPixelSize(R.styleable.SlidingPaneLayout_paneSpacing, 0)
}
accessibilityManager =
context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
@@ -911,7 +938,10 @@
var canSlide = false
val isLayoutRtl = isLayoutRtl
val widthAvailable = (widthSize - paddingLeft - paddingRight).coerceAtLeast(0)
- var widthRemaining = widthAvailable
+ // Coerce the paneSpacing so that it at most equals to widthAvailable.
+ val paneSpacing = paneSpacing.coerceAtMost(widthAvailable).coerceAtLeast(0)
+
+ var widthRemaining = widthAvailable - paneSpacing
val childCount = childCount
if (childCount > 2) {
error("SlidingPaneLayout: More than two child views are not supported.")
@@ -1032,17 +1062,26 @@
(lp.weight * widthToDistribute / weightSum).roundToInt()
measuredWidth + addedWidth
} else { // Explicit dividing line is defined
+ val paneSpacingLeftHalf = paneSpacing / 2
+ val paneSpacingRightHalf = paneSpacing - paneSpacingLeftHalf
val clampedPos =
dividerPos
- .coerceAtMost(width - paddingRight)
- .coerceAtLeast(paddingLeft)
+ .coerceAtMost(
+ widthSize - paddingRight - paneSpacingRightHalf
+ )
+ .coerceAtLeast(paddingLeft + paneSpacingLeftHalf)
val availableWidthDivider = clampedPos - paddingLeft
if ((index == 0) xor isLayoutRtl) {
- availableWidthDivider - lp.horizontalMargin
+ availableWidthDivider -
+ lp.horizontalMargin -
+ paneSpacingLeftHalf
} else {
// padding accounted for in widthAvailable;
// dividerPos includes left padding
- widthAvailable - lp.horizontalMargin - availableWidthDivider
+ widthAvailable -
+ lp.horizontalMargin -
+ availableWidthDivider -
+ paneSpacingRightHalf
}
}
}
@@ -1211,16 +1250,21 @@
val childBottom = paddingTop + child.measuredHeight
child.layout(childLeft, paddingTop, childRight, childBottom)
+ val paneSpacing =
+ paneSpacing.coerceAtMost(width - paddingStart - paddingEnd).coerceAtLeast(0)
// If a folding feature separates the content, we use its width as the extra
// offset for the next child, in order to avoid rendering the content under it.
- var nextXOffset = 0
- if (
- foldingFeature != null &&
- foldingFeature.orientation == FoldingFeature.Orientation.VERTICAL &&
- foldingFeature.isSeparating
- ) {
- nextXOffset = foldingFeature.bounds.width()
- }
+ val nextXOffset =
+ if (
+ foldingFeature != null &&
+ foldingFeature.orientation == FoldingFeature.Orientation.VERTICAL &&
+ foldingFeature.isSeparating
+ ) {
+ foldingFeature.bounds.width() + paneSpacing
+ } else {
+ // paneSpacing added between panes.
+ paneSpacing
+ }
nextXStart += child.width + abs(nextXOffset)
}
if (isUserResizable) {
@@ -1461,15 +1505,17 @@
}
if (!isSlideable && isChildClippingToResizeDividerEnabled) {
val visualDividerPosition = visualDividerPosition
+ val paneSpacing =
+ paneSpacing.coerceAtMost(width - paddingLeft - paddingRight).coerceAtLeast(0)
if (visualDividerPosition >= 0) {
with(tmpRect) {
if (isLayoutRtl xor (child === getChildAt(0))) {
// left child
left = paddingLeft
- right = visualDividerPosition
+ right = visualDividerPosition - paneSpacing / 2
} else {
// right child
- left = visualDividerPosition
+ left = visualDividerPosition + (paneSpacing + 1) / 2
right = width - paddingRight
}
top = paddingTop
@@ -1975,7 +2021,10 @@
node.contentDescription = context.getString(R.string.draggable_divider_handler)
node.isScrollable = true
- if (visualDividerPosition > 0) {
+ val paneSpacing =
+ paneSpacing.coerceAtMost(width - paddingLeft - paddingRight).coerceAtLeast(0)
+
+ if (visualDividerPosition > paddingLeft + paneSpacing / 2) {
node.addAction(AccessibilityActionCompat.ACTION_SCROLL_LEFT)
if (isLayoutRtl) {
node.addAction(AccessibilityActionCompat.ACTION_SCROLL_FORWARD)
@@ -1988,7 +2037,7 @@
context.getString(R.string.draggable_divider_handler_state_left_edge)
}
- if (visualDividerPosition < width) {
+ if (visualDividerPosition < width - paddingRight - (paneSpacing + 1) / 2) {
node.addAction(AccessibilityActionCompat.ACTION_SCROLL_RIGHT)
if (isLayoutRtl) {
node.addAction(AccessibilityActionCompat.ACTION_SCROLL_BACKWARD)
@@ -2155,7 +2204,7 @@
}
private fun sendAccessibilityEventForDivider(eventType: Int) {
- parent.requestSendAccessibilityEvent(
+ parent?.requestSendAccessibilityEvent(
this,
@Suppress("DEPRECATION")
AccessibilityEvent.obtain().apply {
diff --git a/slidingpanelayout/slidingpanelayout/src/main/res/values/attrs.xml b/slidingpanelayout/slidingpanelayout/src/main/res/values/attrs.xml
index 14c032e..a0ee796 100644
--- a/slidingpanelayout/slidingpanelayout/src/main/res/values/attrs.xml
+++ b/slidingpanelayout/slidingpanelayout/src/main/res/values/attrs.xml
@@ -25,6 +25,7 @@
<enum name="relayoutWhenComplete" value="0"/>
<enum name="relayoutWhenMoved" value="1"/>
</attr>
+ <attr name="paneSpacing" format="dimension"/>
</declare-styleable>
<declare-styleable name="SlidingPaneLayout_Layout">
<attr name="android:layout_weight"/>
diff --git a/slidingpanelayout/slidingpanelayout/src/main/res/values/public.xml b/slidingpanelayout/slidingpanelayout/src/main/res/values/public.xml
index c8e7a8f..7912408 100644
--- a/slidingpanelayout/slidingpanelayout/src/main/res/values/public.xml
+++ b/slidingpanelayout/slidingpanelayout/src/main/res/values/public.xml
@@ -21,4 +21,5 @@
<public type="attr" name="userResizingDividerTint"/>
<public type="attr" name="isChildClippingToResizeDividerEnabled"/>
<public type="attr" name="userResizeBehavior"/>
+ <public type="attr" name="paneSpacing"/>
</resources>
diff --git a/sqlite/sqlite-bundled/api/api_lint.ignore b/sqlite/sqlite-bundled/api/api_lint.ignore
deleted file mode 100644
index 1ad4322..0000000
--- a/sqlite/sqlite-bundled/api/api_lint.ignore
+++ /dev/null
@@ -1,5 +0,0 @@
-// Baseline format: 1.0
-AcronymName: androidx.sqlite.driver.bundled.BundledSQLite:
- Acronyms should not be capitalized in class names: was `BundledSQLite`, should this be `BundledSqLite`?
-AcronymName: androidx.sqlite.driver.bundled.BundledSQLiteDriver:
- Acronyms should not be capitalized in class names: was `BundledSQLiteDriver`, should this be `BundledSqLiteDriver`?
diff --git a/sqlite/sqlite-framework/api/api_lint.ignore b/sqlite/sqlite-framework/api/api_lint.ignore
deleted file mode 100644
index 03491a3..0000000
--- a/sqlite/sqlite-framework/api/api_lint.ignore
+++ /dev/null
@@ -1,5 +0,0 @@
-// Baseline format: 1.0
-AcronymName: androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory:
- Acronyms should not be capitalized in class names: was `FrameworkSQLiteOpenHelperFactory`, should this be `FrameworkSqLiteOpenHelperFactory`?
-AcronymName: androidx.sqlite.driver.AndroidSQLiteDriver:
- Acronyms should not be capitalized in class names: was `AndroidSQLiteDriver`, should this be `AndroidSqLiteDriver`?
diff --git a/sqlite/sqlite-ktx/api/api_lint.ignore b/sqlite/sqlite-ktx/api/api_lint.ignore
deleted file mode 100644
index 3948bf5..0000000
--- a/sqlite/sqlite-ktx/api/api_lint.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-AcronymName: androidx.sqlite.db.SupportSQLiteDatabaseKt:
- Acronyms should not be capitalized in class names: was `SupportSQLiteDatabaseKt`, should this be `SupportSqLiteDatabaseKt`?
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
index 1939a45..4bf9c1b 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
@@ -23,7 +23,6 @@
* @param bindArgs The bind argument value that will replace the placeholders in the query.
* @constructor Creates an SQL query with the sql string and the bind arguments.
*/
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public class SimpleSQLiteQuery(
private val query: String,
@Suppress("ArrayReturn") // Due to legacy API
@@ -45,7 +44,6 @@
*
* @param [statement] The SQL query to execute. Cannot include bind parameters.
*/
- @Suppress("AcronymName") // SQL is a known term and should remain capitalized
override fun bindTo(statement: SupportSQLiteProgram) {
bind(statement, bindArgs)
}
@@ -62,7 +60,6 @@
*/
@JvmStatic
public fun bind(
- @Suppress("AcronymName") // SQL is a known term and should remain capitalized
statement: SupportSQLiteProgram,
@Suppress("ArrayReturn") // Due to legacy API
bindArgs: Array<out Any?>?
@@ -78,12 +75,7 @@
}
}
- private fun bind(
- @Suppress("AcronymName") // SQL is a known term and should remain capitalized
- statement: SupportSQLiteProgram,
- index: Int,
- arg: Any?
- ) {
+ private fun bind(statement: SupportSQLiteProgram, index: Int, arg: Any?) {
// extracted from android.database.sqlite.SQLiteConnection
if (arg == null) {
statement.bindNull(index)
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
index 5c6d9dd..ba6f65c 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
@@ -29,7 +29,6 @@
* A database abstraction which removes the framework dependency and allows swapping underlying sql
* versions. It mimics the behavior of [android.database.sqlite.SQLiteDatabase]
*/
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public interface SupportSQLiteDatabase : Closeable {
/**
* Compiles the given SQL statement.
@@ -250,7 +249,6 @@
public fun yieldIfContendedSafely(sleepAfterYieldDelayMillis: Long): Boolean
/** Is true if [execPerConnectionSQL] is supported by the implementation. */
- @get:Suppress("AcronymName") // To keep consistency with framework method name.
public val isExecPerConnectionSQLSupported: Boolean
get() = false
@@ -275,7 +273,6 @@
* @throws UnsupportedOperationException if this operation is not supported. To check if it
* supported use [isExecPerConnectionSQLSupported]
*/
- @Suppress("AcronymName") // To keep consistency with framework method name.
public fun execPerConnectionSQL(
sql: String,
@SuppressLint("ArrayReturn") bindArgs: Array<out Any?>?
@@ -425,9 +422,7 @@
* not supported.
* @throws SQLException if the SQL string is invalid
*/
- @Suppress("AcronymName") // SQL is a known term and should remain capitalized
- @Throws(SQLException::class)
- public fun execSQL(sql: String)
+ @Throws(SQLException::class) public fun execSQL(sql: String)
/**
* Execute a single SQL statement that does not return any data.
@@ -441,9 +436,7 @@
* @param bindArgs only byte[], String, Long and Double are supported in selectionArgs.
* @throws SQLException if the SQL string is invalid
*/
- @Suppress("AcronymName") // SQL is a known term and should remain capitalized
- @Throws(SQLException::class)
- public fun execSQL(sql: String, bindArgs: Array<out Any?>)
+ @Throws(SQLException::class) public fun execSQL(sql: String, bindArgs: Array<out Any?>)
/** Is true if the database is opened as read only. */
public val isReadOnly: Boolean
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
index 2be3a94..c597f84 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
@@ -31,7 +31,6 @@
* that class requires overriding certain methods, support implementation uses [Factory.create] to
* create this and [Callback] to implement the methods that should be overridden.
*/
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public interface SupportSQLiteOpenHelper : Closeable {
/**
* Return the name of the SQLite database being opened, as given to the constructor. `null`
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
index 572879d..37965b1 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
@@ -18,7 +18,6 @@
import java.io.Closeable
/** An interface to map the behavior of [android.database.sqlite.SQLiteProgram]. */
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public interface SupportSQLiteProgram : Closeable {
/**
* Bind a NULL value to this statement. The value remains bound until [.clearBindings] is
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
index 3db42f5..657b85a3 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
@@ -19,7 +19,6 @@
* A query with typed bindings. It is better to use this API instead of
* [android.database.sqlite.SQLiteDatabase.rawQuery] because it allows binding type safe parameters.
*/
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public interface SupportSQLiteQuery {
/** The SQL query. This query can have placeholders(?) for bind arguments. */
public val sql: String
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
index 770820c..49ec1f3 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
@@ -18,7 +18,6 @@
import java.util.regex.Pattern
/** A simple query builder to create SQL SELECT queries. */
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public class SupportSQLiteQueryBuilder private constructor(private val table: String) {
private var distinct = false
private var columns: Array<out String>? = null
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
index a5c36ae..bf1bca3 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
@@ -16,7 +16,6 @@
package androidx.sqlite.db
/** An interface to map the behavior of [android.database.sqlite.SQLiteStatement]. */
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public interface SupportSQLiteStatement : SupportSQLiteProgram {
/**
* Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
index 9b63cba..653b597 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@file:Suppress("AcronymName") // SQL is a known term and should remain capitalized
@file:JvmName("SQLite")
package androidx.sqlite
@@ -53,13 +52,11 @@
public annotation class DataType
/** Executes a single SQL statement that returns no values. */
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public fun SQLiteConnection.execSQL(sql: String) {
prepare(sql).use { it.step() }
}
/** Throws a [SQLiteException] with its message formed by the given [errorCode] amd [errorMsg]. */
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public fun throwSQLiteException(errorCode: Int, errorMsg: String?): Nothing {
val message = buildString {
append("Error code: $errorCode")
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
index 14b76d4..e988034 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
@@ -24,7 +24,7 @@
*
* See also [Database Connection](https://www.sqlite.org/c3ref/sqlite3.html)
*/
-@Suppress("NotCloseable", "AcronymName") // SQL is a known term and should remain capitalized
+@Suppress("NotCloseable")
public interface SQLiteConnection : AutoCloseable {
/**
* Prepares a new SQL statement.
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
index 5cb23bf..a1f3e50 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
@@ -17,7 +17,6 @@
package androidx.sqlite
/** An interface to open database connections. */
-@Suppress("AcronymName") // SQL is a known term and should remain capitalized
public interface SQLiteDriver {
/**
* Opens a new database connection.
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
index 7f42c8b..8b319b9 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
@@ -26,7 +26,7 @@
*
* See also [Prepared Statement](https://www.sqlite.org/c3ref/stmt.html)
*/
-@Suppress("NotCloseable", "AcronymName") // SQL is a known term and should remain capitalized
+@Suppress("NotCloseable")
public interface SQLiteStatement : AutoCloseable {
/**
* Binds a ByteArray value to this statement at an index.
diff --git a/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java b/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java
index 4761400..487fc51 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java
@@ -34,7 +34,6 @@
*
* @see android.webkit.URLUtil
*/
-@SuppressWarnings("AcronymName") // Compat class for similarly named URLUtil in Android SDK
public final class URLUtilCompat {
private URLUtilCompat() {} // Class should not be instantiated
diff --git a/window/window-demos/demo/lint-baseline.xml b/window/window-demos/demo/lint-baseline.xml
index 57a5f51..d4d73fc 100644
--- a/window/window-demos/demo/lint-baseline.xml
+++ b/window/window-demos/demo/lint-baseline.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.8.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (8.8.0-alpha08)" variant="all" version="8.8.0-alpha08">
+<issues format="6" by="lint 8.9.0-alpha06" type="baseline" client="gradle" dependencies="false" name="AGP (8.9.0-alpha06)" variant="all" version="8.9.0-alpha06">
<issue
id="NewApi"
@@ -29,19 +29,19 @@
</issue>
<issue
- id="WrongConstant"
- message="Must be one or more of: LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, LayoutParams.FLAG_DIM_BEHIND, LayoutParams.FLAG_BLUR_BEHIND, LayoutParams.FLAG_NOT_FOCUSABLE, LayoutParams.FLAG_NOT_TOUCHABLE, LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING, LayoutParams.FLAG_KEEP_SCREEN_ON, LayoutParams.FLAG_LAYOUT_IN_SCREEN, LayoutParams.FLAG_LAYOUT_NO_LIMITS, LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, LayoutParams.FLAG_DITHER, LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SCALED, LayoutParams.FLAG_IGNORE_CHEEK_PRESSES, LayoutParams.FLAG_LAYOUT_INSET_DECOR, LayoutParams.FLAG_ALT_FOCUSABLE_IM, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_SHOW_WHEN_LOCKED, LayoutParams.FLAG_SHOW_WALLPAPER, LayoutParams.FLAG_TURN_SCREEN_ON, LayoutParams.FLAG_DISMISS_KEYGUARD, LayoutParams.FLAG_SPLIT_TOUCH, LayoutParams.FLAG_HARDWARE_ACCELERATED, LayoutParams.FLAG_LAYOUT_IN_OVERSCAN, LayoutParams.FLAG_TRANSLUCENT_STATUS, LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, LayoutParams.FLAG_LOCAL_FOCUS_MODE, LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR, LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS"
- errorLine1=" ?.or(android.R.attr.showWhenLocked or android.R.attr.turnScreenOn)"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ id="NewApi"
+ message="Call requires API level 30 (current min is 23): `android.view.WindowManager.LayoutParams#setFitInsetsTypes`"
+ errorLine1=" attrs.fitInsetsTypes = WindowInsets.Type.statusBars()"
+ errorLine2=" ~">
<location
- file="src/main/java/androidx/window/demo/PresentationActivity.kt"/>
+ file="src/main/java/androidx/window/demo/embedding/SplitImeActivityPlaceholder.kt"/>
</issue>
<issue
id="WrongConstant"
message="Must be one or more of: LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, LayoutParams.FLAG_DIM_BEHIND, LayoutParams.FLAG_BLUR_BEHIND, LayoutParams.FLAG_NOT_FOCUSABLE, LayoutParams.FLAG_NOT_TOUCHABLE, LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING, LayoutParams.FLAG_KEEP_SCREEN_ON, LayoutParams.FLAG_LAYOUT_IN_SCREEN, LayoutParams.FLAG_LAYOUT_NO_LIMITS, LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, LayoutParams.FLAG_DITHER, LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SCALED, LayoutParams.FLAG_IGNORE_CHEEK_PRESSES, LayoutParams.FLAG_LAYOUT_INSET_DECOR, LayoutParams.FLAG_ALT_FOCUSABLE_IM, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_SHOW_WHEN_LOCKED, LayoutParams.FLAG_SHOW_WALLPAPER, LayoutParams.FLAG_TURN_SCREEN_ON, LayoutParams.FLAG_DISMISS_KEYGUARD, LayoutParams.FLAG_SPLIT_TOUCH, LayoutParams.FLAG_HARDWARE_ACCELERATED, LayoutParams.FLAG_LAYOUT_IN_OVERSCAN, LayoutParams.FLAG_TRANSLUCENT_STATUS, LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, LayoutParams.FLAG_LOCAL_FOCUS_MODE, LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR, LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS"
errorLine1=" ?.or(android.R.attr.showWhenLocked or android.R.attr.turnScreenOn)"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/androidx/window/demo/PresentationActivity.kt"/>
</issue>
diff --git a/xr/compose/material3/material3/build.gradle b/xr/compose/material3/material3/build.gradle
index 0cad526..ec48d06 100644
--- a/xr/compose/material3/material3/build.gradle
+++ b/xr/compose/material3/material3/build.gradle
@@ -42,7 +42,7 @@
implementation(project(":compose:material3:material3"))
implementation(project(":compose:material3:material3-adaptive-navigation-suite"))
- implementation(project(":xr:compose:compose"))
+ implementation("androidx.xr.compose:compose:1.0.0-alpha01")
}
android {