Merge "Fix WithConstraints test failing on API 30" into androidx-master-dev
diff --git a/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java b/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java
index bd51eb5..aac6d87 100644
--- a/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java
+++ b/annotation/annotation/src/main/java/androidx/annotation/RestrictTo.java
@@ -71,7 +71,7 @@
/**
* Restrict usage to code within packages whose groups share
* the same library group prefix up to the last ".", so for
- * example libraries foo.bar:lib1 amd foo.baz:lib2 share
+ * example libraries foo.bar:lib1 and foo.baz:lib2 share
* the prefix "foo." and so they can use each other's
* apis that are restricted to this scope. Similarly for
* com.foo.bar:lib1 and com.foo.baz:lib2 where they share
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
index bdc7ed8..8ffece6 100644
--- a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/AppCompatIssueRegistry.kt
@@ -18,6 +18,7 @@
import androidx.appcompat.res.ColorStateListAlphaDetector
import androidx.appcompat.res.ColorStateListLoadingDetector
+import androidx.appcompat.res.DrawableLoadingDetector
import androidx.appcompat.res.ImageViewTintDetector
import com.android.tools.lint.client.api.IssueRegistry
import com.android.tools.lint.detector.api.CURRENT_API
@@ -27,6 +28,7 @@
override val issues get() = listOf(
ColorStateListAlphaDetector.NOT_USING_ANDROID_ALPHA,
ColorStateListLoadingDetector.NOT_USING_COMPAT_LOADING,
+ DrawableLoadingDetector.NOT_USING_COMPAT_LOADING,
ImageViewTintDetector.USING_ANDROID_TINT
)
}
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/BaseMethodDeprecationDetector.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/BaseMethodDeprecationDetector.kt
new file mode 100644
index 0000000..9d7123f
--- /dev/null
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/BaseMethodDeprecationDetector.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2020 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.appcompat.res
+
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+
+// Base class for all AppCompat Lint checks that flag usages of methods that should be
+// converted to use matching API(s) provided by AppCompat.
+@Suppress("UnstableApiUsage")
+abstract class BaseMethodDeprecationDetector(
+ private val issue: Issue,
+ vararg val conditions: DeprecationCondition
+) : Detector(), SourceCodeScanner {
+
+ // Collect unique method names from all deprecation conditions defined in this detector
+ private val applicableMethods = conditions.map { it.methodLocation.methodName }.distinct()
+
+ interface Predicate {
+ fun matches(context: JavaContext, node: UCallExpression, method: PsiMethod): Boolean
+ }
+
+ class ApiAtOrAbove(private val sdkLevel: Int) : Predicate {
+ override fun matches(
+ context: JavaContext,
+ node: UCallExpression,
+ method: PsiMethod
+ ): Boolean {
+ return context.mainProject.minSdkVersion.featureLevel >= sdkLevel
+ }
+ }
+
+ class ApiAbove(private val sdkLevel: Int) : Predicate {
+ override fun matches(
+ context: JavaContext,
+ node: UCallExpression,
+ method: PsiMethod
+ ): Boolean {
+ return context.mainProject.minSdkVersion.featureLevel > sdkLevel
+ }
+ }
+
+ class ApiAtOrBelow(private val sdkLevel: Int) : Predicate {
+ override fun matches(
+ context: JavaContext,
+ node: UCallExpression,
+ method: PsiMethod
+ ): Boolean {
+ return context.mainProject.minSdkVersion.featureLevel <= sdkLevel
+ }
+ }
+
+ class ApiBelow(private val sdkLevel: Int) : Predicate {
+ override fun matches(
+ context: JavaContext,
+ node: UCallExpression,
+ method: PsiMethod
+ ): Boolean {
+ return context.mainProject.minSdkVersion.featureLevel < sdkLevel
+ }
+ }
+
+ class MethodLocation(
+ private val className: String,
+ val methodName: String,
+ private vararg val params: String
+ ) : Predicate {
+ override fun matches(
+ context: JavaContext,
+ node: UCallExpression,
+ method: PsiMethod
+ ): Boolean {
+ if (!context.evaluator.isMemberInClass(method, className)) {
+ // Method is not in the right class
+ return false
+ }
+ if (method.name != methodName) {
+ // Method name does not match
+ return false
+ }
+ if (!context.evaluator.methodMatches(method, className, true, *params)) {
+ // Method signature does not match
+ return false
+ }
+ return true
+ }
+ }
+
+ class DeprecationCondition(
+ val methodLocation: MethodLocation,
+ val message: String,
+ private vararg val predicates: Predicate
+ ) : Predicate {
+ override fun matches(
+ context: JavaContext,
+ node: UCallExpression,
+ method: PsiMethod
+ ): Boolean {
+ if (!methodLocation.matches(context, node, method)) {
+ // Method location does not match. The whole condition is not applicable
+ return false
+ }
+
+ for (predicate in predicates) {
+ if (!predicate.matches(context, node, method)) {
+ // The predicate does not match. The whole condition is not applicable
+ return false
+ }
+ }
+ return true
+ }
+ }
+
+ // Mark final so that extending classes are forced to only use the constructor-level
+ // configuration APIs
+ final override fun getApplicableMethodNames(): List<String>? = applicableMethods
+
+ // Mark final so that extending classes are forced to only use the constructor-level
+ // configuration APIs
+ final override fun visitMethodCall(
+ context: JavaContext,
+ node: UCallExpression,
+ method: PsiMethod
+ ) {
+ // Find the first condition that matches and report the issue
+ for (condition in conditions) {
+ if (condition.matches(context, node, method)) {
+ context.report(issue, context.getLocation(node), condition.message)
+ return
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt
index 55d4f82..0477130 100644
--- a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/ColorStateListLoadingDetector.kt
@@ -16,22 +16,35 @@
package androidx.appcompat.res
+import com.android.tools.lint.client.api.TYPE_INT
import com.android.tools.lint.detector.api.Category
-import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
-import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
-import com.android.tools.lint.detector.api.SourceCodeScanner
-import com.intellij.psi.PsiMethod
-import org.jetbrains.uast.UCallExpression
+// Flags usage of Resources.getColorStateList and suggests converting it to either
+// ContextCompat.getColorStateList or AppCompatResources.getColorStateList based
+// on the API level
@Suppress("UnstableApiUsage")
-class ColorStateListLoadingDetector : Detector(), SourceCodeScanner {
+class ColorStateListLoadingDetector : BaseMethodDeprecationDetector(
+ NOT_USING_COMPAT_LOADING,
+ // Suggest using ContextCompat.getColorStateList at API > 23
+ DeprecationCondition(
+ MethodLocation("android.content.res.Resources", "getColorStateList", TYPE_INT),
+ "Use `ContextCompat.getColorStateList()`",
+ ApiAbove(23)
+ ),
+ // Suggest using AppCompatResources.getColorStateList at API <= 23
+ DeprecationCondition(
+ MethodLocation("android.content.res.Resources", "getColorStateList", TYPE_INT),
+ "Use `AppCompatResources.getColorStateList()`",
+ ApiAtOrBelow(23)
+ )
+) {
companion object {
internal val NOT_USING_COMPAT_LOADING: Issue = Issue.create(
- "UseCompatLoading",
+ "UseCompatLoadingForColorStateLists",
"Should not call `Resources.getColorStateList` directly",
"Use Compat loading of color state lists",
Category.CORRECTNESS,
@@ -40,22 +53,4 @@
Implementation(ColorStateListLoadingDetector::class.java, Scope.JAVA_FILE_SCOPE)
)
}
-
- override fun getApplicableMethodNames(): List<String>? = listOf("getColorStateList")
-
- override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
- // Only flag Resources.getColorStateList calls with one argument (parameter)
- if (context.evaluator.isMemberInClass(method, "android.content.res.Resources") &&
- (node.valueArgumentCount == 1)
- ) {
- val message = if (context.mainProject.minSdkVersion.featureLevel > 23)
- "Use `ContextCompat.getColorStateList()`" else
- "Use `AppCompatResources.getColorStateList()`"
- context.report(
- NOT_USING_COMPAT_LOADING,
- context.getLocation(node),
- message
- )
- }
- }
}
\ No newline at end of file
diff --git a/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/DrawableLoadingDetector.kt b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/DrawableLoadingDetector.kt
new file mode 100644
index 0000000..1dcc823
--- /dev/null
+++ b/appcompat/appcompat-lint/src/main/kotlin/androidx/appcompat/res/DrawableLoadingDetector.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 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.appcompat.res
+
+import com.android.tools.lint.client.api.TYPE_INT
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+
+// Flags usage of Context.getDrawable and Resources.getDrawable and suggests converting them
+// to either ContextCompat.getDrawable or ResourcesCompat.getDrawable
+@Suppress("UnstableApiUsage")
+class DrawableLoadingDetector : BaseMethodDeprecationDetector(
+ NOT_USING_COMPAT_LOADING,
+ // Suggest using ContextCompat.getDrawable
+ DeprecationCondition(
+ MethodLocation("android.content.Context", "getDrawable", TYPE_INT),
+ "Use `ContextCompat.getDrawable()`"
+ ),
+ // Suggest using ResourcesCompat.getDrawable for one-parameter Resources.getDrawable calls
+ DeprecationCondition(
+ MethodLocation("android.content.res.Resources", "getDrawable", TYPE_INT),
+ "Use `ResourcesCompat.getDrawable()`"
+ ),
+ // Suggest using ResourcesCompat.getDrawable for two-parameter Resources.getDrawable calls
+ DeprecationCondition(
+ MethodLocation("android.content.res.Resources", "getDrawable", TYPE_INT,
+ "android.content.res.Resources.Theme"),
+ "Use `ResourcesCompat.getDrawable()`"
+ )
+) {
+ companion object {
+ internal val NOT_USING_COMPAT_LOADING: Issue = Issue.create(
+ "UseCompatLoadingForDrawables",
+ "Should not call `Context.getDrawable` or `Resources.getDrawable` directly",
+ "Use Compat loading of drawables",
+ Category.CORRECTNESS,
+ 1,
+ Severity.WARNING,
+ Implementation(DrawableLoadingDetector::class.java, Scope.JAVA_FILE_SCOPE)
+ )
+ }
+}
\ No newline at end of file
diff --git a/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt
index b3f550a..8aadf18 100644
--- a/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt
+++ b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/ColorStateListLoadingDetectorTest.kt
@@ -110,7 +110,7 @@
).issues(ColorStateListLoadingDetector.NOT_USING_COMPAT_LOADING)
.run()
.expect("""
-src/com/example/CustomActivity.kt:8: Warning: Use ContextCompat.getColorStateList() [UseCompatLoading]
+src/com/example/CustomActivity.kt:8: Warning: Use ContextCompat.getColorStateList() [UseCompatLoadingForColorStateLists]
getResources().getColorStateList(R.color.color_state_list)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 errors, 1 warnings
@@ -167,7 +167,7 @@
).issues(ColorStateListLoadingDetector.NOT_USING_COMPAT_LOADING)
.run()
.expect("""
-src/com/example/CustomActivity.kt:8: Warning: Use AppCompatResources.getColorStateList() [UseCompatLoading]
+src/com/example/CustomActivity.kt:8: Warning: Use AppCompatResources.getColorStateList() [UseCompatLoadingForColorStateLists]
getResources().getColorStateList(R.color.color_state_list)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 errors, 1 warnings
diff --git a/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/DrawableLoadingDetectorTest.kt b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/DrawableLoadingDetectorTest.kt
new file mode 100644
index 0000000..de28066
--- /dev/null
+++ b/appcompat/appcompat-lint/src/test/kotlin/androidx/appcompat/lint/res/DrawableLoadingDetectorTest.kt
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2020 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.appcompat.lint.res
+
+import androidx.appcompat.lint.Stubs
+import androidx.appcompat.res.DrawableLoadingDetector
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest.kotlin
+import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
+import org.junit.Test
+
+class DrawableLoadingDetectorTest {
+ @Test
+ fun testCustomGetDrawable() {
+ val customActivity = kotlin(
+ "com/example/CustomActivity.kt",
+ """
+ package com.example
+
+ import android.graphics.drawable.Drawable
+ import androidx.appcompat.app.AppCompatActivity
+ import androidx.core.content.ContextCompat
+
+ class ResourceLoader {
+ private fun getDrawable(resourceId: Int): Drawable {
+ return ContextCompat.getDrawable(CustomActivity.this, resourceId)
+ }
+ }
+
+ class CustomActivity: AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ ResourceLoader().getDrawable(android.R.drawable.ic_delete)
+ }
+ }
+ """
+ ).indented().within("src")
+
+ // We expect a clean Lint run since the call to getDrawable in activity's onCreate
+ // is on our own custom inner class
+ lint().files(
+ Stubs.APPCOMPAT_ACTIVITY,
+ customActivity
+ ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun testCoreContextGetDrawable() {
+ val customActivity = kotlin(
+ "com/example/CustomActivity.kt",
+ """
+ package com.example
+
+ import android.graphics.drawable.Drawable
+ import android.os.Bundle
+ import androidx.appcompat.app.AppCompatActivity
+
+ class CustomActivity: AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ getDrawable(android.R.drawable.ic_delete)
+ }
+ }
+ """
+ ).indented().within("src")
+
+ // We expect the call to Context.getDrawable to be flagged to use ContextCompat loading
+ /* ktlint-disable max-line-length */
+ lint().files(
+ Stubs.APPCOMPAT_ACTIVITY,
+ customActivity
+ ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+ .run()
+ .expect("""
+src/com/example/CustomActivity.kt:9: Warning: Use ContextCompat.getDrawable() [UseCompatLoadingForDrawables]
+ getDrawable(android.R.drawable.ic_delete)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+0 errors, 1 warnings
+ """.trimIndent())
+ /* ktlint-enable max-line-length */
+ }
+
+ @Test
+ fun testCoreResourcesGetDrawable() {
+ val customActivity = kotlin(
+ "com/example/CustomActivity.kt",
+ """
+ package com.example
+
+ import android.graphics.drawable.Drawable
+ import android.os.Bundle
+ import androidx.appcompat.app.AppCompatActivity
+
+ class CustomActivity: AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ getResources().getDrawable(android.R.drawable.ic_delete)
+ }
+ }
+ """
+ ).indented().within("src")
+
+ // We expect the call to Resources.getDrawable to be flagged to use ResourcesCompat loading
+ /* ktlint-disable max-line-length */
+ lint().files(
+ Stubs.APPCOMPAT_ACTIVITY,
+ customActivity
+ ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+ .run()
+ .expect("""
+src/com/example/CustomActivity.kt:9: Warning: Use ResourcesCompat.getDrawable() [UseCompatLoadingForDrawables]
+ getResources().getDrawable(android.R.drawable.ic_delete)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+0 errors, 1 warnings
+ """.trimIndent())
+ /* ktlint-enable max-line-length */
+ }
+
+ @Test
+ fun testCoreResourcesThemeGetDrawable() {
+ val customActivity = kotlin(
+ "com/example/CustomActivity.kt",
+ """
+ package com.example
+
+ import android.graphics.drawable.Drawable
+ import android.os.Bundle
+ import androidx.appcompat.app.AppCompatActivity
+
+ class CustomActivity: AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ getResources().getDrawable(android.R.drawable.ic_delete, getTheme())
+ }
+ }
+ """
+ ).indented().within("src")
+
+ // We expect the call to Resources.getDrawable to be flagged to use ResourcesCompat loading
+ /* ktlint-disable max-line-length */
+ lint().files(
+ Stubs.APPCOMPAT_ACTIVITY,
+ customActivity
+ ).issues(DrawableLoadingDetector.NOT_USING_COMPAT_LOADING)
+ .run()
+ .expect("""
+src/com/example/CustomActivity.kt:9: Warning: Use ResourcesCompat.getDrawable() [UseCompatLoadingForDrawables]
+ getResources().getDrawable(android.R.drawable.ic_delete, getTheme())
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+0 errors, 1 warnings
+ """.trimIndent())
+ /* ktlint-enable max-line-length */
+ }
+}
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeBaseContextThemeTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeBaseContextThemeTestCase.kt
new file mode 100644
index 0000000..71b8c84
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeBaseContextThemeTestCase.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 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.appcompat.app
+
+import android.view.InflateException
+import android.widget.Toast
+import androidx.appcompat.testutils.NightModeActivityTestRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import junit.framework.TestCase.assertNotNull
+import junit.framework.TestCase.assertNull
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class NightModeBaseContextThemeTestCase {
+ @get:Rule
+ val rule = NightModeActivityTestRule(NightModeActivity::class.java)
+
+ @Test
+ fun testBaseContextShowToast() {
+ var result: Exception? = null
+
+ rule.runOnUiThread {
+ try {
+ Toast.makeText(rule.activity.baseContext, "test", Toast.LENGTH_SHORT).show()
+ } catch (e: InflateException) {
+ e.printStackTrace()
+ result = e
+ }
+ }
+
+ assertNull("Showed Toast without exception", result)
+ }
+
+ @Test
+ fun testBaseContextResolveAttribute() {
+ var baseContext = rule.activity.baseContext
+ var resolved = baseContext.obtainStyledAttributes(
+ intArrayOf(android.R.attr.textColorLink))
+ assertNotNull("Resolved @attr/textColorLink", resolved.getColorStateList(0))
+ }
+}
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
index cd5c5c79..0ce4cb2 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
@@ -446,7 +446,7 @@
// Next, we'll wrap the base context to ensure any method overrides or themes are left
// intact. Since ThemeOverlay.AppCompat theme is empty, we'll get the base context's theme.
final ContextThemeWrapper wrappedContext = new ContextThemeWrapper(baseContext,
- R.style.ThemeOverlay_AppCompat);
+ R.style.Theme_AppCompat_Empty);
wrappedContext.applyOverrideConfiguration(config);
// Check whether the base context has an explicit theme or is able to obtain one
diff --git a/appcompat/appcompat/src/main/res/values/themes.xml b/appcompat/appcompat/src/main/res/values/themes.xml
index 28ea38e..f2c0ed6 100644
--- a/appcompat/appcompat/src/main/res/values/themes.xml
+++ b/appcompat/appcompat/src/main/res/values/themes.xml
@@ -25,6 +25,9 @@
that need to vary based on platform version should be defined in the corresponding
"Theme.Base" theme. -->
+ <!-- Empty theme used to create a no-op ContextThemeWrapper. -->
+ <style name="Theme.AppCompat.Empty" parent="" />
+
<!-- Platform-independent theme providing an action bar in a dark-themed activity. -->
<style name="Theme.AppCompat" parent="Base.Theme.AppCompat" />
diff --git a/benchmark/common/api/1.1.0-alpha01.ignore b/benchmark/common/api/1.1.0-alpha01.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/1.1.0-alpha01.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+ Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/1.1.0-alpha01.txt b/benchmark/common/api/1.1.0-alpha01.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/1.1.0-alpha01.txt
+++ b/benchmark/common/api/1.1.0-alpha01.txt
@@ -14,8 +14,5 @@
public static final class BenchmarkState.Companion {
}
- public final class TraceCompatKt {
- }
-
}
diff --git a/benchmark/common/api/current.txt b/benchmark/common/api/current.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/current.txt
+++ b/benchmark/common/api/current.txt
@@ -14,8 +14,5 @@
public static final class BenchmarkState.Companion {
}
- public final class TraceCompatKt {
- }
-
}
diff --git a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
index e87771e..907fabb 100644
--- a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
+++ b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
@@ -21,8 +21,5 @@
@kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
}
- public final class TraceCompatKt {
- }
-
}
diff --git a/benchmark/common/api/public_plus_experimental_current.txt b/benchmark/common/api/public_plus_experimental_current.txt
index e87771e..907fabb 100644
--- a/benchmark/common/api/public_plus_experimental_current.txt
+++ b/benchmark/common/api/public_plus_experimental_current.txt
@@ -21,8 +21,5 @@
@kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
}
- public final class TraceCompatKt {
- }
-
}
diff --git a/benchmark/common/api/restricted_1.1.0-alpha01.ignore b/benchmark/common/api/restricted_1.1.0-alpha01.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/restricted_1.1.0-alpha01.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+ Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/restricted_1.1.0-alpha01.txt b/benchmark/common/api/restricted_1.1.0-alpha01.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/restricted_1.1.0-alpha01.txt
+++ b/benchmark/common/api/restricted_1.1.0-alpha01.txt
@@ -14,8 +14,5 @@
public static final class BenchmarkState.Companion {
}
- public final class TraceCompatKt {
- }
-
}
diff --git a/benchmark/common/api/restricted_current.txt b/benchmark/common/api/restricted_current.txt
index 26eb848..61b357d 100644
--- a/benchmark/common/api/restricted_current.txt
+++ b/benchmark/common/api/restricted_current.txt
@@ -14,8 +14,5 @@
public static final class BenchmarkState.Companion {
}
- public final class TraceCompatKt {
- }
-
}
diff --git a/benchmark/common/build.gradle b/benchmark/common/build.gradle
index edbc120..047827b 100644
--- a/benchmark/common/build.gradle
+++ b/benchmark/common/build.gradle
@@ -31,6 +31,7 @@
implementation(KOTLIN_STDLIB)
api("androidx.annotation:annotation:1.0.0")
api("androidx.annotation:annotation-experimental:1.0.0-rc01")
+ implementation(project(':tracing:tracing-ktx'))
implementation(ANDROIDX_TEST_MONITOR)
androidTestImplementation(ANDROIDX_TEST_RULES)
diff --git a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
index 10c0751..4cee094 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
@@ -27,6 +27,7 @@
import androidx.annotation.VisibleForTesting
import androidx.benchmark.Errors.PREFIX
import androidx.test.platform.app.InstrumentationRegistry
+import androidx.tracing.Trace
import java.io.File
import java.text.NumberFormat
import java.util.concurrent.TimeUnit
@@ -176,7 +177,7 @@
}
private fun beginWarmup() {
- beginTraceSection("Warmup")
+ Trace.beginSection("Warmup")
// Run GC to avoid memory pressure from previous run from affecting this one.
// Note, we don't use System.gc() because it doesn't always have consistent behavior
Runtime.getRuntime().gc()
@@ -217,12 +218,12 @@
thermalThrottleSleepSeconds = 0
state = RUNNING
metrics.captureInit()
- beginTraceSection("Benchmark")
+ Trace.beginSection("Benchmark")
metrics.captureStart()
}
private fun endBenchmark() {
- endTraceSection() // paired with start in beginBenchmark()
+ Trace.endSection() // paired with start in beginBenchmark()
when (Arguments.profilingMode) {
ProfilingMode.Sampled, ProfilingMode.Method -> {
Debug.stopMethodTracing()
@@ -364,7 +365,7 @@
throwIfPaused() // check each loop during warmup
if (warmupManager.onNextIteration(lastDuration)) {
- endTraceSection() // paired with start in beginWarmup()
+ Trace.endSection() // paired with start in beginWarmup()
beginBenchmark()
}
return true
diff --git a/benchmark/common/src/main/java/androidx/benchmark/TraceCompat.kt b/benchmark/common/src/main/java/androidx/benchmark/TraceCompat.kt
deleted file mode 100644
index 491fe42..0000000
--- a/benchmark/common/src/main/java/androidx/benchmark/TraceCompat.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2019 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.benchmark
-
-import android.os.Build
-import android.os.Trace
-import androidx.annotation.RestrictTo
-
-/*
- * Simple reimplementation of TraceCompat, to avoid androidx.core dependency for two methods
- *
- * Note:
- * Benchmark isn't especially careful about terminating tracing sections, because our APIs are
- * called *from* the long-running synchronous chunks of work, instead of wrapping them.
- *
- * We try and match up begi/end pairs, but it's entirely possibly that ends will be missed due to
- * the app returning early from the benchmark loop (whether intentionally, or by crashing).
- *
- * Because there's no elegant way to fix this, we just accept that crashing benchmarks can result in
- * never-terminating traces from benchmark.
- */
-
-/**
- * @suppress
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-fun beginTraceSection(sectionName: String) {
- if (Build.VERSION.SDK_INT >= 18) {
- Trace.beginSection(sectionName)
- }
-}
-
-/**
- * @suppress
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-fun endTraceSection() {
- if (Build.VERSION.SDK_INT >= 18) {
- Trace.endSection()
- }
-}
\ No newline at end of file
diff --git a/benchmark/junit4/build.gradle b/benchmark/junit4/build.gradle
index 8aef6fb..639c57a 100644
--- a/benchmark/junit4/build.gradle
+++ b/benchmark/junit4/build.gradle
@@ -33,6 +33,7 @@
dependencies {
api(project(":benchmark:benchmark-common"))
+ implementation(project(':tracing:tracing-ktx'))
api(JUNIT)
api(KOTLIN_STDLIB)
diff --git a/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt b/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt
index 9d149e9..21aa740 100644
--- a/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt
+++ b/benchmark/junit4/src/main/java/androidx/benchmark/junit4/BenchmarkRule.kt
@@ -20,9 +20,8 @@
import android.util.Log
import androidx.annotation.RestrictTo
import androidx.benchmark.BenchmarkState
-import androidx.benchmark.beginTraceSection
-import androidx.benchmark.endTraceSection
import androidx.test.rule.GrantPermissionRule
+import androidx.tracing.trace
import org.junit.Assert.assertTrue
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
@@ -188,11 +187,8 @@
internalState.traceUniqueName = description.testClass.simpleName + "_" +
invokeMethodName
- try {
- beginTraceSection(description.displayName)
+ trace(description.displayName) {
base.evaluate()
- } finally {
- endTraceSection()
}
if (enableReport) {
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java
index 61d1cf7..cb58c7a 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/GLUtil.java
@@ -36,6 +36,8 @@
import android.opengl.EGLSurface;
import android.opengl.GLES20;
+import java.util.Objects;
+
/**
* Utility functions interacting with OpenGL.
*
@@ -46,11 +48,9 @@
}
/** Set up a GL context so that GL calls requiring a context can be made. */
- // TODO(b/141957748): Suppressed during upgrade to AGP 3.6.
- @SuppressWarnings("ReferenceEquality")
private static void setupGLContext() {
EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (eglDisplay == EGL_NO_DISPLAY) {
+ if (Objects.equals(eglDisplay, EGL_NO_DISPLAY)) {
throw new RuntimeException("Unable to get EGL display.");
}
int[] majorVer = new int[1];
@@ -96,7 +96,7 @@
EGLSurface eglPbuffer =
EGL14.eglCreatePbufferSurface(eglDisplay, eglConfig, pbufferAttribs,
pbufferAttribsOffset);
- if (eglPbuffer == EGL_NO_SURFACE) {
+ if (Objects.equals(eglPbuffer, EGL_NO_SURFACE)) {
throw new RuntimeException("Unable to create pbuffer surface.");
}
@@ -106,7 +106,7 @@
EGL14.eglCreateContext(
eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs,
contextAttribsOffset);
- if (eglContext == EGL_NO_CONTEXT) {
+ if (Objects.equals(eglContext, EGL_NO_CONTEXT)) {
throw new RuntimeException("Unable to create EGL context.");
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java
index f609c48..3f47890 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageProxy.java
@@ -144,16 +144,15 @@
if (mReleaseFuture == null) {
mReleaseFuture = CallbackToFutureAdapter.getFuture(
new CallbackToFutureAdapter.Resolver<Void>() {
- // TODO(b/141957748): Suppressed during upgrade to AGP 3.6.
- @SuppressWarnings("GuardedBy")
@Override
public Object attachCompleter(@NonNull
CallbackToFutureAdapter.Completer<Void> completer) {
- Preconditions.checkState(Thread.holdsLock(mReleaseLock));
- Preconditions.checkState(mReleaseCompleter == null,
- "Release completer expected to be null");
- mReleaseCompleter = completer;
- return "Release[imageProxy=" + FakeImageProxy.this + "]";
+ synchronized (mReleaseLock) {
+ Preconditions.checkState(mReleaseCompleter == null,
+ "Release completer expected to be null");
+ mReleaseCompleter = completer;
+ return "Release[imageProxy=" + FakeImageProxy.this + "]";
+ }
}
});
}
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/FixedSizeSurfaceTexture.java b/camera/camera-view/src/main/java/androidx/camera/view/FixedSizeSurfaceTexture.java
deleted file mode 100644
index 4f494cd..0000000
--- a/camera/camera-view/src/main/java/androidx/camera/view/FixedSizeSurfaceTexture.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2019 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.camera.view;
-
-import android.graphics.SurfaceTexture;
-import android.os.Build.VERSION_CODES;
-import android.util.Size;
-
-import androidx.annotation.RequiresApi;
-
-/**
- * An implementation of {@link SurfaceTexture} with a fixed default buffer size.
- *
- * <p>The fixed default buffer size used at construction time cannot be changed through the {@link
- * #setDefaultBufferSize(int, int)} method. This should only be used for the
- * {@link TextureViewImplementation} as a temporary solution to prevent the
- * {@link android.view.TextureView} from changing the resolution of the {@link SurfaceTexture},
- * because the {@link android.hardware.camera2.CameraCaptureSession} can not handle any arbitrary
- * resolution.
- */
-final class FixedSizeSurfaceTexture extends SurfaceTexture {
- /**
- * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
- *
- * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
- * @param fixedSize the fixed default buffer size
- * @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
- */
- FixedSizeSurfaceTexture(int texName, Size fixedSize) {
- super(texName);
- super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
- }
-
- /**
- * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
- *
- * <p>In single buffered mode the application is responsible for serializing access to the image
- * content buffer. Each time the image content is to be updated, the {@link #releaseTexImage()}
- * method must be called before the image content producer takes ownership of the buffer. For
- * example, when producing image content with the NDK ANativeWindow_lock and
- * ANativeWindow_unlockAndPost functions, {@link #releaseTexImage()} must be called before each
- * ANativeWindow_lock, or that call will fail. When producing image content with OpenGL ES,
- * {@link #releaseTexImage()} must be called before the first OpenGL ES function call each
- * frame.
- *
- * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
- * @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
- * @param fixedSize the fixed default buffer size
- * @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
- */
- FixedSizeSurfaceTexture(int texName, boolean singleBufferMode, Size fixedSize) {
- super(texName, singleBufferMode);
- super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
- }
-
- /**
- * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
- *
- * <p>In single buffered mode the application is responsible for serializing access to the image
- * content buffer. Each time the image content is to be updated, the {@link #releaseTexImage()}
- * method must be called before the image content producer takes ownership of the buffer. For
- * example, when producing image content with the NDK ANativeWindow_lock and
- * ANativeWindow_unlockAndPost functions, {@link #releaseTexImage()} must be called before each
- * ANativeWindow_lock, or that call will fail. When producing image content with OpenGL ES,
- * {@link #releaseTexImage()} must be called before the first OpenGL ES function call each
- * frame.
- *
- * <p>Unlike {@link SurfaceTexture(int, boolean)}, which takes an OpenGL texture object name,
- * this constructor creates the SurfaceTexture in detached mode. A texture name must be passed
- * in using {@link #attachToGLContext} before calling {@link #releaseTexImage()} and producing
- * image content using OpenGL ES.
- *
- * @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
- * @param fixedSize the fixed default buffer size
- * @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
- */
- @RequiresApi(api = VERSION_CODES.O)
- FixedSizeSurfaceTexture(boolean singleBufferMode, Size fixedSize) {
- super(singleBufferMode);
- super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
- }
-
- /**
- * This method has no effect.
- *
- * <p>Unlike {@link SurfaceTexture}, this method does not affect the default buffer size. The
- * default buffer size will remain what it was set to during construction.
- *
- * @param width ignored width
- * @param height ignored height
- */
- @Override
- public void setDefaultBufferSize(int width, int height) {
- // No-op
- }
-}
-
diff --git a/development/release-notes/GitClient.py b/development/release-notes/GitClient.py
index 257eee1..cabef02 100644
--- a/development/release-notes/GitClient.py
+++ b/development/release-notes/GitClient.py
@@ -137,8 +137,9 @@
self.summary = ""
self.changeType = CommitType.BUG_FIX
self.releaseNote = ""
- self.releaseNoteDelimiter = "Relnote:"
- listedCommit = gitCommit.split('\n')
+ self.releaseNoteDelimiter = "relnote:"
+ self.formatGitCommitRelnoteTag()
+ listedCommit = self.gitCommit.split('\n')
for line in listedCommit:
if line.strip() == "": continue
if self.commitSHADelimiter in line:
@@ -152,10 +153,20 @@
if ("Bug:" in line) or ("b/" in line) or ("bug:" in line) or ("Fixes:" in line) or ("fixes b/" in line):
self.getBugsFromGitLine(line)
if self.releaseNoteDelimiter in line:
- self.getReleaseNotesFromGitLine(line, gitCommit)
+ self.getReleaseNotesFromGitLine(line, self.gitCommit)
if self.projectDir.strip('/') in line:
self.getFileFromGitLine(line)
+ def formatGitCommitRelnoteTag(self):
+ """ This method accounts for the fact that the releaseNoteDelimiter is case insensitive
+ To do this, we just replace it with the tag we expect and can easily parse
+ """
+ relnoteIndex = self.gitCommit.lower().find(self.releaseNoteDelimiter)
+ if relnoteIndex > -1:
+ self.gitCommit = self.gitCommit[:relnoteIndex] + \
+ self.releaseNoteDelimiter + \
+ self.gitCommit[relnoteIndex + len(self.releaseNoteDelimiter):]
+
def isExternalAuthorEmail(self, authorEmail):
return "@google.com" not in self.authorEmail
diff --git a/development/release-notes/testReleaseNotes.py b/development/release-notes/testReleaseNotes.py
index a877008..95cb52e 100755
--- a/development/release-notes/testReleaseNotes.py
+++ b/development/release-notes/testReleaseNotes.py
@@ -168,6 +168,98 @@
)
self.assertEqual("Added an awesome new API!", commitWithApiChange.releaseNote)
+ def test_parseAPICommitWithDefaultDelimitersAndUncapitalizedRelnoteTag(self):
+ commitWithApiChangeString = """
+ _CommitStart
+ _CommitSHA:mySha
+ _Author:anemail@google.com
+ _Date:Tue Aug 6 15:05:55 2019 -0700
+ _Subject:Added a new API!
+ _Body:Also fixed some other bugs
+
+ Here is an explanation of my commit
+
+ "This is a quote about why it's great!"
+
+ Bug: 123456
+ Bug: b/1234567
+ Fixes: 123123
+ Test: ./gradlew buildOnServer
+
+ relnote: Added an awesome new API!
+
+ Change-Id: myChangeId
+
+ projectdir/a.java
+ projectdir/b.java
+ projectdir/androidTest/c.java
+ projectdir/api/some_api_file.txt
+ projectdir/api/current.txt
+ """
+ commitWithApiChange = Commit(commitWithApiChangeString, "/projectdir/")
+ self.assertEqual("mySha", commitWithApiChange.sha)
+ self.assertEqual("anemail@google.com", commitWithApiChange.authorEmail)
+ self.assertEqual("myChangeId", commitWithApiChange.changeId)
+ self.assertEqual("Added a new API!", commitWithApiChange.summary)
+ self.assertEqual(CommitType.API_CHANGE, commitWithApiChange.changeType)
+ self.assertEqual([123456, 1234567, 123123], commitWithApiChange.bugs)
+ self.assertEqual([
+ "projectdir/a.java",
+ "projectdir/b.java",
+ "projectdir/androidTest/c.java",
+ "projectdir/api/some_api_file.txt",
+ "projectdir/api/current.txt"
+ ],
+ commitWithApiChange.files
+ )
+ self.assertEqual("Added an awesome new API!", commitWithApiChange.releaseNote)
+
+ def test_parseAPICommitWithDefaultDelimitersAndCapitalizedRelnoteTag(self):
+ commitWithApiChangeString = """
+ _CommitStart
+ _CommitSHA:mySha
+ _Author:anemail@google.com
+ _Date:Tue Aug 6 15:05:55 2019 -0700
+ _Subject:Added a new API!
+ _Body:Also fixed some other bugs
+
+ Here is an explanation of my commit
+
+ "This is a quote about why it's great!"
+
+ Bug: 123456
+ Bug: b/1234567
+ Fixes: 123123
+ Test: ./gradlew buildOnServer
+
+ RelNotE: Added an awesome new API!
+
+ Change-Id: myChangeId
+
+ projectdir/a.java
+ projectdir/b.java
+ projectdir/androidTest/c.java
+ projectdir/api/some_api_file.txt
+ projectdir/api/current.txt
+ """
+ commitWithApiChange = Commit(commitWithApiChangeString, "/projectdir/")
+ self.assertEqual("mySha", commitWithApiChange.sha)
+ self.assertEqual("anemail@google.com", commitWithApiChange.authorEmail)
+ self.assertEqual("myChangeId", commitWithApiChange.changeId)
+ self.assertEqual("Added a new API!", commitWithApiChange.summary)
+ self.assertEqual(CommitType.API_CHANGE, commitWithApiChange.changeType)
+ self.assertEqual([123456, 1234567, 123123], commitWithApiChange.bugs)
+ self.assertEqual([
+ "projectdir/a.java",
+ "projectdir/b.java",
+ "projectdir/androidTest/c.java",
+ "projectdir/api/some_api_file.txt",
+ "projectdir/api/current.txt"
+ ],
+ commitWithApiChange.files
+ )
+ self.assertEqual("Added an awesome new API!", commitWithApiChange.releaseNote)
+
def test_parseBugFixCommitWithCustomDelimiters(self):
commitSHADelimiter = "_MyCommitSHA:"
authorEmailDelimiter = "_MyAuthor:"
diff --git a/fragment/fragment/build.gradle b/fragment/fragment/build.gradle
index 87e57e9..04c6674 100644
--- a/fragment/fragment/build.gradle
+++ b/fragment/fragment/build.gradle
@@ -43,6 +43,9 @@
api(project(":lifecycle:lifecycle-viewmodel"))
api(project(":lifecycle:lifecycle-viewmodel-savedstate"))
+ androidTestImplementation("androidx.appcompat:appcompat:1.1.0", {
+ exclude group: 'androidx.fragment', module: 'fragment'
+ })
androidTestImplementation(KOTLIN_STDLIB)
androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
androidTestImplementation(ANDROIDX_TEST_CORE)
diff --git a/fragment/fragment/src/androidTest/AndroidManifest.xml b/fragment/fragment/src/androidTest/AndroidManifest.xml
index b55fe6e..5bac34a 100644
--- a/fragment/fragment/src/androidTest/AndroidManifest.xml
+++ b/fragment/fragment/src/androidTest/AndroidManifest.xml
@@ -50,6 +50,8 @@
<activity android:name="androidx.fragment.app.SimpleContainerActivity" />
<activity android:name="androidx.fragment.app.DialogActivity"
android:theme="@style/DialogTheme"/>
+ <activity android:name="androidx.fragment.app.TestAppCompatActivity"
+ android:theme="@style/Theme.AppCompat.Light" />
</application>
</manifest>
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentInflatedChildTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentInflatedChildTest.kt
new file mode 100644
index 0000000..7ef6461
--- /dev/null
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentInflatedChildTest.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2020 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.fragment.app
+
+import android.app.Dialog
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.app.AppCompatDialog
+import androidx.fragment.test.R
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+// the Layout used to inflate the view
+sealed class InflatedViewLayout {
+ abstract fun getLayoutId(): Int
+ abstract fun getChildFragment(f: Fragment): Fragment?
+ override fun toString(): String = this.javaClass.simpleName
+}
+// When to inflate the view
+sealed class InflateViewLocation {
+ override fun toString(): String = this.javaClass.simpleName
+}
+
+object UseFragmentContainerView : InflatedViewLayout() {
+ override fun getLayoutId() = R.layout.inflated_fragment_container_view
+ override fun getChildFragment(f: Fragment) =
+ f.childFragmentManager.findFragmentByTag("fragment1")
+}
+
+object UseFragmentTag : InflatedViewLayout() {
+ override fun getLayoutId() = R.layout.nested_inflated_fragment_parent
+ override fun getChildFragment(f: Fragment) =
+ f.childFragmentManager.findFragmentById(R.id.child_fragment)
+}
+
+object OnCreateDialog : InflateViewLocation()
+object OnCreateView : InflateViewLocation()
+
+@LargeTest
+@RunWith(Parameterized::class)
+class DialogFragmentInflatedChildTest(
+ private val inflatedView: InflatedViewLayout,
+ private val inflateLocation: InflateViewLocation
+) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "inflatedView={0}, inflateLocation={1}")
+ fun data() = mutableListOf<Array<Any>>().apply {
+ arrayOf(
+ UseFragmentContainerView,
+ UseFragmentTag
+ ).forEach { inflatedViewLayout ->
+ add(arrayOf(inflatedViewLayout, OnCreateDialog))
+ add(arrayOf(inflatedViewLayout, OnCreateView))
+ }
+ }
+ }
+
+ @Test
+ fun testInflatedChildDialogFragment() {
+ with(ActivityScenario.launch(SimpleContainerActivity::class.java)) {
+ val dialogFragment = TestInflatedChildDialogFragment(
+ false, inflatedView.getLayoutId(), inflateLocation is OnCreateDialog)
+
+ withActivity {
+ supportFragmentManager.beginTransaction()
+ .add(dialogFragment, null)
+ .commitNow()
+ }
+
+ val child = inflatedView.getChildFragment(dialogFragment)
+ assertWithMessage("Inflated child fragment should not be null")
+ .that(child).isNotNull()
+ }
+ }
+
+ @Test
+ fun testInflatedChildAppCompatDialogFragment() {
+ with(ActivityScenario.launch(TestAppCompatActivity::class.java)) {
+ val dialogFragment = TestInflatedChildDialogFragment(
+ true, inflatedView.getLayoutId(), inflateLocation is OnCreateDialog)
+
+ withActivity {
+ supportFragmentManager.beginTransaction()
+ .add(dialogFragment, null)
+ .commitNow()
+ }
+
+ val child = inflatedView.getChildFragment(dialogFragment)
+ assertWithMessage("Inflated child fragment should not be null")
+ .that(child).isNotNull()
+ }
+ }
+}
+
+// This Activity has an AppCompatTheme
+class TestAppCompatActivity : AppCompatActivity(R.layout.simple_container)
+
+class TestInflatedChildDialogFragment(
+ val useAppCompat: Boolean,
+ val layoutId: Int,
+ val onCreateDialog: Boolean
+) : DialogFragment() {
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ) = if (!onCreateDialog) inflater.inflate(layoutId, container, false) else null
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val dialog =
+ if (useAppCompat) AppCompatDialog(requireContext()) else Dialog(requireContext())
+ if (onCreateDialog) {
+ dialog.setContentView(layoutInflater.inflate(layoutId, null))
+ }
+ return dialog
+ }
+}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java b/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
index a8c1715..2761130 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
@@ -39,6 +39,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.StyleRes;
+import androidx.core.view.LayoutInflaterCompat;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -128,6 +129,7 @@
private boolean mCancelable = true;
private boolean mShowsDialog = true;
private int mBackStackId = -1;
+ private boolean mCreatingDialog;
@Nullable
private Dialog mDialog;
@@ -427,19 +429,32 @@
}
}
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * If this is called from within {@link #onCreateDialog(Bundle)}, the layout inflater from
+ * {@link Fragment#onGetLayoutInflater(Bundle)}, without the dialog theme, will be returned.
+ */
@Override
@NonNull
public LayoutInflater onGetLayoutInflater(@Nullable Bundle savedInstanceState) {
- if (!mShowsDialog) {
+ if (!mShowsDialog || mCreatingDialog) {
return super.onGetLayoutInflater(savedInstanceState);
}
- mDialog = onCreateDialog(savedInstanceState);
+ try {
+ mCreatingDialog = true;
+ mDialog = onCreateDialog(savedInstanceState);
+ setupDialog(mDialog, mStyle);
+ } finally {
+ mCreatingDialog = false;
+ }
- setupDialog(mDialog, mStyle);
-
- return (LayoutInflater) mDialog.getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater layoutInflater = LayoutInflater.from(mDialog.getContext());
+ LayoutInflaterCompat.setFactory2(layoutInflater,
+ mChildFragmentManager.getLayoutInflaterFactory());
+ return layoutInflater;
}
/** @hide */
diff --git a/heifwriter/heifwriter/lint-baseline.xml b/heifwriter/heifwriter/lint-baseline.xml
index 9dfbdcc..1ff86da 100644
--- a/heifwriter/heifwriter/lint-baseline.xml
+++ b/heifwriter/heifwriter/lint-baseline.xml
@@ -2,6 +2,16 @@
<issues format="5" by="lint 3.6.0-beta05" client="gradle" variant="debug" version="3.6.0-beta05">
<issue
+ id="NewApi"
+ message="Call requires API level 29 (current min is 28): `android.media.MediaCodecInfo#isHardwareAccelerated`"
+ errorLine1=" if (info.isHardwareAccelerated()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/heifwriter/HeifEncoder.java"
+ line="401"
+ column="26"/>
+ </issue>
+ <issue
id="UnknownNullness"
message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
errorLine1=" public static FloatBuffer createFloatBuffer(float[] coords) {"
diff --git a/jetifier/jetifier/core/src/main/resources/default.config b/jetifier/jetifier/core/src/main/resources/default.config
index 493210a..9b14a9d 100644
--- a/jetifier/jetifier/core/src/main/resources/default.config
+++ b/jetifier/jetifier/core/src/main/resources/default.config
@@ -318,11 +318,11 @@
"to": "androidx/core/content/res/GrowingArrayUtils{0}"
},
- {
+ {
"from": "android/support/v4/content/res/ColorStateListInflaterCompat(.*)",
"to": "androidx/core/content/res/ColorStateListInflaterCompat{0}"
},
- {
+ {
"from": "android/support/v7/content/res/AppCompatColorStateListInflater(.*)",
"to": "androidx/core/content/res/ColorStateListInflaterCompat{0}"
},
diff --git a/jetifier/jetifier/migration.config b/jetifier/jetifier/migration.config
index c0471a6..d585d2e 100644
--- a/jetifier/jetifier/migration.config
+++ b/jetifier/jetifier/migration.config
@@ -441,6 +441,10 @@
"to": "ignore"
},
{
+ "from": "androidx/tracing/(.*)",
+ "to": "ignore"
+ },
+ {
"from": "androidx/fragment/app/DefaultSpecialEffectsController(.*)",
"to": "android/support/v4/app/DefaultSpecialEffectsController{0}"
},
diff --git a/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java b/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java
index d7ed4e1..cb7620b 100644
--- a/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java
+++ b/lifecycle/lifecycle-process/src/main/java/androidx/lifecycle/ProcessLifecycleOwner.java
@@ -25,6 +25,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.ReportFragment.ActivityInitializationListener;
@@ -159,6 +160,7 @@
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
Application app = (Application) context.getApplicationContext();
app.registerActivityLifecycleCallbacks(new EmptyActivityLifecycleCallbacks() {
+ @RequiresApi(29)
@Override
public void onActivityPreCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
diff --git a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
index 84b030d..3c0857f 100644
--- a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
+++ b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
@@ -30,7 +30,7 @@
* It also handles the communication of the Activity / Fragment with the rest of the application
* (e.g. calling the business logic classes).
* <p>
- * A ViewModel is always created in association with a scope (an fragment or an activity) and will
+ * A ViewModel is always created in association with a scope (a fragment or an activity) and will
* be retained as long as the scope is alive. E.g. if it is an Activity, until it is
* finished.
* <p>
diff --git a/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java b/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
index 87642ca..29721da 100644
--- a/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
+++ b/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
@@ -17,6 +17,7 @@
package com.example.android.appcompat;
import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.TextView;
@@ -49,5 +50,8 @@
ColorStateList csl2 = new ResourceLoader().getColorStateList(
R.color.color_state_list_missing_android_alpha);
dummy.setTextColor(csl2);
+
+ Drawable dr = getResources().getDrawable(R.drawable.app_sample_code);
+ dummy.setCompoundDrawables(dr, null, null, null);
}
}
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
index 2645d54..7223b1a 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/ui/AbstractProgressFragment.kt
@@ -98,9 +98,7 @@
protected fun navigate() {
Log.i(TAG, "navigate: ")
val installMonitor = DynamicInstallMonitor()
- val extras = DynamicExtras.Builder()
- .setInstallMonitor(installMonitor)
- .build()
+ val extras = DynamicExtras(installMonitor)
findNavController().navigate(destinationId, destinationArgs, null, extras)
if (!installMonitor.isInstallRequired) {
Log.i(TAG, "navigate: install not required")
diff --git a/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt b/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/2.3.0-alpha04.txt
@@ -15,17 +15,13 @@
}
public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+ ctor public DynamicExtras();
method public androidx.navigation.Navigator.Extras? getDestinationExtras();
method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
}
- public static final class DynamicExtras.Builder {
- ctor public DynamicExtras.Builder();
- method public androidx.navigation.dynamicfeatures.DynamicExtras build();
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
- }
-
@androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/current.txt b/navigation/navigation-dynamic-features-runtime/api/current.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/current.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/current.txt
@@ -15,17 +15,13 @@
}
public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+ ctor public DynamicExtras();
method public androidx.navigation.Navigator.Extras? getDestinationExtras();
method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
}
- public static final class DynamicExtras.Builder {
- ctor public DynamicExtras.Builder();
- method public androidx.navigation.dynamicfeatures.DynamicExtras build();
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
- }
-
@androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -15,17 +15,13 @@
}
public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+ ctor public DynamicExtras();
method public androidx.navigation.Navigator.Extras? getDestinationExtras();
method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
}
- public static final class DynamicExtras.Builder {
- ctor public DynamicExtras.Builder();
- method public androidx.navigation.dynamicfeatures.DynamicExtras build();
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
- }
-
@androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/public_plus_experimental_current.txt
@@ -15,17 +15,13 @@
}
public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+ ctor public DynamicExtras();
method public androidx.navigation.Navigator.Extras? getDestinationExtras();
method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
}
- public static final class DynamicExtras.Builder {
- ctor public DynamicExtras.Builder();
- method public androidx.navigation.dynamicfeatures.DynamicExtras build();
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
- }
-
@androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt b/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/restricted_2.3.0-alpha04.txt
@@ -15,17 +15,13 @@
}
public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+ ctor public DynamicExtras();
method public androidx.navigation.Navigator.Extras? getDestinationExtras();
method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
}
- public static final class DynamicExtras.Builder {
- ctor public DynamicExtras.Builder();
- method public androidx.navigation.dynamicfeatures.DynamicExtras build();
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
- }
-
@androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt b/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt
index 0513b0ba..a559409 100644
--- a/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt
+++ b/navigation/navigation-dynamic-features-runtime/api/restricted_current.txt
@@ -15,17 +15,13 @@
}
public final class DynamicExtras implements androidx.navigation.Navigator.Extras {
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor, androidx.navigation.Navigator.Extras? destinationExtras);
+ ctor public DynamicExtras(androidx.navigation.dynamicfeatures.DynamicInstallMonitor? installMonitor);
+ ctor public DynamicExtras();
method public androidx.navigation.Navigator.Extras? getDestinationExtras();
method public androidx.navigation.dynamicfeatures.DynamicInstallMonitor? getInstallMonitor();
}
- public static final class DynamicExtras.Builder {
- ctor public DynamicExtras.Builder();
- method public androidx.navigation.dynamicfeatures.DynamicExtras build();
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setDestinationExtras(androidx.navigation.Navigator.Extras destinationExtras);
- method public androidx.navigation.dynamicfeatures.DynamicExtras.Builder setInstallMonitor(androidx.navigation.dynamicfeatures.DynamicInstallMonitor monitor);
- }
-
@androidx.navigation.Navigator.Name("navigation") public final class DynamicGraphNavigator extends androidx.navigation.NavGraphNavigator {
ctor public DynamicGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider, androidx.navigation.dynamicfeatures.DynamicInstallManager installManager);
method public androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph createDestination();
diff --git a/navigation/navigation-dynamic-features-runtime/build.gradle b/navigation/navigation-dynamic-features-runtime/build.gradle
index 58e3624..593f64a 100644
--- a/navigation/navigation-dynamic-features-runtime/build.gradle
+++ b/navigation/navigation-dynamic-features-runtime/build.gradle
@@ -28,7 +28,7 @@
dependencies {
api(project(":navigation:navigation-runtime-ktx"))
- api("com.google.android.play:core:1.6.4")
+ api("com.google.android.play:core:1.6.5")
api(KOTLIN_STDLIB)
testImplementation(ANDROIDX_TEST_CORE)
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt
index c949aa0..1e5a09d 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicExtras.kt
@@ -21,56 +21,16 @@
/**
* Extras for dynamic navigators.
*
- * You can set a [DynamicInstallMonitor] here to be notified of install state changes.
+ * You can set a [DynamicInstallMonitor] here to be notified of install state changes as well as any
+ * [Navigator.Extras].
*/
-class DynamicExtras internal constructor(
+class DynamicExtras @JvmOverloads constructor(
/**
* @return The [DynamicInstallMonitor] used.
*/
- val installMonitor: DynamicInstallMonitor?,
+ val installMonitor: DynamicInstallMonitor? = null,
/**
* @return [Navigator.Extras] associated with these [DynamicExtras].
*/
- val destinationExtras: Navigator.Extras?
-) : Navigator.Extras {
-
- /**
- * Builder that enables creation of [DynamicExtras].
- */
- class Builder {
-
- private var monitor: DynamicInstallMonitor? = null
- private var destinationExtras: Navigator.Extras? = null
-
- /**
- * Set the [DynamicInstallMonitor].
- *
- * @param monitor The [DynamicInstallMonitor] to set.
- * @return This [Builder].
- */
- fun setInstallMonitor(monitor: DynamicInstallMonitor): Builder {
- this.monitor = monitor
- return this
- }
-
- /**
- * Set the [Navigator.Extras].
- *
- * @param destinationExtras The [Navigator.Extras] to set.
- * @return This [Builder].
- */
- fun setDestinationExtras(destinationExtras: Navigator.Extras): Builder {
- this.destinationExtras = destinationExtras
- return this
- }
-
- /**
- * Build [DynamicExtras].
- *
- * @return A new instance of [DynamicExtras] with all attributes set in the builder.
- */
- fun build(): DynamicExtras {
- return DynamicExtras(monitor, destinationExtras)
- }
- }
-}
+ val destinationExtras: Navigator.Extras? = null
+) : Navigator.Extras
diff --git a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt
index 9161689..7a9dc0e 100644
--- a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicExtrasTest.kt
@@ -33,17 +33,14 @@
fun build_withMonitorAndExtras() {
val monitor = DynamicInstallMonitor()
val navExtras = TestNavigatorExtras()
- val builder = DynamicExtras.Builder()
- .setInstallMonitor(monitor)
- .setDestinationExtras(navExtras)
- val extras = builder.build()
+ val extras = DynamicExtras(monitor, navExtras)
assertThat(extras.destinationExtras).isNotNull()
assertThat(extras.installMonitor).isNotNull()
}
@Test
fun build_withoutMonitorOrExtras() {
- val extras = DynamicExtras.Builder().build()
+ val extras = DynamicExtras()
assertThat(extras.destinationExtras).isNull()
assertThat(extras.installMonitor).isNull()
}
diff --git a/paging/common/api/3.0.0-alpha01.txt b/paging/common/api/3.0.0-alpha01.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/3.0.0-alpha01.txt
+++ b/paging/common/api/3.0.0-alpha01.txt
@@ -253,13 +253,14 @@
method public static <T> androidx.paging.PagingData<T> empty();
method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
- method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
field public static final androidx.paging.PagingData.Companion! Companion;
}
public static final class PagingData.Companion {
method public <T> androidx.paging.PagingData<T> empty();
+ method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
}
public final class PagingDataFlow {
@@ -267,6 +268,10 @@
method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
}
+ public final class PagingDataKt {
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
public abstract class PagingSource<Key, Value> {
ctor public PagingSource();
method public final boolean getInvalid();
diff --git a/paging/common/api/current.txt b/paging/common/api/current.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/current.txt
+++ b/paging/common/api/current.txt
@@ -253,13 +253,14 @@
method public static <T> androidx.paging.PagingData<T> empty();
method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
- method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
field public static final androidx.paging.PagingData.Companion! Companion;
}
public static final class PagingData.Companion {
method public <T> androidx.paging.PagingData<T> empty();
+ method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
}
public final class PagingDataFlow {
@@ -267,6 +268,10 @@
method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
}
+ public final class PagingDataKt {
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
public abstract class PagingSource<Key, Value> {
ctor public PagingSource();
method public final boolean getInvalid();
diff --git a/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt b/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
+++ b/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
@@ -253,13 +253,14 @@
method public static <T> androidx.paging.PagingData<T> empty();
method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
- method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
field public static final androidx.paging.PagingData.Companion! Companion;
}
public static final class PagingData.Companion {
method public <T> androidx.paging.PagingData<T> empty();
+ method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
}
public final class PagingDataFlow {
@@ -267,6 +268,10 @@
method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
}
+ public final class PagingDataKt {
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
public abstract class PagingSource<Key, Value> {
ctor public PagingSource();
method public final boolean getInvalid();
diff --git a/paging/common/api/public_plus_experimental_current.txt b/paging/common/api/public_plus_experimental_current.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/public_plus_experimental_current.txt
+++ b/paging/common/api/public_plus_experimental_current.txt
@@ -253,13 +253,14 @@
method public static <T> androidx.paging.PagingData<T> empty();
method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
- method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
field public static final androidx.paging.PagingData.Companion! Companion;
}
public static final class PagingData.Companion {
method public <T> androidx.paging.PagingData<T> empty();
+ method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
}
public final class PagingDataFlow {
@@ -267,6 +268,10 @@
method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
}
+ public final class PagingDataKt {
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
public abstract class PagingSource<Key, Value> {
ctor public PagingSource();
method public final boolean getInvalid();
diff --git a/paging/common/api/restricted_3.0.0-alpha01.txt b/paging/common/api/restricted_3.0.0-alpha01.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/restricted_3.0.0-alpha01.txt
+++ b/paging/common/api/restricted_3.0.0-alpha01.txt
@@ -253,13 +253,14 @@
method public static <T> androidx.paging.PagingData<T> empty();
method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
- method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
field public static final androidx.paging.PagingData.Companion! Companion;
}
public static final class PagingData.Companion {
method public <T> androidx.paging.PagingData<T> empty();
+ method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
}
public final class PagingDataFlow {
@@ -267,6 +268,10 @@
method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
}
+ public final class PagingDataKt {
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
public abstract class PagingSource<Key, Value> {
ctor public PagingSource();
method public final boolean getInvalid();
diff --git a/paging/common/api/restricted_current.txt b/paging/common/api/restricted_current.txt
index 2ab42bfb..9498cba 100644
--- a/paging/common/api/restricted_current.txt
+++ b/paging/common/api/restricted_current.txt
@@ -253,13 +253,14 @@
method public static <T> androidx.paging.PagingData<T> empty();
method public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
- method public <R extends T> androidx.paging.PagingData<T> insertSeparators(kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
field public static final androidx.paging.PagingData.Companion! Companion;
}
public static final class PagingData.Companion {
method public <T> androidx.paging.PagingData<T> empty();
+ method public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
}
public final class PagingDataFlow {
@@ -267,6 +268,10 @@
method public static <Key, Value> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> create(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
}
+ public final class PagingDataKt {
+ method public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
public abstract class PagingSource<Key, Value> {
ctor public PagingSource();
method public final boolean getInvalid();
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagingData.kt b/paging/common/src/main/kotlin/androidx/paging/PagingData.kt
index 50024228..73a92e4 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagingData.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagingData.kt
@@ -61,22 +61,6 @@
fun filter(predicate: (T) -> Boolean): PagingData<T> = transform { it.filter(predicate) }
/**
- * Returns a [PagingData] containing each original element, with an optional separator generated
- * by [generator], given the elements before and after (or null, in boundary conditions).
- *
- * Note that this transform is applied asynchronously, as pages are loaded. Potential
- * separators between pages are only computed once both pages are loaded.
- *
- * @sample androidx.paging.samples.insertSeparatorsSample
- */
- fun <R : T> insertSeparators(
- generator: (T?, T?) -> R?
- ) = PagingData(
- flow = flow.insertSeparators(generator),
- receiver = receiver
- )
-
- /**
* Returns a [PagingData] containing each original element, with the passed header [item] added
* to the start of the list.
*
@@ -128,11 +112,129 @@
@Suppress("UNCHECKED_CAST", "SyntheticAccessor")
@JvmStatic // Convenience for Java developers.
fun <T : Any> empty() = EMPTY as PagingData<T>
+
+ // NOTE: samples in the doc below are manually imported from Java code in the samples
+ // project, since Java cannot be linked with @sample.
+ // DO NOT CHANGE THE BELOW COMMENT WITHOUT MAKING THE CORRESPONDING CHANGE IN `samples/`
+ /**
+ * Returns a [PagingData] containing each original element, with an optional separator
+ * generated by [generator], given the elements before and after (or null, in boundary
+ * conditions).
+ *
+ * Note that this transform is applied asynchronously, as pages are loaded. Potential
+ * separators between pages are only computed once both pages are loaded.
+ *
+ * **Kotlin callers should instead use the extension function [insertSeparators]**
+ *
+ * ```
+ * /*
+ * * Create letter separators in an alphabetically sorted list.
+ * *
+ * * For example, if the input is:
+ * * "apple", "apricot", "banana", "carrot"
+ * *
+ * * The operator would output:
+ * * "A", "apple", "apricot", "B", "banana", "C", "carrot"
+ * */
+ * pagingData = PagingData.insertSeparators(pagingData,
+ * (@Nullable String before, @Nullable String after) -> {
+ * if (after != null && (before == null
+ * || before.charAt(0) != after.charAt(0))) {
+ * // separator - after is first item that starts with its first letter
+ * return Character.toString(Character.toUpperCase(after.charAt(0)));
+ * } else {
+ * // no separator - either end of list, or first letters of before/after
+ * // are the same
+ * return null;
+ * }
+ * });
+ *
+ * /*
+ * * Create letter separators in an alphabetically sorted list of Items, with UiModel objects.
+ * *
+ * * For example, if the input is (each an `Item`):
+ * * "apple", "apricot", "banana", "carrot"
+ * *
+ * * The operator would output a list of UiModels corresponding to:
+ * * "A", "apple", "apricot", "B", "banana", "C", "carrot"
+ * */
+ * // first convert items in stream to UiModel.Item
+ * PagingData<UiModel.ItemModel> itemModelPagingData =
+ * itemPagingData.map(UiModel.ItemModel::new);
+ *
+ * // Now insert UiModel.Separators, which makes the PagingData of generic type UiModel
+ * PagingData<UiModel> pagingDataWithSeparators = PagingData.insertSeparators(
+ * itemModelPagingData,
+ * (@Nullable UiModel.ItemModel before, @Nullable UiModel.ItemModel after) -> {
+ * if (after != null
+ * && (before == null
+ * || before.item.label.charAt(0) != after.item.label.charAt(0))) {
+ * // separator - after is first item that starts with its first letter
+ * return new UiModel.SeparatorModel(
+ * Character.toUpperCase(after.item.label.charAt(0)));
+ * } else {
+ * // no separator - either end of list, or first letters of items are the same
+ * return null;
+ * }
+ * });
+ *
+ *
+ * public class UiModel {
+ * static class ItemModel extends UiModel {
+ * public Item item;
+ * ItemModel(Item item) {
+ * this.item = item;
+ * }
+ * }
+ * static class SeparatorModel extends UiModel {
+ * public char character;
+ * SeparatorModel(char character) {
+ * this.character = character;
+ * }
+ * }
+ * }
+ */
+ @JvmStatic
+ fun <T : R, R : Any> insertSeparators(
+ pagingData: PagingData<T>,
+ generator: (T?, T?) -> R?
+ ): PagingData<R> {
+ return pagingData.insertSeparators(generator)
+ }
}
}
+/**
+ * Returns a [PagingData] containing each original element, with an optional separator
+ * generated by [generator], given the elements before and after (or null, in boundary
+ * conditions).
+ *
+ * Note that this transform is applied asynchronously, as pages are loaded. Potential
+ * separators between pages are only computed once both pages are loaded.
+ *
+ * **Java callers should instead use the static function [PagingData.insertSeparators]**
+ *
+ * @sample androidx.paging.samples.insertSeparatorsSample
+ * @sample androidx.paging.samples.insertSeparatorsUiModelSample
+ */
+fun <T : R, R : Any> PagingData<T>.insertSeparators(
+ generator: (T?, T?) -> R?
+): PagingData<R> {
+ // This function must be an extension method, as it indirectly imposes a constraint on
+ // the type of T (because T extends R). Ideally it would be declared not be an
+ // extension, to make this method discoverable for Java callers, but we need to support
+ // the common UI model pattern for separators:
+ // class UiModel
+ // class ItemModel: UiModel
+ // class SeparatorModel: UiModel
+ return PagingData(
+ flow = flow.insertSeparators(generator),
+ receiver = receiver
+ )
+}
+
internal interface UiReceiver {
fun addHint(hint: ViewportHint)
fun retry()
fun refresh()
-}
\ No newline at end of file
+}
diff --git a/paging/common/src/main/kotlin/androidx/paging/Separators.kt b/paging/common/src/main/kotlin/androidx/paging/Separators.kt
index 2c6a803..bb645a4 100644
--- a/paging/common/src/main/kotlin/androidx/paging/Separators.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/Separators.kt
@@ -359,7 +359,7 @@
}
}
-internal fun <R : Any, T : R> Flow<PageEvent<T>>.insertSeparators(
+internal fun <T : R, R : Any> Flow<PageEvent<T>>.insertSeparators(
generator: (T?, T?) -> R?
): Flow<PageEvent<R>> {
val separatorState = SeparatorState(generator)
diff --git a/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt b/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
index 41fb019..04fb0ed 100644
--- a/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/SeparatorsTest.kt
@@ -596,6 +596,43 @@
)
}
+ @Test
+ fun types() = runBlockingTest {
+ open class Base
+ data class PrimaryType(val string: String) : Base()
+ data class SeparatorType(val string: String) : Base()
+
+ assertInsertData(
+ listOf(
+ Refresh(
+ pages = listOf(
+ listOf(
+ PrimaryType("a1"),
+ SeparatorType("B"),
+ PrimaryType("b1")
+ )
+ ).toTransformablePages(),
+ placeholdersStart = 0,
+ placeholdersEnd = 1,
+ loadStates = mapOf(REFRESH to Idle, START to Idle, END to Idle)
+ )
+ ),
+ flowOf(
+ Refresh(
+ pages = listOf(listOf(PrimaryType("a1"), PrimaryType("b1")))
+ .toTransformablePages(),
+ placeholdersStart = 0,
+ placeholdersEnd = 1,
+ loadStates = mapOf(REFRESH to Idle, START to Idle, END to Idle)
+ )
+ ).insertSeparators<PrimaryType, Base> { before, after ->
+ return@insertSeparators (if (before != null && after != null) {
+ SeparatorType("B")
+ } else null)
+ }.toList()
+ )
+ }
+
companion object {
/**
* Creates an upper-case letter at the beginning of each section of strings that start
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt
index dd1cffb..0954001 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/V3ViewModel.kt
@@ -22,6 +22,7 @@
import androidx.paging.PagingConfig
import androidx.paging.PagingDataFlow
import androidx.paging.cachedIn
+import androidx.paging.insertSeparators
import kotlinx.coroutines.flow.map
class V3ViewModel : ViewModel() {
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
index c6ba658..3f3ec1b 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RoomViewModel.kt
@@ -24,6 +24,7 @@
import androidx.paging.PagingConfig
import androidx.paging.PagingDataFlow
import androidx.paging.cachedIn
+import androidx.paging.insertSeparators
import androidx.paging.integration.testapp.room.Customer
import androidx.paging.integration.testapp.room.SampleDatabase
import androidx.room.Room
diff --git a/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt b/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt
index 27fdbf6..9ffd45a 100644
--- a/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt
+++ b/paging/samples/src/main/java/androidx/paging/samples/CachedInSample.kt
@@ -18,6 +18,7 @@
package androidx.paging.samples
+import android.annotation.SuppressLint
import android.os.Bundle
import androidx.activity.viewModels
import androidx.annotation.Sampled
@@ -34,13 +35,14 @@
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
-internal class UiModel(@Suppress("UNUSED_PARAMETER") string: String)
-internal class MyPagingAdapter : BasePagingAdapter<UiModel>()
-internal class MyViewModel : BaseViewModel<UiModel>()
-lateinit var pagingSourceFactory: () -> PagingSource<String, String>
+private class UiModel(@Suppress("UNUSED_PARAMETER") string: String)
+private class MyPagingAdapter : BasePagingAdapter<UiModel>()
+private class MyViewModel : BaseViewModel<UiModel>()
+private lateinit var pagingSourceFactory: () -> PagingSource<String, String>
@ExperimentalCoroutinesApi
@Sampled
+@SuppressLint("SyntheticAccessor")
fun cachedInSample() {
class MyViewModel : ViewModel() {
val flow = PagingDataFlow(PagingConfig(pageSize = 40), pagingSourceFactory)
diff --git a/paging/samples/src/main/java/androidx/paging/samples/PagingDataSample.kt b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
similarity index 94%
rename from paging/samples/src/main/java/androidx/paging/samples/PagingDataSample.kt
rename to paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
index 061284d..8016bc3 100644
--- a/paging/samples/src/main/java/androidx/paging/samples/PagingDataSample.kt
+++ b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsSample.kt
@@ -20,8 +20,9 @@
import androidx.annotation.Sampled
import androidx.paging.PagingData
+import androidx.paging.insertSeparators
-lateinit var pagingData: PagingData<String>
+private lateinit var pagingData: PagingData<String>
@Sampled
fun insertSeparatorsSample() {
diff --git a/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt
new file mode 100644
index 0000000..5a85638
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/InsertSeparatorsUiModelSample.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 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.
+ */
+
+@file:Suppress("unused") // Currently, all samples incorrectly labeled as unused.
+
+package androidx.paging.samples
+
+import androidx.annotation.Sampled
+import androidx.paging.PagingData
+import androidx.paging.insertSeparators
+
+class Item(
+ @JvmField
+ val label: String
+)
+
+private lateinit var pagingData: PagingData<Item>
+
+@Sampled
+fun insertSeparatorsUiModelSample() {
+ open class UiModel
+ data class ItemUiModel(val item: Item) : UiModel()
+ data class SeparatorUiModel(val char: Char) : UiModel()
+
+ /*
+ * Create letter separators in an alphabetically sorted list of Items, with UiModel objects.
+ *
+ * For example, if the input is (each an `Item`):
+ * "apple", "apricot", "banana", "carrot"
+ *
+ * The operator would output a list of UiModels corresponding to:
+ * "A", "apple", "apricot", "B", "banana", "C", "carrot"
+ */
+ pagingData
+ .map { item ->
+ ItemUiModel(item) // convert items in stream to ItemUiModel
+ }
+ .insertSeparators<ItemUiModel, UiModel> { before: ItemUiModel?, after: ItemUiModel? ->
+ if (after != null && before?.item?.label?.first() != after.item.label.first()) {
+ // separator - after is first item that starts with its first letter
+ SeparatorUiModel(after.item.label.first().toUpperCase())
+ } else {
+ // no separator - either end of list, or first letters of before/after are the same
+ null
+ }
+ }
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaSample.java b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaSample.java
new file mode 100644
index 0000000..7e5d9f8
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaSample.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2020 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.paging.samples.java;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.paging.PagingData;
+
+/**
+ * NOTE - MANUALLY COPIED SAMPLE
+ *
+ * Since @sample from kdoc doesn't support Java, this code must manually kept in sync with
+ * the @JvmStatic `PagingData.insertSeparators` method
+ */
+@SuppressWarnings({"unused", "WeakerAccess"})
+class InsertSeparatorsJavaSample {
+ @NonNull
+ public PagingData<String> pagingData = PagingData.empty();
+
+ @SuppressWarnings("unused")
+ public void insertSeparatorsSample() {
+ /*
+ * Create letter separators in an alphabetically sorted list.
+ *
+ * For example, if the input is:
+ * "apple", "apricot", "banana", "carrot"
+ *
+ * The operator would output:
+ * "A", "apple", "apricot", "B", "banana", "C", "carrot"
+ */
+ pagingData = PagingData.insertSeparators(pagingData,
+ (@Nullable String before, @Nullable String after) -> {
+ if (after != null && (before == null
+ || before.charAt(0) != after.charAt(0))) {
+ // separator - after is first item that starts with its first letter
+ return Character.toString(Character.toUpperCase(after.charAt(0)));
+ } else {
+ // no separator - either end of list, or first letters of before/after
+ // are the same
+ return null;
+ }
+ });
+ }
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaUiModelSample.java b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaUiModelSample.java
new file mode 100644
index 0000000..54a9c14
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/InsertSeparatorsJavaUiModelSample.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 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.paging.samples.java;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.paging.PagingData;
+
+/**
+ * NOTE - MANUALLY COPIED SAMPLE
+ *
+ * Since @sample from kdoc doesn't support Java, this code must manually kept in sync with
+ * the @JvmStatic `PagingData.insertSeparators` method
+ */
+@SuppressWarnings({"unused", "WeakerAccess"})
+class InsertSeparatorsJavaUiModelSample {
+ @NonNull
+ public PagingData<Item> itemPagingData = PagingData.empty();
+
+ @SuppressWarnings("unused")
+ public void insertSeparatorsSample() {
+ /*
+ * Create letter separators in an alphabetically sorted list of Items, with UiModel objects.
+ *
+ * For example, if the input is (each an `Item`):
+ * "apple", "apricot", "banana", "carrot"
+ *
+ * The operator would output a list of UiModels corresponding to:
+ * "A", "apple", "apricot", "B", "banana", "C", "carrot"
+ */
+ // first convert items in stream to UiModel.Item
+ PagingData<UiModel.ItemModel> itemModelPagingData =
+ itemPagingData.map(UiModel.ItemModel::new);
+
+ // Now insert UiModel.Separators, which makes the PagingData of generic type UiModel
+ PagingData<UiModel> pagingDataWithSeparators = PagingData.insertSeparators(
+ itemModelPagingData,
+ (@Nullable UiModel.ItemModel before, @Nullable UiModel.ItemModel after) -> {
+ if (after != null
+ && (before == null
+ || before.item.label.charAt(0) != after.item.label.charAt(0))) {
+ // separator - after is first item that starts with its first letter
+ return new UiModel.SeparatorModel(
+ Character.toUpperCase(after.item.label.charAt(0)));
+ } else {
+ // no separator - either end of list, or first letters of items are the same
+ return null;
+ }
+ });
+ }
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/Item.java b/paging/samples/src/main/java/androidx/paging/samples/java/Item.java
new file mode 100644
index 0000000..44b9485
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/Item.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020 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.paging.samples.java;
+
+class Item {
+ @SuppressWarnings("WeakerAccess")
+ public String label;
+}
diff --git a/paging/samples/src/main/java/androidx/paging/samples/java/UiModel.java b/paging/samples/src/main/java/androidx/paging/samples/java/UiModel.java
new file mode 100644
index 0000000..2562c72
--- /dev/null
+++ b/paging/samples/src/main/java/androidx/paging/samples/java/UiModel.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 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.paging.samples.java;
+
+/**
+ * NOTE - MANUALLY COPIED SAMPLE
+ *
+ * Since @sample from kdoc doesn't support Java, this code must manually kept in sync with
+ * the @JvmStatic `PagingData.insertSeparators` method
+ */
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class UiModel {
+ public UiModel() {}
+
+ static class ItemModel extends UiModel {
+ public Item item;
+
+ ItemModel(Item item) {
+ this.item = item;
+ }
+ }
+
+ static class SeparatorModel extends UiModel {
+ public char character;
+ SeparatorModel(char character) {
+ this.character = character;
+ }
+ }
+}
diff --git a/recyclerview/recyclerview/build.gradle b/recyclerview/recyclerview/build.gradle
index 5ae4a86..3c03669 100644
--- a/recyclerview/recyclerview/build.gradle
+++ b/recyclerview/recyclerview/build.gradle
@@ -31,6 +31,7 @@
testImplementation(JUNIT)
testImplementation(MOCKITO_CORE)
+ testImplementation(KOTLIN_STDLIB)
lintPublish(project(':recyclerview:recyclerview-lint'))
}
diff --git a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.java b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.java
deleted file mode 100644
index 2262294..0000000
--- a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.java
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * Copyright 2018 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.recyclerview.widget;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.fail;
-
-import androidx.annotation.Nullable;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-
-@RunWith(JUnit4.class)
-public class DiffUtilTest {
- private static Random sRand = new Random(System.nanoTime());
- private List<Item> mBefore = new ArrayList<>();
- private List<Item> mAfter = new ArrayList<>();
- private StringBuilder mLog = new StringBuilder();
-
- private DiffUtil.Callback mCallback = new DiffUtil.Callback() {
- @Override
- public int getOldListSize() {
- return mBefore.size();
- }
-
- @Override
- public int getNewListSize() {
- return mAfter.size();
- }
-
- @Override
- public boolean areItemsTheSame(int oldItemIndex, int newItemIndex) {
- return mBefore.get(oldItemIndex).id == mAfter.get(newItemIndex).id;
- }
-
- @Override
- public boolean areContentsTheSame(int oldItemIndex, int newItemIndex) {
- assertThat(mBefore.get(oldItemIndex).id,
- CoreMatchers.equalTo(mAfter.get(newItemIndex).id));
- return mBefore.get(oldItemIndex).data.equals(mAfter.get(newItemIndex).data);
- }
-
- @Nullable
- @Override
- public Object getChangePayload(int oldItemIndex, int newItemIndex) {
- assertThat(mBefore.get(oldItemIndex).id,
- CoreMatchers.equalTo(mAfter.get(newItemIndex).id));
- assertThat(mBefore.get(oldItemIndex).data,
- not(CoreMatchers.equalTo(mAfter.get(newItemIndex).data)));
- return mAfter.get(newItemIndex).payload;
- }
- };
-
- @Rule
- public TestWatcher mLogOnExceptionWatcher = new TestWatcher() {
- @Override
- protected void failed(Throwable e, Description description) {
- System.err.println(mLog.toString());
- }
- };
-
-
- @Test
- public void testNoChange() {
- initWithSize(5);
- check();
- }
-
- @Test
- public void testAddItems() {
- initWithSize(2);
- add(1);
- check();
- }
-
- //@Test
- //@LargeTest
- // Used for development
- public void testRandom() {
- for (int x = 0; x < 100; x++) {
- for (int i = 0; i < 100; i++) {
- for (int j = 2; j < 40; j++) {
- testRandom(i, j);
- }
- }
- }
- }
-
- @Test
- public void testGen2() {
- initWithSize(5);
- add(5);
- delete(3);
- delete(1);
- check();
- }
-
- @Test
- public void testGen3() {
- initWithSize(5);
- add(0);
- delete(1);
- delete(3);
- check();
- }
-
- @Test
- public void testGen4() {
- initWithSize(5);
- add(5);
- add(1);
- add(4);
- add(4);
- check();
- }
-
- @Test
- public void testGen5() {
- initWithSize(5);
- delete(0);
- delete(2);
- add(0);
- add(2);
- check();
- }
-
- @Test
- public void testGen6() {
- initWithSize(2);
- delete(0);
- delete(0);
- check();
- }
-
- @Test
- public void testGen7() {
- initWithSize(3);
- move(2, 0);
- delete(2);
- add(2);
- check();
- }
-
- @Test
- public void testGen8() {
- initWithSize(3);
- delete(1);
- add(0);
- move(2, 0);
- check();
- }
-
- @Test
- public void testGen9() {
- initWithSize(2);
- add(2);
- move(0, 2);
- check();
- }
-
- @Test
- public void testGen10() {
- initWithSize(3);
- move(0, 1);
- move(1, 2);
- add(0);
- check();
- }
-
- @Test
- public void testGen11() {
- initWithSize(4);
- move(2, 0);
- move(2, 3);
- check();
- }
-
- @Test
- public void testGen12() {
- initWithSize(4);
- move(3, 0);
- move(2, 1);
- check();
- }
-
- @Test
- public void testGen13() {
- initWithSize(4);
- move(3, 2);
- move(0, 3);
- check();
- }
-
- @Test
- public void testGen14() {
- initWithSize(4);
- move(3, 2);
- add(4);
- move(0, 4);
- check();
- }
-
- @Test
- public void testAdd1() {
- initWithSize(1);
- add(1);
- check();
- }
-
- @Test
- public void testMove1() {
- initWithSize(3);
- move(0, 2);
- check();
- }
-
- @Test
- public void tmp() {
- initWithSize(4);
- move(0, 2);
- check();
- }
-
- @Test
- public void testUpdate1() {
- initWithSize(3);
- update(2);
- check();
- }
-
- @Test
- public void testUpdate2() {
- initWithSize(2);
- add(1);
- update(1);
- update(2);
- check();
- }
-
- @Test
- public void testDisableMoveDetection() {
- initWithSize(5);
- move(0, 4);
- List<Item> applied = applyUpdates(mBefore, DiffUtil.calculateDiff(mCallback, false));
- assertThat(applied.size(), is(5));
- assertThat(applied.get(4).newItem, is(true));
- assertThat(applied.contains(mBefore.get(0)), is(false));
- }
-
- @Test(expected = IndexOutOfBoundsException.class)
- public void convertOldPositionToNew_tooSmall() {
- initWithSize(2);
- update(2);
- DiffUtil.calculateDiff(mCallback).convertOldPositionToNew(-1);
- }
-
- @Test(expected = IndexOutOfBoundsException.class)
- public void convertOldPositionToNew_tooLarge() {
- initWithSize(2);
- update(2);
- DiffUtil.calculateDiff(mCallback).convertOldPositionToNew(2);
- }
-
- @Test(expected = IndexOutOfBoundsException.class)
- public void convertNewPositionToOld_tooSmall() {
- initWithSize(2);
- update(2);
- DiffUtil.calculateDiff(mCallback).convertNewPositionToOld(-1);
- }
-
- @Test(expected = IndexOutOfBoundsException.class)
- public void convertNewPositionToOld_tooLarge() {
- initWithSize(2);
- update(2);
- DiffUtil.calculateDiff(mCallback).convertNewPositionToOld(2);
- }
-
- private void testRandom(int initialSize, int operationCount) {
- mLog.setLength(0);
- initWithSize(initialSize);
- for (int i = 0; i < operationCount; i++) {
- int op = sRand.nextInt(5);
- switch (op) {
- case 0:
- add(sRand.nextInt(mAfter.size() + 1));
- break;
- case 1:
- if (!mAfter.isEmpty()) {
- delete(sRand.nextInt(mAfter.size()));
- }
- break;
- case 2:
- // move
- if (mAfter.size() > 0) {
- move(sRand.nextInt(mAfter.size()), sRand.nextInt(mAfter.size()));
- }
- break;
- case 3:
- // update
- if (mAfter.size() > 0) {
- update(sRand.nextInt(mAfter.size()));
- }
- break;
- case 4:
- // update with payload
- if (mAfter.size() > 0) {
- updateWithPayload(sRand.nextInt(mAfter.size()));
- }
- break;
- }
- }
- check();
- }
-
- private void check() {
- DiffUtil.DiffResult result = DiffUtil.calculateDiff(mCallback);
- log("before", mBefore);
- log("after", mAfter);
- log("snakes", result.getSnakes());
-
- // test diff dispatch
- List<Item> applied = applyUpdates(mBefore, result);
- assertEquals(applied, mAfter);
-
- // test position conversion
- for (int oldPos = 0; oldPos < mBefore.size(); oldPos++) {
- int newPos = result.convertOldPositionToNew(oldPos);
- if (newPos != DiffUtil.DiffResult.NO_POSITION) {
- Assert.assertEquals(mBefore.get(oldPos).id, mAfter.get(newPos).id);
- } else {
- assertFalse(mAfter.contains(mBefore.get(oldPos)));
- }
- }
-
- try {
- result.convertOldPositionToNew(mBefore.size());
- fail("out of bounds should occur");
- } catch (IndexOutOfBoundsException e) {
- // expected
- }
- for (int newPos = 0; newPos < mAfter.size(); newPos++) {
- int oldPos = result.convertNewPositionToOld(newPos);
- if (oldPos != DiffUtil.DiffResult.NO_POSITION) {
- Assert.assertEquals(mAfter.get(newPos).id, mBefore.get(oldPos).id);
- } else {
- assertFalse(mBefore.contains(mAfter.get(newPos)));
- }
- }
- try {
- result.convertNewPositionToOld(mAfter.size());
- fail("out of bounds should occur");
- } catch (IndexOutOfBoundsException e) {
- // expected
- }
- }
-
- private void initWithSize(int size) {
- mBefore.clear();
- mAfter.clear();
- for (int i = 0; i < size; i++) {
- mBefore.add(new Item(false));
- }
- mAfter.addAll(mBefore);
- mLog.append("initWithSize(" + size + ");\n");
- }
-
- private void log(String title, List<?> items) {
- mLog.append(title).append(":").append(items.size()).append("\n");
- for (Object item : items) {
- mLog.append(" ").append(item).append("\n");
- }
- }
-
- private void assertEquals(List<Item> applied, List<Item> after) {
- log("applied", applied);
-
- String report = mLog.toString();
- assertThat(report, applied.size(), is(after.size()));
- for (int i = 0; i < after.size(); i++) {
- Item item = applied.get(i);
- if (after.get(i).newItem) {
- assertThat(report, item.newItem, is(true));
- } else if (after.get(i).changed) {
- assertThat(report, item.newItem, is(false));
- assertThat(report, item.changed, is(true));
- assertThat(report, item.id, is(after.get(i).id));
- assertThat(report, item.payload, is(after.get(i).payload));
- } else {
- assertThat(report, item, equalTo(after.get(i)));
- }
- }
- }
-
- private List<Item> applyUpdates(List<Item> before, DiffUtil.DiffResult result) {
- final List<Item> target = new ArrayList<>();
- target.addAll(before);
- result.dispatchUpdatesTo(new ListUpdateCallback() {
- @Override
- public void onInserted(int position, int count) {
- for (int i = 0; i < count; i++) {
- target.add(i + position, new Item(true));
- }
- }
-
- @Override
- public void onRemoved(int position, int count) {
- for (int i = 0; i < count; i++) {
- target.remove(position);
- }
- }
-
- @Override
- public void onMoved(int fromPosition, int toPosition) {
- Item item = target.remove(fromPosition);
- target.add(toPosition, item);
- }
-
- @Override
- public void onChanged(int position, int count, Object payload) {
- for (int i = 0; i < count; i++) {
- int positionInList = position + i;
- Item existing = target.get(positionInList);
- // make sure we don't update same item twice in callbacks
- assertThat(existing.changed, is(false));
- assertThat(existing.newItem, is(false));
- assertThat(existing.payload, is(nullValue()));
- Item replica = new Item(existing);
- replica.payload = (String) payload;
- replica.changed = true;
- target.remove(positionInList);
- target.add(positionInList, replica);
- }
- }
- });
- return target;
- }
-
- private void add(int index) {
- mAfter.add(index, new Item(true));
- mLog.append("add(").append(index).append(");\n");
- }
-
- private void delete(int index) {
- mAfter.remove(index);
- mLog.append("delete(").append(index).append(");\n");
- }
-
- private void update(int index) {
- Item existing = mAfter.get(index);
- if (existing.newItem) {
- return;//new item cannot be changed
- }
- Item replica = new Item(existing);
- replica.changed = true;
- // clean the payload since this might be after an updateWithPayload call
- replica.payload = null;
- replica.data = UUID.randomUUID().toString();
- mAfter.remove(index);
- mAfter.add(index, replica);
- mLog.append("update(").append(index).append(");\n");
- }
-
- private void updateWithPayload(int index) {
- Item existing = mAfter.get(index);
- if (existing.newItem) {
- return;//new item cannot be changed
- }
- Item replica = new Item(existing);
- replica.changed = true;
- replica.data = UUID.randomUUID().toString();
- replica.payload = UUID.randomUUID().toString();
- mAfter.remove(index);
- mAfter.add(index, replica);
- mLog.append("update(").append(index).append(");\n");
- }
-
- private void move(int from, int to) {
- Item removed = mAfter.remove(from);
- mAfter.add(to, removed);
- mLog.append("move(").append(from).append(",").append(to).append(");\n");
- }
-
- static class Item {
- static long idCounter = 0;
- final long id;
- final boolean newItem;
- boolean changed = false;
- String payload;
-
- String data = UUID.randomUUID().toString();
-
- public Item(boolean newItem) {
- id = idCounter++;
- this.newItem = newItem;
- }
-
- public Item(Item other) {
- id = other.id;
- newItem = other.newItem;
- changed = other.changed;
- payload = other.payload;
- data = other.data;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Item item = (Item) o;
-
- if (id != item.id) return false;
- if (newItem != item.newItem) return false;
- if (changed != item.changed) return false;
- if (payload != null ? !payload.equals(item.payload) : item.payload != null) {
- return false;
- }
- return data.equals(item.data);
-
- }
-
- @Override
- public int hashCode() {
- int result = (int) (id ^ (id >>> 32));
- result = 31 * result + (newItem ? 1 : 0);
- result = 31 * result + (changed ? 1 : 0);
- result = 31 * result + (payload != null ? payload.hashCode() : 0);
- result = 31 * result + data.hashCode();
- return result;
- }
-
- @Override
- public String toString() {
- return "Item{" +
- "id=" + id +
- ", newItem=" + newItem +
- ", changed=" + changed +
- ", payload='" + payload + '\'' +
- ", data='" + data + '\'' +
- '}';
- }
- }
-}
diff --git a/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt
new file mode 100644
index 0000000..dea8900
--- /dev/null
+++ b/recyclerview/recyclerview/src/test/java/androidx/recyclerview/widget/DiffUtilTest.kt
@@ -0,0 +1,589 @@
+/*
+ * Copyright 2018 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.recyclerview.widget
+
+import org.hamcrest.CoreMatchers.`is`
+import org.hamcrest.CoreMatchers.equalTo
+import org.hamcrest.CoreMatchers.not
+import org.hamcrest.CoreMatchers.nullValue
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.Assert
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import java.util.Random
+import java.util.UUID
+
+@RunWith(JUnit4::class)
+class DiffUtilTest {
+ private val before = mutableListOf<Item>()
+ private val after = mutableListOf<Item>()
+ private val log = StringBuilder()
+ private val callback: DiffUtil.Callback =
+ object : DiffUtil.Callback() {
+ override fun getOldListSize() = before.size
+
+ override fun getNewListSize() = after.size
+
+ override fun areItemsTheSame(
+ oldItemIndex: Int,
+ newItemIndex: Int
+ ): Boolean {
+ return before[oldItemIndex].id == after[newItemIndex].id
+ }
+
+ override fun areContentsTheSame(
+ oldItemIndex: Int,
+ newItemIndex: Int
+ ): Boolean {
+ assertThat(
+ before[oldItemIndex].id,
+ equalTo(after[newItemIndex].id)
+ )
+ return before[oldItemIndex].data == after[newItemIndex].data
+ }
+
+ override fun getChangePayload(
+ oldItemIndex: Int,
+ newItemIndex: Int
+ ): Any? {
+ assertThat(
+ before[oldItemIndex].id,
+ equalTo(after[newItemIndex].id)
+ )
+ assertThat(
+ before[oldItemIndex].data,
+ not(
+ equalTo(
+ after[newItemIndex].data
+ )
+ )
+ )
+ return after[newItemIndex].payload
+ }
+ }
+
+ @Rule
+ @JvmField
+ val logOnExceptionWatcher: TestWatcher =
+ object : TestWatcher() {
+ override fun failed(
+ e: Throwable,
+ description: Description
+ ) {
+ System.err.println(log.toString())
+ }
+ }
+
+ @Test
+ fun testNoChange() {
+ initWithSize(5)
+ check()
+ }
+
+ @Test
+ fun testAddItems() {
+ initWithSize(2)
+ add(1)
+ check()
+ }
+
+ // @Test
+ // @LargeTest
+ // Used for development
+ @Suppress("unused")
+ fun testRandom() {
+ for (x in 0..99) {
+ for (i in 0..99) {
+ for (j in 2..39) {
+ testRandom(i, j)
+ }
+ }
+ }
+ }
+
+ @Test
+ fun testGen2() {
+ initWithSize(5)
+ add(5)
+ delete(3)
+ delete(1)
+ check()
+ }
+
+ @Test
+ fun testGen3() {
+ initWithSize(5)
+ add(0)
+ delete(1)
+ delete(3)
+ check()
+ }
+
+ @Test
+ fun testGen4() {
+ initWithSize(5)
+ add(5)
+ add(1)
+ add(4)
+ add(4)
+ check()
+ }
+
+ @Test
+ fun testGen5() {
+ initWithSize(5)
+ delete(0)
+ delete(2)
+ add(0)
+ add(2)
+ check()
+ }
+
+ @Test
+ fun testGen6() {
+ initWithSize(2)
+ delete(0)
+ delete(0)
+ check()
+ }
+
+ @Test
+ fun testGen7() {
+ initWithSize(3)
+ move(2, 0)
+ delete(2)
+ add(2)
+ check()
+ }
+
+ @Test
+ fun testGen8() {
+ initWithSize(3)
+ delete(1)
+ add(0)
+ move(2, 0)
+ check()
+ }
+
+ @Test
+ fun testGen9() {
+ initWithSize(2)
+ add(2)
+ move(0, 2)
+ check()
+ }
+
+ @Test
+ fun testGen10() {
+ initWithSize(3)
+ move(0, 1)
+ move(1, 2)
+ add(0)
+ check()
+ }
+
+ @Test
+ fun testGen11() {
+ initWithSize(4)
+ move(2, 0)
+ move(2, 3)
+ check()
+ }
+
+ @Test
+ fun testGen12() {
+ initWithSize(4)
+ move(3, 0)
+ move(2, 1)
+ check()
+ }
+
+ @Test
+ fun testGen13() {
+ initWithSize(4)
+ move(3, 2)
+ move(0, 3)
+ check()
+ }
+
+ @Test
+ fun testGen14() {
+ initWithSize(4)
+ move(3, 2)
+ add(4)
+ move(0, 4)
+ check()
+ }
+
+ @Test
+ fun testAdd1() {
+ initWithSize(1)
+ add(1)
+ check()
+ }
+
+ @Test
+ fun testMove1() {
+ initWithSize(3)
+ move(0, 2)
+ check()
+ }
+
+ @Test
+ fun tmp() {
+ initWithSize(4)
+ move(0, 2)
+ check()
+ }
+
+ @Test
+ fun testUpdate1() {
+ initWithSize(3)
+ update(2)
+ check()
+ }
+
+ @Test
+ fun testUpdate2() {
+ initWithSize(2)
+ add(1)
+ update(1)
+ update(2)
+ check()
+ }
+
+ @Test
+ fun testDisableMoveDetection() {
+ initWithSize(5)
+ move(0, 4)
+ val applied = applyUpdates(
+ before,
+ DiffUtil.calculateDiff(callback, false)
+ )
+ assertThat(
+ applied.size,
+ `is`(5)
+ )
+ assertThat(
+ applied[4].newItem,
+ `is`(true)
+ )
+ assertThat(
+ applied.contains(before[0]),
+ `is`(false)
+ )
+ }
+
+ @Test(expected = IndexOutOfBoundsException::class)
+ fun convertOldPositionToNew_tooSmall() {
+ initWithSize(2)
+ update(2)
+ DiffUtil.calculateDiff(callback).convertOldPositionToNew(-1)
+ }
+
+ @Test(expected = IndexOutOfBoundsException::class)
+ fun convertOldPositionToNew_tooLarge() {
+ initWithSize(2)
+ update(2)
+ DiffUtil.calculateDiff(callback).convertOldPositionToNew(2)
+ }
+
+ @Test(expected = IndexOutOfBoundsException::class)
+ fun convertNewPositionToOld_tooSmall() {
+ initWithSize(2)
+ update(2)
+ DiffUtil.calculateDiff(callback).convertNewPositionToOld(-1)
+ }
+
+ @Test(expected = IndexOutOfBoundsException::class)
+ fun convertNewPositionToOld_tooLarge() {
+ initWithSize(2)
+ update(2)
+ DiffUtil.calculateDiff(callback).convertNewPositionToOld(2)
+ }
+
+ private fun testRandom(initialSize: Int, operationCount: Int) {
+ log.setLength(0)
+ initWithSize(initialSize)
+ for (i in 0 until operationCount) {
+ val op = sRand.nextInt(5)
+ when (op) {
+ 0 -> add(sRand.nextInt(after.size + 1))
+ 1 -> if (after.isNotEmpty()) {
+ delete(sRand.nextInt(after.size))
+ }
+ 2 -> // move
+ if (after.size > 0) {
+ move(
+ sRand.nextInt(after.size),
+ sRand.nextInt(after.size)
+ )
+ }
+ 3 -> // update
+ if (after.size > 0) {
+ update(sRand.nextInt(after.size))
+ }
+ 4 -> // update with payload
+ if (after.size > 0) {
+ updateWithPayload(sRand.nextInt(after.size))
+ }
+ }
+ }
+ check()
+ }
+
+ private fun check() {
+ val result =
+ DiffUtil.calculateDiff(callback)
+ log("before", before)
+ log("after", after)
+ log("snakes", result.snakes)
+ // test diff dispatch
+ val applied =
+ applyUpdates(before, result)
+ assertEquals(applied, after)
+ // test position conversion
+ before.indices.forEach { oldPos ->
+ val newPos = result.convertOldPositionToNew(oldPos)
+ if (newPos != DiffUtil.DiffResult.NO_POSITION) {
+ assertEquals(before[oldPos].id, after[newPos].id)
+ } else {
+ assertFalse(after.contains(before[oldPos]))
+ }
+ }
+
+ try {
+ result.convertOldPositionToNew(before.size)
+ Assert.fail("out of bounds should occur")
+ } catch (e: IndexOutOfBoundsException) { // expected
+ }
+ after.indices.forEach { newPos ->
+ val oldPos = result.convertNewPositionToOld(newPos)
+ if (oldPos != DiffUtil.DiffResult.NO_POSITION) {
+ assertEquals(after[newPos].id, before[oldPos].id)
+ } else {
+ assertFalse(before.contains(after[newPos]))
+ }
+ }
+
+ try {
+ result.convertNewPositionToOld(after.size)
+ Assert.fail("out of bounds should occur")
+ } catch (e: IndexOutOfBoundsException) { // expected
+ }
+ }
+
+ private fun initWithSize(size: Int) {
+ before.clear()
+ after.clear()
+ repeat(size) {
+ before.add(Item(false))
+ }
+ after.addAll(before)
+ log.append("initWithSize($size);\n")
+ }
+
+ private fun log(title: String, items: List<*>) {
+ log.append(title).append(":").append(items.size).append("\n")
+ items.forEach { item ->
+ log.append(" ").append(item).append("\n")
+ }
+ }
+
+ private fun assertEquals(
+ applied: List<Item>,
+ after: List<Item>
+ ) {
+ log("applied", applied)
+ val report = log.toString()
+ assertThat(
+ report,
+ applied.size,
+ `is`(after.size)
+ )
+ after.indices.forEach { index ->
+ val item = applied[index]
+ if (after[index].newItem) {
+ assertThat(
+ report,
+ item.newItem,
+ `is`(true)
+ )
+ } else if (after[index].changed) {
+ assertThat(
+ report,
+ item.newItem,
+ `is`(false)
+ )
+ assertThat(
+ report,
+ item.changed,
+ `is`(true)
+ )
+ assertThat(
+ report,
+ item.id,
+ `is`(after[index].id)
+ )
+ assertThat(
+ report,
+ item.payload,
+ `is`(after[index].payload)
+ )
+ } else {
+ assertThat(
+ report,
+ item,
+ equalTo(
+ after[index]
+ )
+ )
+ }
+ }
+ }
+
+ private fun applyUpdates(
+ before: List<Item>,
+ result: DiffUtil.DiffResult
+ ): List<Item> {
+ val target = mutableListOf<Item>()
+ target.addAll(before)
+ result.dispatchUpdatesTo(object : ListUpdateCallback {
+ override fun onInserted(position: Int, count: Int) {
+ repeat(count) {
+ target.add(it + position, Item(true))
+ }
+ }
+
+ override fun onRemoved(position: Int, count: Int) {
+ repeat(count) {
+ target.removeAt(position)
+ }
+ }
+
+ override fun onMoved(
+ fromPosition: Int,
+ toPosition: Int
+ ) {
+ val item = target.removeAt(fromPosition)
+ target.add(toPosition, item)
+ }
+
+ override fun onChanged(
+ position: Int,
+ count: Int,
+ payload: Any?
+ ) {
+ repeat(count) { offset ->
+ val positionInList = position + offset
+ val existing =
+ target[positionInList]
+ // make sure we don't update same item twice in callbacks
+ assertThat(
+ existing.changed,
+ `is`(false)
+ )
+ assertThat(
+ existing.newItem,
+ `is`(false)
+ )
+ assertThat(
+ existing.payload,
+ `is`(nullValue())
+ )
+ val replica = existing.copy(
+ changed = true
+ )
+ target.removeAt(positionInList)
+ target.add(positionInList, replica)
+ }
+ }
+ })
+ return target
+ }
+
+ private fun add(index: Int) {
+ after.add(index, Item(true))
+ log.append("add(").append(index).append(");\n")
+ }
+
+ private fun delete(index: Int) {
+ after.removeAt(index)
+ log.append("delete(").append(index).append(");\n")
+ }
+
+ private fun update(index: Int) {
+ val existing = after[index]
+ if (existing.newItem) {
+ return // new item cannot be changed
+ }
+ // clean the payload since this might be after an updateWithPayload call
+ val replica = existing.copy(
+ changed = true,
+ payload = null,
+ data = UUID.randomUUID().toString()
+ )
+ after.removeAt(index)
+ after.add(index, replica)
+ log.append("update(").append(index).append(");\n")
+ }
+
+ private fun updateWithPayload(index: Int) {
+ val existing = after[index]
+ if (existing.newItem) {
+ return // new item cannot be changed
+ }
+ val replica = existing.copy(
+ changed = true,
+ data = UUID.randomUUID().toString(),
+ payload = UUID.randomUUID().toString()
+ )
+ after.removeAt(index)
+ after.add(index, replica)
+ log.append("update(").append(index).append(");\n")
+ }
+
+ private fun move(from: Int, to: Int) {
+ val removed = after.removeAt(from)
+ after.add(to, removed)
+ log.append("move(").append(from).append(",").append(to).append(");\n")
+ }
+
+ internal data class Item(
+ val id: Long,
+ val newItem: Boolean,
+ var changed: Boolean = false,
+ var payload: String? = null,
+ var data: String = UUID.randomUUID().toString()
+ ) {
+
+ constructor(newItem: Boolean) : this(id = idCounter++, newItem = newItem)
+
+ companion object {
+ var idCounter: Long = 0
+ }
+ }
+
+ companion object {
+ private val sRand = Random(System.nanoTime())
+ }
+}
\ No newline at end of file
diff --git a/room/common/src/main/java/androidx/room/Query.java b/room/common/src/main/java/androidx/room/Query.java
index 298c7b6..68015fa 100644
--- a/room/common/src/main/java/androidx/room/Query.java
+++ b/room/common/src/main/java/androidx/room/Query.java
@@ -72,7 +72,28 @@
* UPDATE or DELETE queries can return {@code void} or {@code int}. If it is an {@code int},
* the value is the number of rows affected by this query.
* <p>
- * <b>RxJava2</b> If you are using RxJava2, you can also return {@code Flowable<T>} or
+ * <b>Flow</b>
+ * <p>
+ * If you are using Kotlin, you can also return {@code Flow<T>} from query methods. This creates a
+ * {@code Flow<T>} object that emits the results of the query and re-dispatches the query every
+ * time the data in the queried table changes.
+ * <p>
+ * Note that querying a table with a return type of {@code Flow<T>} always returns the first row
+ * in the result set, rather than emitting all of the rows in sequence. To observe changes over
+ * multiple rows in a table, use a return type of {@code Flow<List<T>>} instead.
+ * <p>
+ * Keep nullability in mind when choosing a return type, as it affects how the query method handles
+ * empty tables:
+ * <ul>
+ * <li> <p>When the return type is {@code Flow<T>}, querying an empty table throws a null pointer
+ * exception.
+ * <li> <p>When the return type is {@code Flow<T?>}, querying an empty table emits a null value.
+ * <li> <p>When the return type is {@code Flow<List<T>>}, querying an empty table emits an empty
+ * list. </ul>
+ * <p>
+ * <b>RxJava2</b>
+ * <p>
+ * If you are using RxJava2, you can also return {@code Flowable<T>} or
* {@code Publisher<T>} from query methods. Since Reactive Streams does not allow {@code null}, if
* the query returns a nullable type, it will not dispatch anything if the value is {@code null}
* (like fetching an {@link Entity} row that does not exist).
diff --git a/samples/SupportLeanbackDemos/lint-baseline.xml b/samples/SupportLeanbackDemos/lint-baseline.xml
index d91b2b8..13b4966 100644
--- a/samples/SupportLeanbackDemos/lint-baseline.xml
+++ b/samples/SupportLeanbackDemos/lint-baseline.xml
@@ -31,6 +31,28 @@
</issue>
<issue
+ id="MissingClass"
+ message="Class referenced in the layout file, `com.example.android.leanback.PlaybackOverlayFragment`, was not found in the project or the libraries"
+ errorLine1=" android:name="com.example.android.leanback.PlaybackOverlayFragment""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/layout/playback_controls.xml"
+ line="23"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="MissingClass"
+ message="Class referenced in the layout file, `com.example.android.leanback.PlaybackOverlaySupportFragment`, was not found in the project or the libraries"
+ errorLine1=" android:name="com.example.android.leanback.PlaybackOverlaySupportFragment""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/layout/playback_controls_support.xml"
+ line="25"
+ column="23"/>
+ </issue>
+
+ <issue
id="DefaultLocale"
message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
errorLine1=" b.append(String.format("%.2f", ((float) seconds + seconds2)));"
@@ -1219,6 +1241,94 @@
</issue>
<issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_SearchDetails` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.SearchDetails" parent="Theme.AppCompat.Leanback.Details.NoSharedElementTransition">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="23"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_Details` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.Details" parent="Theme.AppCompat.Leanback.Details">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="25"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_Details_CustomTitle` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.Details.CustomTitle">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="27"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_Rows` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.Rows" parent="Theme.AppCompat.Leanback">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="32"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_GuidedStep` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.GuidedStep" parent="Theme.AppCompat.Leanback.GuidedStep">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="36"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_GuidedStep_First` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.GuidedStep.First">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="39"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_GuidedStep_Half` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.GuidedStep.Half" parent="Theme.AppCompat.Leanback.GuidedStep.Half">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="42"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.Theme_Example_AppCompat_Leanback_Preferences` appears to be unused"
+ errorLine1=" <style name="Theme.Example.AppCompat.Leanback.Preferences">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/res/values/themes_appcompat.xml"
+ line="44"
+ column="12"/>
+ </issue>
+
+ <issue
id="UselessParent"
message="This `LinearLayout` layout or its `RelativeLayout` parent is useless"
errorLine1=" <LinearLayout"
diff --git a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt
index 69c295f..18000a4 100644
--- a/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt
+++ b/startup/startup-runtime-lint/src/main/java/androidx/startup/lint/ComponentInitializerConstructorDetector.kt
@@ -37,7 +37,7 @@
companion object {
private const val DESCRIPTION = "Missing ComponentInitializer no-arg constructor"
val ISSUE = Issue.create(
- id = "EnsureComponentInitializerNoArgConstructor",
+ id = "EnsureComponentInitializerNoArgConstr",
briefDescription = DESCRIPTION,
explanation = """
Every `ComponentInitializer` must have a no argument constructor.
diff --git a/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt b/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt
index 9a0eee4..6eef693 100644
--- a/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt
+++ b/startup/startup-runtime-lint/src/test/java/androidx/startup/lint/ComponentInitializerConstructorTest.kt
@@ -76,7 +76,7 @@
/* ktlint-disable max-line-length */
.expect(
"""
- src/com/example/TestComponentInitializer.kt:5: Error: Missing ComponentInitializer no-arg constructor [EnsureComponentInitializerNoArgConstructor]
+ src/com/example/TestComponentInitializer.kt:5: Error: Missing ComponentInitializer no-arg constructor [EnsureComponentInitializerNoArgConstr]
class TestComponentInitializer(val int: Int): ComponentInitializer<Unit> {
^
1 errors, 0 warnings
diff --git a/startup/startup-runtime/build.gradle b/startup/startup-runtime/build.gradle
index 6a4c794..45014d0 100644
--- a/startup/startup-runtime/build.gradle
+++ b/startup/startup-runtime/build.gradle
@@ -39,6 +39,7 @@
dependencies {
implementation("androidx.annotation:annotation:1.1.0")
+ implementation(project(':tracing:tracing-ktx'))
lintPublish(project(':startup:startup-runtime-lint'))
androidTestImplementation(KOTLIN_STDLIB)
androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
diff --git a/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java b/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java
index 1d925bd..bda6dcb 100644
--- a/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java
+++ b/startup/startup-runtime/src/main/java/androidx/startup/AppInitializer.java
@@ -24,6 +24,7 @@
import android.os.Bundle;
import androidx.annotation.NonNull;
+import androidx.tracing.Trace;
import java.util.HashMap;
import java.util.HashSet;
@@ -102,11 +103,11 @@
@NonNull Class<? extends ComponentInitializer<?>> component,
@NonNull Set<Class<?>> initializing) {
synchronized (sLock) {
- boolean isTracingEnabled = TraceCompat.isEnabled();
+ boolean isTracingEnabled = Trace.isEnabled();
try {
if (isTracingEnabled) {
// Use the simpleName here because section names would get too big otherwise.
- TraceCompat.beginSection(component.getSimpleName());
+ Trace.beginSection(component.getSimpleName());
}
if (initializing.contains(component)) {
String message = String.format(
@@ -147,7 +148,7 @@
}
return (T) result;
} finally {
- TraceCompat.endSection();
+ Trace.endSection();
}
}
}
@@ -155,7 +156,7 @@
@SuppressWarnings("unchecked")
void discoverAndInitialize() {
try {
- TraceCompat.beginSection(SECTION_NAME);
+ Trace.beginSection(SECTION_NAME);
ApplicationInfo applicationInfo =
mContext.getPackageManager()
.getApplicationInfo(mContext.getPackageName(), GET_META_DATA);
@@ -183,7 +184,7 @@
} catch (PackageManager.NameNotFoundException | ClassNotFoundException exception) {
throw new StartupException(exception);
} finally {
- TraceCompat.endSection();
+ Trace.endSection();
}
}
}
diff --git a/startup/startup-runtime/src/main/java/androidx/startup/TraceCompat.java b/startup/startup-runtime/src/main/java/androidx/startup/TraceCompat.java
deleted file mode 100644
index 16e896b..0000000
--- a/startup/startup-runtime/src/main/java/androidx/startup/TraceCompat.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2020 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.startup;
-
-import android.os.Build;
-import android.os.Trace;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-/**
- * Writes trace events to the system trace buffer. These trace events can be
- * collected and visualized using the Systrace tool.
- *
- * <p>This tracing mechanism is independent of the method tracing mechanism
- * offered by {@link android.os.Debug#startMethodTracing}. In particular, it enables
- * tracing of events that occur across multiple processes.
- * <p>For information about using the Systrace tool, read <a
- * href="{@docRoot}studio/profile/systrace/">Overview of system tracing</a>.
- */
-final class TraceCompat {
-
- private static final String TAG = "TraceCompat";
-
- private static long sTraceTagApp;
- private static Method sIsTagEnabledMethod;
-
- static {
- if (Build.VERSION.SDK_INT >= 18 && Build.VERSION.SDK_INT < 29) {
- try {
- Field traceTagAppField = Trace.class.getField("TRACE_TAG_APP");
- sTraceTagApp = traceTagAppField.getLong(null);
- sIsTagEnabledMethod = Trace.class.getMethod("isTagEnabled", long.class);
- } catch (Exception e) {
- Log.i(TAG, "Unable to initialize via reflection.", e);
- }
- }
- }
-
- /**
- * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate
- * string creation for trace sections that require formatting. It is not necessary
- * to guard all Trace method calls as they internally already check this. However it is
- * recommended to use this to prevent creating any temporary objects that would then be
- * passed to those methods to reduce runtime cost when tracing isn't enabled.
- *
- * @return true if tracing is currently enabled, false otherwise
- */
- public static boolean isEnabled() {
- if (Build.VERSION.SDK_INT >= 29) {
- return Trace.isEnabled();
- } else if (Build.VERSION.SDK_INT >= 18) {
- try {
- return (boolean) sIsTagEnabledMethod.invoke(null, sTraceTagApp);
- } catch (Exception e) {
- Log.v(TAG, "Unable to invoke isTagEnabled() via reflection.");
- }
- }
-
- // Never enabled on < API 18
- return false;
- }
-
- /**
- * Writes a trace message to indicate that a given section of code has begun. This call must
- * be followed by a corresponding call to {@link #endSection()} on the same thread.
- *
- * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
- * null character '\0' are used internally by the tracing mechanism. If sectionName contains
- * these characters they will be replaced with a space character in the trace.
- *
- * @param sectionName The name of the code section to appear in the trace. This may be at
- * most 127 Unicode code units long.
- */
- public static void beginSection(@NonNull String sectionName) {
- if (Build.VERSION.SDK_INT >= 18) {
- Trace.beginSection(sectionName);
- }
- }
-
- /**
- * Writes a trace message to indicate that a given section of code has ended. This call must
- * be preceded by a corresponding call to {@link #beginSection(String)}. Calling this method
- * will mark the end of the most recently begun section of code, so care must be taken to
- * ensure that beginSection / endSection pairs are properly nested and called from the same
- * thread.
- */
- public static void endSection() {
- if (Build.VERSION.SDK_INT >= 18) {
- Trace.endSection();
- }
- }
-
- private TraceCompat() {}
-}
diff --git a/tracing/tracing-ktx/src/main/AndroidManifest.xml b/tracing/tracing-ktx/src/main/AndroidManifest.xml
index 976de72..ede3fba 100644
--- a/tracing/tracing-ktx/src/main/AndroidManifest.xml
+++ b/tracing/tracing-ktx/src/main/AndroidManifest.xml
@@ -15,6 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.tracing">
+ package="androidx.tracing.ktx">
</manifest>
diff --git a/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java b/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java
index cbe3564..40ac8f1 100644
--- a/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java
+++ b/transition/transition/src/androidTest/java/androidx/transition/GhostViewTest.java
@@ -287,10 +287,20 @@
float offsetLargerThanSize = SIZE * 2;
Matrix matrix = new Matrix();
matrix.postTranslate(0f, offsetLargerThanSize);
- Matrix invertedMatrix = new Matrix();
- invertedMatrix.postTranslate(0f, -offsetLargerThanSize);
GhostViewUtils.addGhost(view, parent2, matrix);
- ViewUtils.setAnimationMatrix(view, invertedMatrix);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
+ && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ // this test uses setAnimationMatrix which applies the matrix for the
+ // RenderNode starting from 21 and RenderNode is only used with the
+ // hardware acceleration. and the logic we use in drawBitmap() is drawing
+ // without the hardware acceleration for the API before 26. so instead of
+ // setAnimationMatrix we will just use TranslationY for this API versions
+ view.setTranslationY(-offsetLargerThanSize);
+ } else {
+ Matrix invertedMatrix = new Matrix();
+ invertedMatrix.postTranslate(0f, -offsetLargerThanSize);
+ ViewUtils.setAnimationMatrix(view, invertedMatrix);
+ }
}
});
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt
index 7c87816..d91145b 100644
--- a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/SpringEstimationBenchmark.kt
@@ -41,7 +41,7 @@
mass = 491.0,
springConstant = 4500.0,
dampingCoefficient = dampingCoeff,
- initialPosition = -3000.0,
+ initialDisplacement = -3000.0,
initialVelocity = 800.0,
delta = 1.0
)
@@ -56,7 +56,7 @@
mass = 81.0,
springConstant = 130321.0,
dampingCoefficient = 6501.0,
- initialPosition = -200000.0,
+ initialDisplacement = -200000.0,
initialVelocity = 4200.0,
delta = 1.0
)
@@ -71,7 +71,7 @@
mass = 1.0,
springConstant = 1.0,
dampingCoefficient = 1.0,
- initialPosition = -200000.0,
+ initialDisplacement = -200000.0,
initialVelocity = 100.0,
delta = 1.0
)
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt
index 3f2a74f..f1845a6 100644
--- a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/core/OnPositionedBenchmark.kt
@@ -22,10 +22,10 @@
import androidx.test.filters.LargeTest
import androidx.ui.benchmark.ComposeBenchmarkRule
import androidx.ui.benchmark.toggleStateBenchmarkLayout
+import androidx.ui.integration.test.ToggleableTestCase
import androidx.ui.layout.Center
import androidx.ui.layout.Container
import androidx.ui.test.ComposeTestCase
-import androidx.ui.integration.test.ToggleableTestCase
import androidx.ui.unit.Dp
import androidx.ui.unit.dp
import org.junit.Rule
@@ -67,11 +67,14 @@
@Composable
private fun StaticChildren(count: Int) {
if (count > 0) {
- Container(width = 100.dp, height = 100.dp) {
+ val modifier = if (count == 1) {
+ onPositioned { it.size }
+ } else {
+ Modifier.None
+ }
+ Container(modifier, width = 100.dp, height = 100.dp) {
StaticChildren(count - 1)
}
- } else {
- OnPositioned { coordinates -> coordinates.size }
}
}
diff --git a/ui/settings.gradle b/ui/settings.gradle
index fc7f4a4..f25e347 100644
--- a/ui/settings.gradle
+++ b/ui/settings.gradle
@@ -43,6 +43,8 @@
includeProject(":compose:compose-runtime-benchmark", "../compose/compose-runtime/compose-runtime-benchmark")
includeProject(":compose:compose-runtime:samples", "../compose/compose-runtime/samples")
includeProject(":lint-checks", "../lint-checks")
+includeProject(":tracing:tracing", "../tracing/tracing")
+includeProject(":tracing:tracing-ktx", "../tracing/tracing-ktx")
includeProject(":ui:integration-tests:benchmark", "integration-tests/benchmark")
includeProject(":ui:integration-tests:demos", "integration-tests/demos")
includeProject(":ui:integration-tests:test", "integration-tests/test")
@@ -88,6 +90,7 @@
includeProject(":ui:ui-unit:samples", "ui-unit/samples")
includeProject(":ui:ui-util", "ui-util")
includeProject(":ui:ui-vector", "ui-vector")
+includeProject(":ui:ui-saved-instance-state", "ui-saved-instance-state")
/////////////////////////////
//
diff --git a/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt b/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
index 0009f95..c601921 100644
--- a/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
+++ b/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
@@ -54,6 +54,7 @@
import androidx.text.LayoutCompat.TextLayoutAlignment
import androidx.text.style.BaselineShiftSpan
import kotlin.math.ceil
+import kotlin.math.min
/**
* Wrapper for Static Text Layout classes.
@@ -122,6 +123,8 @@
@VisibleForTesting
val layout: Layout
+ val lineCount: Int
+
init {
val end = charSequence.length
val frameworkTextDir = getTextDirectionHeuristic(textDirectionHeuristic)
@@ -188,16 +191,18 @@
} else {
layout.lineCount > maxLines
}
+ lineCount = min(layout.lineCount, maxLines)
}
- val lineCount: Int
- get() = layout.lineCount
-
val text: CharSequence
get() = layout.text
val height: Int
- get() = layout.height
+ get() = if (didExceedMaxLines) {
+ layout.getLineBottom(lineCount - 1)
+ } else {
+ layout.height
+ }
fun getLineLeft(lineIndex: Int): Float = layout.getLineLeft(lineIndex)
diff --git a/ui/ui-animation-core/api/0.1.0-dev07.txt b/ui/ui-animation-core/api/0.1.0-dev07.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/0.1.0-dev07.txt
+++ b/ui/ui-animation-core/api/0.1.0-dev07.txt
@@ -157,10 +157,10 @@
public interface DecayAnimation {
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public abstract float absVelocityThreshold;
}
@@ -194,10 +194,10 @@
ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
ctor public ExponentialDecay();
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
}
diff --git a/ui/ui-animation-core/api/current.txt b/ui/ui-animation-core/api/current.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/current.txt
+++ b/ui/ui-animation-core/api/current.txt
@@ -157,10 +157,10 @@
public interface DecayAnimation {
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public abstract float absVelocityThreshold;
}
@@ -194,10 +194,10 @@
ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
ctor public ExponentialDecay();
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
}
diff --git a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev07.txt
@@ -157,10 +157,10 @@
public interface DecayAnimation {
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public abstract float absVelocityThreshold;
}
@@ -194,10 +194,10 @@
ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
ctor public ExponentialDecay();
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
}
diff --git a/ui/ui-animation-core/api/public_plus_experimental_current.txt b/ui/ui-animation-core/api/public_plus_experimental_current.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_current.txt
@@ -157,10 +157,10 @@
public interface DecayAnimation {
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public abstract float absVelocityThreshold;
}
@@ -194,10 +194,10 @@
ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
ctor public ExponentialDecay();
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
}
diff --git a/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt b/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-animation-core/api/restricted_0.1.0-dev07.txt
@@ -157,10 +157,10 @@
public interface DecayAnimation {
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public abstract float absVelocityThreshold;
}
@@ -194,10 +194,10 @@
ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
ctor public ExponentialDecay();
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
}
diff --git a/ui/ui-animation-core/api/restricted_current.txt b/ui/ui-animation-core/api/restricted_current.txt
index 3dd6437..fc7d09b 100644
--- a/ui/ui-animation-core/api/restricted_current.txt
+++ b/ui/ui-animation-core/api/restricted_current.txt
@@ -157,10 +157,10 @@
public interface DecayAnimation {
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public abstract float absVelocityThreshold;
}
@@ -194,10 +194,10 @@
ctor public ExponentialDecay(@FloatRange(from=null, fromInclusive=null) float frictionMultiplier, @FloatRange(from=null, fromInclusive=null) float absVelocityThreshold);
ctor public ExponentialDecay();
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
}
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt b/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt
index 403877f..6626e48 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/AnimationBuilder.kt
@@ -232,15 +232,6 @@
private lateinit var valueVector: V
private lateinit var velocityVector: V
- override fun isFinished(playTime: Long, start: V, end: V, startVelocity: V): Boolean {
- for (i in 0 until start.size) {
- if (!anim.isFinished(playTime, start[i], end[i], startVelocity[i])) {
- return false
- }
- }
- return true
- }
-
override fun getValue(playTime: Long, start: V, end: V, startVelocity: V): V {
if (!::valueVector.isInitialized) {
valueVector = start.newInstance()
@@ -253,13 +244,24 @@
override fun getVelocity(playTime: Long, start: V, end: V, startVelocity: V): V {
if (!::velocityVector.isInitialized) {
- velocityVector = start.newInstance()
+ velocityVector = startVelocity.newInstance()
}
for (i in 0 until velocityVector.size) {
velocityVector[i] = anim.getVelocity(playTime, start[i], end[i], startVelocity[i])
}
return velocityVector
}
+
+ override fun getDurationMillis(start: V, end: V, startVelocity: V): Long {
+ var maxDuration = 0L
+ (0 until start.size).forEach {
+ maxDuration = maxOf(
+ maxDuration,
+ anim.getDurationMillis(start[it], end[it], startVelocity[it])
+ )
+ }
+ return maxDuration
+ }
}
/**
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
index 0dcdb8e..9152843 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/DecayAnimation.kt
@@ -37,19 +37,6 @@
val absVelocityThreshold: Float
/**
- * Returns whether the animation is finished at the given time.
- *
- * @param playTime The time elapsed in milliseconds since the start of the animation
- * @param start The start value of the animation
- * @param startVelocity The start velocity of the animation
- */
- fun isFinished(
- playTime: Long,
- start: Float,
- startVelocity: Float
- ): Boolean
-
- /**
* Returns the value of the animation at the given time.
*
* @param playTime The time elapsed in milliseconds since the start of the animation
@@ -62,6 +49,11 @@
startVelocity: Float
): Float
+ fun getDurationMillis(
+ start: Float,
+ startVelocity: Float
+ ): Long
+
/**
* Returns the velocity of the animation at the given time.
*
@@ -105,14 +97,6 @@
override val absVelocityThreshold: Float = max(0.0000001f, abs(absVelocityThreshold))
private val friction: Float = ExponentialDecayFriction * max(0.0001f, frictionMultiplier)
- override fun isFinished(
- playTime: Long,
- start: Float,
- startVelocity: Float
- ): Boolean {
- return abs(getVelocity(playTime, start, startVelocity)) <= absVelocityThreshold
- }
-
override fun getValue(
playTime: Long,
start: Float,
@@ -130,6 +114,11 @@
return (startVelocity * exp(((playTime / 1000f) * friction)))
}
+ override fun getDurationMillis(start: Float, startVelocity: Float): Long {
+ // Inverse of getVelocity
+ return (1000f * ln(absVelocityThreshold / abs(startVelocity)) / friction).toLong()
+ }
+
override fun getTarget(
start: Float,
startVelocity: Float
@@ -164,6 +153,7 @@
return target
}
}
+
override fun getVelocity(playTime: Long): AnimationVector1D {
if (!isFinished(playTime)) {
velocityVector.value = anim.getVelocity(playTime, startValue, startVelocity)
@@ -172,8 +162,8 @@
}
return velocityVector
}
- override fun isFinished(playTime: Long): Boolean =
- anim.isFinished(playTime, startValue, startVelocity)
+
+ override val durationMillis: Long = anim.getDurationMillis(startValue, startVelocity)
}
internal fun DecayAnimation.createWrapper(
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt
index 8895469..723a2cb 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/FloatAnimation.kt
@@ -20,13 +20,6 @@
* FloatAnimation interface to avoid boxing/unboxing on floats.
*/
internal interface FloatAnimation {
- fun isFinished(
- playTime: Long,
- start: Float,
- end: Float,
- startVelocity: Float
- ): Boolean
-
fun getValue(
playTime: Long,
start: Float,
@@ -40,6 +33,16 @@
end: Float,
startVelocity: Float
): Float
+
+ /**
+ * Note that this may be a computation that is expensive - especially with spring based
+ * animations
+ */
+ fun getDurationMillis(
+ start: Float,
+ end: Float,
+ startVelocity: Float
+ ): Long
}
/**
@@ -111,16 +114,6 @@
it.stiffness = stiffness
}
- override fun isFinished(
- playTime: Long,
- start: Float,
- end: Float,
- startVelocity: Float
- ): Boolean {
- spring.finalPosition = end
- return spring.isAtEquilibrium(start, startVelocity, playTime)
- }
-
override fun getValue(
playTime: Long,
start: Float,
@@ -142,6 +135,15 @@
val (_, velocity) = spring.updateValues(start, startVelocity, playTime)
return velocity
}
+
+ override fun getDurationMillis(start: Float, end: Float, startVelocity: Float): Long =
+ estimateAnimationDurationMillis(
+ stiffness = spring.stiffness,
+ dampingRatio = spring.dampingRatio,
+ initialDisplacement = (start - end) * 100f,
+ initialVelocity = startVelocity * 100f,
+ delta = 1f
+ )
}
/**
@@ -154,13 +156,6 @@
val delay: Long,
private val easing: Easing
) : FloatAnimation {
- override fun isFinished(
- playTime: Long,
- start: Float,
- end: Float,
- startVelocity: Float
- ): Boolean = playTime >= delay + duration
-
override fun getValue(
playTime: Long,
start: Float,
@@ -177,6 +172,10 @@
return (playTime - delay).coerceIn(0, duration)
}
+ override fun getDurationMillis(start: Float, end: Float, startVelocity: Float): Long {
+ return delay + duration
+ }
+
/**
* Calculate velocity by difference between the current value and the value 1 ms ago. This is a
* preliminary way of calculating velocity used by easing curve based animations, and keyframe
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
index bf32420..2126129 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/SpringEstimation.kt
@@ -28,10 +28,28 @@
*/
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
fun estimateAnimationDurationMillis(
+ stiffness: Float,
+ dampingRatio: Float,
+ initialVelocity: Float,
+ initialDisplacement: Float,
+ delta: Float
+): Long = estimateAnimationDurationMillis(
+ stiffness = stiffness.toDouble(),
+ dampingRatio = dampingRatio.toDouble(),
+ initialVelocity = initialVelocity.toDouble(),
+ initialDisplacement = initialDisplacement.toDouble(),
+ delta = delta.toDouble()
+)
+
+/**
+ * Returns the estimated time that the spring will last be at [delta]
+ */
+@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+fun estimateAnimationDurationMillis(
stiffness: Double,
dampingRatio: Double,
initialVelocity: Double,
- initialPosition: Double,
+ initialDisplacement: Double,
delta: Double
): Long {
val dampingCoefficient = 2.0 * dampingRatio * sqrt(stiffness)
@@ -41,7 +59,7 @@
roots,
dampingRatio,
initialVelocity,
- initialPosition,
+ initialDisplacement,
delta
)
}
@@ -55,14 +73,20 @@
dampingCoefficient: Double,
mass: Double,
initialVelocity: Double,
- initialPosition: Double,
+ initialDisplacement: Double,
delta: Double
): Long {
val criticalDamping = 2.0 * sqrt(springConstant * mass)
val dampingRatio = dampingCoefficient / criticalDamping
val roots = complexQuadraticFormula(mass, dampingCoefficient, springConstant)
- return estimateDurationInternal(roots, dampingRatio, initialVelocity, initialPosition, delta)
+ return estimateDurationInternal(
+ roots = roots,
+ dampingRatio = dampingRatio,
+ initialVelocity = initialVelocity,
+ initialPosition = initialDisplacement,
+ delta = delta
+ )
}
/**
@@ -285,4 +309,5 @@
return x - fn(x) / fnPrime(x)
}
-private fun Double.isNotFinite() = !this.isFinite()
+@Suppress("NOTHING_TO_INLINE")
+private inline fun Double.isNotFinite() = !this.isFinite()
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt b/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt
index 3c83b39..99b0935 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/VectorAnimation.kt
@@ -33,13 +33,6 @@
*/
// TODO: Use Duration or TimeStamp for playtime once they are inlined.
internal interface Animation<V : AnimationVector> {
- fun isFinished(
- playTime: Long,
- start: V,
- end: V,
- startVelocity: V
- ): Boolean
-
fun getValue(
playTime: Long,
start: V,
@@ -53,6 +46,12 @@
end: V,
startVelocity: V
): V
+
+ fun getDurationMillis(
+ start: V,
+ end: V,
+ startVelocity: V
+ ): Long
}
/**
@@ -69,12 +68,7 @@
*/
val delay: Long
- override fun isFinished(
- playTime: Long,
- start: V,
- end: V,
- startVelocity: V
- ): Boolean = playTime >= delay + duration
+ override fun getDurationMillis(start: V, end: V, startVelocity: V): Long = delay + duration
fun clampPlayTime(playTime: Long): Long {
return (playTime - delay).coerceIn(0, duration)
@@ -171,9 +165,6 @@
* [SnapAnimation] immediately snaps the animating value to the end value.
*/
internal class SnapAnimation<V : AnimationVector> : Animation<V> {
- override fun isFinished(playTime: Long, start: V, end: V, startVelocity: V): Boolean {
- return true
- }
override fun getValue(playTime: Long, start: V, end: V, startVelocity: V): V {
return end
@@ -182,6 +173,10 @@
override fun getVelocity(playTime: Long, start: V, end: V, startVelocity: V): V {
return startVelocity
}
+
+ override fun getDurationMillis(start: V, end: V, startVelocity: V): Long {
+ return 0
+ }
}
/**
@@ -217,14 +212,6 @@
} else
startVelocity
- override fun isFinished(
- playTime: Long,
- start: V,
- end: V,
- startVelocity: V
- ): Boolean =
- duration <= 0 || playTime / duration >= iterationCount
-
override fun getValue(
playTime: Long,
start: V,
@@ -252,6 +239,10 @@
repetitionStartVelocity(playTime, start, startVelocity, end)
)
}
+
+ override fun getDurationMillis(start: V, end: V, startVelocity: V): Long {
+ return iterationCount * duration
+ }
}
internal class Animation1D(
@@ -259,13 +250,6 @@
) : Animation<AnimationVector1D> {
private val tempVelocityVector = AnimationVector1D(0f)
private val tempValueVector = AnimationVector1D(0f)
- override fun isFinished(
- playTime: Long,
- start: AnimationVector1D,
- end: AnimationVector1D,
- startVelocity: AnimationVector1D
- ): Boolean =
- anim.isFinished(playTime, start.value, end.value, startVelocity.value)
override fun getValue(
playTime: Long,
@@ -286,6 +270,14 @@
tempVelocityVector.apply {
value = anim.getVelocity(playTime, start.value, end.value, startVelocity.value)
}
+
+ override fun getDurationMillis(
+ start: AnimationVector1D,
+ end: AnimationVector1D,
+ startVelocity: AnimationVector1D
+ ): Long {
+ return anim.getDurationMillis(start.value, end.value, startVelocity.value)
+ }
}
/**
@@ -297,15 +289,6 @@
) : Animation<AnimationVector2D> {
private var velocityVector: AnimationVector2D = AnimationVector2D(0f, 0f)
private var valueVector: AnimationVector2D = AnimationVector2D(0f, 0f)
- override fun isFinished(
- playTime: Long,
- start: AnimationVector2D,
- end: AnimationVector2D,
- startVelocity: AnimationVector2D
- ): Boolean {
- return a1.isFinished(playTime, start.v1, end.v1, startVelocity.v1) &&
- a2.isFinished(playTime, start.v2, end.v2, startVelocity.v2)
- }
override fun getValue(
playTime: Long,
@@ -328,6 +311,17 @@
velocityVector.v2 = a2.getVelocity(playTime, start.v2, end.v2, startVelocity.v2)
return velocityVector
}
+
+ override fun getDurationMillis(
+ start: AnimationVector2D,
+ end: AnimationVector2D,
+ startVelocity: AnimationVector2D
+ ): Long {
+ return maxOf(
+ a1.getDurationMillis(start.v1, end.v1, startVelocity.v1),
+ a2.getDurationMillis(start.v2, end.v2, startVelocity.v2)
+ )
+ }
}
/**
@@ -340,16 +334,6 @@
) : Animation<AnimationVector3D> {
private var velocityVector: AnimationVector3D = AnimationVector3D(0f, 0f, 0f)
private var valueVector: AnimationVector3D = AnimationVector3D(0f, 0f, 0f)
- override fun isFinished(
- playTime: Long,
- start: AnimationVector3D,
- end: AnimationVector3D,
- startVelocity: AnimationVector3D
- ): Boolean {
- return a1.isFinished(playTime, start.v1, end.v1, startVelocity.v1) &&
- a2.isFinished(playTime, start.v2, end.v2, startVelocity.v2) &&
- a3.isFinished(playTime, start.v3, end.v3, startVelocity.v3)
- }
override fun getValue(
playTime: Long,
@@ -374,6 +358,18 @@
velocityVector.v3 = a3.getVelocity(playTime, start.v3, end.v3, startVelocity.v3)
return velocityVector
}
+
+ override fun getDurationMillis(
+ start: AnimationVector3D,
+ end: AnimationVector3D,
+ startVelocity: AnimationVector3D
+ ): Long {
+ return maxOf(
+ a1.getDurationMillis(start.v1, end.v1, startVelocity.v1),
+ a2.getDurationMillis(start.v2, end.v2, startVelocity.v2),
+ a3.getDurationMillis(start.v3, end.v3, startVelocity.v3)
+ )
+ }
}
/**
@@ -387,17 +383,6 @@
) : Animation<AnimationVector4D> {
private var velocityVector: AnimationVector4D = AnimationVector4D(0f, 0f, 0f, 0f)
private var valueVector: AnimationVector4D = AnimationVector4D(0f, 0f, 0f, 0f)
- override fun isFinished(
- playTime: Long,
- start: AnimationVector4D,
- end: AnimationVector4D,
- startVelocity: AnimationVector4D
- ): Boolean {
- return a1.isFinished(playTime, start.v1, end.v1, startVelocity.v1) &&
- a2.isFinished(playTime, start.v2, end.v2, startVelocity.v2) &&
- a3.isFinished(playTime, start.v3, end.v3, startVelocity.v3) &&
- a4.isFinished(playTime, start.v4, end.v4, startVelocity.v4)
- }
override fun getValue(
playTime: Long,
@@ -424,6 +409,21 @@
velocityVector.v4 = a4.getVelocity(playTime, start.v4, end.v4, startVelocity.v4)
return velocityVector
}
+
+ override fun getDurationMillis(
+ start: AnimationVector4D,
+ end: AnimationVector4D,
+ startVelocity: AnimationVector4D
+ ): Long {
+ return maxOf(
+ a1.getDurationMillis(start.v1, end.v1, startVelocity.v1),
+ a2.getDurationMillis(start.v2, end.v2, startVelocity.v2),
+ maxOf(
+ a3.getDurationMillis(start.v3, end.v3, startVelocity.v3),
+ a4.getDurationMillis(start.v4, end.v4, startVelocity.v4)
+ )
+ )
+ }
}
/**
@@ -435,7 +435,10 @@
internal interface AnimationWrapper<T, V : AnimationVector> {
fun getValue(playTime: Long): T
fun getVelocity(playTime: Long): V
- fun isFinished(playTime: Long): Boolean
+ fun isFinished(playTime: Long): Boolean {
+ return playTime >= durationMillis
+ }
+ val durationMillis: Long
}
/**
@@ -454,8 +457,6 @@
) : AnimationWrapper<T, V> {
private val startValueVector = typeConverter.convertToVector.invoke(startValue)
private val endValueVector = typeConverter.convertToVector.invoke(endValue)
- override fun isFinished(playTime: Long) =
- animation.isFinished(playTime, startValueVector, endValueVector, startVelocity)
override fun getValue(playTime: Long): T =
typeConverter.convertFromVector.invoke(
@@ -465,6 +466,12 @@
)
)
+ override val durationMillis: Long = animation.getDurationMillis(
+ start = startValueVector,
+ end = endValueVector,
+ startVelocity = startVelocity
+ )
+
override fun getVelocity(playTime: Long): V =
animation.getVelocity(playTime, startValueVector, endValueVector, startVelocity)
}
\ No newline at end of file
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt b/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt
index 4ac6ab6..e341412 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/AnimationTestUtils.kt
@@ -24,9 +24,6 @@
AnimationVector1D(0f)
).value
-internal fun Animation<AnimationVector1D>.isFinished(time: Int): Boolean =
- isFinished(time.toLong(), AnimationVector1D(0f), AnimationVector1D(1f), AnimationVector1D(0f))
-
// Convenient method to build a Float animation.
internal fun AnimationBuilder<Float>.build() = this.build(FloatToVectorConverter)
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt
index 7e831a2..8a39417 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/DecayAnimationTest.kt
@@ -36,11 +36,12 @@
val animWrapper = anim.createWrapper(startValue, startVelocity)
// Obtain finish value by passing in an absurdly large playtime.
val finishValue = animWrapper.getValue(Int.MAX_VALUE.toLong())
+ val finishTime = animWrapper.durationMillis
for (playTime in 0L..4000L step 200L) {
val value = anim.getValue(playTime, startValue, startVelocity)
val velocity = anim.getVelocity(playTime, startValue, startVelocity)
- val finished = anim.isFinished(playTime, startValue, startVelocity)
+ val finished = playTime >= finishTime
assertTrue(finished == animWrapper.isFinished(playTime))
if (!finished) {
@@ -48,12 +49,15 @@
assertTrue(Math.abs(velocity) >= 2.0f)
assertEquals(value, animWrapper.getValue(playTime), epsilon)
assertEquals(velocity, animWrapper.getVelocity(playTime).value, epsilon)
+ assertTrue(playTime < finishTime)
} else {
// When the animation is finished, expect absolute velocity < threshold
assertTrue(Math.abs(velocity) < 2.0f)
// Once the animation is finished, the value should not change any more
assertEquals(finishValue, animWrapper.getValue(playTime), epsilon)
+
+ assertTrue(playTime >= finishTime)
}
}
}
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt
index 38a57d4..c6a262b 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/PhysicsAnimationTest.kt
@@ -17,6 +17,7 @@
package androidx.animation
import com.google.common.truth.Truth.assertThat
+import junit.framework.TestCase.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -88,6 +89,108 @@
assertThat(resultVelocity).isEqualTo(expectedVelocity)
}
+ @Test
+ fun testCriticallydampedDuration() {
+ val startValue = 100f
+ val endValue = 0f
+ val startVelocity = 3000f
+ val stiffness = 100f
+ val delta = 1.0
+
+ val criticalBuilder = PhysicsBuilder<Float>(
+ dampingRatio = 1f,
+ stiffness = stiffness
+ )
+ val criticalWrapper = criticalBuilder.build().toWrapper(
+ startValue = startValue,
+ endValue = endValue,
+ startVelocity = startVelocity
+ )
+
+ assertEquals(
+ estimateAnimationDurationMillis(
+ stiffness = stiffness.toDouble(),
+ dampingRatio = 1.0,
+ initialVelocity = startVelocity.toDouble() * 100.0,
+ initialDisplacement = startValue.toDouble() * 100.0,
+ delta = delta
+ ) /* = 811 ms*/,
+ criticalWrapper.durationMillis
+ )
+ }
+
+ @Test
+ fun testOverdampedDuration() {
+ val startValue = 100f
+ val endValue = 0f
+ val startVelocity = 3000f
+ val stiffness = 100f
+ val delta = 1.0
+
+ val overBuilder = PhysicsBuilder<Float>(
+ dampingRatio = 5f,
+ stiffness = stiffness
+ )
+ val overWrapper = overBuilder.build().toWrapper(
+ startValue = startValue,
+ endValue = endValue,
+ startVelocity = startVelocity
+ )
+
+ assertEquals(
+ estimateAnimationDurationMillis(
+ stiffness = stiffness.toDouble(),
+ dampingRatio = 5.0,
+ initialVelocity = startVelocity.toDouble() * 100.0,
+ initialDisplacement = startValue.toDouble() * 100.0,
+ delta = delta
+ ) /* = 4830 ms*/,
+ overWrapper.durationMillis
+ )
+ }
+ @Test
+ fun testUnderdampedDuration() {
+ val startValue = 100f
+ val endValue = 0f
+ val startVelocity = 3000f
+ val stiffness = 100f
+ val delta = 1.0
+
+ val underBuilder = PhysicsBuilder<Float>(
+ dampingRatio = .5f,
+ stiffness = stiffness
+ )
+ val underWrapper = underBuilder.build().toWrapper(
+ startValue = startValue,
+ endValue = endValue,
+ startVelocity = startVelocity
+ )
+
+ assertEquals(
+ estimateAnimationDurationMillis(
+ stiffness = stiffness.toDouble(),
+ dampingRatio = 0.5,
+ initialVelocity = startVelocity.toDouble() * 100.0,
+ initialDisplacement = startValue.toDouble() * 100.0,
+ delta = delta) /* = 1206 ms*/,
+ underWrapper.durationMillis
+ )
+ }
+
+ private fun Animation<AnimationVector1D>.toWrapper(
+ startValue: Float,
+ startVelocity: Float,
+ endValue: Float
+ ): AnimationWrapper<Float, AnimationVector1D> {
+ return TargetBasedAnimationWrapper(
+ startValue = startValue,
+ startVelocity = AnimationVector(startVelocity),
+ endValue = endValue,
+ animation = this,
+ typeConverter = FloatToVectorConverter
+ )
+ }
+
private fun PhysicsBuilder<out Number>.toSpring(endValue: Number) =
SpringSimulation(endValue.toFloat()).also {
it.dampingRatio = dampingRatio
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt
index f46c8d6..192ba6f 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/RepeatableAnimationTest.kt
@@ -17,6 +17,7 @@
package androidx.animation
import com.google.common.truth.Truth.assertThat
+import junit.framework.TestCase.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -24,12 +25,15 @@
@RunWith(JUnit4::class)
class RepeatableAnimationTest {
- private val Duration = 50
-
private val Animation = TweenBuilder<Float>().apply {
duration = Duration
}
+ private val DelayedAnimation = TweenBuilder<Float>().apply {
+ delay = DelayDuration
+ duration = Duration
+ }
+
@Test
fun twoRepeatsValuesCalculation() {
val repeat = RepeatableBuilder<Float>().run {
@@ -37,13 +41,42 @@
animation = Animation
build()
}
+ val animationWrapper = TargetBasedAnimationWrapper(
+ 0f,
+ AnimationVector(0f),
+ 0f,
+ repeat,
+ FloatToVectorConverter
+ )
assertThat(repeat.at(0)).isEqualTo(0f)
assertThat(repeat.at(Duration - 1)).isGreaterThan(0.9f)
assertThat(repeat.at(Duration + 1)).isLessThan(0.1f)
assertThat(repeat.at(Duration * 2 - 1)).isGreaterThan(0.9f)
assertThat(repeat.at(Duration * 2)).isEqualTo(1f)
- assertThat(repeat.isFinished(Duration * 2 - 1)).isFalse()
- assertThat(repeat.isFinished(Duration * 2)).isTrue()
+ assertThat(animationWrapper.isFinished(Duration * 2L - 1L)).isFalse()
+ assertThat(animationWrapper.isFinished(Duration * 2L)).isTrue()
+ }
+
+ @Test
+ fun testRepeatedAnimationDuration() {
+ val iters = 5
+ val repeat = RepeatableBuilder<Float>().apply {
+ iterations = iters
+ animation = DelayedAnimation
+ }.build()
+
+ val duration = repeat.getDurationMillis(
+ AnimationVector1D(0f),
+ AnimationVector1D(0f),
+ AnimationVector1D(0f)
+ )
+
+ assertEquals((DelayDuration + Duration) * iters.toLong(), duration)
+ }
+
+ private companion object {
+ private val DelayDuration = 13
+ private val Duration = 50
}
}
\ No newline at end of file
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt
index 2db045e..1475fa9 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/SnapAnimationTest.kt
@@ -27,8 +27,15 @@
@Test
fun isFinishedAtTheBeginning() {
val animation = SnapBuilder<Float>().build()
+ val animationWrapper = TargetBasedAnimationWrapper(
+ 0f,
+ AnimationVector(0f),
+ 0f,
+ animation,
+ FloatToVectorConverter
+ )
assertThat(animation.at(0)).isEqualTo(1f)
- assertThat(animation.isFinished(0)).isTrue()
+ assertThat(animationWrapper.isFinished(0)).isTrue()
}
}
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt
index 45c96d3b..c14bc41 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/SpringEstimationTest.kt
@@ -84,7 +84,7 @@
mass = testCase.mass,
springConstant = testCase.springConstant,
dampingCoefficient = testCase.dampingCoefficient,
- initialPosition = testCase.initialPosition,
+ initialDisplacement = testCase.initialDisplacement,
initialVelocity = testCase.initialVelocity,
delta = 1.0
)
@@ -92,7 +92,7 @@
val alternateEndTime = estimateAnimationDurationMillis(
stiffness = testCase.stiffness,
dampingRatio = testCase.dampingRatio,
- initialPosition = testCase.initialPosition,
+ initialDisplacement = testCase.initialDisplacement,
initialVelocity = testCase.initialVelocity,
delta = 1.0
)
@@ -110,17 +110,17 @@
return TestCaseResult(false, testCase, "End time +infinity")
val simTwoFramesAfter = springSimulation.updateValues(
- lastDisplacement = testCase.initialPosition.toFloat(),
+ lastDisplacement = testCase.initialDisplacement.toFloat(),
lastVelocity = testCase.initialVelocity.toFloat(),
timeElapsed = endTime + TwoFrames60fpsMillis
)
val simTwoFramesBefore = springSimulation.updateValues(
- lastDisplacement = testCase.initialPosition.toFloat(),
+ lastDisplacement = testCase.initialDisplacement.toFloat(),
lastVelocity = testCase.initialVelocity.toFloat(),
timeElapsed = max(endTime - TwoFrames60fpsMillis, 0L)
)
val simAtTime = springSimulation.updateValues(
- lastDisplacement = testCase.initialPosition.toFloat(),
+ lastDisplacement = testCase.initialDisplacement.toFloat(),
lastVelocity = testCase.initialVelocity.toFloat(),
timeElapsed = endTime
)
@@ -164,7 +164,7 @@
springConstant = k,
dampingCoefficient = c.toDouble(),
initialVelocity = v0.toDouble(),
- initialPosition = p0.toDouble()
+ initialDisplacement = p0.toDouble()
)
synchronized(testCases) {
testCases.add(
@@ -189,7 +189,7 @@
springConstant = k,
dampingCoefficient = c,
initialVelocity = v0.toDouble(),
- initialPosition = p0.toDouble()
+ initialDisplacement = p0.toDouble()
)
synchronized(testCases) {
@@ -208,7 +208,7 @@
val springConstant: Double,
val dampingCoefficient: Double,
val initialVelocity: Double,
- val initialPosition: Double
+ val initialDisplacement: Double
) {
val dampingRatio: Double
get() {
diff --git a/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt b/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt
index fc1cab6..f2758b6 100644
--- a/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt
+++ b/ui/ui-animation-core/src/test/java/androidx/animation/TransitionAnimationTest.kt
@@ -30,17 +30,19 @@
anim.toState(AnimState.B)
val physicsAnim = SpringAnimation()
var playTime = 0L
+ clock.clockTimeMillis = playTime
do {
- // Increment the time stamp until the animation finishes
- clock.clockTimeMillis = playTime
assertEquals(anim[prop1],
physicsAnim.getValue(playTime, 0f, 1f, 0f),
- epsilon)
+ 0.01f) // TODO(b/151115895) Replace placeholder delta with epsilon
assertEquals(anim[prop2],
physicsAnim.getValue(playTime, 100f, -100f, 0f),
epsilon)
+
+ // Increment the time stamp until the animation finishes
playTime += 20L
+ clock.clockTimeMillis = playTime
} while (anim.isRunning)
}
diff --git a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt
index c7501b8..b7ac545 100644
--- a/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt
+++ b/ui/ui-animation/integration-tests/animation-demos/src/main/java/androidx/ui/animation/demos/SwipeToDismiss.kt
@@ -29,10 +29,10 @@
import androidx.compose.state
import androidx.ui.animation.animatedFloat
import androidx.ui.core.DensityAmbient
-import androidx.ui.core.OnChildPositioned
import androidx.ui.core.Text
import androidx.ui.core.gesture.DragObserver
import androidx.ui.core.gesture.RawDragGestureDetector
+import androidx.ui.core.onPositioned
import androidx.ui.core.setContent
import androidx.ui.foundation.Canvas
import androidx.ui.foundation.CanvasScope
@@ -127,25 +127,23 @@
}
}) {
- OnChildPositioned({ coordinates ->
+ val heightDp = with(DensityAmbient.current) { height.toDp() }
+ val paint = remember { Paint() }
+ Canvas(LayoutWidth.Fill + LayoutHeight(heightDp) + onPositioned { coordinates ->
itemWidth.value = coordinates.size.width.value * 2 / 3f
}) {
- val heightDp = with(DensityAmbient.current) { height.toDp() }
- val paint = remember { Paint() }
- Canvas(LayoutWidth.Fill + LayoutHeight(heightDp)) {
- val progress = 1 - itemBottom.value / height
- // TODO: this progress can be used to drive state transitions
- val alpha = 1f - FastOutSlowInEasing(progress)
- val horizontalOffset = progress * itemWidth.value
- drawLeftItems(
- paint, horizontalOffset, itemWidth.value, itemHeight, index.value
- )
- drawDismissingItem(
- paint,
- itemBottom.value, itemWidth.value, itemHeight, index.value + 1,
- alpha
- )
- }
+ val progress = 1 - itemBottom.value / height
+ // TODO: this progress can be used to drive state transitions
+ val alpha = 1f - FastOutSlowInEasing(progress)
+ val horizontalOffset = progress * itemWidth.value
+ drawLeftItems(
+ paint, horizontalOffset, itemWidth.value, itemHeight, index.value
+ )
+ drawDismissingItem(
+ paint,
+ itemBottom.value, itemWidth.value, itemHeight, index.value + 1,
+ alpha
+ )
}
}
}
diff --git a/ui/ui-foundation/api/0.1.0-dev07.txt b/ui/ui-foundation/api/0.1.0-dev07.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/0.1.0-dev07.txt
+++ b/ui/ui-foundation/api/0.1.0-dev07.txt
@@ -173,11 +173,11 @@
public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
}
diff --git a/ui/ui-foundation/api/current.txt b/ui/ui-foundation/api/current.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/current.txt
+++ b/ui/ui-foundation/api/current.txt
@@ -173,11 +173,11 @@
public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
}
diff --git a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev07.txt
@@ -173,11 +173,11 @@
public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
}
diff --git a/ui/ui-foundation/api/public_plus_experimental_current.txt b/ui/ui-foundation/api/public_plus_experimental_current.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/public_plus_experimental_current.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_current.txt
@@ -173,11 +173,11 @@
public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
}
diff --git a/ui/ui-foundation/api/restricted_0.1.0-dev07.txt b/ui/ui-foundation/api/restricted_0.1.0-dev07.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-foundation/api/restricted_0.1.0-dev07.txt
@@ -173,11 +173,11 @@
public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
}
diff --git a/ui/ui-foundation/api/restricted_current.txt b/ui/ui-foundation/api/restricted_current.txt
index 8b05809..69e28a1 100644
--- a/ui/ui-foundation/api/restricted_current.txt
+++ b/ui/ui-foundation/api/restricted_current.txt
@@ -173,11 +173,11 @@
public final class AndroidFlingDecayAnimation implements androidx.animation.DecayAnimation {
ctor public AndroidFlingDecayAnimation(androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator);
method public float getAbsVelocityThreshold();
+ method public long getDurationMillis(float start, float startVelocity);
method public androidx.ui.foundation.animation.AndroidFlingCalculator getFlingCalculator();
method public float getTarget(float start, float startVelocity);
method public float getValue(long playTime, float start, float startVelocity);
method public float getVelocity(long playTime, float start, float startVelocity);
- method public boolean isFinished(long playTime, float start, float startVelocity);
property public float absVelocityThreshold;
property public final androidx.ui.foundation.animation.AndroidFlingCalculator flingCalculator;
}
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt
index 3a2f4da..9de1463 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/BoxTest.kt
@@ -21,8 +21,8 @@
import androidx.test.filters.MediumTest
import androidx.test.filters.SdkSuppress
import androidx.ui.core.DensityAmbient
-import androidx.ui.core.OnChildPositioned
import androidx.ui.core.TestTag
+import androidx.ui.core.onPositioned
import androidx.ui.foundation.shape.RectangleShape
import androidx.ui.foundation.shape.corner.CircleShape
import androidx.ui.graphics.Color
@@ -64,9 +64,7 @@
composeTestRule.setContent {
SemanticsParent {
Box(LayoutSize(size), padding = padding) {
- OnChildPositioned({ childSize = it.size }) {
- Box(LayoutSize.Fill)
- }
+ Box(LayoutSize.Fill + onPositioned { childSize = it.size })
}
}
}
@@ -95,12 +93,10 @@
paddingTop = top,
paddingBottom = bottom
) {
- OnChildPositioned({
+ Box(LayoutSize.Fill + onPositioned {
childSize = it.size
childPosition = it.localToGlobal(PxPosition.Origin)
- }) {
- Box(LayoutSize.Fill)
- }
+ })
}
}
}
@@ -133,12 +129,10 @@
paddingTop = top,
paddingBottom = bottom
) {
- OnChildPositioned({
+ Box(LayoutSize.Fill + onPositioned {
childSize = it.size
childPosition = it.localToGlobal(PxPosition.Origin)
- }) {
- Box(LayoutSize.Fill)
- }
+ })
}
}
}
@@ -170,9 +164,7 @@
paddingTop = top,
paddingBottom = bottom
) {
- OnChildPositioned({ childSize = it.size }) {
- Box(LayoutSize.Fill)
- }
+ Box(LayoutSize.Fill + onPositioned { childSize = it.size })
}
}
}
@@ -322,9 +314,7 @@
composeTestRule.setContent {
SemanticsParent {
Box(LayoutSize(size), border = Border(borderSize, Color.Red)) {
- OnChildPositioned({ childSize = it.size }) {
- Box(LayoutSize.Fill)
- }
+ Box(LayoutSize.Fill + onPositioned { childSize = it.size })
}
}
}
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt
index 5e12b39..ca53113 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/CanvasTest.kt
@@ -22,8 +22,8 @@
import androidx.test.filters.SdkSuppress
import androidx.ui.core.DensityAmbient
import androidx.ui.core.Modifier
-import androidx.ui.core.OnChildPositioned
import androidx.ui.core.TestTag
+import androidx.ui.core.onPositioned
import androidx.ui.foundation.shape.RectangleShape
import androidx.ui.foundation.shape.corner.CircleShape
import androidx.ui.graphics.Color
@@ -76,10 +76,9 @@
var canvasSize: IntPxSize? = null
composeTestRule.setContentAndCollectSizes {
SemanticParent {
- OnChildPositioned({ position -> canvasSize = position.size }) {
- Canvas(modifier = LayoutSize(100.dp)) {
- drawRect(size.toRect(), Paint().apply { color = Color.Red })
- }
+ Canvas(modifier = LayoutSize(100.dp) +
+ onPositioned { position -> canvasSize = position.size }) {
+ drawRect(size.toRect(), Paint().apply { color = Color.Red })
}
}
}
@@ -103,14 +102,13 @@
var canvasSize: IntPxSize? = null
composeTestRule.setContentAndCollectSizes {
SemanticParent {
- OnChildPositioned({ position -> canvasSize = position.size }) {
- Canvas(modifier = LayoutSize(100.dp)) {
- drawRect(size.toRect(), Paint().apply { color = Color.Red })
- drawCircle(
- size.center().toOffset(),
- 10f,
- Paint().apply { color = Color.Blue })
- }
+ Canvas(modifier = LayoutSize(100.dp) +
+ onPositioned { position -> canvasSize = position.size }) {
+ drawRect(size.toRect(), Paint().apply { color = Color.Red })
+ drawCircle(
+ size.center().toOffset(),
+ 10f,
+ Paint().apply { color = Color.Blue })
}
}
}
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt
index a4c7180..0646b29 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/animation/AndroidFlingDecayAnimation.kt
@@ -17,7 +17,6 @@
package androidx.ui.foundation.animation
import androidx.animation.DecayAnimation
-import kotlin.math.roundToInt
import kotlin.math.sign
/**
@@ -43,13 +42,9 @@
override fun getValue(playTime: Long, start: Float, startVelocity: Float): Float =
start + flingCalculator.flingInfo(startVelocity).position(playTime)
+ override fun getDurationMillis(start: Float, startVelocity: Float): Long =
+ flingCalculator.flingDuration(startVelocity)
+
override fun getVelocity(playTime: Long, start: Float, startVelocity: Float): Float =
flingCalculator.flingInfo(startVelocity).velocity(playTime)
-
- override fun isFinished(playTime: Long, start: Float, startVelocity: Float): Boolean {
- val flingInfo = flingCalculator.flingInfo(startVelocity)
- if (playTime > flingInfo.duration) return true
-
- return flingInfo.distance.roundToInt() == flingInfo.position(playTime).roundToInt()
- }
}
\ No newline at end of file
diff --git a/ui/ui-framework/api/0.1.0-dev07.txt b/ui/ui-framework/api/0.1.0-dev07.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/0.1.0-dev07.txt
+++ b/ui/ui-framework/api/0.1.0-dev07.txt
@@ -75,7 +75,7 @@
}
public final class PasswordTextFieldKt {
- method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+ method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
}
public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
}
public final class TextFieldKt {
- method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
}
public final class TextKt {
method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
- method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
method public static androidx.ui.text.TextStyle currentTextStyle();
method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/current.txt b/ui/ui-framework/api/current.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/current.txt
+++ b/ui/ui-framework/api/current.txt
@@ -75,7 +75,7 @@
}
public final class PasswordTextFieldKt {
- method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+ method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
}
public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
}
public final class TextFieldKt {
- method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
}
public final class TextKt {
method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
- method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
method public static androidx.ui.text.TextStyle currentTextStyle();
method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-framework/api/public_plus_experimental_0.1.0-dev07.txt
@@ -75,7 +75,7 @@
}
public final class PasswordTextFieldKt {
- method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+ method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
}
public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
}
public final class TextFieldKt {
- method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
}
public final class TextKt {
method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
- method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
method public static androidx.ui.text.TextStyle currentTextStyle();
method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/public_plus_experimental_current.txt b/ui/ui-framework/api/public_plus_experimental_current.txt
index c0c95c7..b32ab38 100644
--- a/ui/ui-framework/api/public_plus_experimental_current.txt
+++ b/ui/ui-framework/api/public_plus_experimental_current.txt
@@ -75,7 +75,7 @@
}
public final class PasswordTextFieldKt {
- method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+ method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
}
public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
}
public final class TextFieldKt {
- method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
}
public final class TextKt {
method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
- method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
method public static androidx.ui.text.TextStyle currentTextStyle();
method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/restricted_0.1.0-dev07.txt b/ui/ui-framework/api/restricted_0.1.0-dev07.txt
index eed64b91..4187b9a 100644
--- a/ui/ui-framework/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-framework/api/restricted_0.1.0-dev07.txt
@@ -75,7 +75,7 @@
}
public final class PasswordTextFieldKt {
- method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+ method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
}
public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
}
public final class TextFieldKt {
- method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
}
public final class TextKt {
method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
- method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
method public static androidx.ui.text.TextStyle currentTextStyle();
method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/api/restricted_current.txt b/ui/ui-framework/api/restricted_current.txt
index eed64b91..4187b9a 100644
--- a/ui/ui-framework/api/restricted_current.txt
+++ b/ui/ui-framework/api/restricted_current.txt
@@ -75,7 +75,7 @@
}
public final class PasswordTextFieldKt {
- method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
+ method public static void PasswordTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, char mask = '\u2022', androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> >
}
public final class PointerInputWrapperKt {
@@ -107,15 +107,15 @@
}
public final class TextFieldKt {
- method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
- method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle? textStyle = null, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(String value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue value, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextFieldValue,kotlin.Unit> androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
+ method public static void TextField(androidx.ui.text.TextFieldValue model, androidx.ui.text.TextRange? compositionRange, androidx.ui.core.Modifier modifier = Modifier.None, kotlin.jvm.functions.Function2<? super androidx.ui.text.TextFieldValue,? super androidx.ui.text.TextRange,kotlin.Unit> _, _ -> }, androidx.ui.text.TextStyle textStyle = TextStyle.Default, androidx.ui.input.KeyboardType keyboardType = KeyboardType.Text, androidx.ui.input.ImeAction imeAction = ImeAction.Unspecified, kotlin.jvm.functions.Function0<kotlin.Unit> kotlin.jvm.functions.Function0<kotlin.Unit> String? focusIdentifier = null, kotlin.jvm.functions.Function1<? super androidx.ui.input.ImeAction,kotlin.Unit> androidx.ui.input.VisualTransformation? visualTransformation = null);
}
public final class TextKt {
method public static void CurrentTextStyleProvider(androidx.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
- method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle? style = null, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(String text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
+ method public static void Text(androidx.ui.text.AnnotatedString text, androidx.ui.core.Modifier modifier = Modifier.None, androidx.ui.text.TextStyle style = TextStyle.Default, boolean softWrap = true, androidx.ui.text.style.TextOverflow overflow = androidx.ui.core.TextKt.DefaultOverflow, int maxLines = 2147483647, kotlin.jvm.functions.Function1<? super androidx.ui.text.TextLayoutResult,kotlin.Unit> >
method public static androidx.ui.text.TextStyle currentTextStyle();
method public static androidx.ui.core.HorizontalAlignmentLine getFirstBaseline();
method public static androidx.ui.core.HorizontalAlignmentLine getLastBaseline();
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt
index f094c74..1ba6b89 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextFieldDelegateIntegrationTest.kt
@@ -62,7 +62,7 @@
fun draw_selection_test() {
val textDelegate = TextDelegate(
text = AnnotatedString("Hello, World"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
maxLines = 2,
density = density,
resourceLoader = resourceLoader,
@@ -103,7 +103,7 @@
val textDelegate = TextDelegate(
text = AnnotatedString("Hello, World"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
maxLines = 2,
density = density,
resourceLoader = resourceLoader,
@@ -138,7 +138,7 @@
val textDelegate = TextDelegate(
text = AnnotatedString("Hello, World"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
maxLines = 2,
density = density,
resourceLoader = resourceLoader,
@@ -169,7 +169,7 @@
fun layout_height_constraint_max_height() {
val textDelegate = TextDelegate(
text = AnnotatedString("Hello, World"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
maxLines = 2,
density = density,
resourceLoader = resourceLoader,
@@ -190,7 +190,7 @@
fun layout_height_constraint_min_height() {
val textDelegate = TextDelegate(
text = AnnotatedString("Hello, World"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
maxLines = 2,
density = density,
resourceLoader = resourceLoader,
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt
index 74f5d42..3cfd025 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/TextLayoutTest.kt
@@ -23,10 +23,10 @@
import androidx.ui.framework.test.TestActivity
import androidx.ui.text.TextLayoutResult
import androidx.ui.text.TextStyle
-import androidx.ui.text.font.font
import androidx.ui.text.font.FontStyle
import androidx.ui.text.font.FontWeight
import androidx.ui.text.font.asFontFamily
+import androidx.ui.text.font.font
import androidx.ui.unit.Density
import androidx.ui.unit.IntPx
import androidx.ui.unit.IntPxSize
@@ -72,18 +72,18 @@
val textSize = Ref<IntPxSize>()
val doubleTextSize = Ref<IntPxSize>()
show {
- OnChildPositioned({ coordinates ->
- textSize.value = coordinates.size
- layoutLatch.countDown()
- }) {
- Text("aa", style = TextStyle(fontFamily = fontFamily))
- }
- OnChildPositioned({ coordinates ->
- doubleTextSize.value = coordinates.size
- layoutLatch.countDown()
- }) {
- Text("aaaa", style = TextStyle(fontFamily = fontFamily))
- }
+ Text("aa", style = TextStyle(fontFamily = fontFamily),
+ modifier = onPositioned { coordinates ->
+ textSize.value = coordinates.size
+ layoutLatch.countDown()
+ }
+ )
+ Text("aaaa", style = TextStyle(fontFamily = fontFamily),
+ modifier = onPositioned { coordinates ->
+ doubleTextSize.value = coordinates.size
+ layoutLatch.countDown()
+ }
+ )
}
assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
assertNotNull(textSize.value)
@@ -100,18 +100,18 @@
val textSize = Ref<IntPxSize>()
val doubleTextSize = Ref<IntPxSize>()
show {
- OnChildPositioned({ coordinates ->
- textSize.value = coordinates.size
- layoutLatch.countDown()
- }) {
- Text("aa ", style = TextStyle(fontFamily = fontFamily))
- }
- OnChildPositioned({ coordinates ->
- doubleTextSize.value = coordinates.size
- layoutLatch.countDown()
- }) {
- Text("aa aa ", style = TextStyle(fontFamily = fontFamily))
- }
+ Text("aa ", style = TextStyle(fontFamily = fontFamily),
+ modifier = onPositioned { coordinates ->
+ textSize.value = coordinates.size
+ layoutLatch.countDown()
+ }
+ )
+ Text("aa aa ", style = TextStyle(fontFamily = fontFamily),
+ modifier = onPositioned { coordinates ->
+ doubleTextSize.value = coordinates.size
+ layoutLatch.countDown()
+ }
+ )
}
assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
val textWidth = textSize.value!!.width
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
index 98229b9..95c3f96 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
@@ -45,7 +45,6 @@
import androidx.ui.core.LayoutTag
import androidx.ui.core.Measurable
import androidx.ui.core.Modifier
-import androidx.ui.core.OnPositioned
import androidx.ui.core.ParentData
import androidx.ui.core.ParentDataModifier
import androidx.ui.core.Ref
@@ -55,6 +54,7 @@
import androidx.ui.core.drawWithContent
import androidx.ui.core.globalPosition
import androidx.ui.core.offset
+import androidx.ui.core.onPositioned
import androidx.ui.core.setContent
import androidx.ui.core.tag
import androidx.ui.framework.test.TestActivity
@@ -1694,18 +1694,18 @@
SimpleRow {
for (i in 0 until 2) {
if (model.offset.value == i) {
- Wrap(minWidth = size, minHeight = size) {
- OnPositioned { coordinates ->
+ Wrap(minWidth = size, minHeight = size,
+ modifier = onPositioned { coordinates ->
wrap1Position = coordinates.globalPosition.x
latch.countDown()
- }
+ }) {
}
} else {
- Wrap(minWidth = size, minHeight = size) {
- OnPositioned { coordinates ->
+ Wrap(minWidth = size, minHeight = size,
+ modifier = onPositioned { coordinates ->
wrap2Position = coordinates.globalPosition.x
latch.countDown()
- }
+ }) {
}
}
}
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
index 8d40221..417a19f 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/RtlLayoutTest.kt
@@ -22,8 +22,9 @@
import androidx.ui.core.Layout
import androidx.ui.core.LayoutDirection
import androidx.ui.core.LayoutModifier
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.Modifier
import androidx.ui.core.Ref
+import androidx.ui.core.onPositioned
import androidx.ui.core.setContent
import androidx.ui.unit.Density
import androidx.ui.unit.PxPosition
@@ -137,14 +138,11 @@
}
Layout(
children = @Composable {
- FixedSize(size) {
- SaveLayoutInfo(position[0], countDownLatch)
+ FixedSize(size, modifier = saveLayoutInfo(position[0], countDownLatch)) {
}
- FixedSize(size) {
- SaveLayoutInfo(position[1], countDownLatch)
+ FixedSize(size, modifier = saveLayoutInfo(position[1], countDownLatch)) {
}
- FixedSize(size) {
- SaveLayoutInfo(position[2], countDownLatch)
+ FixedSize(size, modifier = saveLayoutInfo(position[2], countDownLatch)) {
}
},
modifier = modifier
@@ -169,10 +167,11 @@
}
@Composable
- private fun SaveLayoutInfo(position: Ref<PxPosition>, countDownLatch: CountDownLatch) {
- OnPositioned {
- position.value = it.localToGlobal(PxPosition(0.ipx, 0.ipx))
- countDownLatch.countDown()
- }
+ private fun saveLayoutInfo(
+ position: Ref<PxPosition>,
+ countDownLatch: CountDownLatch
+ ): Modifier = onPositioned {
+ position.value = it.localToGlobal(PxPosition(0.ipx, 0.ipx))
+ countDownLatch.countDown()
}
}
\ No newline at end of file
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
index 3b3ebc0..b495d89 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/WithConstraintsTest.kt
@@ -31,10 +31,10 @@
import androidx.ui.core.LayoutModifier
import androidx.ui.core.MeasureBlock
import androidx.ui.core.Modifier
-import androidx.ui.core.OnPositioned
import androidx.ui.core.Ref
import androidx.ui.core.WithConstraints
import androidx.ui.core.draw
+import androidx.ui.core.onPositioned
import androidx.ui.core.setContent
import androidx.ui.framework.test.TestActivity
import androidx.ui.graphics.Color
@@ -308,24 +308,23 @@
rule.runOnUiThreadIR {
activity.setContentInFrameLayout {
Container(width = 200.ipx, height = 200.ipx) {
- WithConstraints { _, _ ->
- OnPositioned {
- // OnPositioned can be fired multiple times with the same value
- // for example when requestLayout() was triggered on ComposeView.
- // if we called twice, let's make sure we got the correct values.
- assertTrue(withConstSize == null || withConstSize == it.size)
- withConstSize = it.size
- withConstLatch.countDown()
- }
- Container(width = size.value, height = size.value) {
- OnPositioned {
+ WithConstraints(modifier = onPositioned {
+ // OnPositioned can be fired multiple times with the same value
+ // for example when requestLayout() was triggered on ComposeView.
+ // if we called twice, let's make sure we got the correct values.
+ assertTrue(withConstSize == null || withConstSize == it.size)
+ withConstSize = it.size
+ withConstLatch.countDown()
+ }) { _, _ ->
+ Container(width = size.value, height = size.value,
+ modifier = onPositioned {
// OnPositioned can be fired multiple times with the same value
// for example when requestLayout() was triggered on ComposeView.
// if we called twice, let's make sure we got the correct values.
assertTrue(childSize == null || childSize == it.size)
childSize = it.size
childLatch.countDown()
- }
+ }) {
}
}
}
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt b/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt
index baa557e..ab081e3 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/PasswordTextField.kt
@@ -63,7 +63,7 @@
fun PasswordTextField(
value: String,
onValueChange: (String) -> Unit = {},
- textStyle: TextStyle? = null,
+ textStyle: TextStyle = TextStyle.Default,
mask: Char = '\u2022',
imeAction: ImeAction = ImeAction.Unspecified,
onFocus: () -> Unit = {},
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt b/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt
index a2c5b69..38c30bb 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/Text.kt
@@ -19,6 +19,7 @@
import androidx.compose.Providers
import androidx.compose.StructurallyEqual
import androidx.compose.ambientOf
+import androidx.compose.emptyContent
import androidx.compose.mutableStateOf
import androidx.compose.onCommit
import androidx.compose.remember
@@ -70,7 +71,7 @@
fun Text(
text: String,
modifier: Modifier = Modifier.None,
- style: TextStyle? = null,
+ style: TextStyle = TextStyle.Default,
softWrap: Boolean = DefaultSoftWrap,
overflow: TextOverflow = DefaultOverflow,
maxLines: Int = DefaultMaxLines,
@@ -107,7 +108,7 @@
fun Text(
text: AnnotatedString,
modifier: Modifier = Modifier.None,
- style: TextStyle? = null,
+ style: TextStyle = TextStyle.Default,
softWrap: Boolean = DefaultSoftWrap,
overflow: TextOverflow = DefaultOverflow,
maxLines: Int = DefaultMaxLines,
@@ -165,36 +166,32 @@
state.textDelegate.paint(canvas, layoutResult)
}
}
- val children = @Composable {
- // Get the layout coordinates of the text composable. This is for hit test of
- // cross-composable selection.
- OnPositioned(
- >
- val oldLayoutCoordinates = state.layoutCoordinates
- state.layoutCoordinates = it
+ // Get the layout coordinates of the text composable. This is for hit test of
+ // cross-composable selection.
+ val {
+ val oldLayoutCoordinates = state.layoutCoordinates
+ state.layoutCoordinates = it
- if ((oldLayoutCoordinates == null || !oldLayoutCoordinates.isAttached) &&
- it.isAttached
- ) {
- selectionRegistrar?.onPositionChange()
- }
+ if ((oldLayoutCoordinates == null || !oldLayoutCoordinates.isAttached) &&
+ it.isAttached
+ ) {
+ selectionRegistrar?.onPositionChange()
+ }
- if (oldLayoutCoordinates != null && oldLayoutCoordinates.isAttached &&
- it.isAttached
- ) {
- if (
- oldLayoutCoordinates.localToGlobal(PxPosition.Origin) !=
- it.localToGlobal(PxPosition.Origin)
- ) {
- selectionRegistrar?.onPositionChange()
- }
- }
+ if (oldLayoutCoordinates != null && oldLayoutCoordinates.isAttached &&
+ it.isAttached
+ ) {
+ if (
+ oldLayoutCoordinates.localToGlobal(PxPosition.Origin) !=
+ it.localToGlobal(PxPosition.Origin)
+ ) {
+ selectionRegistrar?.onPositionChange()
}
- )
+ }
}
Layout(
- children = children,
- modifier = modifier + textDrawModifier,
+ children = emptyContent(),
+ modifier = modifier + textDrawModifier + onPositioned,
minIntrinsicWidthMeasureBlock = { _, _, _ ->
state.textDelegate.layoutIntrinsics()
state.textDelegate.minIntrinsicWidth
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt b/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt
index 8422f4a..b8d1150 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/TextField.kt
@@ -16,6 +16,7 @@
package androidx.ui.core
import androidx.compose.Composable
+import androidx.compose.emptyContent
import androidx.compose.mutableStateOf
import androidx.compose.onDispose
import androidx.compose.remember
@@ -94,7 +95,7 @@
value: String,
modifier: Modifier = Modifier.None,
onValueChange: (String) -> Unit = {},
- textStyle: TextStyle? = null,
+ textStyle: TextStyle = TextStyle.Default,
keyboardType: KeyboardType = KeyboardType.Text,
imeAction: ImeAction = ImeAction.Unspecified,
onFocus: () -> Unit = {},
@@ -187,7 +188,7 @@
value: TextFieldValue,
modifier: Modifier = Modifier.None,
onValueChange: (TextFieldValue) -> Unit = {},
- textStyle: TextStyle? = null,
+ textStyle: TextStyle = TextStyle.Default,
keyboardType: KeyboardType = KeyboardType.Text,
imeAction: ImeAction = ImeAction.Unspecified,
onFocus: () -> Unit = {},
@@ -286,7 +287,7 @@
compositionRange: TextRange?,
modifier: Modifier = Modifier.None,
onValueChange: (TextFieldValue, TextRange?) -> Unit = { _, _ -> },
- textStyle: TextStyle? = null,
+ textStyle: TextStyle = TextStyle.Default,
keyboardType: KeyboardType = KeyboardType.Text,
imeAction: ImeAction = ImeAction.Unspecified,
onFocus: () -> Unit = {},
@@ -318,7 +319,7 @@
value: InputState,
modifier: Modifier,
onValueChange: (InputState) -> Unit = { },
- textStyle: TextStyle? = null,
+ textStyle: TextStyle = TextStyle.Default,
keyboardType: KeyboardType = KeyboardType.Text,
imeAction: ImeAction = ImeAction.Unspecified,
onFocus: () -> Unit = {},
@@ -403,12 +404,13 @@
}
onFocus()
},
- >
+ hasNextClient ->
state.hasFocus = false
TextFieldDelegate.onBlur(
textInputService,
state.inputSession,
state.processor,
+ hasNextClient,
onValueChangeWrapper)
onBlur()
},
@@ -440,26 +442,25 @@
}
}
Layout(
- modifier = modifier + textDrawModifier,
- children = @Composable {
- OnPositioned {
- if (textInputService != null) {
- state.layoutCoordinates = it
- state.layoutResult?.let { layoutResult ->
- TextFieldDelegate.notifyFocusedRect(
- value,
- state.textDelegate,
- layoutResult,
- it,
- textInputService,
- state.inputSession,
- state.hasFocus,
- offsetMap
- )
+ modifier = modifier + textDrawModifier +
+ onPositioned {
+ if (textInputService != null) {
+ state.layoutCoordinates = it
+ state.layoutResult?.let { layoutResult ->
+ TextFieldDelegate.notifyFocusedRect(
+ value,
+ state.textDelegate,
+ layoutResult,
+ it,
+ textInputService,
+ state.inputSession,
+ state.hasFocus,
+ offsetMap
+ )
+ }
}
- }
- }
- },
+ },
+ children = emptyContent(),
measureBlock = { _, constraints, _ ->
TextFieldDelegate.layout(
state.textDelegate,
@@ -499,7 +500,7 @@
onPress: (PxPosition) -> Unit,
onRelease: (PxPosition) -> Unit,
onFocus: () -> Unit,
- onBlur: () -> Unit,
+ onBlur: (hasNextClient: Boolean) -> Unit,
focusIdentifier: String?,
children: @Composable() () -> Unit
) {
@@ -513,8 +514,8 @@
focused.value = true
}
- override fun onBlur() {
- onBlur()
+ override fun onBlur(hasNextClient: Boolean) {
+ onBlur(hasNextClient)
focused.value = false
}
}
@@ -526,6 +527,9 @@
}
onDispose {
+ if (focused.value) {
+ focusManager.blur(focusNode)
+ }
if (focusIdentifier != null)
focusManager.unregisterFocusNode(focusIdentifier)
}
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt b/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt
index 0668307..0b85806 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/TextFieldDelegate.kt
@@ -325,10 +325,14 @@
textInputService: TextInputService?,
token: InputSessionToken,
editProcessor: EditProcessor,
+ hasNextClient: Boolean,
onValueChange: (InputState) -> Unit
) {
onEditCommand(listOf(FinishComposingTextEditOp()), editProcessor, onValueChange)
textInputService?.stopInput(token)
+ if (!hasNextClient) {
+ textInputService?.hideSoftwareKeyboard(token)
+ }
}
/**
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt b/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt
index 759525f..8b91c7f 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/input/FocusManager.kt
@@ -30,8 +30,13 @@
/** Called when this component gained the focus */
fun onFocus()
- /** Called when this component is about to lose the focus */
- fun onBlur()
+ /**
+ * Called when this component is about to lose the focus
+ *
+ * @param hasNextClient True if this node loses focus due to focusing in to another node
+ * . False if this node loses focus due to calling [FocusManager#blur].
+ */
+ fun onBlur(hasNextClient: Boolean)
}
/**
@@ -84,18 +89,20 @@
}
if (currentFocus != null) {
- focusOut(currentFocus)
+ currentFocus.onBlur(true)
}
focusedClient = client
- focusIn(client)
- }
-
- private fun focusIn(client: FocusNode) {
client.onFocus()
}
- private fun focusOut(client: FocusNode) {
- client.onBlur()
+ /**
+ * Release the focus if given focus node is focused
+ */
+ internal fun blur(client: FocusNode) {
+ if (focusedClient == client) {
+ focusedClient = null
+ client.onBlur(false)
+ }
}
}
\ No newline at end of file
diff --git a/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt b/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
index ccfdc53..ef1d756 100644
--- a/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
+++ b/ui/ui-framework/src/main/java/androidx/ui/core/selection/SelectionContainer.kt
@@ -24,7 +24,7 @@
import androidx.ui.core.Constraints
import androidx.ui.core.HapticFeedBackAmbient
import androidx.ui.core.Layout
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.Modifier
import androidx.ui.core.Placeable
import androidx.ui.core.Popup
import androidx.ui.core.enforce
@@ -33,6 +33,7 @@
import androidx.ui.core.gesture.TouchSlopDragGestureDetector
import androidx.ui.core.hasFixedHeight
import androidx.ui.core.hasFixedWidth
+import androidx.ui.core.onPositioned
import androidx.ui.unit.Dp
import androidx.ui.unit.IntPx
import androidx.ui.unit.IntPxPosition
@@ -78,10 +79,9 @@
manager.selection = selection
Providers(SelectionRegistrarAmbient provides registrarImpl) {
- Wrap {
- // Get the layout coordinates of the selection container. This is for hit test of
- // cross-composable selection.
- OnPositioned( manager.containerLayoutCoordinates = it })
+ // Get the layout coordinates of the selection container. This is for hit test of
+ // cross-composable selection.
+ Wrap(onPositioned { manager.containerLayoutCoordinates = it }) {
PressReleasedGestureDetector( manager.onRelease() }) {
LongPressDragGestureDetector(manager.longPressDragObserver, children = children)
}
@@ -164,8 +164,8 @@
* the children.
*/
@Composable
-private fun Wrap(children: @Composable() () -> Unit) {
- Layout(children) { measurables, constraints, _ ->
+private fun Wrap(modifier: Modifier = Modifier.None, children: @Composable() () -> Unit) {
+ Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
val placeables = measurables.map { measurable ->
measurable.measure(constraints)
}
diff --git a/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt b/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt
index e1f5e22..75342f1 100644
--- a/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt
+++ b/ui/ui-framework/src/test/java/androidx/ui/core/TextFieldDelegateTest.kt
@@ -194,12 +194,39 @@
whenever(processor.onEditCommands(captor.capture())).thenReturn(InputState())
- TextFieldDelegate.onBlur(textInputService, dummyInputSessionToken, processor, onValueChange)
+ TextFieldDelegate.onBlur(
+ textInputService,
+ dummyInputSessionToken,
+ processor,
+ true,
+ onValueChange)
assertEquals(1, captor.allValues.size)
assertEquals(1, captor.firstValue.size)
assertTrue(captor.firstValue[0] is FinishComposingTextEditOp)
verify(textInputService).stopInput(eq(dummyInputSessionToken))
+ verify(textInputService, never()).hideSoftwareKeyboard(any())
+ }
+
+ @Test
+ fun on_blur_with_hiding() {
+ val captor = argumentCaptor<List<EditOperation>>()
+ val dummyInputSessionToken = 10 // We are not using this value in this test. Just dummy.
+
+ whenever(processor.onEditCommands(captor.capture())).thenReturn(InputState())
+
+ TextFieldDelegate.onBlur(
+ textInputService,
+ dummyInputSessionToken,
+ processor,
+ false, // There is no next focused client. Hide the keyboard.
+ onValueChange)
+
+ assertEquals(1, captor.allValues.size)
+ assertEquals(1, captor.firstValue.size)
+ assertTrue(captor.firstValue[0] is FinishComposingTextEditOp)
+ verify(textInputService).stopInput(eq(dummyInputSessionToken))
+ verify(textInputService).hideSoftwareKeyboard(eq(dummyInputSessionToken))
}
@Test
diff --git a/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt b/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt
index 2785335..a5dca661 100644
--- a/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt
+++ b/ui/ui-framework/src/test/java/androidx/ui/core/input/FocusManagerTest.kt
@@ -16,6 +16,8 @@
package androidx.ui.core.input
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.inOrder
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
@@ -35,7 +37,7 @@
fm.requestFocus(FocusNode1)
verify(FocusNode1, times(1)).onFocus()
- verify(FocusNode1, never()).onBlur()
+ verify(FocusNode1, never()).onBlur(eq(true /* hasNextClient */))
}
@Test
@@ -50,7 +52,7 @@
// onBlur must be called to currently focused object, then onFocus is called to the next
// object.
inOrder(FocusNode1, FocusNode2) {
- verify(FocusNode1, times(1)).onBlur()
+ verify(FocusNode1, times(1)).onBlur(eq(true /* hasNextClient */))
verify(FocusNode2, times(1)).onFocus()
}
}
@@ -62,12 +64,12 @@
val fm = FocusManager()
fm.requestFocus(FocusNode1)
verify(FocusNode1, times(1)).onFocus()
- verify(FocusNode1, never()).onBlur()
+ verify(FocusNode1, never()).onBlur(any())
// Either onFocus or onBlur must not be called for the already focused object.
fm.requestFocus(FocusNode1)
verify(FocusNode1, times(1)).onFocus()
- verify(FocusNode1, never()).onBlur()
+ verify(FocusNode1, never()).onBlur(any())
}
@Test
@@ -80,7 +82,7 @@
fm.registerFocusNode(id, node)
fm.requestFocusById(id)
verify(node, times(1)).onFocus()
- verify(node, never()).onBlur()
+ verify(node, never()).onBlur(any())
}
@Test
@@ -95,6 +97,19 @@
fm.unregisterFocusNode(id)
fm.requestFocusById(id)
verify(node, never()).onFocus()
- verify(node, never()).onBlur()
+ verify(node, never()).onBlur(any())
+ }
+
+ @Test
+ fun blur() {
+ val focusNode: FocusManager.FocusNode = mock()
+
+ val fm = FocusManager()
+ fm.requestFocus(focusNode)
+
+ // onBlur must be called to currently focused object, then onFocus is called to the next
+ // object.
+ fm.blur(focusNode)
+ verify(focusNode, times(1)).onBlur(eq(false /* hasNextClient */))
}
}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt
index 3685b3b..ade1767 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/BottomNavigationTest.kt
@@ -19,9 +19,9 @@
import androidx.ui.core.LastBaseline
import androidx.ui.core.LayoutCoordinates
import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
import androidx.ui.core.Text
import androidx.ui.core.globalPosition
+import androidx.ui.core.onPositioned
import androidx.ui.foundation.Box
import androidx.ui.foundation.Icon
import androidx.ui.material.icons.Icons
@@ -59,10 +59,11 @@
lateinit var parentCoords: LayoutCoordinates
val height = 56.dp
composeTestRule
- .setMaterialContentAndCollectSizes {
- OnPositioned { coords ->
+ .setMaterialContentAndCollectSizes(modifier =
+ onPositioned { coords ->
parentCoords = coords
}
+ ) {
BottomNavigationSample()
}
.assertWidthEqualsTo { parentCoords.size.width }
@@ -73,10 +74,9 @@
fun bottomNavigationItem_sizeAndPositions() {
lateinit var parentCoords: LayoutCoordinates
val itemCoords = mutableMapOf<Int, LayoutCoordinates>()
- composeTestRule.setMaterialContent {
- OnPositioned { coords ->
- parentCoords = coords
- }
+ composeTestRule.setMaterialContent(modifier = onPositioned { coords ->
+ parentCoords = coords
+ }) {
Box {
BottomNavigation {
repeat(4) { index ->
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
index fef24de..b0cf66c 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
@@ -20,11 +20,11 @@
import androidx.compose.state
import androidx.test.filters.MediumTest
import androidx.ui.core.LayoutCoordinates
-import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
import androidx.ui.core.TestTag
import androidx.ui.core.Text
import androidx.ui.core.currentTextStyle
+import androidx.ui.core.onChildPositioned
+import androidx.ui.core.onPositioned
import androidx.ui.layout.Center
import androidx.ui.layout.Column
import androidx.ui.layout.Stack
@@ -291,16 +291,9 @@
var parentCoordinates: LayoutCoordinates? = null
var childCoordinates: LayoutCoordinates? = null
composeTestRule.setMaterialContent {
- Stack {
+ Stack(onChildPositioned { parentCoordinates = it }) {
button {
- OnPositioned {
- parentCoordinates = it
- }
- OnChildPositioned(>
- childCoordinates = it
- }) {
- Text("Test button")
- }
+ Text("Test button", onPositioned { childCoordinates = it })
}
}
}
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
index bef16f7..7bf194e 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/DrawerTest.kt
@@ -21,8 +21,8 @@
import androidx.compose.emptyContent
import androidx.test.filters.MediumTest
import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
import androidx.ui.core.TestTag
+import androidx.ui.core.onPositioned
import androidx.ui.foundation.Clickable
import androidx.ui.layout.Container
import androidx.ui.semantics.Semantics
@@ -64,10 +64,9 @@
var position: PxPosition? = null
composeTestRule.setMaterialContent {
ModalDrawerLayout(DrawerState.Opened, {}, drawerContent = {
- Container(expanded = true) {
- OnPositioned { coords ->
- position = coords.localToGlobal(PxPosition.Origin)
- }
+ Container(onPositioned { coords ->
+ position = coords.localToGlobal(PxPosition.Origin)
+ }, expanded = true) {
}
}, bodyContent = emptyContent())
}
@@ -81,10 +80,9 @@
var position: PxPosition? = null
composeTestRule.setMaterialContent {
ModalDrawerLayout(DrawerState.Closed, {}, drawerContent = {
- Container(expanded = true) {
- OnPositioned { coords ->
- position = coords.localToGlobal(PxPosition.Origin)
- }
+ Container(onPositioned { coords ->
+ position = coords.localToGlobal(PxPosition.Origin)
+ }, expanded = true) {
}
}, bodyContent = emptyContent())
}
@@ -99,10 +97,9 @@
var size: IntPxSize? = null
composeTestRule.setMaterialContent {
ModalDrawerLayout(DrawerState.Opened, {}, drawerContent = {
- Container(expanded = true) {
- OnPositioned { coords ->
- size = coords.size
- }
+ Container(onPositioned { coords ->
+ size = coords.size
+ }, expanded = true) {
}
}, bodyContent = emptyContent())
}
@@ -119,10 +116,9 @@
var position: PxPosition? = null
composeTestRule.setMaterialContent {
BottomDrawerLayout(DrawerState.Opened, {}, drawerContent = {
- Container(expanded = true) {
- OnPositioned { coords ->
- position = coords.localToGlobal(PxPosition.Origin)
- }
+ Container(onPositioned { coords ->
+ position = coords.localToGlobal(PxPosition.Origin)
+ }, expanded = true) {
}
}, bodyContent = emptyContent())
}
@@ -141,10 +137,9 @@
var position: PxPosition? = null
composeTestRule.setMaterialContent {
BottomDrawerLayout(DrawerState.Closed, {}, drawerContent = {
- Container(expanded = true) {
- OnPositioned { coords ->
- position = coords.localToGlobal(PxPosition.Origin)
- }
+ Container(onPositioned { coords ->
+ position = coords.localToGlobal(PxPosition.Origin)
+ }, expanded = true) {
}
}, bodyContent = emptyContent())
}
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt
index 07bf5f7..1f0cf5d 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/MaterialTest.kt
@@ -17,6 +17,7 @@
package androidx.ui.material
import androidx.compose.Composable
+import androidx.ui.core.Modifier
import androidx.ui.layout.DpConstraints
import androidx.ui.test.BigTestConstraints
import androidx.ui.test.CollectedSizes
@@ -25,10 +26,13 @@
import androidx.ui.unit.Density
import androidx.ui.unit.PxSize
-fun ComposeTestRule.setMaterialContent(composable: @Composable() () -> Unit) {
+fun ComposeTestRule.setMaterialContent(
+ modifier: Modifier = Modifier.None,
+ composable: @Composable() () -> Unit
+) {
setContent {
MaterialTheme {
- Surface(children = composable)
+ Surface(modifier = modifier, children = composable)
}
}
}
@@ -38,21 +42,23 @@
}
}
fun ComposeTestRule.setMaterialContentAndCollectSizes(
+ modifier: Modifier = Modifier.None,
parentConstraints: DpConstraints = BigTestConstraints,
children: @Composable() () -> Unit
): CollectedSizes {
- val sizes = setMaterialContentAndGetPixelSize(parentConstraints, children)
+ val sizes = setMaterialContentAndGetPixelSize(modifier, parentConstraints, children)
return CollectedSizes(sizes, density)
}
fun ComposeTestRule.setMaterialContentAndGetPixelSize(
+ modifier: Modifier = Modifier.None,
parentConstraints: DpConstraints = BigTestConstraints,
children: @Composable() () -> Unit
): PxSize = setContentAndGetPixelSize(
parentConstraints,
- { setMaterialContent(it) }
+ { setMaterialContent(composable = it) }
) {
MaterialTheme {
- Surface(children = children)
+ Surface(modifier = modifier, children = children)
}
}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
index 813992e..70d9631 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
@@ -107,7 +107,7 @@
composeTestRule
.setMaterialContentAndCollectSizes(
- DpConstraints(maxWidth = 100.dp, maxHeight = 100.dp)
+ parentConstraints = DpConstraints(maxWidth = 100.dp, maxHeight = 100.dp)
) { Slider(position) }
.assertHeightEqualsTo(48.dp)
.assertWidthEqualsTo(100.dp)
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt b/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
index 07ba3cd..633c146 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/FloatingActionButton.kt
@@ -147,7 +147,7 @@
if (icon == null) {
Text(
text = text,
- style = textStyle,
+ style = textStyle ?: TextStyle.Default,
modifier = LayoutPadding(
start = ExtendedFabTextPadding,
end = ExtendedFabTextPadding
@@ -157,7 +157,7 @@
Row(LayoutPadding(start = ExtendedFabIconPadding, end = ExtendedFabTextPadding)) {
Image(image = icon)
Spacer(LayoutWidth(ExtendedFabIconPadding))
- Text(text = text, style = textStyle)
+ Text(text = text, style = textStyle ?: TextStyle.Default)
}
}
}
diff --git a/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt b/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt
index 6f443a1..60c86f1 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/input/TextInputServiceAndroid.kt
@@ -106,12 +106,17 @@
>
imm.restartInput(view)
+ editorHasFocus = false
}
override fun showSoftwareKeyboard() {
imm.showSoftInput(view, 0)
}
+ override fun hideSoftwareKeyboard() {
+ imm.hideSoftInputFromWindow(view.windowToken, 0)
+ }
+
override fun onStateUpdated(model: InputState) {
this.state = model
ic?.updateInputState(this.state, imm, view)
diff --git a/ui/ui-saved-instance-state/OWNERS b/ui/ui-saved-instance-state/OWNERS
new file mode 100644
index 0000000..5b1abd9
--- /dev/null
+++ b/ui/ui-saved-instance-state/OWNERS
@@ -0,0 +1 @@
+andreykulikov@google.com
\ No newline at end of file
diff --git a/ui/ui-saved-instance-state/api/0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/0.1.0-dev07.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/0.1.0-dev07.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+ public interface UiSavedStateRegistry {
+ method public boolean canBeSaved(Object value);
+ method public Object? consumeRestored(String key);
+ method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+ method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public void unregisterProvider(String key);
+ }
+
+ public final class UiSavedStateRegistryKt {
+ method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+ }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/current.txt b/ui/ui-saved-instance-state/api/current.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/current.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+ public interface UiSavedStateRegistry {
+ method public boolean canBeSaved(Object value);
+ method public Object? consumeRestored(String key);
+ method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+ method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public void unregisterProvider(String key);
+ }
+
+ public final class UiSavedStateRegistryKt {
+ method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+ }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/public_plus_experimental_0.1.0-dev07.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/public_plus_experimental_0.1.0-dev07.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+ public interface UiSavedStateRegistry {
+ method public boolean canBeSaved(Object value);
+ method public Object? consumeRestored(String key);
+ method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+ method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public void unregisterProvider(String key);
+ }
+
+ public final class UiSavedStateRegistryKt {
+ method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+ }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/public_plus_experimental_current.txt b/ui/ui-saved-instance-state/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/public_plus_experimental_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+ public interface UiSavedStateRegistry {
+ method public boolean canBeSaved(Object value);
+ method public Object? consumeRestored(String key);
+ method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+ method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public void unregisterProvider(String key);
+ }
+
+ public final class UiSavedStateRegistryKt {
+ method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+ }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/res-0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/res-0.1.0-dev07.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/res-0.1.0-dev07.txt
diff --git a/ui/ui-saved-instance-state/api/restricted_0.1.0-dev07.txt b/ui/ui-saved-instance-state/api/restricted_0.1.0-dev07.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/restricted_0.1.0-dev07.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+ public interface UiSavedStateRegistry {
+ method public boolean canBeSaved(Object value);
+ method public Object? consumeRestored(String key);
+ method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+ method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public void unregisterProvider(String key);
+ }
+
+ public final class UiSavedStateRegistryKt {
+ method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+ }
+
+}
+
diff --git a/ui/ui-saved-instance-state/api/restricted_current.txt b/ui/ui-saved-instance-state/api/restricted_current.txt
new file mode 100644
index 0000000..a0cffb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/api/restricted_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 3.0
+package androidx.ui.savedinstancestate {
+
+ public interface UiSavedStateRegistry {
+ method public boolean canBeSaved(Object value);
+ method public Object? consumeRestored(String key);
+ method public java.util.Map<java.lang.String,java.lang.Object> performSave();
+ method public void registerProvider(String key, kotlin.jvm.functions.Function0<?> valueProvider);
+ method public void unregisterProvider(String key);
+ }
+
+ public final class UiSavedStateRegistryKt {
+ method public static androidx.ui.savedinstancestate.UiSavedStateRegistry UiSavedStateRegistry(java.util.Map<java.lang.String,?>? restoredValues, kotlin.jvm.functions.Function1<java.lang.Object,java.lang.Boolean> canBeSaved);
+ }
+
+}
+
diff --git a/ui/ui-saved-instance-state/build.gradle b/ui/ui-saved-instance-state/build.gradle
new file mode 100644
index 0000000..a42851c
--- /dev/null
+++ b/ui/ui-saved-instance-state/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 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.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("AndroidXUiPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ kotlinPlugin project(path: ":compose:compose-compiler")
+
+ implementation(KOTLIN_STDLIB)
+
+ api "androidx.annotation:annotation:1.1.0"
+
+ api project(":compose:compose-runtime")
+
+ testImplementation(ANDROIDX_TEST_RULES)
+ testImplementation(ANDROIDX_TEST_RUNNER)
+ testImplementation(JUNIT)
+ testImplementation(TRUTH)
+}
+
+androidx {
+ name = "Compose Saved Instance State support"
+ publish = Publish.SNAPSHOT_AND_RELEASE
+ mavenVersion = LibraryVersions.UI
+ mavenGroup = LibraryGroups.UI
+ inceptionYear = "2020"
+ description = "Compose components that allows to save and restore the ui local state"
+}
+
+tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions {
+ useIR = true
+ }
+}
diff --git a/ui/ui-saved-instance-state/src/main/AndroidManifest.xml b/ui/ui-saved-instance-state/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..bb92a23
--- /dev/null
+++ b/ui/ui-saved-instance-state/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 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.
+ -->
+<manifest package="androidx.ui.savedinstancestate" />
diff --git a/ui/ui-saved-instance-state/src/main/java/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt b/ui/ui-saved-instance-state/src/main/java/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
new file mode 100644
index 0000000..f4aaeb5
--- /dev/null
+++ b/ui/ui-saved-instance-state/src/main/java/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2020 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.ui.savedinstancestate
+
+/**
+ * Allows components to save and restore their state using the saved instance state mechanism.
+ */
+interface UiSavedStateRegistry {
+ /**
+ * Returns the restored value for the given key.
+ * Once being restored the value is cleared, so you can't restore the same key twice.
+ *
+ * @param key Key used to save the value
+ */
+ fun consumeRestored(key: String): Any?
+
+ /**
+ * Registers the value provider.
+ *
+ * The same [key] cannot be registered twice, if you need to update the provider call
+ * [unregisterProvider] first and then register again.
+ *
+ * @param key Key to use for storing the value
+ * @param valueProvider Provides the current value, to be executed when [performSave]
+ * will be triggered to collect all the registered values
+ */
+ fun registerProvider(key: String, valueProvider: () -> Any?)
+
+ /**
+ * Unregisters the value provider previously registered via [registerProvider].
+ *
+ * @param key Key of the value which shouldn't be saved anymore
+ */
+ fun unregisterProvider(key: String)
+
+ /**
+ * Returns true if the value can be saved using this Registry.
+ * The default implementation will return true if this value can be stored in Bundle.
+ *
+ * @param value The value which we want to save using this Registry
+ */
+ fun canBeSaved(value: Any): Boolean
+
+ /**
+ * Executes all the registered value providers and combines these values into a key-value map.
+ */
+ fun performSave(): Map<String, Any>
+}
+
+/**
+ * Creates [UiSavedStateRegistry].
+ *
+ * @param restoredValues The map of the restored values
+ * @param canBeSaved Function which returns true if the given value can be saved by the registry
+ */
+fun UiSavedStateRegistry(
+ restoredValues: Map<String, Any>?,
+ canBeSaved: (Any) -> Boolean
+): UiSavedStateRegistry = UiSavedStateRegistryImpl(restoredValues, canBeSaved)
+
+private class UiSavedStateRegistryImpl(
+ restored: Map<String, Any>?,
+ private val canBeSaved: (Any) -> Boolean
+) : UiSavedStateRegistry {
+
+ private val restored: MutableMap<String, Any> = restored?.toMutableMap() ?: mutableMapOf()
+ private val valueProviders = mutableMapOf<String, () -> Any?>()
+
+ override fun canBeSaved(value: Any): Boolean = canBeSaved.invoke(value)
+
+ override fun consumeRestored(key: String): Any? = restored.remove(key)
+
+ override fun registerProvider(key: String, valueProvider: () -> Any?) {
+ require(key.isNotBlank()) { "Registered key is empty or blank" }
+ require(!valueProviders.contains(key)) {
+ "Key $key was already registered. Please call " +
+ "unregister before registering again"
+ }
+ @Suppress("UNCHECKED_CAST")
+ valueProviders[key] = valueProvider
+ }
+
+ override fun unregisterProvider(key: String) {
+ require(valueProviders.contains(key)) {
+ "Key $key wasn't registered, but unregister " +
+ "requested"
+ }
+ valueProviders.remove(key)
+ }
+
+ override fun performSave(): Map<String, Any> {
+ val map = restored.toMutableMap()
+ valueProviders.forEach {
+ val value = it.value()
+ if (value != null) {
+ check(canBeSaved(value))
+ map[it.key] = value
+ }
+ }
+ return map
+ }
+}
diff --git a/ui/ui-saved-instance-state/src/test/java/androidx/ui/savedinstancestate/UiSavedStateRegistryTest.kt b/ui/ui-saved-instance-state/src/test/java/androidx/ui/savedinstancestate/UiSavedStateRegistryTest.kt
new file mode 100644
index 0000000..d175ee9
--- /dev/null
+++ b/ui/ui-saved-instance-state/src/test/java/androidx/ui/savedinstancestate/UiSavedStateRegistryTest.kt
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2020 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.ui.savedinstancestate
+
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class UiSavedStateRegistryTest {
+
+ @Test
+ fun saveSimpleValue() {
+ val registry = createRegistry()
+
+ registry.registerProvider("key") { 10 }
+
+ registry.performSave().apply {
+ assertThat(get("key")).isEqualTo(10)
+ }
+ }
+
+ @Test
+ fun unregisteredValuesAreNotSaved() {
+ val registry = createRegistry()
+
+ registry.registerProvider("key") { 10 }
+ registry.unregisterProvider("key")
+
+ registry.performSave().apply {
+ assertThat(containsKey("key")).isFalse()
+ }
+ }
+
+ @Test
+ fun registerAgainAfterUnregister() {
+ val registry = createRegistry()
+
+ registry.registerProvider("key") { "value1" }
+ registry.unregisterProvider("key")
+ registry.registerProvider("key") { "value2" }
+
+ registry.performSave().apply {
+ assertThat(get("key")).isEqualTo("value2")
+ }
+ }
+
+ @Test
+ fun registerMultipleValues() {
+ val registry = createRegistry()
+
+ registry.registerProvider("key1") { 100L }
+ registry.registerProvider("key2") { 100L }
+ registry.registerProvider("key3") { "value" }
+ registry.registerProvider("key4") { listOf("item") }
+ registry.unregisterProvider("key2")
+
+ registry.performSave().apply {
+ assertThat(get("key1")).isEqualTo(100L)
+ assertThat(containsKey("key2")).isFalse()
+ assertThat(get("key3")).isEqualTo("value")
+ assertThat(get("key4")).isEqualTo(listOf("item"))
+ }
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun registeringTheSameKeysTwiceIsNotAllowed() {
+ val registry = createRegistry()
+
+ registry.registerProvider("key") { 100L }
+ registry.registerProvider("key") { 100L }
+ }
+
+ @Test
+ fun nullValuesAreNotSaved() {
+ val registry = createRegistry()
+
+ registry.registerProvider("key") { null }
+
+ registry.performSave().apply {
+ assertThat(containsKey("key")).isFalse()
+ }
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun emptyKeysAreNotAllowed() {
+ val registry = createRegistry()
+
+ registry.registerProvider("") { null }
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun blankKeysAreNotAllowed() {
+ val registry = createRegistry()
+
+ registry.registerProvider(" ") { null }
+ }
+
+ @Test
+ fun restoreSimpleValues() {
+ val restored = mapOf("key1" to "value", "key2" to 2f)
+ val registry = createRegistry(restored)
+
+ assertThat(registry.consumeRestored("key1")).isEqualTo("value")
+ assertThat(registry.consumeRestored("key2")).isEqualTo(2f)
+ }
+
+ @Test
+ fun restoreClearsTheStoredValue() {
+ val restored = mapOf("key" to "value")
+ val registry = createRegistry(restored)
+
+ assertThat(registry.consumeRestored("key")).isEqualTo("value")
+ assertThat(registry.consumeRestored("key")).isNull()
+ }
+
+ @Test
+ fun unusedRestoredValueSavedAgain() {
+ val restored = mapOf("key1" to "value")
+ val registry = createRegistry(restored)
+
+ registry.registerProvider("key2") { 1 }
+
+ registry.performSave().apply {
+ assertThat(get("key1")).isEqualTo("value")
+ assertThat(get("key2")).isEqualTo(1)
+ }
+ }
+
+ @Test
+ fun canBeSavedIsCallingOurCallback() {
+ var canBeSavedCalled = false
+ val registry = createRegistry {
+ canBeSavedCalled = true
+ it is String
+ }
+
+ assertThat(registry.canBeSaved(1)).isFalse()
+ assertThat(canBeSavedCalled).isTrue()
+
+ canBeSavedCalled = false
+ assertThat(registry.canBeSaved("test")).isTrue()
+ assertThat(canBeSavedCalled).isTrue()
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun valueWhichCantBeSavedIsNotAllowed() {
+ val registry = createRegistry { false }
+
+ registry.registerProvider("key") { 1 }
+
+ registry.performSave()
+ }
+
+ private fun createRegistry(
+ restored: Map<String, Any>? = null,
+ canBeSaved: (Any) -> Boolean = { true }
+ ) = UiSavedStateRegistry(restored, canBeSaved)
+}
\ No newline at end of file
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt
index f2d03fe..352eaef 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/LayoutCoordinatesHelperTest.kt
@@ -19,8 +19,7 @@
import androidx.test.filters.MediumTest
import androidx.ui.core.LayoutCoordinates
import androidx.ui.core.DensityAmbient
-import androidx.ui.core.OnChildPositioned
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.onPositioned
import androidx.ui.layout.Column
import androidx.ui.layout.Container
import androidx.ui.layout.LayoutGravity
@@ -51,17 +50,16 @@
var parentCoordinates: LayoutCoordinates? = null
var childCoordinates: LayoutCoordinates? = null
composeTestRule.setContent {
- Column {
- OnPositioned { coordinates ->
- parentCoordinates = coordinates
- latch.countDown()
- }
- OnChildPositioned( coordinates ->
- childCoordinates = coordinates
- latch.countDown()
- }) {
- Container(width = 10.dp, height = 10.dp, modifier = LayoutGravity.Start) {}
- }
+ Column(onPositioned { coordinates ->
+ parentCoordinates = coordinates
+ latch.countDown()
+ }) {
+ Container(width = 10.dp, height = 10.dp, modifier = LayoutGravity.Start +
+ onPositioned { coordinates ->
+ childCoordinates = coordinates
+ latch.countDown()
+ }
+ ) {}
}
}
@@ -78,21 +76,20 @@
composeTestRule.setContent {
with(DensityAmbient.current) {
Container(LayoutWidth(40.ipx.toDp())) {
- Column(LayoutWidth(20.ipx.toDp())) {
- OnPositioned { coordinates ->
- parentCoordinates = coordinates
- latch.countDown()
- }
- OnChildPositioned( coordinates ->
- childCoordinates = coordinates
- latch.countDown()
- }) {
- Container(
- width = 10.ipx.toDp(),
- height = 10.ipx.toDp(),
- modifier = LayoutGravity.Center
- ) {}
- }
+ Column(LayoutWidth(20.ipx.toDp()) +
+ onPositioned { coordinates ->
+ parentCoordinates = coordinates
+ latch.countDown()
+ }) {
+ Container(
+ width = 10.ipx.toDp(),
+ height = 10.ipx.toDp(),
+ modifier = LayoutGravity.Center +
+ onPositioned { coordinates ->
+ childCoordinates = coordinates
+ latch.countDown()
+ }
+ ) {}
}
}
}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt b/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt
index f9600d6..272a3f2 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/SizesTesting.kt
@@ -20,7 +20,7 @@
import androidx.ui.unit.Density
import androidx.ui.unit.Dp
import androidx.ui.unit.IntPx
-import androidx.ui.core.OnChildPositioned
+import androidx.ui.core.onChildPositioned
import androidx.ui.unit.PxSize
import androidx.ui.unit.dp
import androidx.ui.layout.DpConstraints
@@ -55,12 +55,10 @@
Stack {
Stack(
LayoutSize.Min(parentConstraints.minWidth, parentConstraints.minHeight) +
- LayoutSize.Max(parentConstraints.maxWidth, parentConstraints.maxHeight)
+ LayoutSize.Max(parentConstraints.maxWidth, parentConstraints.maxHeight) +
+ onChildPositioned { coordinates -> realSize = coordinates.size.toPxSize() }
) {
- OnChildPositioned(
- coordinates -> realSize = coordinates.size.toPxSize() },
- children = children
- )
+ children()
}
}
}
diff --git a/ui/ui-text/api/0.1.0-dev06.txt b/ui/ui-text/api/0.1.0-dev06.txt
index 8e3f6f5..ed15346 100644
--- a/ui/ui-text/api/0.1.0-dev06.txt
+++ b/ui/ui-text/api/0.1.0-dev06.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
diff --git a/ui/ui-text/api/0.1.0-dev07.txt b/ui/ui-text/api/0.1.0-dev07.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/0.1.0-dev07.txt
+++ b/ui/ui-text/api/0.1.0-dev07.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
}
public static final class TextStyle.Companion {
- method public androidx.ui.text.TextStyle getEmpty();
- property public final androidx.ui.text.TextStyle Empty;
+ method public androidx.ui.text.TextStyle getDefault();
+ property public final androidx.ui.text.TextStyle Default;
}
public final class TextStyleKt {
diff --git a/ui/ui-text/api/current.txt b/ui/ui-text/api/current.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/current.txt
+++ b/ui/ui-text/api/current.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
}
public static final class TextStyle.Companion {
- method public androidx.ui.text.TextStyle getEmpty();
- property public final androidx.ui.text.TextStyle Empty;
+ method public androidx.ui.text.TextStyle getDefault();
+ property public final androidx.ui.text.TextStyle Default;
}
public final class TextStyleKt {
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt
index 8e3f6f5..ed15346 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev06.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev07.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
}
public static final class TextStyle.Companion {
- method public androidx.ui.text.TextStyle getEmpty();
- property public final androidx.ui.text.TextStyle Empty;
+ method public androidx.ui.text.TextStyle getDefault();
+ property public final androidx.ui.text.TextStyle Default;
}
public final class TextStyleKt {
diff --git a/ui/ui-text/api/public_plus_experimental_current.txt b/ui/ui-text/api/public_plus_experimental_current.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/ui/ui-text/api/public_plus_experimental_current.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
}
public static final class TextStyle.Companion {
- method public androidx.ui.text.TextStyle getEmpty();
- property public final androidx.ui.text.TextStyle Empty;
+ method public androidx.ui.text.TextStyle getDefault();
+ property public final androidx.ui.text.TextStyle Default;
}
public final class TextStyleKt {
diff --git a/ui/ui-text/api/restricted_0.1.0-dev06.txt b/ui/ui-text/api/restricted_0.1.0-dev06.txt
index 8e3f6f5..ed15346 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev06.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev06.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
diff --git a/ui/ui-text/api/restricted_0.1.0-dev07.txt b/ui/ui-text/api/restricted_0.1.0-dev07.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev07.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev07.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
}
public static final class TextStyle.Companion {
- method public androidx.ui.text.TextStyle getEmpty();
- property public final androidx.ui.text.TextStyle Empty;
+ method public androidx.ui.text.TextStyle getDefault();
+ property public final androidx.ui.text.TextStyle Default;
}
public final class TextStyleKt {
diff --git a/ui/ui-text/api/restricted_current.txt b/ui/ui-text/api/restricted_current.txt
index 8e3f6f5..2310490 100644
--- a/ui/ui-text/api/restricted_current.txt
+++ b/ui/ui-text/api/restricted_current.txt
@@ -119,6 +119,7 @@
}
public interface PlatformTextInputService {
+ method public void hideSoftwareKeyboard();
method public void notifyFocusedRect(androidx.ui.geometry.Rect rect);
method public void onStateUpdated(androidx.ui.input.InputState model);
method public void showSoftwareKeyboard();
@@ -158,6 +159,7 @@
public class TextInputService {
ctor public TextInputService(androidx.ui.input.PlatformTextInputService platformTextInputService);
+ method public void hideSoftwareKeyboard(int token);
method public void notifyFocusedRect(int token, androidx.ui.geometry.Rect rect);
method public void onStateUpdated(int token, androidx.ui.input.InputState model);
method public void showSoftwareKeyboard(int token);
@@ -625,8 +627,8 @@
}
public static final class TextStyle.Companion {
- method public androidx.ui.text.TextStyle getEmpty();
- property public final androidx.ui.text.TextStyle Empty;
+ method public androidx.ui.text.TextStyle getDefault();
+ property public final androidx.ui.text.TextStyle Default;
}
public final class TextStyleKt {
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
index f9b7e4a..f0b351a 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
@@ -1628,6 +1628,40 @@
}
}
+ @Test
+ fun lineCount_withMaxLineSmallerThanTextLines() {
+ with(defaultDensity) {
+ val text = "a\na\na"
+ val fontSize = 100.sp
+ val lineCount = text.lines().size
+ val maxLines = lineCount - 1
+ val paragraph = simpleParagraph(
+ text = text,
+ style = TextStyle(fontSize = fontSize),
+ maxLines = maxLines
+ )
+
+ assertThat(paragraph.lineCount).isEqualTo(maxLines)
+ }
+ }
+
+ @Test
+ fun lineCount_withMaxLineGreaterThanTextLines() {
+ with(defaultDensity) {
+ val text = "a\na\na"
+ val fontSize = 100.sp
+ val lineCount = text.lines().size
+ val maxLines = lineCount + 1
+ val paragraph = simpleParagraph(
+ text = text,
+ style = TextStyle(fontSize = fontSize),
+ maxLines = maxLines
+ )
+
+ assertThat(paragraph.lineCount).isEqualTo(lineCount)
+ }
+ }
+
@Test(expected = java.lang.IllegalArgumentException::class)
fun maxLines_withMaxLineEqualsZero_throwsException() {
simpleParagraph(
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt
index b3815a3..e7ec69c 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextDelegateIntegrationTest.kt
@@ -54,7 +54,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -75,7 +75,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -99,7 +99,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -161,7 +161,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -216,7 +216,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -281,7 +281,7 @@
val selectionColor = Color(0x66AABB33)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -323,7 +323,7 @@
fun multiParagraphIntrinsics_isReused() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = "abc"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -353,7 +353,7 @@
fun TextLayoutInput_reLayout_withDifferentHeight() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = "Hello World!"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -375,7 +375,7 @@
fun TextLayoutResult_reLayout_withDifferentHeight() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = "Hello World!"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
index 409f75a..628b44e 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/TextLayoutResultIntegrationTest.kt
@@ -52,7 +52,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -74,7 +74,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -94,7 +94,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -110,7 +110,7 @@
fun layout_build_layoutResult() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = "Hello"),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -131,7 +131,7 @@
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -157,7 +157,7 @@
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = this,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -179,7 +179,7 @@
val annotatedString = AnnotatedString(text, spanStyle)
val textDelegate = TextDelegate(
text = annotatedString,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
diff --git a/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt b/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt
index e626d2e..f3ee0ac 100644
--- a/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/input/TextInputService.kt
@@ -89,6 +89,13 @@
platformTextInputService.showSoftwareKeyboard()
}
+ /**
+ * Hide onscreen keyboard
+ */
+ open fun hideSoftwareKeyboard(token: InputSessionToken) = ignoreIfExpired(token) {
+ platformTextInputService.hideSoftwareKeyboard()
+ }
+
/*
* Notify the new editor model to IME.
*/
@@ -131,6 +138,11 @@
*/
fun showSoftwareKeyboard()
+ /**
+ * Hide software keyboard
+ */
+ fun hideSoftwareKeyboard()
+
/*
* Notify the new editor model to IME.
*/
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt b/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt
index c1a1f3b..e2a8406 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/TextStyle.kt
@@ -160,7 +160,7 @@
* If the given text style is null, returns this text style.
*/
fun merge(other: TextStyle? = null): TextStyle {
- if (other == null) return this
+ if (other == null || other == Default) return this
return TextStyle(
spanStyle = toSpanStyle().merge(other.toSpanStyle()),
paragraphStyle = toParagraphStyle().merge(other.toParagraphStyle())
@@ -183,9 +183,9 @@
companion object {
/**
- * Constant for no text style.
+ * Constant for default text style.
*/
- val Empty = TextStyle()
+ val Default = TextStyle()
}
}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
index 498c302..a09c425 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
@@ -120,14 +120,7 @@
}
override val height: Float
- get() = layout.let {
- val lineCount = it.lineCount
- if (maxLines < lineCount) {
- it.getLineBottom(maxLines - 1)
- } else {
- it.height.toFloat()
- }
- }
+ get() = layout.height.toFloat()
override val maxIntrinsicWidth: Float
get() = paragraphIntrinsics.maxIntrinsicWidth
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
index 6531ca1..d1b7b81 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
@@ -36,7 +36,7 @@
fun `constructor with default values`() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = ""),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -51,7 +51,7 @@
val text = AnnotatedString("Hello")
val textDelegate = TextDelegate(
text = text,
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr
@@ -66,7 +66,7 @@
val textDelegate = TextDelegate(
text = AnnotatedString(text = ""),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
maxLines = maxLines,
density = density,
resourceLoader = resourceLoader,
@@ -82,7 +82,7 @@
val textDelegate = TextDelegate(
text = AnnotatedString(text = ""),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
overflow = overflow,
density = density,
resourceLoader = resourceLoader,
@@ -96,7 +96,7 @@
fun `minIntrinsicWidth without layout assertion should fail`() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = ""),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr)
@@ -108,7 +108,7 @@
fun `maxIntrinsicWidth without layout assertion should fail`() {
val textDelegate = TextDelegate(
text = AnnotatedString(text = ""),
- style = TextStyle.Empty,
+ style = TextStyle.Default,
density = density,
resourceLoader = resourceLoader,
layoutDirection = LayoutDirection.Ltr)
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
index 36ab1f4..7f6b960 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/ToolingTest.kt
@@ -19,8 +19,10 @@
import android.os.Handler
import androidx.compose.Composable
import androidx.test.rule.ActivityTestRule
-import androidx.ui.core.OnPositioned
+import androidx.ui.core.onPositioned
import androidx.ui.core.setContent
+import androidx.ui.foundation.Box
+import androidx.ui.layout.LayoutSize
import org.junit.Before
import org.junit.Rule
import java.util.concurrent.CountDownLatch
@@ -43,17 +45,12 @@
activityTestRule.onUiThread { handler = Handler() }
}
- @Composable
- internal fun Positioned() {
- OnPositioned( positionedLatch.countDown() })
- }
-
internal fun show(composable: @Composable() () -> Unit) {
positionedLatch = CountDownLatch(1)
activityTestRule.onUiThread {
activity.setContent {
- Positioned()
- composable()
+ Box(onPositioned { positionedLatch.countDown() } + LayoutSize.Fill,
+ children = composable)
}
}
diff --git a/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java b/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java
index 59472f5..c36bbd7 100644
--- a/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java
+++ b/vectordrawable/integration-tests/testapp/src/main/java/com/example/android/support/vectordrawable/app/SeekableDemo.java
@@ -93,7 +93,7 @@
seekBar.setMax((int) avd.getTotalDuration());
start.setOnClickListener((v) -> {
- if (!avd.isStarted()) {
+ if (!avd.isRunning()) {
avd.start();
} else if (!avd.isPaused()) {
avd.pause();
diff --git a/vectordrawable/vectordrawable-seekable/api/1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/1.0.0-alpha01.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/1.0.0-alpha01.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+ public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+ method public void clearAnimationCallbacks();
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public void draw(android.graphics.Canvas);
+ method @IntRange(from=0) public long getCurrentPlayTime();
+ method @Deprecated public int getOpacity();
+ method public long getTotalDuration();
+ method public boolean isPaused();
+ method public boolean isRunning();
+ method public void pause();
+ method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ method public void resume();
+ method public void setAlpha(@IntRange(from=0, to=255) int);
+ method public void setColorFilter(android.graphics.ColorFilter?);
+ method public void setCurrentPlayTime(@IntRange(from=0) long);
+ method public void start();
+ method public void stop();
+ method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ }
+
+ public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+ ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+ method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/current.txt b/vectordrawable/vectordrawable-seekable/api/current.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/current.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+ public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+ method public void clearAnimationCallbacks();
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public void draw(android.graphics.Canvas);
+ method @IntRange(from=0) public long getCurrentPlayTime();
+ method @Deprecated public int getOpacity();
+ method public long getTotalDuration();
+ method public boolean isPaused();
+ method public boolean isRunning();
+ method public void pause();
+ method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ method public void resume();
+ method public void setAlpha(@IntRange(from=0, to=255) int);
+ method public void setColorFilter(android.graphics.ColorFilter?);
+ method public void setCurrentPlayTime(@IntRange(from=0) long);
+ method public void start();
+ method public void stop();
+ method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ }
+
+ public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+ ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+ method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_1.0.0-alpha01.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+ public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+ method public void clearAnimationCallbacks();
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public void draw(android.graphics.Canvas);
+ method @IntRange(from=0) public long getCurrentPlayTime();
+ method @Deprecated public int getOpacity();
+ method public long getTotalDuration();
+ method public boolean isPaused();
+ method public boolean isRunning();
+ method public void pause();
+ method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ method public void resume();
+ method public void setAlpha(@IntRange(from=0, to=255) int);
+ method public void setColorFilter(android.graphics.ColorFilter?);
+ method public void setCurrentPlayTime(@IntRange(from=0) long);
+ method public void start();
+ method public void stop();
+ method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ }
+
+ public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+ ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+ method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_current.txt b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/public_plus_experimental_current.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+ public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+ method public void clearAnimationCallbacks();
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public void draw(android.graphics.Canvas);
+ method @IntRange(from=0) public long getCurrentPlayTime();
+ method @Deprecated public int getOpacity();
+ method public long getTotalDuration();
+ method public boolean isPaused();
+ method public boolean isRunning();
+ method public void pause();
+ method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ method public void resume();
+ method public void setAlpha(@IntRange(from=0, to=255) int);
+ method public void setColorFilter(android.graphics.ColorFilter?);
+ method public void setCurrentPlayTime(@IntRange(from=0) long);
+ method public void start();
+ method public void stop();
+ method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ }
+
+ public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+ ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+ method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/res-1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/res-1.0.0-alpha01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/res-1.0.0-alpha01.txt
diff --git a/vectordrawable/vectordrawable-seekable/api/restricted_1.0.0-alpha01.txt b/vectordrawable/vectordrawable-seekable/api/restricted_1.0.0-alpha01.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/restricted_1.0.0-alpha01.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+ public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+ method public void clearAnimationCallbacks();
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public void draw(android.graphics.Canvas);
+ method @IntRange(from=0) public long getCurrentPlayTime();
+ method @Deprecated public int getOpacity();
+ method public long getTotalDuration();
+ method public boolean isPaused();
+ method public boolean isRunning();
+ method public void pause();
+ method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ method public void resume();
+ method public void setAlpha(@IntRange(from=0, to=255) int);
+ method public void setColorFilter(android.graphics.ColorFilter?);
+ method public void setCurrentPlayTime(@IntRange(from=0) long);
+ method public void start();
+ method public void stop();
+ method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ }
+
+ public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+ ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+ method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/api/restricted_current.txt b/vectordrawable/vectordrawable-seekable/api/restricted_current.txt
new file mode 100644
index 0000000..dc158b1
--- /dev/null
+++ b/vectordrawable/vectordrawable-seekable/api/restricted_current.txt
@@ -0,0 +1,35 @@
+// Signature format: 3.0
+package androidx.vectordrawable.graphics.drawable {
+
+ public class SeekableAnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+ method public void clearAnimationCallbacks();
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable? create(android.content.Context, @DrawableRes int);
+ method public static androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme?) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public void draw(android.graphics.Canvas);
+ method @IntRange(from=0) public long getCurrentPlayTime();
+ method @Deprecated public int getOpacity();
+ method public long getTotalDuration();
+ method public boolean isPaused();
+ method public boolean isRunning();
+ method public void pause();
+ method public void registerAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ method public void resume();
+ method public void setAlpha(@IntRange(from=0, to=255) int);
+ method public void setColorFilter(android.graphics.ColorFilter?);
+ method public void setCurrentPlayTime(@IntRange(from=0) long);
+ method public void start();
+ method public void stop();
+ method public boolean unregisterAnimationCallback(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable.AnimationCallback);
+ }
+
+ public abstract static class SeekableAnimatedVectorDrawable.AnimationCallback {
+ ctor public SeekableAnimatedVectorDrawable.AnimationCallback();
+ method public void onAnimationEnd(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationPause(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationResume(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationStart(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ method public void onAnimationUpdate(androidx.vectordrawable.graphics.drawable.SeekableAnimatedVectorDrawable);
+ }
+
+}
+
diff --git a/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java b/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java
index 7dcaa9d..bd117b2 100644
--- a/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java
+++ b/vectordrawable/vectordrawable-seekable/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/SeekableAnimatedVectorDrawableTest.java
@@ -302,7 +302,7 @@
assertThat(bitmap.getPixel(0, 0)).isEqualTo(Color.RED);
avd.start();
- assertThat(avd.isStarted()).isTrue();
+ assertThat(avd.isRunning()).isTrue();
assertThat(avd.isPaused()).isFalse();
animationRule.advanceTimeBy(100L);
avd.draw(canvas);
@@ -310,14 +310,14 @@
assertThat(Color.red(pausedColor)).isLessThan(0xff);
avd.pause();
- assertThat(avd.isStarted()).isTrue();
+ assertThat(avd.isRunning()).isTrue();
assertThat(avd.isPaused()).isTrue();
animationRule.advanceTimeBy(1000L);
avd.draw(canvas);
assertThat(bitmap.getPixel(0, 0)).isEqualTo(pausedColor);
avd.resume();
- assertThat(avd.isStarted()).isTrue();
+ assertThat(avd.isRunning()).isTrue();
assertThat(avd.isPaused()).isFalse();
animationRule.advanceTimeBy(100L);
avd.draw(canvas);
diff --git a/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java b/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java
index 838d098..6600573 100644
--- a/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java
+++ b/vectordrawable/vectordrawable-seekable/src/main/java/androidx/vectordrawable/graphics/drawable/SeekableAnimatedVectorDrawable.java
@@ -581,15 +581,21 @@
}
}
+ /**
+ * Returns whether the animation is running (has started and not yet ended).
+ *
+ * @return {@code true} if the animation is running.
+ */
@Override
public boolean isRunning() {
return mAnimatedVectorState.mAnimatorSet.isRunning();
}
- public boolean isStarted() {
- return mAnimatedVectorState.mAnimatorSet.isStarted();
- }
-
+ /**
+ * Returns whether the animation is currently in a paused state.
+ *
+ * @return {@code true} if the animation is paused.
+ */
public boolean isPaused() {
return mAnimatedVectorState.mAnimatorSet.isPaused();
}
diff --git a/webkit/integration-tests/testapp/src/main/res/values/styles.xml b/webkit/integration-tests/testapp/src/main/res/values/styles.xml
index 3bb68e4..c4c7a20 100644
--- a/webkit/integration-tests/testapp/src/main/res/values/styles.xml
+++ b/webkit/integration-tests/testapp/src/main/res/values/styles.xml
@@ -15,7 +15,8 @@
~ limitations under the License.
-->
-<resources>
+<resources xmlns:tools="http://schemas.android.com/tools"
+ tools:ignore="NewApi">
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
index f6b3999..31433d2 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
@@ -744,7 +744,7 @@
*/
// WebViewRenderProcessClient is a callback class, so it should be last. See
// https://issuetracker.google.com/issues/139770271.
- @SuppressLint("LambdaLast")
+ @SuppressLint({"LambdaLast", "NewApi"})
@RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setWebViewRenderProcessClient(
@@ -784,6 +784,7 @@
* @param webViewRenderProcessClient the {@link WebViewRenderProcessClient} to set for
* callbacks.
*/
+ @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setWebViewRenderProcessClient(
@@ -814,6 +815,7 @@
* {@link #setWebViewRenderProcessClient(WebView,WebViewRenderProcessClient)} or {@code null}
* otherwise.
*/
+ @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @Nullable WebViewRenderProcessClient getWebViewRenderProcessClient(
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java
index cc64ac5..936275a 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessClientFrameworkAdapter.java
@@ -20,11 +20,13 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import androidx.webkit.WebViewRenderProcessClient;
/**
* Adapter class to pass a {@link android.webkit.WebViewRenderProcessClient} over to chromium.
*/
+@RequiresApi(29)
public class WebViewRenderProcessClientFrameworkAdapter extends
android.webkit.WebViewRenderProcessClient {
private WebViewRenderProcessClient mWebViewRenderProcessClient;
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
index 4ce5462..b1d3040 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
@@ -16,6 +16,8 @@
package androidx.webkit.internal;
+import android.annotation.SuppressLint;
+
import androidx.annotation.NonNull;
import androidx.webkit.WebViewFeature;
import androidx.webkit.WebViewRenderProcess;
@@ -84,6 +86,7 @@
return renderer;
}
+ @SuppressLint("NewApi")
@Override
public boolean terminate() {
final WebViewFeatureInternal feature =
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java
index 899463c..533b154 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDeviceState.java
@@ -55,7 +55,7 @@
}
/**
- * Get the current posture of the foldable device.
+ * Gets the current posture of the foldable device.
*/
@Posture
public int getPosture() {
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java
index 90b0468..eceedb1 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionDisplayFeature.java
@@ -64,13 +64,13 @@
mType = type;
}
- /** Get the bounding rect of the display feature in window coordinate space. */
+ /** Gets the bounding rect of the display feature in window coordinate space. */
@NonNull
public Rect getBounds() {
return mBounds;
}
- /** Get the type of the display feature. */
+ /** Gets the type of the display feature. */
@Type
public int getType() {
return mType;
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java
index 6b1720f..b73ee6c 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionInterface.java
@@ -31,38 +31,38 @@
public interface ExtensionInterface {
/**
- * Register the support library as the callback for the extension. This interface will be used
+ * Registers the support library as the callback for the extension. This interface will be used
* to report all extension changes to the support library.
*/
void setExtensionCallback(@NonNull ExtensionCallback callback);
/**
- * Get current information about the display features present within the application window.
+ * Gets current information about the display features present within the application window.
*/
@NonNull
ExtensionWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken);
/**
- * Notify extension that a listener for display feature layout changes was registered for the
+ * Notifies extension that a listener for display feature layout changes was registered for the
* given window token.
*/
void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken);
/**
- * Notify extension that a listener for display feature layout changes was removed for the
+ * Notifies extension that a listener for display feature layout changes was removed for the
* given window token.
*/
void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken);
/**
- * Get current device state.
+ * Gets current device state.
* @see #onDeviceStateListenersChanged(boolean)
*/
@NonNull
ExtensionDeviceState getDeviceState();
/**
- * Notify the extension that a device state change listener was updated.
+ * Notifies the extension that a device state change listener was updated.
* @param isEmpty flag indicating if the list of device state change listeners is empty.
*/
void onDeviceStateListenersChanged(boolean isEmpty);
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java
index 46d213e..067736e 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionProvider.java
@@ -33,7 +33,7 @@
private ExtensionProvider() {}
/**
- * Instantiate the Extension for the use by the WindowManager library.
+ * Instantiates the Extension for the use by the WindowManager library.
*
* <p>The library will instantiate the vendor implementation using this interface.
* @return A compatible version of the {@link ExtensionInterface} for the provided library
@@ -45,7 +45,7 @@
}
/**
- * Get the version of the vendor library on this device. If the returned version is not
+ * Gets the version of the vendor library on this device. If the returned version is not
* supported by the WindowManager library, then some functions may not be available or
* replaced with stub implementations.
*
diff --git a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java
index 2cd77a3..fdc931d 100644
--- a/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java
+++ b/window/window-extensions/src/main/java/androidx/window/extensions/ExtensionWindowLayoutInfo.java
@@ -42,7 +42,7 @@
}
/**
- * Get the list of display features present within the window.
+ * Gets the list of display features present within the window.
*/
@Nullable
public List<ExtensionDisplayFeature> getDisplayFeatures() {
diff --git a/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt b/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt
index fae4092..46a203f 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/DisplayFeaturesActivity.kt
@@ -68,7 +68,7 @@
windowManager.unregisterLayoutChangeCallback(layoutStateChangeCallback)
}
- /** Update the device state and display feature positions. */
+ /** Updates the device state and display feature positions. */
internal fun updateCurrentState() {
// Cleanup previously added feature views
val rootLayout = findViewById<FrameLayout>(R.id.featureContainerLayout)
@@ -118,7 +118,7 @@
findViewById<TextView>(R.id.currentState).text = stateStringBuilder.toString()
}
- /** Add the current state to the text log of changes on screen. */
+ /** Adds the current state to the text log of changes on screen. */
internal fun updateStateLog(info: Any) {
stateLog.append(getCurrentTimeString())
.append(" ")
diff --git a/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt b/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
index 5e78b29..958d5a1 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/PresentationActivity.kt
@@ -135,7 +135,7 @@
}
/**
- * Update the display of the current device state.
+ * Updates the display of the current device state.
*/
internal fun updateCurrentState(deviceState: DeviceState) {
val stateStringBuilder = StringBuilder()
diff --git a/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt b/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
index 2a79691..2907a9e 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/SampleTools.kt
@@ -22,7 +22,7 @@
import androidx.window.DisplayFeature
/**
- * Get the bounds of the display feature translated to the View's coordinate space and current
+ * Gets the bounds of the display feature translated to the View's coordinate space and current
* position in the window. This will also include view padding in the calculations.
*/
fun getFeaturePositionInViewRect(
@@ -60,7 +60,7 @@
}
/**
- * Get the layout params for placing a rectangle indicating a display feature inside a
+ * Gets the layout params for placing a rectangle indicating a display feature inside a
* [FrameLayout].
*/
fun getLayoutParamsForFeatureInFrameLayout(displayFeature: DisplayFeature, view: FrameLayout):
diff --git a/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt b/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
index c57c5bb..25b7105 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/SplitLayout.kt
@@ -109,7 +109,7 @@
}
/**
- * Get the position of the split for this view.
+ * Gets the position of the split for this view.
* @return A rect that defines of split, or {@code null} if there is no split.
*/
private fun splitViewPositions(startView: View?, endView: View?): Array<Rect>? {
@@ -165,7 +165,7 @@
}
/**
- * Measure a child view and see it if will fit in the provided rect.
+ * Measures a child view and sees if it will fit in the provided rect.
* <p>Note: This method calls [View.measure] on the child view, which updates
* its stored values for measured with and height. If the view will end up with different
* values, it should be measured again.
diff --git a/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt b/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
index a57c905..47950da 100644
--- a/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
+++ b/window/window-samples/src/main/java/androidx/window/sample/backend/MidScreenFoldBackend.kt
@@ -66,7 +66,7 @@
}
/**
- * Unwrap the hierarchy of [ContextWrapper]-s until [Activity] is reached.
+ * Unwraps the hierarchy of [ContextWrapper]-s until [Activity] is reached.
* @return Base [Activity] context or `null` if not available.
*/
private fun getActivityFromContext(c: Context?): Activity? {
diff --git a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java
index 39dcca4..fd431c4 100644
--- a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java
+++ b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarDisplayFeature.java
@@ -60,23 +60,23 @@
})
@interface Type{}
- /** Get the bounding rect of the display feature in window coordinate space. */
+ /** Gets the bounding rect of the display feature in window coordinate space. */
@NonNull
public Rect getRect() {
return mRect;
}
- /** Set the bounding rect of the display feature in window coordinate space. */
+ /** Sets the bounding rect of the display feature in window coordinate space. */
public void setRect(@NonNull Rect rect) {
mRect.set(rect);
}
- /** Get the type of the display feature. */
+ /** Gets the type of the display feature. */
public @Type int getType() {
return mType;
}
- /** Set the type of the display feature. */
+ /** Sets the type of the display feature. */
public void setType(@Type int type) {
mType = type;
}
diff --git a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java
index 3b90b27..5b445da 100644
--- a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java
+++ b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarInterface.java
@@ -29,38 +29,38 @@
public interface SidecarInterface {
/**
- * Register the support library as the callback for the sidecar. This interface will be used to
+ * Registers the support library as the callback for the sidecar. This interface will be used to
* report all sidecar changes to the support library.
*/
void setSidecarCallback(@NonNull SidecarCallback callback);
/**
- * Get current information about the display features present within the application window.
+ * Gets current information about the display features present within the application window.
*/
@NonNull
SidecarWindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken);
/**
- * Notify sidecar that a listener for display feature layout changes was registered for the
+ * Notifies sidecar that a listener for display feature layout changes was registered for the
* given window token.
*/
void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken);
/**
- * Notify sidecar that a listener for display feature layout changes was removed for the
+ * Notifies sidecar that a listener for display feature layout changes was removed for the
* given window token.
*/
void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken);
/**
- * Get current device state.
+ * Gets current device state.
* @see #onDeviceStateListenersChanged(boolean)
*/
@NonNull
SidecarDeviceState getDeviceState();
/**
- * Notify the sidecar that a device state change listener was updated.
+ * Notifies the sidecar that a device state change listener was updated.
* @param isEmpty flag indicating if the list of device state change listeners is empty.
*/
void onDeviceStateListenersChanged(boolean isEmpty);
diff --git a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java
index 701e16c..8f41fa7a 100644
--- a/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java
+++ b/window/window-sidecar/src/main/java/androidx/window/sidecar/SidecarProvider.java
@@ -32,7 +32,7 @@
private SidecarProvider() {}
/**
- * Instantiate the Sidecar for the use by the WindowManager library.
+ * Instantiates the Sidecar for the use by the WindowManager library.
*
* <p>The library will instantiate the vendor implementation using this interface.
* @return A compatible version of the {@link SidecarInterface} for the provided library
@@ -44,7 +44,7 @@
}
/**
- * Get the version of the vendor library on this device. If the returned version is not
+ * Gets the version of the vendor library on this device. If the returned version is not
* supported by the WindowManager library, then some functions may not be available or
* replaced with stub implementations.
*
diff --git a/window/window/src/androidTest/java/androidx/window/TestActivity.java b/window/window/src/androidTest/java/androidx/window/TestActivity.java
index 931acf9..ee73aac 100644
--- a/window/window/src/androidTest/java/androidx/window/TestActivity.java
+++ b/window/window/src/androidTest/java/androidx/window/TestActivity.java
@@ -64,7 +64,7 @@
}
/**
- * Reset layout counter when waiting for a layout to happen before calling
+ * Resets layout counter when waiting for a layout to happen before calling
* {@link #waitForLayout()}.
*/
public void resetLayoutCounter() {
@@ -72,7 +72,7 @@
}
/**
- * Block and wait for the next layout to happen. {@link #resetLayoutCounter()} must be called
+ * Blocks and waits for the next layout to happen. {@link #resetLayoutCounter()} must be called
* before calling this method.
* @return {@code true} if the layout happened before the timeout count reached zero and
* {@code false} if the waiting time elapsed before the layout happened.
@@ -86,7 +86,7 @@
}
/**
- * Reset layout counter when waiting for a layout to happen before calling
+ * Resets layout counter when waiting for a layout to happen before calling
* {@link #waitForOnResume()}.
*/
public static void resetResumeCounter() {
diff --git a/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java b/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java
index 60f2226..86e3e93 100644
--- a/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java
+++ b/window/window/src/androidTest/java/androidx/window/WindowBackendTest.java
@@ -40,7 +40,7 @@
public final class WindowBackendTest extends WindowTestBase {
/**
- * Verify that {@link WindowManager} instance would use the assigned
+ * Verifies that {@link WindowManager} instance would use the assigned
* {@link WindowBackend}.
*/
@Test
diff --git a/window/window/src/main/java/androidx/window/DeviceState.java b/window/window/src/main/java/androidx/window/DeviceState.java
index 1765622..b0b70a3 100644
--- a/window/window/src/main/java/androidx/window/DeviceState.java
+++ b/window/window/src/main/java/androidx/window/DeviceState.java
@@ -91,7 +91,7 @@
}
/**
- * Get the posture of a foldable device with a flexible screen or multiple physical screens.
+ * Gets the posture of a foldable device with a flexible screen or multiple physical screens.
* Devices with a single rigid display will always report {@link #POSTURE_UNKNOWN}.
*/
@Posture
@@ -136,7 +136,7 @@
}
/**
- * Set the posture for the {@link DeviceState} instance.
+ * Sets the posture for the {@link DeviceState} instance.
*/
@NonNull
public Builder setPosture(@Posture int posture) {
diff --git a/window/window/src/main/java/androidx/window/DisplayFeature.java b/window/window/src/main/java/androidx/window/DisplayFeature.java
index a7eb874..0a46eab 100644
--- a/window/window/src/main/java/androidx/window/DisplayFeature.java
+++ b/window/window/src/main/java/androidx/window/DisplayFeature.java
@@ -49,9 +49,9 @@
}
/**
- * Get bounding rectangle of the physical display feature in the coordinate space of the window.
- * The rectangle provides information about the location of the feature in the window and its
- * size.
+ * Gets bounding rectangle of the physical display feature in the coordinate space of the
+ * window. The rectangle provides information about the location of the feature in the window
+ * and its size.
*/
@NonNull
public Rect getBounds() {
@@ -59,7 +59,7 @@
}
/**
- * Get type of the physical display feature.
+ * Gets type of the physical display feature.
*/
@Type
public int getType() {
@@ -115,7 +115,7 @@
}
/**
- * Set the bounds for the {@link DisplayFeature} instance.
+ * Sets the bounds for the {@link DisplayFeature} instance.
*/
@NonNull
public Builder setBounds(@NonNull Rect bounds) {
@@ -124,7 +124,7 @@
}
/**
- * Set the type for the {@link DisplayFeature} instance.
+ * Sets the type for the {@link DisplayFeature} instance.
*/
@NonNull
public Builder setType(@Type int type) {
diff --git a/window/window/src/main/java/androidx/window/ExtensionCompat.java b/window/window/src/main/java/androidx/window/ExtensionCompat.java
index 35d428c..87960fe 100644
--- a/window/window/src/main/java/androidx/window/ExtensionCompat.java
+++ b/window/window/src/main/java/androidx/window/ExtensionCompat.java
@@ -127,8 +127,8 @@
}
/**
- * Convert the display feature from extension. Can return {@code null} if there is an issue with
- * the value passed from extension.
+ * Converts the display feature from extension. Can return {@code null} if there is an issue
+ * with the value passed from extension.
*/
@Nullable
private static DisplayFeature displayFeatureFromExtension(ExtensionDisplayFeature feature) {
@@ -194,7 +194,7 @@
return new DeviceState(posture);
}
- /** Verify that extension implementation corresponds to the interface of the version. */
+ /** Verifies that extension implementation corresponds to the interface of the version. */
@Override
@SuppressWarnings("unused")
public boolean validateExtensionInterface() {
diff --git a/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java b/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java
index 3f19eba..5b26fef 100644
--- a/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java
+++ b/window/window/src/main/java/androidx/window/ExtensionInterfaceCompat.java
@@ -28,42 +28,42 @@
interface ExtensionInterfaceCompat {
/**
- * Verify if the extension interface conforms to the declared version.
+ * Verifies if the extension interface conforms to the declared version.
*/
boolean validateExtensionInterface();
/**
- * Set the callback that is used by the extension to inform about hardware state changes.
+ * Sets the callback that is used by the extension to inform about hardware state changes.
*/
void setExtensionCallback(@NonNull ExtensionCallbackInterface extensionCallback);
/**
- * Get current information about the display features present within the application window.
+ * Gets current information about the display features present within the application window.
*/
@NonNull
WindowLayoutInfo getWindowLayoutInfo(@NonNull IBinder windowToken);
/**
- * Notify extension that a listener for display feature layout changes was registered for the
+ * Notifies extension that a listener for display feature layout changes was registered for the
* given window token.
*/
void onWindowLayoutChangeListenerAdded(@NonNull IBinder windowToken);
/**
- * Notify extension that a listener for display feature layout changes was removed for the
+ * Notifies extension that a listener for display feature layout changes was removed for the
* given window token.
*/
void onWindowLayoutChangeListenerRemoved(@NonNull IBinder windowToken);
/**
- * Get current device state.
+ * Gets current device state.
* @see #onDeviceStateListenersChanged(boolean)
*/
@NonNull
DeviceState getDeviceState();
/**
- * Notify the extension that a device state change listener was updated.
+ * Notifies the extension that a device state change listener was updated.
* @param isEmpty flag indicating if the list of device state change listeners is empty.
*/
void onDeviceStateListenersChanged(boolean isEmpty);
diff --git a/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java b/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
index da9e589..c4098b3 100644
--- a/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
+++ b/window/window/src/main/java/androidx/window/ExtensionWindowBackend.java
@@ -83,7 +83,7 @@
}
/**
- * Get the shared instance of the class.
+ * Gets the shared instance of the class.
*/
@NonNull
public static ExtensionWindowBackend getInstance(@NonNull Context context) {
@@ -98,7 +98,7 @@
return sInstance;
}
- /** Try to initialize Extension, returns early if it's not available. */
+ /** Tries to initialize Extension, returns early if it's not available. */
@SuppressLint("SyntheticAccessor")
@GuardedBy("sLock")
private void initExtension(Context context) {
@@ -201,7 +201,7 @@
}
/**
- * Check if there are no more registered callbacks left for the token and inform extension if
+ * Checks if there are no more registered callbacks left for the token and inform extension if
* needed.
*/
@GuardedBy("sLock")
@@ -363,7 +363,7 @@
}
/**
- * Load an instance of {@link ExtensionInterface} implemented by OEM if available on this
+ * Loads an instance of {@link ExtensionInterface} implemented by OEM if available on this
* device. This also verifies if the loaded implementation conforms to the declared API version.
*/
@Nullable
@@ -400,7 +400,7 @@
}
/**
- * Check if the Extension version provided on this device is supported by the current version
+ * Checks if the Extension version provided on this device is supported by the current version
* of the library.
*/
@VisibleForTesting
diff --git a/window/window/src/main/java/androidx/window/SidecarCompat.java b/window/window/src/main/java/androidx/window/SidecarCompat.java
index 1f5f554..7dd9b80 100644
--- a/window/window/src/main/java/androidx/window/SidecarCompat.java
+++ b/window/window/src/main/java/androidx/window/SidecarCompat.java
@@ -212,8 +212,8 @@
}
/**
- * Convert the display feature from extension. Can return {@code null} if there is an issue with
- * the value passed from extension.
+ * Converts the display feature from extension. Can return {@code null} if there is an issue
+ * with the value passed from extension.
*/
@Nullable
private static DisplayFeature displayFeatureFromExtension(SidecarDisplayFeature feature) {
diff --git a/window/window/src/main/java/androidx/window/WindowBackend.java b/window/window/src/main/java/androidx/window/WindowBackend.java
index 7bcf861..37321f0 100644
--- a/window/window/src/main/java/androidx/window/WindowBackend.java
+++ b/window/window/src/main/java/androidx/window/WindowBackend.java
@@ -31,38 +31,38 @@
*/
public interface WindowBackend {
/**
- * Get current window layout information for the provided {@link Context}. Must be called
+ * Gets current window layout information for the provided {@link Context}. Must be called
* only after the it is attached to the window and the layout pass has happened.
*/
@NonNull
WindowLayoutInfo getWindowLayoutInfo(@NonNull Context context);
/**
- * Get the current device state.
+ * Gets the current device state.
*/
@NonNull
DeviceState getDeviceState();
/**
- * Register a callback for layout changes of the window of the current visual {@link Context}.
+ * Registers a callback for layout changes of the window of the current visual {@link Context}.
* Must be called only after the it is attached to the window.
*/
void registerLayoutChangeCallback(@NonNull Context context, @NonNull Executor executor,
@NonNull Consumer<WindowLayoutInfo> callback);
/**
- * Unregister a callback for window layout changes of the {@link Context} window.
+ * Unregisters a callback for window layout changes of the {@link Context} window.
*/
void unregisterLayoutChangeCallback(@NonNull Consumer<WindowLayoutInfo> callback);
/**
- * Register a callback for device state changes.
+ * Registers a callback for device state changes.
*/
void registerDeviceStateChangeCallback(@NonNull Executor executor,
@NonNull Consumer<DeviceState> callback);
/**
- * Unregister a callback for device state changes.
+ * Unregisters a callback for device state changes.
*/
void unregisterDeviceStateChangeCallback(@NonNull Consumer<DeviceState> callback);
}
diff --git a/window/window/src/main/java/androidx/window/WindowLayoutInfo.java b/window/window/src/main/java/androidx/window/WindowLayoutInfo.java
index 7a812df..e926090 100644
--- a/window/window/src/main/java/androidx/window/WindowLayoutInfo.java
+++ b/window/window/src/main/java/androidx/window/WindowLayoutInfo.java
@@ -41,7 +41,7 @@
}
/**
- * Get the list of physical display features within the window.
+ * Gets the list of physical display features within the window.
*/
@NonNull
public List<DisplayFeature> getDisplayFeatures() {
@@ -77,7 +77,7 @@
}
/**
- * Set the display features for the {@link WindowLayoutInfo} instance.
+ * Sets the display features for the {@link WindowLayoutInfo} instance.
*/
@NonNull
public Builder setDisplayFeatures(@NonNull List<DisplayFeature> displayFeatures) {
diff --git a/window/window/src/main/java/androidx/window/WindowManager.java b/window/window/src/main/java/androidx/window/WindowManager.java
index c6caf69..def4990 100644
--- a/window/window/src/main/java/androidx/window/WindowManager.java
+++ b/window/window/src/main/java/androidx/window/WindowManager.java
@@ -45,7 +45,7 @@
private WindowBackend mWindowBackend;
/**
- * Get an instance of the class initialized with and connected to the provided {@link Context}.
+ * Gets an instance of the class initialized with and connected to the provided {@link Context}.
* All methods of this class will return information that is associated with this visual
* context.
* @param context A visual context, such as an {@link Activity} or a {@link ContextWrapper}
@@ -66,7 +66,7 @@
}
/**
- * Get current window layout information for the associated {@link Context}. Must be called
+ * Gets current window layout information for the associated {@link Context}. Must be called
* only after the it is attached to the window and the layout pass has happened.
* @see Activity#onAttachedToWindow()
* @see WindowLayoutInfo
@@ -77,7 +77,7 @@
}
/**
- * Get the current device state.
+ * Gets the current device state.
* @see DeviceState
*/
@NonNull
@@ -86,7 +86,7 @@
}
/**
- * Register a callback for layout changes of the window of the current visual {@link Context}.
+ * Registers a callback for layout changes of the window of the current visual {@link Context}.
* Must be called only after the it is attached to the window.
* @see Activity#onAttachedToWindow()
*/
@@ -96,14 +96,14 @@
}
/**
- * Unregister a callback for window layout changes of the window.
+ * Unregisters a callback for window layout changes of the window.
*/
public void unregisterLayoutChangeCallback(@NonNull Consumer<WindowLayoutInfo> callback) {
mWindowBackend.unregisterLayoutChangeCallback(callback);
}
/**
- * Register a callback for device state changes.
+ * Registers a callback for device state changes.
*/
public void registerDeviceStateChangeCallback(@NonNull Executor executor,
@NonNull Consumer<DeviceState> callback) {
@@ -111,14 +111,14 @@
}
/**
- * Unregister a callback for device state changes.
+ * Unregisters a callback for device state changes.
*/
public void unregisterDeviceStateChangeCallback(@NonNull Consumer<DeviceState> callback) {
mWindowBackend.unregisterDeviceStateChangeCallback(callback);
}
/**
- * Unwrap the hierarchy of {@link ContextWrapper}-s until {@link Activity} is reached.
+ * Unwraps the hierarchy of {@link ContextWrapper}-s until {@link Activity} is reached.
* @return Base {@link Activity} context or {@code null} if not available.
*/
@Nullable
diff --git a/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt b/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt
index 88f7c8b..a4c7cf6 100644
--- a/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt
+++ b/work/workmanager-lint/src/main/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetector.kt
@@ -67,10 +67,10 @@
if (node.valueArgumentCount >= 2) {
val type = node.valueArguments[1].getExpressionType()?.canonicalText
if ("long" == type) {
- val value = node.valueArguments[1].evaluate() as Long
+ val value = node.valueArguments[1].evaluate() as? Long
// TimeUnit
val units = node.valueArguments[2].evaluate() as? Pair<ClassId, Name>
- if (units != null) {
+ if (value != null && units != null) {
val (_, timeUnitType) = units
val interval: Long? = when (timeUnitType.identifier) {
"NANOSECONDS" -> TimeUnit.MINUTES.convert(value, TimeUnit.NANOSECONDS)
diff --git a/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt b/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
index 038fe54..3110fea 100644
--- a/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
+++ b/work/workmanager-lint/src/test/java/androidx/work/lint/InvalidPeriodicWorkRequestIntervalDetectorTest.kt
@@ -212,4 +212,47 @@
.run()
.expectClean()
}
+
+ @Test
+ fun testWithPeriodicRequestHelper() {
+ val worker = kotlin(
+ "com/example/TestWorker.kt",
+ """
+ package com.example
+
+ import androidx.work.ListenableWorker
+
+ class TestWorker: ListenableWorker() {
+
+ }
+ """
+ ).indented().within("src")
+
+ val snippet = kotlin(
+ "com/example/Test.kt",
+ """
+ package com.example
+
+ import androidx.work.PeriodicWorkRequest
+ import com.example.TestWorker
+ import java.util.concurrent.TimeUnit
+
+ class Test {
+ fun buildPeriodicRequest(interval: Long) {
+ val worker = TestWorker()
+ val builder = PeriodicWorkRequest.Builder(worker, interval, TimeUnit.MINUTES)
+ }
+ }
+ """
+ ).indented().within("src")
+
+ lint().files(
+ LISTENABLE_WORKER,
+ PERIODIC_WORK_REQUEST,
+ worker,
+ snippet
+ ).issues(InvalidPeriodicWorkRequestIntervalDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
}