Merge "Implement DataStore.CorruptionHandler" into androidx-master-dev
diff --git a/activity/activity-ktx/api/1.2.0-alpha06.ignore b/activity/activity-ktx/api/1.2.0-alpha06.ignore
new file mode 100644
index 0000000..762b574
--- /dev/null
+++ b/activity/activity-ktx/api/1.2.0-alpha06.ignore
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+ChangedType: androidx.activity.ActivityViewModelLazyKt#viewModels(androidx.activity.ComponentActivity, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Method androidx.activity.ActivityViewModelLazyKt.viewModels has changed return type from kotlin.Lazy<VM> to kotlin.Lazy<? extends VM>
+
+
+InvalidNullConversion: androidx.activity.ActivityViewModelLazyKt#viewModels(androidx.activity.ComponentActivity, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Attempted to remove @NonNull annotation from method androidx.activity.ActivityViewModelLazyKt.viewModels(androidx.activity.ComponentActivity,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>)
diff --git a/activity/activity-ktx/api/1.2.0-alpha06.txt b/activity/activity-ktx/api/1.2.0-alpha06.txt
new file mode 100644
index 0000000..7ece866
--- /dev/null
+++ b/activity/activity-ktx/api/1.2.0-alpha06.txt
@@ -0,0 +1,27 @@
+// Signature format: 3.0
+package androidx.activity {
+
+ public final class ActivityViewModelLazyKt {
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! viewModels(androidx.activity.ComponentActivity, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ }
+
+ public final class OnBackPressedDispatcherKt {
+ method public static androidx.activity.OnBackPressedCallback addCallback(androidx.activity.OnBackPressedDispatcher, androidx.lifecycle.LifecycleOwner? owner = null, boolean enabled = true, kotlin.jvm.functions.Function1<? super androidx.activity.OnBackPressedCallback,kotlin.Unit> onBackPressed);
+ }
+
+}
+
+package androidx.activity.result {
+
+ public final class ActivityResultCallerKt {
+ method public static inline <I, O> kotlin.jvm.functions.Function0<kotlin.Unit> registerForActivityResult(androidx.activity.result.ActivityResultCaller, androidx.activity.result.contract.ActivityResultContract<I,O> contract, I? input, androidx.activity.result.ActivityResultRegistry registry, kotlin.jvm.functions.Function1<? super O,kotlin.Unit> callback);
+ method public static inline <I, O> kotlin.jvm.functions.Function0<kotlin.Unit> registerForActivityResult(androidx.activity.result.ActivityResultCaller, androidx.activity.result.contract.ActivityResultContract<I,O> contract, I? input, kotlin.jvm.functions.Function1<? super O,kotlin.Unit> callback);
+ }
+
+ public final class ActivityResultLauncherKt {
+ method public static void launch(androidx.activity.result.ActivityResultLauncher<java.lang.Void>, androidx.core.app.ActivityOptionsCompat? options = null);
+ method public static void launchUnit(androidx.activity.result.ActivityResultLauncher<kotlin.Unit>, androidx.core.app.ActivityOptionsCompat? options = null);
+ }
+
+}
+
diff --git a/activity/activity-ktx/api/public_plus_experimental_1.2.0-alpha06.txt b/activity/activity-ktx/api/public_plus_experimental_1.2.0-alpha06.txt
new file mode 100644
index 0000000..7ece866
--- /dev/null
+++ b/activity/activity-ktx/api/public_plus_experimental_1.2.0-alpha06.txt
@@ -0,0 +1,27 @@
+// Signature format: 3.0
+package androidx.activity {
+
+ public final class ActivityViewModelLazyKt {
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! viewModels(androidx.activity.ComponentActivity, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ }
+
+ public final class OnBackPressedDispatcherKt {
+ method public static androidx.activity.OnBackPressedCallback addCallback(androidx.activity.OnBackPressedDispatcher, androidx.lifecycle.LifecycleOwner? owner = null, boolean enabled = true, kotlin.jvm.functions.Function1<? super androidx.activity.OnBackPressedCallback,kotlin.Unit> onBackPressed);
+ }
+
+}
+
+package androidx.activity.result {
+
+ public final class ActivityResultCallerKt {
+ method public static inline <I, O> kotlin.jvm.functions.Function0<kotlin.Unit> registerForActivityResult(androidx.activity.result.ActivityResultCaller, androidx.activity.result.contract.ActivityResultContract<I,O> contract, I? input, androidx.activity.result.ActivityResultRegistry registry, kotlin.jvm.functions.Function1<? super O,kotlin.Unit> callback);
+ method public static inline <I, O> kotlin.jvm.functions.Function0<kotlin.Unit> registerForActivityResult(androidx.activity.result.ActivityResultCaller, androidx.activity.result.contract.ActivityResultContract<I,O> contract, I? input, kotlin.jvm.functions.Function1<? super O,kotlin.Unit> callback);
+ }
+
+ public final class ActivityResultLauncherKt {
+ method public static void launch(androidx.activity.result.ActivityResultLauncher<java.lang.Void>, androidx.core.app.ActivityOptionsCompat? options = null);
+ method public static void launchUnit(androidx.activity.result.ActivityResultLauncher<kotlin.Unit>, androidx.core.app.ActivityOptionsCompat? options = null);
+ }
+
+}
+
diff --git a/activity/activity-ktx/api/res-1.2.0-alpha06.txt b/activity/activity-ktx/api/res-1.2.0-alpha06.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/activity/activity-ktx/api/res-1.2.0-alpha06.txt
diff --git a/activity/activity-ktx/api/restricted_1.2.0-alpha06.ignore b/activity/activity-ktx/api/restricted_1.2.0-alpha06.ignore
new file mode 100644
index 0000000..762b574
--- /dev/null
+++ b/activity/activity-ktx/api/restricted_1.2.0-alpha06.ignore
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+ChangedType: androidx.activity.ActivityViewModelLazyKt#viewModels(androidx.activity.ComponentActivity, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Method androidx.activity.ActivityViewModelLazyKt.viewModels has changed return type from kotlin.Lazy<VM> to kotlin.Lazy<? extends VM>
+
+
+InvalidNullConversion: androidx.activity.ActivityViewModelLazyKt#viewModels(androidx.activity.ComponentActivity, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Attempted to remove @NonNull annotation from method androidx.activity.ActivityViewModelLazyKt.viewModels(androidx.activity.ComponentActivity,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>)
diff --git a/activity/activity-ktx/api/restricted_1.2.0-alpha06.txt b/activity/activity-ktx/api/restricted_1.2.0-alpha06.txt
new file mode 100644
index 0000000..7ece866
--- /dev/null
+++ b/activity/activity-ktx/api/restricted_1.2.0-alpha06.txt
@@ -0,0 +1,27 @@
+// Signature format: 3.0
+package androidx.activity {
+
+ public final class ActivityViewModelLazyKt {
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! viewModels(androidx.activity.ComponentActivity, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ }
+
+ public final class OnBackPressedDispatcherKt {
+ method public static androidx.activity.OnBackPressedCallback addCallback(androidx.activity.OnBackPressedDispatcher, androidx.lifecycle.LifecycleOwner? owner = null, boolean enabled = true, kotlin.jvm.functions.Function1<? super androidx.activity.OnBackPressedCallback,kotlin.Unit> onBackPressed);
+ }
+
+}
+
+package androidx.activity.result {
+
+ public final class ActivityResultCallerKt {
+ method public static inline <I, O> kotlin.jvm.functions.Function0<kotlin.Unit> registerForActivityResult(androidx.activity.result.ActivityResultCaller, androidx.activity.result.contract.ActivityResultContract<I,O> contract, I? input, androidx.activity.result.ActivityResultRegistry registry, kotlin.jvm.functions.Function1<? super O,kotlin.Unit> callback);
+ method public static inline <I, O> kotlin.jvm.functions.Function0<kotlin.Unit> registerForActivityResult(androidx.activity.result.ActivityResultCaller, androidx.activity.result.contract.ActivityResultContract<I,O> contract, I? input, kotlin.jvm.functions.Function1<? super O,kotlin.Unit> callback);
+ }
+
+ public final class ActivityResultLauncherKt {
+ method public static void launch(androidx.activity.result.ActivityResultLauncher<java.lang.Void>, androidx.core.app.ActivityOptionsCompat? options = null);
+ method public static void launchUnit(androidx.activity.result.ActivityResultLauncher<kotlin.Unit>, androidx.core.app.ActivityOptionsCompat? options = null);
+ }
+
+}
+
diff --git a/activity/activity/api/1.2.0-alpha06.txt b/activity/activity/api/1.2.0-alpha06.txt
new file mode 100644
index 0000000..a57478dd
--- /dev/null
+++ b/activity/activity/api/1.2.0-alpha06.txt
@@ -0,0 +1,232 @@
+// Signature format: 3.0
+package androidx.activity {
+
+ public class ComponentActivity extends android.app.Activity implements androidx.activity.result.ActivityResultCaller androidx.activity.result.ActivityResultRegistryOwner androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.activity.OnBackPressedDispatcherOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+ ctor public ComponentActivity();
+ ctor @ContentView public ComponentActivity(@LayoutRes int);
+ method public final androidx.activity.result.ActivityResultRegistry getActivityResultRegistry();
+ method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+ method @Deprecated public Object? getLastCustomNonConfigurationInstance();
+ method public androidx.lifecycle.Lifecycle getLifecycle();
+ method public final androidx.activity.OnBackPressedDispatcher getOnBackPressedDispatcher();
+ method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+ method public androidx.lifecycle.ViewModelStore getViewModelStore();
+ method @Deprecated @CallSuper protected void onActivityResult(int, int, android.content.Intent?);
+ method @Deprecated @CallSuper public void onRequestPermissionsResult(int, String![], int[]);
+ method @Deprecated public Object? onRetainCustomNonConfigurationInstance();
+ method public final Object? onRetainNonConfigurationInstance();
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int) throws android.content.IntentSender.SendIntentException;
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ }
+
+ public abstract class OnBackPressedCallback {
+ ctor public OnBackPressedCallback(boolean);
+ method @MainThread public abstract void handleOnBackPressed();
+ method @MainThread public final boolean isEnabled();
+ method @MainThread public final void remove();
+ method @MainThread public final void setEnabled(boolean);
+ }
+
+ public final class OnBackPressedDispatcher {
+ ctor public OnBackPressedDispatcher();
+ ctor public OnBackPressedDispatcher(Runnable?);
+ method @MainThread public void addCallback(androidx.activity.OnBackPressedCallback);
+ method @MainThread public void addCallback(androidx.lifecycle.LifecycleOwner, androidx.activity.OnBackPressedCallback);
+ method @MainThread public boolean hasEnabledCallbacks();
+ method @MainThread public void onBackPressed();
+ }
+
+ public interface OnBackPressedDispatcherOwner extends androidx.lifecycle.LifecycleOwner {
+ method public androidx.activity.OnBackPressedDispatcher getOnBackPressedDispatcher();
+ }
+
+}
+
+package androidx.activity.result {
+
+ public final class ActivityResult implements android.os.Parcelable {
+ ctor public ActivityResult(int, android.content.Intent?);
+ method public int describeContents();
+ method public android.content.Intent? getData();
+ method public int getResultCode();
+ method public static String resultCodeToString(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.activity.result.ActivityResult!> CREATOR;
+ }
+
+ public interface ActivityResultCallback<O> {
+ method public void onActivityResult(O!);
+ }
+
+ public interface ActivityResultCaller {
+ method public <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ }
+
+ public abstract class ActivityResultLauncher<I> {
+ ctor public ActivityResultLauncher();
+ method public void launch(I!);
+ method public abstract void launch(I!, androidx.core.app.ActivityOptionsCompat?);
+ method @MainThread public abstract void unregister();
+ }
+
+ public abstract class ActivityResultRegistry {
+ ctor public ActivityResultRegistry();
+ method @MainThread public final boolean dispatchResult(int, int, android.content.Intent?);
+ method @MainThread public final <O> boolean dispatchResult(int, O!);
+ method @MainThread public abstract <I, O> void invoke(int, androidx.activity.result.contract.ActivityResultContract<I!,O!>, I!, androidx.core.app.ActivityOptionsCompat?);
+ method public final void onRestoreInstanceState(android.os.Bundle?);
+ method public final void onSaveInstanceState(android.os.Bundle);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> register(String, androidx.lifecycle.LifecycleOwner, androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> register(String, androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ }
+
+ public interface ActivityResultRegistryOwner {
+ method public androidx.activity.result.ActivityResultRegistry getActivityResultRegistry();
+ }
+
+ public final class IntentSenderRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.content.Intent? getFillInIntent();
+ method public int getFlagsMask();
+ method public int getFlagsValues();
+ method public android.content.IntentSender getIntentSender();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.activity.result.IntentSenderRequest!> CREATOR;
+ }
+
+ public static final class IntentSenderRequest.Builder {
+ ctor public IntentSenderRequest.Builder(android.content.IntentSender);
+ ctor public IntentSenderRequest.Builder(android.app.PendingIntent);
+ method public androidx.activity.result.IntentSenderRequest build();
+ method public androidx.activity.result.IntentSenderRequest.Builder setFillInIntent(android.content.Intent?);
+ method public androidx.activity.result.IntentSenderRequest.Builder setFlags(int, int);
+ }
+
+}
+
+package androidx.activity.result.contract {
+
+ public abstract class ActivityResultContract<I, O> {
+ ctor public ActivityResultContract();
+ method public abstract android.content.Intent createIntent(android.content.Context, I!);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<O!>? getSynchronousResult(android.content.Context, I!);
+ method public abstract O! parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContract.SynchronousResult<T> {
+ ctor public ActivityResultContract.SynchronousResult(T!);
+ method public T! getValue();
+ }
+
+ public final class ActivityResultContracts {
+ }
+
+ public static class ActivityResultContracts.CreateDocument extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,android.net.Uri> {
+ ctor public ActivityResultContracts.CreateDocument();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.GetContent extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,android.net.Uri> {
+ ctor public ActivityResultContracts.GetContent();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.GetMultipleContents extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,java.util.List<android.net.Uri>> {
+ ctor public ActivityResultContracts.GetMultipleContents();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.List<android.net.Uri!>!>? getSynchronousResult(android.content.Context, String);
+ method public final java.util.List<android.net.Uri!> parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenDocument extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],android.net.Uri> {
+ ctor public ActivityResultContracts.OpenDocument();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String![]);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String![]);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenDocumentTree extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,android.net.Uri> {
+ ctor public ActivityResultContracts.OpenDocumentTree();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri?);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, android.net.Uri?);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenMultipleDocuments extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],java.util.List<android.net.Uri>> {
+ ctor public ActivityResultContracts.OpenMultipleDocuments();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String![]);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.List<android.net.Uri!>!>? getSynchronousResult(android.content.Context, String![]);
+ method public final java.util.List<android.net.Uri!>? parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.PickContact extends androidx.activity.result.contract.ActivityResultContract<java.lang.Void,android.net.Uri> {
+ ctor public ActivityResultContracts.PickContact();
+ method public android.content.Intent createIntent(android.content.Context, Void?);
+ method public android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.RequestMultiplePermissions extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],java.util.Map<java.lang.String,java.lang.Boolean>> {
+ ctor public ActivityResultContracts.RequestMultiplePermissions();
+ method public android.content.Intent createIntent(android.content.Context, String![]);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.Map<java.lang.String!,java.lang.Boolean!>!>? getSynchronousResult(android.content.Context, String![]?);
+ method public java.util.Map<java.lang.String!,java.lang.Boolean!> parseResult(int, android.content.Intent?);
+ field public static final String ACTION_REQUEST_PERMISSIONS = "androidx.activity.result.contract.action.REQUEST_PERMISSIONS";
+ field public static final String EXTRA_PERMISSIONS = "androidx.activity.result.contract.extra.PERMISSIONS";
+ field public static final String EXTRA_PERMISSION_GRANT_RESULTS = "androidx.activity.result.contract.extra.PERMISSION_GRANT_RESULTS";
+ }
+
+ public static final class ActivityResultContracts.RequestPermission extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,java.lang.Boolean> {
+ ctor public ActivityResultContracts.RequestPermission();
+ method public android.content.Intent createIntent(android.content.Context, String);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.lang.Boolean!>? getSynchronousResult(android.content.Context, String?);
+ method public Boolean parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.StartActivityForResult extends androidx.activity.result.contract.ActivityResultContract<android.content.Intent,androidx.activity.result.ActivityResult> {
+ ctor public ActivityResultContracts.StartActivityForResult();
+ method public android.content.Intent createIntent(android.content.Context, android.content.Intent);
+ method public androidx.activity.result.ActivityResult parseResult(int, android.content.Intent?);
+ field public static final String EXTRA_ACTIVITY_OPTIONS_BUNDLE = "androidx.activity.result.contract.extra.ACTIVITY_OPTIONS_BUNDLE";
+ }
+
+ public static final class ActivityResultContracts.StartIntentSenderForResult extends androidx.activity.result.contract.ActivityResultContract<androidx.activity.result.IntentSenderRequest,androidx.activity.result.ActivityResult> {
+ ctor public ActivityResultContracts.StartIntentSenderForResult();
+ method public android.content.Intent createIntent(android.content.Context, androidx.activity.result.IntentSenderRequest);
+ method public androidx.activity.result.ActivityResult parseResult(int, android.content.Intent?);
+ field public static final String ACTION_INTENT_SENDER_REQUEST = "androidx.activity.result.contract.action.INTENT_SENDER_REQUEST";
+ field public static final String EXTRA_INTENT_SENDER_REQUEST = "androidx.activity.result.contract.extra.INTENT_SENDER_REQUEST";
+ field public static final String EXTRA_SEND_INTENT_EXCEPTION = "androidx.activity.result.contract.extra.SEND_INTENT_EXCEPTION";
+ }
+
+ public static class ActivityResultContracts.TakePicture extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,java.lang.Boolean> {
+ ctor public ActivityResultContracts.TakePicture();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.lang.Boolean!>? getSynchronousResult(android.content.Context, android.net.Uri);
+ method public final Boolean parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.TakePicturePreview extends androidx.activity.result.contract.ActivityResultContract<java.lang.Void,android.graphics.Bitmap> {
+ ctor public ActivityResultContracts.TakePicturePreview();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, Void?);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.graphics.Bitmap!>? getSynchronousResult(android.content.Context, Void?);
+ method public final android.graphics.Bitmap? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.TakeVideo extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,android.graphics.Bitmap> {
+ ctor public ActivityResultContracts.TakeVideo();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.graphics.Bitmap!>? getSynchronousResult(android.content.Context, android.net.Uri);
+ method public final android.graphics.Bitmap? parseResult(int, android.content.Intent?);
+ }
+
+}
+
diff --git a/activity/activity/api/api_lint.ignore b/activity/activity/api/api_lint.ignore
index 64382c3..d22641b 100644
--- a/activity/activity/api/api_lint.ignore
+++ b/activity/activity/api/api_lint.ignore
@@ -1,12 +1,12 @@
// Baseline format: 1.0
-CallbackMethodName: androidx.activity.OnBackPressedCallback:
- Callback method names must follow the on<Something> style: setEnabled
-
-
ForbiddenSuperClass: androidx.activity.ComponentActivity:
ComponentActivity should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead.
+KotlinOperator: androidx.activity.result.ActivityResultRegistry#invoke(int, androidx.activity.result.contract.ActivityResultContract<I,O>, I, androidx.core.app.ActivityOptionsCompat):
+ Method can be invoked with function call syntax from Kotlin: `invoke` (this is usually desirable; just make sure it makes sense for this type of object)
+
+
MissingNullability: androidx.activity.ComponentActivity#startActivityForResult(android.content.Intent, int) parameter #0:
Missing nullability on parameter `intent` in method `startActivityForResult`
MissingNullability: androidx.activity.ComponentActivity#startActivityForResult(android.content.Intent, int, android.os.Bundle) parameter #0:
diff --git a/activity/activity/api/public_plus_experimental_1.2.0-alpha06.txt b/activity/activity/api/public_plus_experimental_1.2.0-alpha06.txt
new file mode 100644
index 0000000..4053dc1
--- /dev/null
+++ b/activity/activity/api/public_plus_experimental_1.2.0-alpha06.txt
@@ -0,0 +1,231 @@
+// Signature format: 3.0
+package androidx.activity {
+
+ public class ComponentActivity extends androidx.core.app.ComponentActivity implements androidx.activity.result.ActivityResultCaller androidx.activity.result.ActivityResultRegistryOwner androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.activity.OnBackPressedDispatcherOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+ ctor public ComponentActivity();
+ ctor @ContentView public ComponentActivity(@LayoutRes int);
+ method public final androidx.activity.result.ActivityResultRegistry getActivityResultRegistry();
+ method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+ method @Deprecated public Object? getLastCustomNonConfigurationInstance();
+ method public final androidx.activity.OnBackPressedDispatcher getOnBackPressedDispatcher();
+ method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+ method public androidx.lifecycle.ViewModelStore getViewModelStore();
+ method @Deprecated @CallSuper protected void onActivityResult(int, int, android.content.Intent?);
+ method @Deprecated @CallSuper public void onRequestPermissionsResult(int, String![], int[]);
+ method @Deprecated public Object? onRetainCustomNonConfigurationInstance();
+ method public final Object? onRetainNonConfigurationInstance();
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int) throws android.content.IntentSender.SendIntentException;
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ }
+
+ public abstract class OnBackPressedCallback {
+ ctor public OnBackPressedCallback(boolean);
+ method @MainThread public abstract void handleOnBackPressed();
+ method @MainThread public final boolean isEnabled();
+ method @MainThread public final void remove();
+ method @MainThread public final void setEnabled(boolean);
+ }
+
+ public final class OnBackPressedDispatcher {
+ ctor public OnBackPressedDispatcher();
+ ctor public OnBackPressedDispatcher(Runnable?);
+ method @MainThread public void addCallback(androidx.activity.OnBackPressedCallback);
+ method @MainThread public void addCallback(androidx.lifecycle.LifecycleOwner, androidx.activity.OnBackPressedCallback);
+ method @MainThread public boolean hasEnabledCallbacks();
+ method @MainThread public void onBackPressed();
+ }
+
+ public interface OnBackPressedDispatcherOwner extends androidx.lifecycle.LifecycleOwner {
+ method public androidx.activity.OnBackPressedDispatcher getOnBackPressedDispatcher();
+ }
+
+}
+
+package androidx.activity.result {
+
+ public final class ActivityResult implements android.os.Parcelable {
+ ctor public ActivityResult(int, android.content.Intent?);
+ method public int describeContents();
+ method public android.content.Intent? getData();
+ method public int getResultCode();
+ method public static String resultCodeToString(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.activity.result.ActivityResult!> CREATOR;
+ }
+
+ public interface ActivityResultCallback<O> {
+ method public void onActivityResult(O!);
+ }
+
+ public interface ActivityResultCaller {
+ method public <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ }
+
+ public abstract class ActivityResultLauncher<I> {
+ ctor public ActivityResultLauncher();
+ method public void launch(I!);
+ method public abstract void launch(I!, androidx.core.app.ActivityOptionsCompat?);
+ method @MainThread public abstract void unregister();
+ }
+
+ public abstract class ActivityResultRegistry {
+ ctor public ActivityResultRegistry();
+ method @MainThread public final boolean dispatchResult(int, int, android.content.Intent?);
+ method @MainThread public final <O> boolean dispatchResult(int, O!);
+ method @MainThread public abstract <I, O> void invoke(int, androidx.activity.result.contract.ActivityResultContract<I!,O!>, I!, androidx.core.app.ActivityOptionsCompat?);
+ method public final void onRestoreInstanceState(android.os.Bundle?);
+ method public final void onSaveInstanceState(android.os.Bundle);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> register(String, androidx.lifecycle.LifecycleOwner, androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> register(String, androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ }
+
+ public interface ActivityResultRegistryOwner {
+ method public androidx.activity.result.ActivityResultRegistry getActivityResultRegistry();
+ }
+
+ public final class IntentSenderRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.content.Intent? getFillInIntent();
+ method public int getFlagsMask();
+ method public int getFlagsValues();
+ method public android.content.IntentSender getIntentSender();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.activity.result.IntentSenderRequest!> CREATOR;
+ }
+
+ public static final class IntentSenderRequest.Builder {
+ ctor public IntentSenderRequest.Builder(android.content.IntentSender);
+ ctor public IntentSenderRequest.Builder(android.app.PendingIntent);
+ method public androidx.activity.result.IntentSenderRequest build();
+ method public androidx.activity.result.IntentSenderRequest.Builder setFillInIntent(android.content.Intent?);
+ method public androidx.activity.result.IntentSenderRequest.Builder setFlags(int, int);
+ }
+
+}
+
+package androidx.activity.result.contract {
+
+ public abstract class ActivityResultContract<I, O> {
+ ctor public ActivityResultContract();
+ method public abstract android.content.Intent createIntent(android.content.Context, I!);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<O!>? getSynchronousResult(android.content.Context, I!);
+ method public abstract O! parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContract.SynchronousResult<T> {
+ ctor public ActivityResultContract.SynchronousResult(T!);
+ method public T! getValue();
+ }
+
+ public final class ActivityResultContracts {
+ }
+
+ public static class ActivityResultContracts.CreateDocument extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,android.net.Uri> {
+ ctor public ActivityResultContracts.CreateDocument();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.GetContent extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,android.net.Uri> {
+ ctor public ActivityResultContracts.GetContent();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.GetMultipleContents extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,java.util.List<android.net.Uri>> {
+ ctor public ActivityResultContracts.GetMultipleContents();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.List<android.net.Uri!>!>? getSynchronousResult(android.content.Context, String);
+ method public final java.util.List<android.net.Uri!> parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenDocument extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],android.net.Uri> {
+ ctor public ActivityResultContracts.OpenDocument();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String![]);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String![]);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenDocumentTree extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,android.net.Uri> {
+ ctor public ActivityResultContracts.OpenDocumentTree();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri?);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, android.net.Uri?);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenMultipleDocuments extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],java.util.List<android.net.Uri>> {
+ ctor public ActivityResultContracts.OpenMultipleDocuments();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String![]);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.List<android.net.Uri!>!>? getSynchronousResult(android.content.Context, String![]);
+ method public final java.util.List<android.net.Uri!>? parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.PickContact extends androidx.activity.result.contract.ActivityResultContract<java.lang.Void,android.net.Uri> {
+ ctor public ActivityResultContracts.PickContact();
+ method public android.content.Intent createIntent(android.content.Context, Void?);
+ method public android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.RequestMultiplePermissions extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],java.util.Map<java.lang.String,java.lang.Boolean>> {
+ ctor public ActivityResultContracts.RequestMultiplePermissions();
+ method public android.content.Intent createIntent(android.content.Context, String![]);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.Map<java.lang.String!,java.lang.Boolean!>!>? getSynchronousResult(android.content.Context, String![]?);
+ method public java.util.Map<java.lang.String!,java.lang.Boolean!> parseResult(int, android.content.Intent?);
+ field public static final String ACTION_REQUEST_PERMISSIONS = "androidx.activity.result.contract.action.REQUEST_PERMISSIONS";
+ field public static final String EXTRA_PERMISSIONS = "androidx.activity.result.contract.extra.PERMISSIONS";
+ field public static final String EXTRA_PERMISSION_GRANT_RESULTS = "androidx.activity.result.contract.extra.PERMISSION_GRANT_RESULTS";
+ }
+
+ public static final class ActivityResultContracts.RequestPermission extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,java.lang.Boolean> {
+ ctor public ActivityResultContracts.RequestPermission();
+ method public android.content.Intent createIntent(android.content.Context, String);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.lang.Boolean!>? getSynchronousResult(android.content.Context, String?);
+ method public Boolean parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.StartActivityForResult extends androidx.activity.result.contract.ActivityResultContract<android.content.Intent,androidx.activity.result.ActivityResult> {
+ ctor public ActivityResultContracts.StartActivityForResult();
+ method public android.content.Intent createIntent(android.content.Context, android.content.Intent);
+ method public androidx.activity.result.ActivityResult parseResult(int, android.content.Intent?);
+ field public static final String EXTRA_ACTIVITY_OPTIONS_BUNDLE = "androidx.activity.result.contract.extra.ACTIVITY_OPTIONS_BUNDLE";
+ }
+
+ public static final class ActivityResultContracts.StartIntentSenderForResult extends androidx.activity.result.contract.ActivityResultContract<androidx.activity.result.IntentSenderRequest,androidx.activity.result.ActivityResult> {
+ ctor public ActivityResultContracts.StartIntentSenderForResult();
+ method public android.content.Intent createIntent(android.content.Context, androidx.activity.result.IntentSenderRequest);
+ method public androidx.activity.result.ActivityResult parseResult(int, android.content.Intent?);
+ field public static final String ACTION_INTENT_SENDER_REQUEST = "androidx.activity.result.contract.action.INTENT_SENDER_REQUEST";
+ field public static final String EXTRA_INTENT_SENDER_REQUEST = "androidx.activity.result.contract.extra.INTENT_SENDER_REQUEST";
+ field public static final String EXTRA_SEND_INTENT_EXCEPTION = "androidx.activity.result.contract.extra.SEND_INTENT_EXCEPTION";
+ }
+
+ public static class ActivityResultContracts.TakePicture extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,java.lang.Boolean> {
+ ctor public ActivityResultContracts.TakePicture();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.lang.Boolean!>? getSynchronousResult(android.content.Context, android.net.Uri);
+ method public final Boolean parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.TakePicturePreview extends androidx.activity.result.contract.ActivityResultContract<java.lang.Void,android.graphics.Bitmap> {
+ ctor public ActivityResultContracts.TakePicturePreview();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, Void?);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.graphics.Bitmap!>? getSynchronousResult(android.content.Context, Void?);
+ method public final android.graphics.Bitmap? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.TakeVideo extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,android.graphics.Bitmap> {
+ ctor public ActivityResultContracts.TakeVideo();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.graphics.Bitmap!>? getSynchronousResult(android.content.Context, android.net.Uri);
+ method public final android.graphics.Bitmap? parseResult(int, android.content.Intent?);
+ }
+
+}
+
diff --git a/activity/activity/api/res-1.2.0-alpha06.txt b/activity/activity/api/res-1.2.0-alpha06.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/activity/activity/api/res-1.2.0-alpha06.txt
diff --git a/activity/activity/api/restricted_1.2.0-alpha06.txt b/activity/activity/api/restricted_1.2.0-alpha06.txt
new file mode 100644
index 0000000..4053dc1
--- /dev/null
+++ b/activity/activity/api/restricted_1.2.0-alpha06.txt
@@ -0,0 +1,231 @@
+// Signature format: 3.0
+package androidx.activity {
+
+ public class ComponentActivity extends androidx.core.app.ComponentActivity implements androidx.activity.result.ActivityResultCaller androidx.activity.result.ActivityResultRegistryOwner androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.activity.OnBackPressedDispatcherOwner androidx.savedstate.SavedStateRegistryOwner androidx.lifecycle.ViewModelStoreOwner {
+ ctor public ComponentActivity();
+ ctor @ContentView public ComponentActivity(@LayoutRes int);
+ method public final androidx.activity.result.ActivityResultRegistry getActivityResultRegistry();
+ method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+ method @Deprecated public Object? getLastCustomNonConfigurationInstance();
+ method public final androidx.activity.OnBackPressedDispatcher getOnBackPressedDispatcher();
+ method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+ method public androidx.lifecycle.ViewModelStore getViewModelStore();
+ method @Deprecated @CallSuper protected void onActivityResult(int, int, android.content.Intent?);
+ method @Deprecated @CallSuper public void onRequestPermissionsResult(int, String![], int[]);
+ method @Deprecated public Object? onRetainCustomNonConfigurationInstance();
+ method public final Object? onRetainNonConfigurationInstance();
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int) throws android.content.IntentSender.SendIntentException;
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ }
+
+ public abstract class OnBackPressedCallback {
+ ctor public OnBackPressedCallback(boolean);
+ method @MainThread public abstract void handleOnBackPressed();
+ method @MainThread public final boolean isEnabled();
+ method @MainThread public final void remove();
+ method @MainThread public final void setEnabled(boolean);
+ }
+
+ public final class OnBackPressedDispatcher {
+ ctor public OnBackPressedDispatcher();
+ ctor public OnBackPressedDispatcher(Runnable?);
+ method @MainThread public void addCallback(androidx.activity.OnBackPressedCallback);
+ method @MainThread public void addCallback(androidx.lifecycle.LifecycleOwner, androidx.activity.OnBackPressedCallback);
+ method @MainThread public boolean hasEnabledCallbacks();
+ method @MainThread public void onBackPressed();
+ }
+
+ public interface OnBackPressedDispatcherOwner extends androidx.lifecycle.LifecycleOwner {
+ method public androidx.activity.OnBackPressedDispatcher getOnBackPressedDispatcher();
+ }
+
+}
+
+package androidx.activity.result {
+
+ public final class ActivityResult implements android.os.Parcelable {
+ ctor public ActivityResult(int, android.content.Intent?);
+ method public int describeContents();
+ method public android.content.Intent? getData();
+ method public int getResultCode();
+ method public static String resultCodeToString(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.activity.result.ActivityResult!> CREATOR;
+ }
+
+ public interface ActivityResultCallback<O> {
+ method public void onActivityResult(O!);
+ }
+
+ public interface ActivityResultCaller {
+ method public <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ }
+
+ public abstract class ActivityResultLauncher<I> {
+ ctor public ActivityResultLauncher();
+ method public void launch(I!);
+ method public abstract void launch(I!, androidx.core.app.ActivityOptionsCompat?);
+ method @MainThread public abstract void unregister();
+ }
+
+ public abstract class ActivityResultRegistry {
+ ctor public ActivityResultRegistry();
+ method @MainThread public final boolean dispatchResult(int, int, android.content.Intent?);
+ method @MainThread public final <O> boolean dispatchResult(int, O!);
+ method @MainThread public abstract <I, O> void invoke(int, androidx.activity.result.contract.ActivityResultContract<I!,O!>, I!, androidx.core.app.ActivityOptionsCompat?);
+ method public final void onRestoreInstanceState(android.os.Bundle?);
+ method public final void onSaveInstanceState(android.os.Bundle);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> register(String, androidx.lifecycle.LifecycleOwner, androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> register(String, androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ }
+
+ public interface ActivityResultRegistryOwner {
+ method public androidx.activity.result.ActivityResultRegistry getActivityResultRegistry();
+ }
+
+ public final class IntentSenderRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.content.Intent? getFillInIntent();
+ method public int getFlagsMask();
+ method public int getFlagsValues();
+ method public android.content.IntentSender getIntentSender();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.activity.result.IntentSenderRequest!> CREATOR;
+ }
+
+ public static final class IntentSenderRequest.Builder {
+ ctor public IntentSenderRequest.Builder(android.content.IntentSender);
+ ctor public IntentSenderRequest.Builder(android.app.PendingIntent);
+ method public androidx.activity.result.IntentSenderRequest build();
+ method public androidx.activity.result.IntentSenderRequest.Builder setFillInIntent(android.content.Intent?);
+ method public androidx.activity.result.IntentSenderRequest.Builder setFlags(int, int);
+ }
+
+}
+
+package androidx.activity.result.contract {
+
+ public abstract class ActivityResultContract<I, O> {
+ ctor public ActivityResultContract();
+ method public abstract android.content.Intent createIntent(android.content.Context, I!);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<O!>? getSynchronousResult(android.content.Context, I!);
+ method public abstract O! parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContract.SynchronousResult<T> {
+ ctor public ActivityResultContract.SynchronousResult(T!);
+ method public T! getValue();
+ }
+
+ public final class ActivityResultContracts {
+ }
+
+ public static class ActivityResultContracts.CreateDocument extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,android.net.Uri> {
+ ctor public ActivityResultContracts.CreateDocument();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.GetContent extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,android.net.Uri> {
+ ctor public ActivityResultContracts.GetContent();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.GetMultipleContents extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,java.util.List<android.net.Uri>> {
+ ctor public ActivityResultContracts.GetMultipleContents();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.List<android.net.Uri!>!>? getSynchronousResult(android.content.Context, String);
+ method public final java.util.List<android.net.Uri!> parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenDocument extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],android.net.Uri> {
+ ctor public ActivityResultContracts.OpenDocument();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String![]);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, String![]);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenDocumentTree extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,android.net.Uri> {
+ ctor public ActivityResultContracts.OpenDocumentTree();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri?);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.net.Uri!>? getSynchronousResult(android.content.Context, android.net.Uri?);
+ method public final android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.OpenMultipleDocuments extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],java.util.List<android.net.Uri>> {
+ ctor public ActivityResultContracts.OpenMultipleDocuments();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, String![]);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.List<android.net.Uri!>!>? getSynchronousResult(android.content.Context, String![]);
+ method public final java.util.List<android.net.Uri!>? parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.PickContact extends androidx.activity.result.contract.ActivityResultContract<java.lang.Void,android.net.Uri> {
+ ctor public ActivityResultContracts.PickContact();
+ method public android.content.Intent createIntent(android.content.Context, Void?);
+ method public android.net.Uri? parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.RequestMultiplePermissions extends androidx.activity.result.contract.ActivityResultContract<java.lang.String[],java.util.Map<java.lang.String,java.lang.Boolean>> {
+ ctor public ActivityResultContracts.RequestMultiplePermissions();
+ method public android.content.Intent createIntent(android.content.Context, String![]);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.util.Map<java.lang.String!,java.lang.Boolean!>!>? getSynchronousResult(android.content.Context, String![]?);
+ method public java.util.Map<java.lang.String!,java.lang.Boolean!> parseResult(int, android.content.Intent?);
+ field public static final String ACTION_REQUEST_PERMISSIONS = "androidx.activity.result.contract.action.REQUEST_PERMISSIONS";
+ field public static final String EXTRA_PERMISSIONS = "androidx.activity.result.contract.extra.PERMISSIONS";
+ field public static final String EXTRA_PERMISSION_GRANT_RESULTS = "androidx.activity.result.contract.extra.PERMISSION_GRANT_RESULTS";
+ }
+
+ public static final class ActivityResultContracts.RequestPermission extends androidx.activity.result.contract.ActivityResultContract<java.lang.String,java.lang.Boolean> {
+ ctor public ActivityResultContracts.RequestPermission();
+ method public android.content.Intent createIntent(android.content.Context, String);
+ method public androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.lang.Boolean!>? getSynchronousResult(android.content.Context, String?);
+ method public Boolean parseResult(int, android.content.Intent?);
+ }
+
+ public static final class ActivityResultContracts.StartActivityForResult extends androidx.activity.result.contract.ActivityResultContract<android.content.Intent,androidx.activity.result.ActivityResult> {
+ ctor public ActivityResultContracts.StartActivityForResult();
+ method public android.content.Intent createIntent(android.content.Context, android.content.Intent);
+ method public androidx.activity.result.ActivityResult parseResult(int, android.content.Intent?);
+ field public static final String EXTRA_ACTIVITY_OPTIONS_BUNDLE = "androidx.activity.result.contract.extra.ACTIVITY_OPTIONS_BUNDLE";
+ }
+
+ public static final class ActivityResultContracts.StartIntentSenderForResult extends androidx.activity.result.contract.ActivityResultContract<androidx.activity.result.IntentSenderRequest,androidx.activity.result.ActivityResult> {
+ ctor public ActivityResultContracts.StartIntentSenderForResult();
+ method public android.content.Intent createIntent(android.content.Context, androidx.activity.result.IntentSenderRequest);
+ method public androidx.activity.result.ActivityResult parseResult(int, android.content.Intent?);
+ field public static final String ACTION_INTENT_SENDER_REQUEST = "androidx.activity.result.contract.action.INTENT_SENDER_REQUEST";
+ field public static final String EXTRA_INTENT_SENDER_REQUEST = "androidx.activity.result.contract.extra.INTENT_SENDER_REQUEST";
+ field public static final String EXTRA_SEND_INTENT_EXCEPTION = "androidx.activity.result.contract.extra.SEND_INTENT_EXCEPTION";
+ }
+
+ public static class ActivityResultContracts.TakePicture extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,java.lang.Boolean> {
+ ctor public ActivityResultContracts.TakePicture();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<java.lang.Boolean!>? getSynchronousResult(android.content.Context, android.net.Uri);
+ method public final Boolean parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.TakePicturePreview extends androidx.activity.result.contract.ActivityResultContract<java.lang.Void,android.graphics.Bitmap> {
+ ctor public ActivityResultContracts.TakePicturePreview();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, Void?);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.graphics.Bitmap!>? getSynchronousResult(android.content.Context, Void?);
+ method public final android.graphics.Bitmap? parseResult(int, android.content.Intent?);
+ }
+
+ public static class ActivityResultContracts.TakeVideo extends androidx.activity.result.contract.ActivityResultContract<android.net.Uri,android.graphics.Bitmap> {
+ ctor public ActivityResultContracts.TakeVideo();
+ method @CallSuper public android.content.Intent createIntent(android.content.Context, android.net.Uri);
+ method public final androidx.activity.result.contract.ActivityResultContract.SynchronousResult<android.graphics.Bitmap!>? getSynchronousResult(android.content.Context, android.net.Uri);
+ method public final android.graphics.Bitmap? parseResult(int, android.content.Intent?);
+ }
+
+}
+
diff --git a/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.java b/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.java
index cb1497d..7212de8 100644
--- a/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.java
+++ b/activity/activity/src/main/java/androidx/activity/result/contract/ActivityResultContracts.java
@@ -47,7 +47,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -486,7 +486,9 @@
@NonNull
static List<Uri> getClipDataUris(@NonNull Intent intent) {
- HashSet<Uri> resultSet = new HashSet<>();
+ // Use a LinkedHashSet to maintain any ordering that may be
+ // present in the ClipData
+ LinkedHashSet<Uri> resultSet = new LinkedHashSet<>();
if (intent.getData() != null) {
resultSet.add(intent.getData());
}
diff --git a/appcompat/appcompat-resources/src/androidTest/java/androidx/appcompat/content/res/AppCompatResourcesTestCase.java b/appcompat/appcompat-resources/src/androidTest/java/androidx/appcompat/content/res/AppCompatResourcesTestCase.java
index 917ea00..46fd67d 100644
--- a/appcompat/appcompat-resources/src/androidTest/java/androidx/appcompat/content/res/AppCompatResourcesTestCase.java
+++ b/appcompat/appcompat-resources/src/androidTest/java/androidx/appcompat/content/res/AppCompatResourcesTestCase.java
@@ -18,10 +18,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
+import androidx.appcompat.graphics.drawable.MyDrawable;
import androidx.appcompat.resources.test.R;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -59,4 +62,11 @@
public void testGetAnimatedStateListDrawable() {
assertNotNull(AppCompatResources.getDrawable(mContext, R.drawable.asl_heart));
}
+
+ @Test
+ public void testGetCustomDrawable() {
+ Drawable custom = AppCompatResources.getDrawable(mContext, R.drawable.my_drawable);
+ assertNotNull(custom);
+ assertTrue(custom instanceof MyDrawable);
+ }
}
diff --git a/appcompat/appcompat-resources/src/androidTest/java/androidx/appcompat/graphics/drawable/MyDrawable.java b/appcompat/appcompat-resources/src/androidTest/java/androidx/appcompat/graphics/drawable/MyDrawable.java
new file mode 100644
index 0000000..b0be5f9
--- /dev/null
+++ b/appcompat/appcompat-resources/src/androidTest/java/androidx/appcompat/graphics/drawable/MyDrawable.java
@@ -0,0 +1,62 @@
+/*
+ * 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.graphics.drawable;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+
+/**
+ * Simple custom drawable.
+ */
+public class MyDrawable extends Drawable {
+ private final Paint mPaint;
+
+ public MyDrawable() {
+ mPaint = new Paint();
+ mPaint.setARGB(255, 255, 0, 0);
+ mPaint.setAntiAlias(true);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ // Get the drawable's bounds
+ int width = getBounds().width();
+ int height = getBounds().height();
+ float radius = Math.min(width, height) / 2;
+
+ // Draw a red circle in the center
+ canvas.drawCircle(width / 2, height / 2, radius, mPaint);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // This method is required
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // This method is required
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
+}
diff --git a/appcompat/appcompat-resources/src/androidTest/res/drawable/my_drawable.xml b/appcompat/appcompat-resources/src/androidTest/res/drawable/my_drawable.xml
new file mode 100644
index 0000000..567c210
--- /dev/null
+++ b/appcompat/appcompat-resources/src/androidTest/res/drawable/my_drawable.xml
@@ -0,0 +1,20 @@
+<?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.
+ -->
+
+<drawable xmlns:android="http://schemas.android.com/apk/res/android"
+ class="androidx.appcompat.graphics.drawable.MyDrawable"
+ android:color="#ffff0000" />
diff --git a/appcompat/appcompat-resources/src/main/java/androidx/appcompat/widget/ResourceManagerInternal.java b/appcompat/appcompat-resources/src/main/java/androidx/appcompat/widget/ResourceManagerInternal.java
index 9033007c..c35d8e6 100644
--- a/appcompat/appcompat-resources/src/main/java/androidx/appcompat/widget/ResourceManagerInternal.java
+++ b/appcompat/appcompat-resources/src/main/java/androidx/appcompat/widget/ResourceManagerInternal.java
@@ -36,7 +36,6 @@
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.appcompat.graphics.drawable.AnimatedStateListDrawableCompat;
import androidx.appcompat.resources.R;
@@ -106,6 +105,7 @@
manager.addDelegate("vector", new VdcInflateDelegate());
manager.addDelegate("animated-vector", new AvdcInflateDelegate());
manager.addDelegate("animated-selector", new AsldcInflateDelegate());
+ manager.addDelegate("drawable", new DrawableDelegate());
}
}
@@ -533,7 +533,6 @@
}
}
- @RequiresApi(11)
static class AsldcInflateDelegate implements InflateDelegate {
@Override
public Drawable createFromXmlInner(@NonNull Context context, @NonNull XmlPullParser parser,
@@ -547,4 +546,30 @@
}
}
}
+
+ static class DrawableDelegate implements InflateDelegate {
+ @Override
+ public Drawable createFromXmlInner(@NonNull Context context, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, @Nullable Resources.Theme theme) {
+ String className = attrs.getClassAttribute();
+ if (className != null) {
+ try {
+ Class<? extends Drawable> drawableClass =
+ DrawableDelegate.class.getClassLoader().loadClass(className)
+ .asSubclass(Drawable.class);
+ Drawable drawable = drawableClass.getDeclaredConstructor().newInstance();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ drawable.inflate(context.getResources(), parser, attrs, theme);
+ } else {
+ drawable.inflate(context.getResources(), parser, attrs);
+ }
+ return drawable;
+ } catch (Exception e) {
+ Log.e("DrawableDelegate", "Exception while inflating <drawable>", e);
+ return null;
+ }
+ }
+ return null;
+ }
+ }
}
diff --git a/appcompat/appcompat/api/1.3.0-alpha01.txt b/appcompat/appcompat/api/1.3.0-alpha01.txt
index aed2d02..e06cc21 100644
--- a/appcompat/appcompat/api/1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/1.3.0-alpha01.txt
@@ -517,9 +517,11 @@
ctor public AppCompatEditText(android.content.Context);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>? getRichContentReceiverCompat();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.content.res.ColorStateList? getSupportBackgroundTintList();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
method public void setBackgroundDrawable(android.graphics.drawable.Drawable!);
+ method public void setRichContentReceiverCompat(androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
method public void setTextAppearance(android.content.Context!, int);
diff --git a/appcompat/appcompat/api/api_lint.ignore b/appcompat/appcompat/api/api_lint.ignore
index 039f065..fd01b04 100644
--- a/appcompat/appcompat/api/api_lint.ignore
+++ b/appcompat/appcompat/api/api_lint.ignore
@@ -17,6 +17,12 @@
Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.Future (parameter future in androidx.appcompat.widget.AppCompatTextView.setTextFuture(java.util.concurrent.Future<androidx.core.text.PrecomputedTextCompat> future))
+BuilderSetStyle: androidx.appcompat.app.AlertDialog.Builder#create():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.appcompat.app.AlertDialog.Builder.create()
+BuilderSetStyle: androidx.appcompat.app.AlertDialog.Builder#show():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.appcompat.app.AlertDialog.Builder.show()
+
+
ContextFirst: androidx.appcompat.app.AppCompatDelegate#createView(android.view.View, String, android.content.Context, android.util.AttributeSet) parameter #2:
Context is distinct, so it must be the first argument (method `createView`)
diff --git a/appcompat/appcompat/api/current.txt b/appcompat/appcompat/api/current.txt
index aed2d02..e06cc21 100644
--- a/appcompat/appcompat/api/current.txt
+++ b/appcompat/appcompat/api/current.txt
@@ -517,9 +517,11 @@
ctor public AppCompatEditText(android.content.Context);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>? getRichContentReceiverCompat();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.content.res.ColorStateList? getSupportBackgroundTintList();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
method public void setBackgroundDrawable(android.graphics.drawable.Drawable!);
+ method public void setRichContentReceiverCompat(androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
method public void setTextAppearance(android.content.Context!, int);
diff --git a/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt b/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
index 6f176e4..b48b85b 100644
--- a/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
@@ -517,9 +517,11 @@
ctor public AppCompatEditText(android.content.Context);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>? getRichContentReceiverCompat();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.content.res.ColorStateList? getSupportBackgroundTintList();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
method public void setBackgroundDrawable(android.graphics.drawable.Drawable!);
+ method public void setRichContentReceiverCompat(androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
method public void setTextAppearance(android.content.Context!, int);
diff --git a/appcompat/appcompat/api/public_plus_experimental_current.txt b/appcompat/appcompat/api/public_plus_experimental_current.txt
index 6f176e4..b48b85b 100644
--- a/appcompat/appcompat/api/public_plus_experimental_current.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_current.txt
@@ -517,9 +517,11 @@
ctor public AppCompatEditText(android.content.Context);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>? getRichContentReceiverCompat();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.content.res.ColorStateList? getSupportBackgroundTintList();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
method public void setBackgroundDrawable(android.graphics.drawable.Drawable!);
+ method public void setRichContentReceiverCompat(androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
method public void setTextAppearance(android.content.Context!, int);
diff --git a/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt b/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
index 10b05b7..d722032 100644
--- a/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
@@ -1398,9 +1398,11 @@
ctor public AppCompatEditText(android.content.Context);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>? getRichContentReceiverCompat();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.content.res.ColorStateList? getSupportBackgroundTintList();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
method public void setBackgroundDrawable(android.graphics.drawable.Drawable!);
+ method public void setRichContentReceiverCompat(androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
method public void setTextAppearance(android.content.Context!, int);
diff --git a/appcompat/appcompat/api/restricted_current.txt b/appcompat/appcompat/api/restricted_current.txt
index 10b05b7..d722032 100644
--- a/appcompat/appcompat/api/restricted_current.txt
+++ b/appcompat/appcompat/api/restricted_current.txt
@@ -1398,9 +1398,11 @@
ctor public AppCompatEditText(android.content.Context);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?);
ctor public AppCompatEditText(android.content.Context, android.util.AttributeSet?, int);
+ method public androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>? getRichContentReceiverCompat();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.content.res.ColorStateList? getSupportBackgroundTintList();
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.graphics.PorterDuff.Mode? getSupportBackgroundTintMode();
method public void setBackgroundDrawable(android.graphics.drawable.Drawable!);
+ method public void setRichContentReceiverCompat(androidx.core.widget.RichContentReceiverCompat<android.widget.TextView!>?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintList(android.content.res.ColorStateList?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSupportBackgroundTintMode(android.graphics.PorterDuff.Mode?);
method public void setTextAppearance(android.content.Context!, int);
diff --git a/appcompat/appcompat/src/androidTest/AndroidManifest.xml b/appcompat/appcompat/src/androidTest/AndroidManifest.xml
index 99fab52..59cf853 100644
--- a/appcompat/appcompat/src/androidTest/AndroidManifest.xml
+++ b/appcompat/appcompat/src/androidTest/AndroidManifest.xml
@@ -99,6 +99,11 @@
android:theme="@style/Theme.TextColors"/>
<activity
+ android:name="androidx.appcompat.widget.AppCompatEditTextRichContentReceiverActivity"
+ android:label="@string/app_compat_edit_text_rich_content_receiver_activity"
+ android:theme="@style/Theme.AppCompat.Light"/>
+
+ <activity
android:name="androidx.appcompat.widget.AppCompatButtonAutoSizeActivity"
android:label="@string/app_compat_button_auto_size_activity"
android:theme="@style/Theme.AppCompat.Light"/>
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatEditTextRichContentReceiverActivity.java b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatEditTextRichContentReceiverActivity.java
new file mode 100644
index 0000000..9601ac1
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatEditTextRichContentReceiverActivity.java
@@ -0,0 +1,26 @@
+/*
+ * 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.widget;
+
+import androidx.appcompat.test.R;
+import androidx.appcompat.testutils.BaseTestActivity;
+
+public class AppCompatEditTextRichContentReceiverActivity extends BaseTestActivity {
+ @Override
+ protected int getContentViewLayoutResId() {
+ return R.layout.appcompat_edittext_richcontentreceiver_activity;
+ }
+}
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatEditTextRichContentReceiverTest.java b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatEditTextRichContentReceiverTest.java
new file mode 100644
index 0000000..5f68405
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatEditTextRichContentReceiverTest.java
@@ -0,0 +1,489 @@
+/*
+ * 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.widget;
+
+import static androidx.core.widget.RichContentReceiverCompat.FLAG_CONVERT_TO_PLAIN_TEXT;
+import static androidx.core.widget.RichContentReceiverCompat.SOURCE_CLIPBOARD;
+import static androidx.core.widget.RichContentReceiverCompat.SOURCE_INPUT_METHOD;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Build;
+import android.text.SpannableStringBuilder;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.test.R;
+import androidx.core.view.inputmethod.EditorInfoCompat;
+import androidx.core.view.inputmethod.InputConnectionCompat;
+import androidx.core.view.inputmethod.InputContentInfoCompat;
+import androidx.core.widget.RichContentReceiverCompat;
+import androidx.core.widget.TextViewRichContentReceiverCompat;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.rule.ActivityTestRule;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mockito;
+
+import java.util.Set;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class AppCompatEditTextRichContentReceiverTest {
+ private static final Set<String> ALL_TEXT_AND_IMAGE_MIME_TYPES = ImmutableSet.of(
+ "text/*", "image/*");
+
+ @Rule
+ public final ActivityTestRule<AppCompatEditTextRichContentReceiverActivity> mActivityTestRule =
+ new ActivityTestRule<>(AppCompatEditTextRichContentReceiverActivity.class);
+
+ private Context mContext;
+ private AppCompatEditText mEditText;
+ private RichContentReceiverCompat<TextView> mMockReceiver;
+ private ClipboardManager mClipboardManager;
+
+ @UiThreadTest
+ @Before
+ public void before() {
+ AppCompatActivity activity = mActivityTestRule.getActivity();
+ mContext = activity;
+ mEditText = activity.findViewById(R.id.edit_text_default_values);
+
+ mMockReceiver = Mockito.mock(RichContentReceiverCompat.class);
+
+ mClipboardManager = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+
+ // Clear the clipboard
+ if (Build.VERSION.SDK_INT >= 28) {
+ mClipboardManager.clearPrimaryClip();
+ } else {
+ mClipboardManager.setPrimaryClip(ClipData.newPlainText("", ""));
+ }
+ }
+
+ // ============================================================================================
+ // Tests to verify APIs/accessors/defaults related to RichContentReceiver.
+ // ============================================================================================
+
+ @UiThreadTest
+ @Test
+ public void testGetAndSetRichContentReceiverCompat() throws Exception {
+ // Verify that by default the getter returns null.
+ assertThat(mEditText.getRichContentReceiverCompat()).isNull();
+
+ // Verify that after setting a custom receiver, the getter returns it.
+ TextViewRichContentReceiverCompat receiver = new TextViewRichContentReceiverCompat() {};
+ mEditText.setRichContentReceiverCompat(receiver);
+ assertThat(mEditText.getRichContentReceiverCompat()).isSameInstanceAs(receiver);
+
+ // Verify that the receiver can be reset by passing null.
+ mEditText.setRichContentReceiverCompat(null);
+ assertThat(mEditText.getRichContentReceiverCompat()).isNull();
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnCreateInputConnection_nullEditorInfo() throws Exception {
+ setTextAndCursor("xz", 1);
+ try {
+ mEditText.onCreateInputConnection(null);
+ Assert.fail("Expected NullPointerException");
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnCreateInputConnection_noReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Call onCreateInputConnection() and assert that contentMimeTypes is not set.
+ EditorInfo editorInfo = new EditorInfo();
+ InputConnection ic = mEditText.onCreateInputConnection(editorInfo);
+ assertThat(ic).isNotNull();
+ assertThat(EditorInfoCompat.getContentMimeTypes(editorInfo)).isEqualTo(new String[0]);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnCreateInputConnection_withReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Configure the receiver to a custom impl.
+ Set<String> receiverMimeTypes = ImmutableSet.of("text/plain", "image/png", "video/mp4");
+ when(mMockReceiver.getSupportedMimeTypes()).thenReturn(receiverMimeTypes);
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Call onCreateInputConnection() and assert that contentMimeTypes is set from the receiver.
+ EditorInfo editorInfo = new EditorInfo();
+ InputConnection ic = mEditText.onCreateInputConnection(editorInfo);
+ assertThat(ic).isNotNull();
+ verify(mMockReceiver, times(1)).getSupportedMimeTypes();
+ verifyNoMoreInteractions(mMockReceiver);
+ assertThat(EditorInfoCompat.getContentMimeTypes(editorInfo))
+ .isEqualTo(receiverMimeTypes.toArray(new String[0]));
+ }
+
+ // ============================================================================================
+ // Tests to verify that the receiver callback is invoked for all the appropriate user
+ // interactions:
+ // * Paste from clipboard ("Paste" and "Paste as plain text" actions)
+ // * Content insertion from IME
+ // ============================================================================================
+
+ @UiThreadTest
+ @Test
+ public void testPaste_noReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Copy text to the clipboard.
+ ClipData clip = ClipData.newPlainText("test", "y");
+ clip = copyToClipboard(clip);
+
+ // Trigger the "Paste" action. This should execute the platform paste handling, so the
+ // content should be inserted according to whatever behavior is implemented in the OS
+ // version that's running.
+ boolean result = triggerContextMenuAction(android.R.id.paste);
+ assertThat(result).isTrue();
+ if (Build.VERSION.SDK_INT <= 20) {
+ // The platform code on Android K and earlier had logic to insert a space before and
+ // after the pasted content (if no space was already present). See
+ // https://cs.android.com/android/platform/superproject/+/android-4.4.4_r2:frameworks/base/core/java/android/widget/TextView.java;l=8526,8527,8528,8545,8546
+ assertTextAndCursorPosition("x y z", 3);
+ } else {
+ assertTextAndCursorPosition("xyz", 2);
+ }
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPaste_withReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Copy text to the clipboard.
+ ClipData clip = ClipData.newPlainText("test", "y");
+ clip = copyToClipboard(clip);
+
+ // Setup: Configure to use the mock receiver.
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the "Paste" action and assert that the custom receiver was executed.
+ triggerContextMenuAction(android.R.id.paste);
+ verify(mMockReceiver, times(1)).onReceive(
+ eq(mEditText), clipEq(clip), eq(SOURCE_CLIPBOARD), eq(0));
+ verifyNoMoreInteractions(mMockReceiver);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPaste_withReceiver_resultBoolean() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Copy text to the clipboard.
+ ClipData clip = ClipData.newPlainText("test", "y");
+ clip = copyToClipboard(clip);
+
+ // Setup: Configure to use the mock receiver.
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the "Paste" action and assert that the boolean result is true regardless of
+ // the receiver's return value.
+ when(mMockReceiver.onReceive(eq(mEditText), eq(clip), eq(SOURCE_CLIPBOARD),
+ eq(FLAG_CONVERT_TO_PLAIN_TEXT))).thenReturn(true);
+ boolean result = triggerContextMenuAction(android.R.id.paste);
+ assertThat(result).isTrue();
+
+ when(mMockReceiver.onReceive(eq(mEditText), eq(clip), eq(SOURCE_CLIPBOARD),
+ eq(FLAG_CONVERT_TO_PLAIN_TEXT))).thenReturn(false);
+ result = triggerContextMenuAction(android.R.id.paste);
+ assertThat(result).isTrue();
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPaste_withReceiver_unsupportedMimeType() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Copy a URI to the clipboard with a MIME type that's not supported by the receiver.
+ ClipData clip = new ClipData("test", new String[]{"video/mp4"},
+ new ClipData.Item("text", null, Uri.parse("content://com.example/path")));
+ clip = copyToClipboard(clip);
+
+ // Setup: Configure to use the mock receiver.
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the "Paste" action and assert that the custom receiver was executed. This
+ // confirms that the receiver is invoked (give a chance to handle the content via some
+ // fallback) even if the MIME type of the content is not one of the receiver's supported
+ // MIME types.
+ triggerContextMenuAction(android.R.id.paste);
+ verify(mMockReceiver, times(1)).onReceive(
+ eq(mEditText), clipEq(clip), eq(SOURCE_CLIPBOARD), eq(0));
+ verifyNoMoreInteractions(mMockReceiver);
+ }
+
+ @SdkSuppress(minSdkVersion = 23) // The action "Paste as plain text" was added in SDK 23.
+ @UiThreadTest
+ @Test
+ public void testPasteAsPlainText_noReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Copy HTML to the clipboard.
+ ClipData clip = ClipData.newHtmlText("test", "*y*", "<b>y</b>");
+ clip = copyToClipboard(clip);
+
+ // Trigger the "Paste as plain text" action. This should execute the platform paste
+ // handling, so the content should be inserted according to whatever behavior is implemented
+ // in the OS version that's running.
+ boolean result = triggerContextMenuAction(android.R.id.pasteAsPlainText);
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("x*y*z", 4);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPasteAsPlainText_withReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Copy text to the clipboard.
+ ClipData clip = ClipData.newPlainText("test", "y");
+ clip = copyToClipboard(clip);
+
+ // Setup: Configure to use the mock receiver.
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the "Paste as plain text" action and assert that the custom receiver was
+ // executed.
+ triggerContextMenuAction(android.R.id.pasteAsPlainText);
+ verify(mMockReceiver, times(1)).onReceive(
+ eq(mEditText), clipEq(clip),
+ eq(SOURCE_CLIPBOARD), eq(FLAG_CONVERT_TO_PLAIN_TEXT));
+ verifyNoMoreInteractions(mMockReceiver);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPasteAsPlainText_withReceiver_unsupportedMimeType() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Copy a URI to the clipboard with a MIME type that's not supported by the receiver.
+ ClipData clip = new ClipData("test", new String[]{"video/mp4"},
+ new ClipData.Item("text", null, Uri.parse("content://com.example/path")));
+ clip = copyToClipboard(clip);
+
+ // Setup: Configure to use the mock receiver.
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the "Paste as plain text" action and assert that the custom receiver was
+ // executed. This confirms that the receiver is invoked (given a chance to handle the
+ // content via some fallback) even if the MIME type of the content is not one of the
+ // receiver's supported MIME types.
+ triggerContextMenuAction(android.R.id.pasteAsPlainText);
+ verify(mMockReceiver, times(1)).onReceive(
+ eq(mEditText), clipEq(clip),
+ eq(SOURCE_CLIPBOARD), eq(FLAG_CONVERT_TO_PLAIN_TEXT));
+ verifyNoMoreInteractions(mMockReceiver);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testImeCommitContent_noReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Trigger the IME's commitContent() call and assert its outcome.
+ boolean result = triggerImeCommitContentViaCompat("image/png");
+ assertThat(result).isFalse();
+ assertTextAndCursorPosition("xz", 1);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testImeCommitContent_withReceiver() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Configure the receiver to a custom impl that supports all text and images.
+ when(mMockReceiver.getSupportedMimeTypes()).thenReturn(ALL_TEXT_AND_IMAGE_MIME_TYPES);
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the IME's commitContent() call and assert that the custom receiver was executed.
+ triggerImeCommitContentViaCompat("image/png");
+ verify(mMockReceiver, times(1)).getSupportedMimeTypes();
+ verify(mMockReceiver, times(1)).onReceive(
+ eq(mEditText), any(ClipData.class), eq(SOURCE_INPUT_METHOD), eq(0));
+ verifyNoMoreInteractions(mMockReceiver);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testImeCommitContent_withReceiver_resultBoolean() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Configure the receiver to a custom impl that supports all text and images.
+ when(mMockReceiver.getSupportedMimeTypes()).thenReturn(ALL_TEXT_AND_IMAGE_MIME_TYPES);
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the IME's commitContent() call, once when the mock receiver is configured to
+ // return true and once when the mock receiver is configured to return false.
+ when(mMockReceiver.onReceive(eq(mEditText), any(ClipData.class), eq(SOURCE_INPUT_METHOD),
+ eq(0))).thenReturn(true);
+ boolean result1 = triggerImeCommitContentViaCompat("image/png");
+ when(mMockReceiver.onReceive(eq(mEditText), any(ClipData.class), eq(SOURCE_INPUT_METHOD),
+ eq(0))).thenReturn(false);
+ boolean result2 = triggerImeCommitContentViaCompat("image/png");
+ verify(mMockReceiver, times(2)).onReceive(
+ eq(mEditText), any(ClipData.class), eq(SOURCE_INPUT_METHOD), eq(0));
+ if (Build.VERSION.SDK_INT >= 25) {
+ // On SDK 25 and above, the boolean result should match the return value from the
+ // receiver.
+ assertThat(result1).isTrue();
+ assertThat(result2).isFalse();
+ } else {
+ // On SDK 24 and below, commitContent() is handled via
+ // InputConnection.performPrivateCommand(). This ends up returning true whenever the
+ // command is sent, regardless of the return value of the underlying operation.
+ // Relevant code links:
+ // https://osscs.corp.google.com/androidx/platform/frameworks/support/+/androidx-master-dev:core/core/src/main/java/androidx/core/view/inputmethod/InputConnectionCompat.java;l=294;drc=0c365e84832f5ec5e393be28ab1c618eb18bab1e
+ // https://cs.android.com/android/platform/superproject/+/android-7.0.0_r6:frameworks/base/core/java/com/android/internal/widget/EditableInputConnection.java;l=168
+ assertThat(result1).isTrue();
+ assertThat(result2).isTrue();
+ }
+ }
+
+ @UiThreadTest
+ @Test
+ public void testImeCommitContent_withReceiver_unsupportedMimeType() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Configure the receiver to a custom impl that supports all text and images.
+ when(mMockReceiver.getSupportedMimeTypes()).thenReturn(ALL_TEXT_AND_IMAGE_MIME_TYPES);
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the IME's commitContent() call and assert that the custom receiver was not
+ // executed. This is because InputConnectionCompat.commitContent() checks the supported MIME
+ // types before proceeding.
+ triggerImeCommitContentViaCompat("video/mp4");
+ verify(mMockReceiver, times(1)).getSupportedMimeTypes();
+ verifyNoMoreInteractions(mMockReceiver);
+ }
+
+ @SdkSuppress(minSdkVersion = 25) // InputConnection.commitContent() was added in SDK 25.
+ @UiThreadTest
+ @Test
+ public void testImeCommitContent_direct_withReceiver_unsupportedMimeType() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ // Setup: Configure the receiver to a custom impl that supports all text and images.
+ when(mMockReceiver.getSupportedMimeTypes()).thenReturn(ALL_TEXT_AND_IMAGE_MIME_TYPES);
+ mEditText.setRichContentReceiverCompat(mMockReceiver);
+
+ // Trigger the IME's commitContent() call and assert that the custom receiver was executed.
+ triggerImeCommitContentDirect("video/mp4");
+ verify(mMockReceiver, times(1)).getSupportedMimeTypes();
+ verify(mMockReceiver, times(1)).onReceive(
+ eq(mEditText), any(ClipData.class), eq(SOURCE_INPUT_METHOD), eq(0));
+ verifyNoMoreInteractions(mMockReceiver);
+ }
+
+ private boolean triggerContextMenuAction(final int actionId) {
+ return mEditText.onTextContextMenuItem(actionId);
+ }
+
+ private boolean triggerImeCommitContentViaCompat(String mimeType) {
+ final InputContentInfoCompat contentInfo = new InputContentInfoCompat(
+ Uri.parse("content://com.example/path"),
+ new ClipDescription("from test", new String[]{mimeType}),
+ Uri.parse("https://example.com"));
+ EditorInfo editorInfo = new EditorInfo();
+ InputConnection ic = mEditText.onCreateInputConnection(editorInfo);
+ return InputConnectionCompat.commitContent(ic, editorInfo, contentInfo, 0, null);
+ }
+
+ private boolean triggerImeCommitContentDirect(String mimeType) {
+ final InputContentInfo contentInfo = new InputContentInfo(
+ Uri.parse("content://com.example/path"),
+ new ClipDescription("from test", new String[]{mimeType}),
+ Uri.parse("https://example.com"));
+ EditorInfo editorInfo = new EditorInfo();
+ InputConnection ic = mEditText.onCreateInputConnection(editorInfo);
+ return ic.commitContent(contentInfo, 0, null);
+ }
+
+ private void setTextAndCursor(final String text, final int cursorPosition) {
+ mEditText.requestFocus();
+ SpannableStringBuilder ssb = new SpannableStringBuilder(text);
+ mEditText.setText(ssb);
+ mEditText.setSelection(cursorPosition);
+ assertThat(mEditText.hasFocus()).isTrue();
+ assertTextAndCursorPosition(text, cursorPosition);
+ }
+
+ private void assertTextAndCursorPosition(String expectedText, int cursorPosition) {
+ assertThat(mEditText.getText().toString()).isEqualTo(expectedText);
+ assertThat(mEditText.getSelectionStart()).isEqualTo(cursorPosition);
+ assertThat(mEditText.getSelectionEnd()).isEqualTo(cursorPosition);
+ }
+
+ private ClipData copyToClipboard(final ClipData clip) {
+ mClipboardManager.setPrimaryClip(clip);
+ ClipData primaryClip = mClipboardManager.getPrimaryClip();
+ assertThat(primaryClip).isNotNull();
+ return primaryClip;
+ }
+
+ private static ClipData clipEq(ClipData expected) {
+ return argThat(new ClipDataArgumentMatcher(expected));
+ }
+
+ private static class ClipDataArgumentMatcher implements ArgumentMatcher<ClipData> {
+ private final ClipData mExpected;
+
+ private ClipDataArgumentMatcher(ClipData expected) {
+ this.mExpected = expected;
+ }
+
+ @Override
+ public boolean matches(ClipData actual) {
+ return mExpected.getItemAt(0).getText().equals(actual.getItemAt(0).getText());
+ }
+ }
+}
diff --git a/appcompat/appcompat/src/androidTest/res/layout/appcompat_edittext_richcontentreceiver_activity.xml b/appcompat/appcompat/src/androidTest/res/layout/appcompat_edittext_richcontentreceiver_activity.xml
new file mode 100644
index 0000000..b1c4421
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/res/layout/appcompat_edittext_richcontentreceiver_activity.xml
@@ -0,0 +1,35 @@
+<?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.
+ -->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <androidx.appcompat.widget.AppCompatEditText
+ android:id="@+id/edit_text_default_values"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+</ScrollView>
diff --git a/appcompat/appcompat/src/androidTest/res/values/strings.xml b/appcompat/appcompat/src/androidTest/res/values/strings.xml
index bd41846..21d1659 100644
--- a/appcompat/appcompat/src/androidTest/res/values/strings.xml
+++ b/appcompat/appcompat/src/androidTest/res/values/strings.xml
@@ -57,6 +57,7 @@
<string name="app_compat_text_view_activity">AppCompat text view</string>
<string name="app_compat_text_view_auto_size_activity">AppCompat text view auto-size</string>
<string name="app_compat_edit_text_activity">AppCompat edit text</string>
+ <string name="app_compat_edit_text_rich_content_receiver_activity">AppCompat edit text rich content receiver</string>
<string name="app_compat_button_auto_size_activity">AppCompat button auto-size</string>
<string name="sample_text1">Sample text 1</string>
<string name="sample_text2">Sample text 2</string>
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
index d53d632..514bda6 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegate.java
@@ -92,7 +92,7 @@
* retained until the Activity is destroyed.</p>
*/
public abstract class AppCompatDelegate {
- static final boolean DEBUG = false;
+ static final boolean DEBUG = true;
static final String TAG = "AppCompatDelegate";
/**
@@ -578,6 +578,9 @@
if (sDefaultNightMode != mode) {
sDefaultNightMode = mode;
applyDayNightToActiveDelegates();
+ } else if (DEBUG) {
+ Log.d(TAG, String.format("Not applying changes, sDefaultNightMode already %d",
+ mode));
}
break;
default:
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 17471b0..8ff2f65 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
@@ -2518,10 +2518,12 @@
// attachBaseContext() + createConfigurationContext() code path.
// Else, we need to use updateConfiguration() before we're 'created' (below)
if (DEBUG) {
- Log.d(TAG, "updateForNightMode. Recreating Activity: " + mHost);
+ Log.d(TAG, "updateForNightMode attempting to recreate Activity: " + mHost);
}
ActivityCompat.recreate((Activity) mHost);
handled = true;
+ } else if (DEBUG) {
+ Log.d(TAG, "updateForNightMode not recreating Activity: " + mHost);
}
if (!handled && currentNightMode != newNightMode) {
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java
index a6a64b3..3982161 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java
@@ -17,7 +17,11 @@
package androidx.appcompat.widget;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
+import static androidx.core.widget.RichContentReceiverCompat.FLAG_CONVERT_TO_PLAIN_TEXT;
+import static androidx.core.widget.RichContentReceiverCompat.SOURCE_CLIPBOARD;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
@@ -30,6 +34,7 @@
import android.view.inputmethod.InputConnection;
import android.view.textclassifier.TextClassifier;
import android.widget.EditText;
+import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
@@ -38,6 +43,8 @@
import androidx.annotation.RestrictTo;
import androidx.appcompat.R;
import androidx.core.view.TintableBackgroundView;
+import androidx.core.view.inputmethod.InputConnectionCompat;
+import androidx.core.widget.RichContentReceiverCompat;
import androidx.core.widget.TextViewCompat;
/**
@@ -48,6 +55,10 @@
* {@link androidx.core.view.ViewCompat}.</li>
* <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
* {@link R.attr#backgroundTintMode}.</li>
+ * <li>Allows setting a custom {@link RichContentReceiverCompat receiver callback} in order to
+ * handle insertion of content (e.g. pasting text or an image from the clipboard). This callback
+ * provides the opportunity to implement app-specific handling such as creating an attachment
+ * when an image is pasted.</li>
* </ul>
*
* <p>This will automatically be used when you use {@link EditText} in your layouts
@@ -60,6 +71,8 @@
private final AppCompatBackgroundHelper mBackgroundTintHelper;
private final AppCompatTextHelper mTextHelper;
private final AppCompatTextClassifierHelper mTextClassifierHelper;
+ @Nullable
+ private RichContentReceiverCompat<TextView> mRichContentReceiverCompat;
public AppCompatEditText(@NonNull Context context) {
this(context, null);
@@ -190,10 +203,23 @@
}
}
+ /**
+ * If a {@link #setRichContentReceiverCompat receiver callback} is set, the returned
+ * {@link InputConnection} will use it to handle calls to {@link InputConnection#commitContent}.
+ *
+ * {@inheritDoc}
+ */
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- return AppCompatHintHelper.onCreateInputConnection(super.onCreateInputConnection(outAttrs),
- outAttrs, this);
+ InputConnection ic = super.onCreateInputConnection(outAttrs);
+ ic = AppCompatHintHelper.onCreateInputConnection(ic, outAttrs, this);
+ if (ic != null && mRichContentReceiverCompat != null) {
+ mRichContentReceiverCompat.populateEditorInfoContentMimeTypes(ic, outAttrs);
+ InputConnectionCompat.OnCommitContentListener callback =
+ mRichContentReceiverCompat.buildOnCommitContentListener(this);
+ ic = InputConnectionCompat.createWrapper(ic, outAttrs, callback);
+ }
+ return ic;
}
/**
@@ -235,4 +261,65 @@
}
return mTextClassifierHelper.getTextClassifier();
}
+
+ /**
+ * If a {@link #setRichContentReceiverCompat receiver callback} is set, uses it to execute the
+ * "Paste" and "Paste as plain text" menu actions.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onTextContextMenuItem(int id) {
+ if (mRichContentReceiverCompat == null) {
+ return super.onTextContextMenuItem(id);
+ }
+ if (id == android.R.id.paste || id == android.R.id.pasteAsPlainText) {
+ ClipboardManager cm = (ClipboardManager) getContext().getSystemService(
+ Context.CLIPBOARD_SERVICE);
+ ClipData clip = cm == null ? null : cm.getPrimaryClip();
+ if (clip != null) {
+ int flags = (id == android.R.id.paste) ? 0 : FLAG_CONVERT_TO_PLAIN_TEXT;
+ mRichContentReceiverCompat.onReceive(this, clip, SOURCE_CLIPBOARD, flags);
+ }
+ return true;
+ }
+ return super.onTextContextMenuItem(id);
+ }
+
+ /**
+ * Returns the callback that handles insertion of content into this view (e.g. pasting from
+ * the clipboard). See {@link #setRichContentReceiverCompat} for more info.
+ *
+ * @return The callback that this view is using to handle insertion of content. Returns
+ * {@code null} if no callback is configured, in which case the platform behavior of the
+ * {@link EditText} component will be used for content insertion.
+ */
+ @Nullable
+ public RichContentReceiverCompat<TextView> getRichContentReceiverCompat() {
+ return mRichContentReceiverCompat;
+ }
+
+ /**
+ * Sets the callback to handle insertion of content into this view.
+ *
+ * <p>"Content" and "rich content" here refers to both text and non-text: plain text, styled
+ * text, HTML, images, videos, audio files, etc. The callback configured here should typically
+ * extend from {@link androidx.core.widget.TextViewRichContentReceiverCompat} to provide
+ * consistent behavior for text content.
+ *
+ * <p>This callback will be invoked for the following scenarios:
+ * <ol>
+ * <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
+ * insertion/selection menu)
+ * <li>Content insertion from the keyboard ({@link InputConnection#commitContent})
+ * </ol>
+ *
+ * @param receiver The callback to use. This can be {@code null} to clear any previously set
+ * callback (the platform behavior of the {@link EditText} component will then
+ * be used).
+ */
+ public void setRichContentReceiverCompat(
+ @Nullable RichContentReceiverCompat<TextView> receiver) {
+ mRichContentReceiverCompat = receiver;
+ }
}
diff --git a/autofill/autofill/api/api_lint.ignore b/autofill/autofill/api/api_lint.ignore
new file mode 100644
index 0000000..d0b566f
--- /dev/null
+++ b/autofill/autofill/api/api_lint.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+SetterReturnsThis: androidx.autofill.inline.UiVersions.StylesBuilder#addStyle(androidx.autofill.inline.UiVersions.Style):
+ Methods must return the builder object (return type androidx.autofill.inline.UiVersions.StylesBuilder instead of void): method androidx.autofill.inline.UiVersions.StylesBuilder.addStyle(androidx.autofill.inline.UiVersions.Style)
diff --git a/biometric/biometric/build.gradle b/biometric/biometric/build.gradle
index 60b8f6c..1c26102 100644
--- a/biometric/biometric/build.gradle
+++ b/biometric/biometric/build.gradle
@@ -1,6 +1,5 @@
import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
import androidx.build.Publish
plugins {
@@ -9,11 +8,12 @@
}
dependencies {
+ api("androidx.activity:activity:1.1.0")
api("androidx.annotation:annotation:1.1.0")
api("androidx.appcompat:appcompat:1.1.0")
- api("androidx.core:core:1.1.0")
- api("androidx.fragment:fragment:1.1.0")
- api(project(":lifecycle:lifecycle-viewmodel"))
+ api("androidx.core:core:1.2.0")
+ api("androidx.fragment:fragment:1.2.4")
+ api("androidx.lifecycle:lifecycle-viewmodel:2.2.0")
testImplementation(ANDROIDX_TEST_CORE)
testImplementation(ANDROIDX_TEST_RUNNER)
diff --git a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
index 409a620..d1633e0 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
@@ -224,8 +224,8 @@
void cleanup() {
mShowing = false;
FragmentActivity activity = getActivity();
- if (getFragmentManager() != null) {
- getFragmentManager().beginTransaction().detach(this).commitAllowingStateLoss();
+ if (isAdded()) {
+ getParentFragmentManager().beginTransaction().detach(this).commitAllowingStateLoss();
}
Utils.maybeFinishHandler(activity);
}
diff --git a/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java b/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java
index 69f1fbe..15c3281 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java
@@ -395,7 +395,7 @@
/** Attempts to dismiss this fragment while avoiding potential crashes. */
private void dismissSafely() {
- if (getFragmentManager() != null) {
+ if (isAdded()) {
dismissAllowingStateLoss();
} else {
Log.e(TAG, "Failed to dismiss fingerprint dialog fragment. Fragment manager was null.");
diff --git a/browser/browser/api/api_lint.ignore b/browser/browser/api/api_lint.ignore
index b23baec..a4d5f5e 100644
--- a/browser/browser/api/api_lint.ignore
+++ b/browser/browser/api/api_lint.ignore
@@ -57,8 +57,10 @@
Must avoid boxed primitives (`java.lang.Integer`)
-CallbackMethodName: androidx.browser.customtabs.CustomTabsCallback:
- Callback method names must follow the on<Something> style: extraCallback
+BuilderSetStyle: androidx.browser.customtabs.CustomTabsIntent.Builder#enableUrlBarHiding():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.browser.customtabs.CustomTabsIntent.Builder.enableUrlBarHiding()
+BuilderSetStyle: androidx.browser.trusted.TrustedWebActivityIntentBuilder#buildCustomTabsIntent():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.browser.trusted.TrustedWebActivityIntentBuilder.buildCustomTabsIntent()
ConcreteCollection: androidx.browser.browseractions.BrowserActionsIntent#openBrowserAction(android.content.Context, android.net.Uri, int, java.util.ArrayList<androidx.browser.browseractions.BrowserActionItem>, android.app.PendingIntent) parameter #3:
@@ -77,6 +79,10 @@
Listeners should always be at end of argument list (method `newSession`)
+OptionalBuilderConstructorAgrument: androidx.browser.customtabs.CustomTabsIntent.Builder#Builder(androidx.browser.customtabs.CustomTabsSession) parameter #0:
+ Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter session in androidx.browser.customtabs.CustomTabsIntent.Builder(androidx.browser.customtabs.CustomTabsSession session)
+
+
PublicTypedef: androidx.browser.customtabs.CustomTabsService.Relation:
Don't expose @IntDef: Relation must be hidden.
PublicTypedef: androidx.browser.customtabs.CustomTabsService.Result:
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 91f795a..af29b9f 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -20,7 +20,7 @@
* The list of versions codes of all the libraries in this project.
*/
object LibraryVersions {
- val ACTIVITY = Version("1.2.0-alpha05")
+ val ACTIVITY = Version("1.2.0-alpha06")
val ADS_IDENTIFIER = Version("1.0.0-alpha04")
val ANNOTATION = Version("1.2.0-alpha01")
val ANNOTATION_EXPERIMENTAL = Version("1.1.0-alpha01")
@@ -58,7 +58,7 @@
val EMOJI = Version("1.2.0-alpha01")
val ENTERPRISE = Version("1.1.0-alpha01")
val EXIFINTERFACE = Version("1.3.0-alpha02")
- val FRAGMENT = Version("1.3.0-alpha05")
+ val FRAGMENT = Version("1.3.0-alpha06")
val FUTURES = Version("1.1.0-beta01")
val GRIDLAYOUT = Version("1.1.0-alpha01")
val HEIFWRITER = Version("1.1.0-alpha01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
index 3580d2a..161803c 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
@@ -112,6 +112,10 @@
"NotCloseable",
"SamShouldBeLast",
"MissingJvmstatic",
+ "CallbackMethodName",
+ "GetterOnBuilder",
+ "StaticFinalBuilder",
+ "MissingGetterMatchingBuilder",
// We should only treat these as warnings
"IntentBuilderName",
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
index 06b03c5..04120e0 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
@@ -132,6 +132,8 @@
baselineFile
)
args += listOf(
+ "--baseline",
+ baselineFile.toString(),
"--check-compatibility:api:released",
prevApi.toString(),
"--source-files",
@@ -171,7 +173,6 @@
return mutableListOf(
"--update-baseline",
baselineFile.toString(),
- "--baseline", baselineFile.toString(),
"--pass-baseline-updates",
"--delete-empty-baselines",
"--format=v3",
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java
index f026cde..42b79fa 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java
@@ -29,6 +29,7 @@
import androidx.camera.core.impl.MutableConfig;
import androidx.camera.core.impl.MutableOptionsBundle;
import androidx.camera.core.impl.OptionsBundle;
+import androidx.camera.core.impl.ReadableConfig;
import java.util.HashSet;
import java.util.Set;
@@ -36,7 +37,7 @@
/**
* Internal shared implementation details for camera 2 interop.
*/
-public final class Camera2ImplConfig implements Config {
+public final class Camera2ImplConfig implements ReadableConfig {
/** @hide */
@RestrictTo(Scope.LIBRARY)
@@ -202,43 +203,12 @@
return mConfig.retrieveOption(CAMERA_EVENT_CALLBACK_OPTION, valueIfMissing);
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- @Override
@NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
+ @Override
+ public Config getConfig() {
+ return mConfig;
}
- // End of the default implementation of Config
- // *********************************************************************************************
-
/**
* Builder for creating {@link Camera2ImplConfig} instance.
*
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControl.java
index ade6c1f..6222e11 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControl.java
@@ -282,9 +282,10 @@
return cropRect;
}
+ @Override
@WorkerThread
@NonNull
- Rect getSensorRect() {
+ public Rect getSensorRect() {
return Preconditions.checkNotNull(
mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE));
}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingConfig.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingConfig.java
index 6268999..f38d5d6 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingConfig.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/MeteringRepeatingConfig.java
@@ -17,10 +17,10 @@
package androidx.camera.camera2.internal;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.UseCase;
import androidx.camera.core.impl.CaptureConfig;
+import androidx.camera.core.impl.Config;
import androidx.camera.core.impl.MutableConfig;
import androidx.camera.core.impl.MutableOptionsBundle;
import androidx.camera.core.impl.OptionsBundle;
@@ -28,7 +28,6 @@
import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.core.internal.TargetConfig;
-import java.util.Set;
import java.util.UUID;
/**
@@ -43,168 +42,10 @@
mConfig = config;
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- @Nullable
- @Override
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- @Nullable
- @Override
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- @Override
- public void findOptions(@NonNull String idSearchString, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idSearchString, matcher);
- }
-
@NonNull
@Override
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
- @Nullable
- @Override
- public Class<MeteringRepeating> getTargetClass(
- @Nullable Class<MeteringRepeating> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<MeteringRepeating> storedClass =
- (Class<MeteringRepeating>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
- }
-
- @NonNull
- @Override
- public Class<MeteringRepeating> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<MeteringRepeating> storedClass =
- (Class<MeteringRepeating>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- @Nullable
- @Override
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- @NonNull
- @Override
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
-
-
- // Implementations of UseCaseConfig default methods
-
- @Nullable
- @Override
- public SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
- }
-
- @NonNull
- @Override
- public SessionConfig getDefaultSessionConfig() {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
- }
-
- @Nullable
- @Override
- public CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
- }
-
- @NonNull
- @Override
- public CaptureConfig getDefaultCaptureConfig() {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
- }
-
- @Nullable
- @Override
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @NonNull
- @Override
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
- }
-
- @Nullable
- @Override
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @NonNull
- @Override
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
- }
-
- @Override
- public int getSurfaceOccupancyPriority(int valueIfMissing) {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, valueIfMissing);
- }
-
- @Override
- public int getSurfaceOccupancyPriority() {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
- }
-
- @Nullable
- @Override
- public CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
- return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
- }
-
- @NonNull
- @Override
- public CameraSelector getCameraSelector() {
- return retrieveOption(OPTION_CAMERA_SELECTOR);
- }
-
- @Nullable
- @Override
- public UseCase.EventCallback getUseCaseEventCallback(
- @Nullable UseCase.EventCallback valueIfMissing) {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
- }
-
- @NonNull
- @Override
- public UseCase.EventCallback getUseCaseEventCallback() {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
- }
-
- @Override
- public int getInputFormat() {
- return retrieveOption(OPTION_INPUT_FORMAT);
+ public Config getConfig() {
+ return mConfig;
}
/** Builder for an empty Config */
@@ -344,6 +185,5 @@
}
}
-
}
diff --git a/camera/camera-core/api/api_lint.ignore b/camera/camera-core/api/api_lint.ignore
index 075bc7c..71e1926 100644
--- a/camera/camera-core/api/api_lint.ignore
+++ b/camera/camera-core/api/api_lint.ignore
@@ -1,3 +1,11 @@
// Baseline format: 1.0
+BuilderSetStyle: androidx.camera.core.CameraSelector.Builder#requireLensFacing(int):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.camera.core.CameraSelector.Builder.requireLensFacing(int)
+BuilderSetStyle: androidx.camera.core.CameraXConfig.Builder#fromConfig(androidx.camera.core.CameraXConfig):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.camera.core.CameraXConfig.Builder.fromConfig(androidx.camera.core.CameraXConfig)
+BuilderSetStyle: androidx.camera.core.FocusMeteringAction.Builder#disableAutoCancel():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.camera.core.FocusMeteringAction.Builder.disableAutoCancel()
+
+
TopLevelBuilder: androidx.camera.core.ExtendableBuilder:
Builder should be defined as inner class: androidx.camera.core.ExtendableBuilder
diff --git a/camera/camera-core/build.gradle b/camera/camera-core/build.gradle
index b9ab7e4..0615e08 100644
--- a/camera/camera-core/build.gradle
+++ b/camera/camera-core/build.gradle
@@ -37,7 +37,8 @@
implementation(AUTO_VALUE_ANNOTATIONS)
annotationProcessor(AUTO_VALUE)
-
+
+ testImplementation(KOTLIN_STDLIB)
testImplementation(ANDROIDX_TEST_CORE)
testImplementation(ANDROIDX_TEST_RUNNER)
testImplementation(JUNIT)
@@ -55,9 +56,7 @@
androidTestImplementation(TRUTH)
androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it's own MockMaker
androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it's own MockMaker
- androidTestImplementation project(":camera:camera-testing"), {
- exclude group: "androidx.camera", module: "camera-core"
- }
+ androidTestImplementation(project(":camera:camera-testing"))
androidTestImplementation(KOTLIN_STDLIB)
androidTestImplementation(KOTLIN_COROUTINES_ANDROID)
androidTestImplementation(project(":concurrent:concurrent-futures-ktx"))
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java
index a4f9844..8b6a9bc 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/FakeOtherUseCaseConfig.java
@@ -17,7 +17,6 @@
package androidx.camera.core;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.camera.core.impl.CaptureConfig;
import androidx.camera.core.impl.Config;
@@ -28,12 +27,10 @@
import androidx.camera.core.impl.SessionConfig;
import androidx.camera.core.impl.UseCaseConfig;
-import java.util.Set;
import java.util.UUID;
/** A fake configuration for {@link FakeOtherUseCase}. */
-public class FakeOtherUseCaseConfig
- implements UseCaseConfig<FakeOtherUseCase> {
+public class FakeOtherUseCaseConfig implements UseCaseConfig<FakeOtherUseCase> {
private final Config mConfig;
@@ -41,146 +38,10 @@
mConfig = config;
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
@NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
@Override
- @Nullable
- public Class<FakeOtherUseCase> getTargetClass(
- @Nullable Class<FakeOtherUseCase> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<FakeOtherUseCase> storedClass = (Class<FakeOtherUseCase>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
- }
-
- @Override
- @NonNull
- public Class<FakeOtherUseCase> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<FakeOtherUseCase> storedClass = (Class<FakeOtherUseCase>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- @Override
- @Nullable
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- @Override
- @NonNull
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
- }
-
- // Implementations of UseCaseConfig default methods
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @NonNull
- public SessionConfig getDefaultSessionConfig() {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
- }
-
- @Override
- @Nullable
- public CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig getDefaultCaptureConfig() {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @NonNull
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @NonNull
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
+ public Config getConfig() {
+ return mConfig;
}
/** @hide */
@@ -195,49 +56,11 @@
return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
}
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
- return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @NonNull
- public CameraSelector getCameraSelector() {
- return retrieveOption(OPTION_CAMERA_SELECTOR);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public UseCase.EventCallback getUseCaseEventCallback(
- @Nullable UseCase.EventCallback valueIfMissing) {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- @Override
- @NonNull
- public UseCase.EventCallback getUseCaseEventCallback() {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
- }
-
- // Implementations of ImageInputConfig default methods
-
@Override
public int getInputFormat() {
return ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE;
}
- // End of the default implementation of Config
- // *********************************************************************************************
-
/** Builder for an empty Config */
public static final class Builder implements
UseCaseConfig.Builder<FakeOtherUseCase, FakeOtherUseCaseConfig,
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java
index b0effe5..422d9b7 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.java
@@ -23,10 +23,12 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
+import android.graphics.Rect;
import android.util.Size;
import android.view.Surface;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.fakes.FakeCameraInfoInternal;
import androidx.core.content.ContextCompat;
@@ -47,6 +49,7 @@
public final class SurfaceRequestTest {
private static final Size FAKE_SIZE = new Size(0, 0);
+ private static final Rect FAKE_VIEW_PORT_RECT = new Rect(0, 0, 640, 480);
private static final Consumer<SurfaceRequest.Result> NO_OP_RESULT_LISTENER = ignored -> {
};
private static final Surface MOCK_SURFACE = mock(Surface.class);
@@ -187,8 +190,29 @@
verify(listener, timeout(500)).run();
}
+ @Test
+ public void createSurfaceRequestWithViewPort_viewPortIsSet() {
+ assertThat(createNewRequest(FAKE_SIZE, FAKE_VIEW_PORT_RECT).getViewPortRect()).isEqualTo(
+ FAKE_VIEW_PORT_RECT);
+ }
+
+ @Test
+ public void createSurfaceRequestWithNullViewPort_viewPortIsFullSurface() {
+ // Arrange.
+ Size size = new Size(200, 100);
+
+ // Assert.
+ assertThat(createNewRequest(size, null).getViewPortRect()).isEqualTo(
+ new Rect(0, 0, size.getWidth(), size.getHeight()));
+ }
+
private SurfaceRequest createNewRequest(@NonNull Size size) {
- SurfaceRequest request = new SurfaceRequest(size, new FakeCameraInfoInternal());
+ return createNewRequest(size, FAKE_VIEW_PORT_RECT);
+ }
+
+ private SurfaceRequest createNewRequest(@NonNull Size size, @Nullable Rect viewPortRect) {
+ SurfaceRequest request = new SurfaceRequest(size, new FakeCameraInfoInternal(),
+ viewPortRect);
mSurfaceRequests.add(request);
return request;
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
index 98acfd3..0f720f8 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
@@ -292,6 +292,7 @@
@NonNull UseCase... useCases) {
Threads.checkMainThread();
CameraX cameraX = checkInitialized();
+ // TODO(b/153096869): override UseCase's target rotation.
UseCaseGroupLifecycleController useCaseGroupLifecycleController =
cameraX.getOrCreateUseCaseGroup(lifecycleOwner);
@@ -355,7 +356,19 @@
originalUseCases,
Arrays.asList(useCases));
- // TODO(b/153096869): calculates crop rect using viewPort.
+ if (viewPort != null) {
+ // Calculate crop rect if view port is provided.
+ Map<UseCase, Rect> cropRectMap = calculateViewPortRects(
+ camera.getCameraControlInternal().getSensorRect(),
+ viewPort.getAspectRatio(),
+ camera.getCameraInfoInternal().getSensorRotationDegrees(
+ viewPort.getRotation()),
+ viewPort.getScaleType(),
+ suggestedResolutionsMap);
+ for (UseCase useCase : useCases) {
+ useCase.setViewPortCropRect(cropRectMap.get(useCase));
+ }
+ }
// At this point the binding will succeed since all the calculations are done
// Do all binding related work
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraXConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraXConfig.java
index c313920..9a8200f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraXConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraXConfig.java
@@ -32,7 +32,6 @@
import androidx.camera.core.impl.UseCaseConfigFactory;
import androidx.camera.core.internal.TargetConfig;
-import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
@@ -53,7 +52,7 @@
* @see androidx.camera.lifecycle
* @see CameraXConfig.Builder
*/
-public final class CameraXConfig implements TargetConfig<CameraX>, Config {
+public final class CameraXConfig implements TargetConfig<CameraX> {
/**
* An interface which can be implemented to provide the configuration for CameraX.
@@ -163,103 +162,22 @@
return mConfig.retrieveOption(OPTION_SCHEDULER_HANDLER, valueIfMissing);
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
/** @hide */
@RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
@NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
@Override
- @Nullable
- public Class<CameraX> getTargetClass(
- @Nullable Class<CameraX> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<CameraX> storedClass = (Class<CameraX>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
+ public Config getConfig() {
+ return mConfig;
}
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- @NonNull
- public Class<CameraX> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<CameraX> storedClass = (Class<CameraX>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- @NonNull
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
- // End of the default implementation of Config
- // *********************************************************************************************
-
/** A builder for generating {@link CameraXConfig} objects. */
public static final class Builder
implements TargetConfig.Builder<CameraX, CameraXConfig.Builder> {
private final MutableOptionsBundle mMutableConfig;
- /** Creates a new Builder object.
+ /**
+ * Creates a new Builder object.
*
* @hide
*/
@@ -299,7 +217,6 @@
* Sets the {@link CameraFactory} implementation for the application.
*
* @hide
- * @param cameraFactory
*/
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
@@ -366,8 +283,8 @@
* used in applications with very specific threading requirements. If not set, CameraX
* will create and use an optimized default internal handler.
*
- * @see #setCameraExecutor(Executor)
* @hide
+ * @see #setCameraExecutor(Executor)
*/
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index fcc3103..a3bd3a0 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -368,7 +368,13 @@
public void setAnalyzer(@NonNull Executor executor, @NonNull Analyzer analyzer) {
synchronized (mAnalysisLock) {
mImageAnalysisAbstractAnalyzer.open();
- mImageAnalysisAbstractAnalyzer.setAnalyzer(executor, analyzer);
+ mImageAnalysisAbstractAnalyzer.setAnalyzer(executor, image -> {
+ if (getViewPortCropRect() != null) {
+ image.setViewPortRect(getViewPortCropRect());
+ image.setCropRect(getViewPortCropRect());
+ }
+ analyzer.analyze(image);
+ });
if (mSubscribedAnalyzer == null) {
notifyActive();
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 6cb252b..bdf786e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -44,6 +44,7 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.graphics.ImageFormat;
+import android.graphics.Rect;
import android.location.Location;
import android.media.Image;
import android.media.ImageReader;
@@ -743,7 +744,7 @@
mPendingImageCaptureRequests.offer(
new ImageCaptureRequest(relativeRotation, getJpegQuality(), targetRatio,
- listenerExecutor, callback));
+ getViewPortCropRect(), listenerExecutor, callback));
issueImageCaptureRequests();
}
@@ -1872,6 +1873,8 @@
AtomicBoolean mDispatched = new AtomicBoolean(false);
+ private final Rect mViewPortCropRect;
+
/**
* @param rotationDegrees The degrees to rotate the image buffer from sensor
* coordinates into the final output coordinate space.
@@ -1883,6 +1886,7 @@
@RotationValue int rotationDegrees,
@IntRange(from = 1, to = 100) int jpegQuality,
Rational targetRatio,
+ @Nullable Rect viewPortCropRect,
@NonNull Executor executor,
@NonNull OnImageCapturedCallback callback) {
mRotationDegrees = rotationDegrees;
@@ -1893,6 +1897,7 @@
+ "positive");
}
mTargetRatio = targetRatio;
+ mViewPortCropRect = viewPortCropRect;
mListenerExecutor = executor;
mCallback = callback;
}
@@ -1943,7 +1948,12 @@
// Update the crop rect aspect ratio after it has been rotated into the buffer
// orientation
- if (mTargetRatio != null) {
+ if (mViewPortCropRect != null) {
+ // ViewPort rect has higher priority than the custom aspect ratio.
+ dispatchedImageProxy.setViewPortRect(mViewPortCropRect);
+ dispatchedImageProxy.setCropRect(mViewPortCropRect);
+ } else if (mTargetRatio != null) {
+ // Fall back to custom aspect ratio if view port is not available.
Rational dispatchRatio = mTargetRatio;
if ((dispatchRotation % 180) != 0) {
dispatchRatio = new Rational(
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index d49aef2..c430306 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -188,7 +188,7 @@
}
final SurfaceRequest surfaceRequest = new SurfaceRequest(resolution,
- getBoundCamera().getCameraInfo());
+ getBoundCamera().getCameraInfo(), getViewPortCropRect());
setUpSurfaceProviderWrap(surfaceRequest);
if (captureProcessor != null) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
index 61f47d7..ef9338c 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
@@ -56,6 +56,7 @@
private final Size mResolution;
private final CameraInfo mCameraInfo;
+ private final Rect mViewPortRect;
// For the camera to retrieve the surface from the user
@SuppressWarnings("WeakerAccess") /*synthetic accessor */
@@ -70,6 +71,16 @@
// cancellation listeners.
private final CallbackToFutureAdapter.Completer<Void> mRequestCancellationCompleter;
+ /**
+ * Creates a new surface request with the given resolution.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public SurfaceRequest(@NonNull Size resolution, @NonNull CameraInfo cameraInfo) {
+ this(resolution, cameraInfo, null);
+ }
+
private DeferrableSurface mInternalDeferrableSurface;
/**
@@ -78,10 +89,16 @@
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- public SurfaceRequest(@NonNull Size resolution, @NonNull CameraInfo cameraInfo) {
+ public SurfaceRequest(
+ @NonNull Size resolution,
+ @NonNull CameraInfo cameraInfo,
+ @Nullable Rect viewPortRect) {
super();
mResolution = resolution;
mCameraInfo = cameraInfo;
+ // Use full surface rect if viewPortRect is null.
+ mViewPortRect = viewPortRect != null ? viewPortRect : new Rect(0, 0, resolution.getWidth(),
+ resolution.getHeight());
// To ensure concurrency and ordering, operations are chained. Completion can only be
// triggered externally by the top-level completer (mSurfaceCompleter). The other future
@@ -248,8 +265,8 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@NonNull
- public Rect getCropRect() {
- throw new UnsupportedOperationException("Not implemented.");
+ public Rect getViewPortRect() {
+ return mViewPortRect;
}
/**
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index 489887c..4d172c3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -16,7 +16,10 @@
package androidx.camera.core;
+import android.graphics.Rect;
+import android.media.ImageReader;
import android.util.Size;
+import android.view.Surface;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
@@ -56,11 +59,16 @@
private SessionConfig mAttachedSessionConfig = SessionConfig.defaultEmptySessionConfig();
/**
- * A map of the names of the {@link android.hardware.camera2.CameraDevice} to the surface
- * resolution that have been attached to this UseCase
+ * The resolution assigned to the {@link UseCase} based on the attached camera.
*/
private Size mAttachedResolution;
+ /**
+ * The crop rect calculated at the time of binding based on {@link ViewPort}.
+ */
+ @Nullable
+ private Rect mViewPortCropRect;
+
private State mState = State.INACTIVE;
private UseCaseConfig<?> mUseCaseConfig;
@@ -96,7 +104,7 @@
*/
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
- protected UseCaseConfig.Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
+ protected Builder<?, ?, ?> getDefaultBuilder(@Nullable CameraInfo cameraInfo) {
return null;
}
@@ -119,7 +127,7 @@
@RestrictTo(Scope.LIBRARY_GROUP)
protected final void updateUseCaseConfig(@NonNull UseCaseConfig<?> useCaseConfig) {
// Attempt to retrieve builder containing defaults for this use case's config
- UseCaseConfig.Builder<?, ?, ?> defaultBuilder =
+ Builder<?, ?, ?> defaultBuilder =
getDefaultBuilder(
getBoundCamera() == null ? null : getBoundCamera().getCameraInfo());
@@ -143,7 +151,7 @@
@NonNull
protected UseCaseConfig<?> applyDefaults(
@NonNull UseCaseConfig<?> userConfig,
- @Nullable UseCaseConfig.Builder<?, ?, ?> defaultConfigBuilder) {
+ @Nullable Builder<?, ?, ?> defaultConfigBuilder) {
if (defaultConfigBuilder == null) {
// No default builder was retrieved, return config directly
return userConfig;
@@ -205,6 +213,7 @@
/**
* Get the current {@link SessionConfig}.
+ *
* @hide
*/
@RestrictTo(Scope.LIBRARY_GROUP)
@@ -317,7 +326,8 @@
* @hide
*/
@RestrictTo(Scope.LIBRARY_GROUP)
- public void clear() {}
+ public void clear() {
+ }
/**
* Called use case is unbound from lifecycle or the bound lifecycle is destroyed.
@@ -331,7 +341,8 @@
* @hide
*/
@RestrictTo(Scope.LIBRARY_GROUP)
- public void onDestroy() {}
+ public void onDestroy() {
+ }
/** @hide */
@RestrictTo(Scope.LIBRARY_GROUP)
@@ -390,12 +401,12 @@
* Called when binding new use cases via {@code CameraX#bindToLifecycle(LifecycleOwner,
* CameraSelector, UseCase...)}.
*
- * <p>Override to create necessary objects like {@link android.media.ImageReader} depending
+ * <p>Override to create necessary objects like {@link ImageReader} depending
* on the resolution.
*
* @param suggestedResolution The suggested resolution that depends on camera
- * device capability and what and how many use cases will be
- * bound.
+ * device capability and what and how many use cases will be
+ * bound.
* @return The resolution that finally used to create the SessionConfig to
* attach to the camera device.
* @hide
@@ -494,6 +505,27 @@
}
/**
+ * Sets the view port crop rect calculated at the time of binding.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ protected void setViewPortCropRect(@Nullable Rect viewPortCropRect) {
+ mViewPortCropRect = viewPortCropRect;
+ }
+
+ /**
+ * Gets the view port crop rect.
+ *
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @Nullable
+ protected Rect getViewPortCropRect() {
+ return mViewPortCropRect;
+ }
+
+ /**
* Get image format for the use case.
*
* @return image format for the use case
@@ -549,7 +581,7 @@
* camera.
*
* <p>Updating certain parameters of the use case require a full reset of the camera. This
- * includes updating the {@link android.view.Surface} used by the use case.
+ * includes updating the {@link Surface} used by the use case.
*/
void onUseCaseReset(@NonNull UseCase useCase);
}
@@ -559,7 +591,7 @@
*
* @hide
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @RestrictTo(Scope.LIBRARY_GROUP)
public interface EventCallback {
/**
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java
index 7e57571..8eacc77 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java
@@ -87,6 +87,12 @@
*/
void submitCaptureRequests(@NonNull List<CaptureConfig> captureConfigs);
+ /**
+ * Gets the full sensor rect.
+ */
+ @NonNull
+ Rect getSensorRect();
+
CameraControlInternal DEFAULT_EMPTY_INSTANCE = new CameraControlInternal() {
@Override
public void setCropRegion(@Nullable Rect crop) {
@@ -131,6 +137,12 @@
@NonNull
@Override
+ public Rect getSensorRect() {
+ return new Rect();
+ }
+
+ @NonNull
+ @Override
public ListenableFuture<FocusMeteringResult> startFocusAndMetering(
@NonNull FocusMeteringAction action) {
return Futures.immediateFuture(FocusMeteringResult.emptyInstance());
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageAnalysisConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageAnalysisConfig.java
index bf9b060..c414fe3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageAnalysisConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageAnalysisConfig.java
@@ -18,27 +18,16 @@
import android.graphics.ImageFormat;
import android.media.ImageReader;
-import android.util.Pair;
-import android.util.Rational;
-import android.util.Size;
-import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
-import androidx.camera.core.AspectRatio;
-import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageAnalysis.BackpressureStrategy;
import androidx.camera.core.ImageReaderProxyProvider;
-import androidx.camera.core.UseCase;
import androidx.camera.core.internal.ThreadConfig;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-
/**
* Configuration for an image analysis use case.
*/
@@ -67,6 +56,12 @@
mConfig = config;
}
+ @NonNull
+ @Override
+ public Config getConfig() {
+ return mConfig;
+ }
+
/**
* Retrieves the backpressure strategy applied to the image producer to deal with scenarios
* where images may be produced faster than they can be analyzed.
@@ -138,95 +133,6 @@
return retrieveOption(OPTION_IMAGE_READER_PROXY_PROVIDER, null);
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- @Override
- @NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
- @Override
- @Nullable
- public Class<ImageAnalysis> getTargetClass(
- @Nullable Class<ImageAnalysis> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<ImageAnalysis> storedClass =
- (Class<ImageAnalysis>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
- }
-
- @Override
- @NonNull
- public Class<ImageAnalysis> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<ImageAnalysis> storedClass =
- (Class<ImageAnalysis>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
/**
* Retrieves the format of the image that is fed as input.
*
@@ -236,285 +142,4 @@
public int getInputFormat() {
return ImageFormat.YUV_420_888;
}
-
- // Implementations of ImageOutputConfig default methods
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Rational getTargetAspectRatioCustom(@Nullable Rational valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM, valueIfMissing);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @NonNull
- @Override
- public Rational getTargetAspectRatioCustom() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
- }
-
- @Override
- public boolean hasTargetAspectRatio() {
- return containsOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @AspectRatio.Ratio
- @Override
- public int getTargetAspectRatio() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation(int valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ROTATION, valueIfMissing);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation() {
- return retrieveOption(OPTION_TARGET_ROTATION);
- }
-
- /**
- * Retrieves the resolution of the target intending to use from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Size getTargetResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION, valueIfMissing);
- }
-
- /**
- * Retrieves the resolution of the target intending to use from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Size getTargetResolution() {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
- @Override
- public Size getDefaultResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(ImageOutputConfig.OPTION_DEFAULT_RESOLUTION, valueIfMissing);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @NonNull
- @Override
- public Size getDefaultResolution() {
- return retrieveOption(ImageOutputConfig.OPTION_DEFAULT_RESOLUTION);
- }
-
- @Override
- @Nullable
- public Size getMaxResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_MAX_RESOLUTION, valueIfMissing);
- }
-
- @Override
- @NonNull
- public Size getMaxResolution() {
- return retrieveOption(OPTION_MAX_RESOLUTION);
- }
-
- @Override
- @Nullable
- public List<Pair<Integer, Size[]>> getSupportedResolutions(
- @Nullable List<Pair<Integer, Size[]>> valueIfMissing) {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS, valueIfMissing);
- }
-
- @Override
- @NonNull
- public List<Pair<Integer, Size[]>> getSupportedResolutions() {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS);
- }
-
- // Implementations of ThreadConfig default methods
-
- /**
- * Returns the executor that will be used for background tasks.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Executor getBackgroundExecutor(@Nullable Executor valueIfMissing) {
- return retrieveOption(OPTION_BACKGROUND_EXECUTOR, valueIfMissing);
- }
-
- /**
- * Returns the executor that will be used for background tasks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Executor getBackgroundExecutor() {
- return retrieveOption(OPTION_BACKGROUND_EXECUTOR);
- }
-
- // Implementations of UseCaseConfig default methods
-
- @Override
- @Nullable
- public SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig getDefaultSessionConfig() {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
- }
-
- @Override
- @Nullable
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
- }
-
- @Override
- @Nullable
- public CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig getDefaultCaptureConfig() {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
- }
-
- @Override
- @Nullable
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
- }
-
- @Override
- public int getSurfaceOccupancyPriority(int valueIfMissing) {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, valueIfMissing);
- }
-
- @Override
- public int getSurfaceOccupancyPriority() {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY)
- @Override
- @Nullable
- public CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
- return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY)
- @Override
- @NonNull
- public CameraSelector getCameraSelector() {
- return retrieveOption(OPTION_CAMERA_SELECTOR);
- }
-
- @Override
- @Nullable
- public UseCase.EventCallback getUseCaseEventCallback(
- @Nullable UseCase.EventCallback valueIfMissing) {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
- }
-
- @Override
- @NonNull
- public UseCase.EventCallback getUseCaseEventCallback() {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
- }
-
- // End of the default implementation of Config
- // *********************************************************************************************
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java
index 9c19af5..f7b499c 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java
@@ -17,32 +17,21 @@
package androidx.camera.core.impl;
import android.graphics.ImageFormat;
-import android.util.Pair;
-import android.util.Rational;
-import android.util.Size;
-import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
-import androidx.camera.core.AspectRatio;
-import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCapture.CaptureMode;
import androidx.camera.core.ImageReaderProxyProvider;
-import androidx.camera.core.UseCase;
import androidx.camera.core.internal.IoConfig;
-import java.util.List;
-import java.util.Set;
import java.util.concurrent.Executor;
/**
* Configuration for an image capture use case.
*/
-public final class ImageCaptureConfig
- implements UseCaseConfig<ImageCapture>,
- ImageOutputConfig,
+public final class ImageCaptureConfig implements UseCaseConfig<ImageCapture>, ImageOutputConfig,
IoConfig {
// Option Declarations:
@@ -74,6 +63,12 @@
mConfig = config;
}
+ @NonNull
+ @Override
+ public Config getConfig() {
+ return mConfig;
+ }
+
/**
* Returns whether a {@link CaptureMode} option has been set in this configuration.
*
@@ -217,255 +212,6 @@
return retrieveOption(OPTION_IMAGE_READER_PROXY_PROVIDER, null);
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- @Override
- @NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
- @Override
- @Nullable
- public Class<ImageCapture> getTargetClass(
- @Nullable Class<ImageCapture> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<ImageCapture> storedClass =
- (Class<ImageCapture>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
- }
-
- @Override
- @NonNull
- public Class<ImageCapture> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<ImageCapture> storedClass =
- (Class<ImageCapture>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
- // Implementations of ImageOutputConfig default methods
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Rational getTargetAspectRatioCustom(@Nullable Rational valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM, valueIfMissing);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @NonNull
- @Override
- public Rational getTargetAspectRatioCustom() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
- }
-
- @Override
- public boolean hasTargetAspectRatio() {
- return containsOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @AspectRatio.Ratio
- @Override
- public int getTargetAspectRatio() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation(int valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ROTATION, valueIfMissing);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation() {
- return retrieveOption(OPTION_TARGET_ROTATION);
- }
-
- /**
- * Retrieves the resolution of the target intending to use from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Size getTargetResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION, valueIfMissing);
- }
-
- /**
- * Retrieves the resolution of the target intending to use from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Size getTargetResolution() {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
- @Override
- public Size getDefaultResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_RESOLUTION, valueIfMissing);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @NonNull
- @Override
- public Size getDefaultResolution() {
- return retrieveOption(OPTION_DEFAULT_RESOLUTION);
- }
-
- @Override
- @Nullable
- public Size getMaxResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_MAX_RESOLUTION, valueIfMissing);
- }
-
- @Override
- @NonNull
- public Size getMaxResolution() {
- return retrieveOption(OPTION_MAX_RESOLUTION);
- }
-
- @Override
- @Nullable
- public List<Pair<Integer, Size[]>> getSupportedResolutions(
- @Nullable List<Pair<Integer, Size[]>> valueIfMissing) {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS, valueIfMissing);
- }
-
- @Override
- @NonNull
- public List<Pair<Integer, Size[]>> getSupportedResolutions() {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS);
- }
-
// Implementations of IO default methods
/**
@@ -502,94 +248,4 @@
public Executor getIoExecutor() {
return retrieveOption(OPTION_IO_EXECUTOR);
}
-
- // Implementations of UseCaseConfig default methods
-
- @Override
- @Nullable
- public SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig getDefaultSessionConfig() {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
- }
-
- @Override
- @Nullable
- public CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig getDefaultCaptureConfig() {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
- }
-
- @Override
- @Nullable
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
- }
-
- @Override
- @Nullable
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
- }
-
- @Override
- public int getSurfaceOccupancyPriority(int valueIfMissing) {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, valueIfMissing);
- }
-
- @Override
- public int getSurfaceOccupancyPriority() {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
- }
-
- @Override
- @Nullable
- public CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
- return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CameraSelector getCameraSelector() {
- return retrieveOption(OPTION_CAMERA_SELECTOR);
- }
-
- @Override
- @Nullable
- public UseCase.EventCallback getUseCaseEventCallback(
- @Nullable UseCase.EventCallback valueIfMissing) {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
- }
-
- @Override
- @NonNull
- public UseCase.EventCallback getUseCaseEventCallback() {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
- }
-
- // End of the default implementation of Config
- // *********************************************************************************************
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageInputConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageInputConfig.java
index 3e5d563..225e6e6 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageInputConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageInputConfig.java
@@ -19,7 +19,7 @@
import androidx.camera.core.Camera;
/** Configuration containing options for configuring the input image data of a pipeline. */
-public interface ImageInputConfig {
+public interface ImageInputConfig extends ReadableConfig {
Config.Option<Integer> OPTION_INPUT_FORMAT =
Config.Option.create("camerax.core.imageInput.inputFormat", int.class);
@@ -37,5 +37,7 @@
* code 0x22 for internal corresponding format HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED.
* Therefore, setting 0x22 as default image format.
*/
- int getInputFormat();
+ default int getInputFormat() {
+ return retrieveOption(OPTION_INPUT_FORMAT);
+ }
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageOutputConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageOutputConfig.java
index 5d9c4a4..25bf123 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageOutputConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageOutputConfig.java
@@ -26,7 +26,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.core.AspectRatio;
-import androidx.camera.core.impl.Config.Option;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -35,7 +34,7 @@
/**
* Configuration containing options for configuring the output image data of a pipeline.
*/
-public interface ImageOutputConfig {
+public interface ImageOutputConfig extends ReadableConfig {
/**
* Default aspect ratio for portrait and landscape
*/
@@ -102,7 +101,9 @@
* configuration.
*/
@Nullable
- Rational getTargetAspectRatioCustom(@Nullable Rational valueIfMissing);
+ default Rational getTargetAspectRatioCustom(@Nullable Rational valueIfMissing) {
+ return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM, valueIfMissing);
+ }
/**
* Retrieves the aspect ratio of the target intending to use images from this configuration.
@@ -115,7 +116,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- Rational getTargetAspectRatioCustom();
+ default Rational getTargetAspectRatioCustom() {
+ return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
+ }
/**
* Verifies whether the aspect ratio of the target intending to use images from this
@@ -123,7 +126,9 @@
*
* @return true is the value exists in this configuration, false otherwise.
*/
- boolean hasTargetAspectRatio();
+ default boolean hasTargetAspectRatio() {
+ return containsOption(OPTION_TARGET_ASPECT_RATIO);
+ }
/**
* Retrieves the aspect ratio of the target intending to use images from this configuration.
@@ -132,7 +137,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@AspectRatio.Ratio
- int getTargetAspectRatio();
+ default int getTargetAspectRatio() {
+ return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
+ }
/**
* Retrieves the rotation of the target intending to use images from this configuration.
@@ -146,7 +153,9 @@
* configuration.
*/
@RotationValue
- int getTargetRotation(int valueIfMissing);
+ default int getTargetRotation(int valueIfMissing) {
+ return retrieveOption(OPTION_TARGET_ROTATION, valueIfMissing);
+ }
/**
* Retrieves the rotation of the target intending to use images from this configuration.
@@ -159,7 +168,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@RotationValue
- int getTargetRotation();
+ default int getTargetRotation() {
+ return retrieveOption(OPTION_TARGET_ROTATION);
+ }
/**
* Retrieves the resolution of the target intending to use from this configuration.
@@ -169,7 +180,9 @@
* configuration.
*/
@Nullable
- Size getTargetResolution(@Nullable Size valueIfMissing);
+ default Size getTargetResolution(@Nullable Size valueIfMissing) {
+ return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION, valueIfMissing);
+ }
/**
* Retrieves the resolution of the target intending to use from this configuration.
@@ -178,7 +191,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- Size getTargetResolution();
+ default Size getTargetResolution() {
+ return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION);
+ }
/**
* Retrieves the default resolution of the target intending to use from this configuration.
@@ -188,7 +203,9 @@
* configuration.
*/
@Nullable
- Size getDefaultResolution(@Nullable Size valueIfMissing);
+ default Size getDefaultResolution(@Nullable Size valueIfMissing) {
+ return retrieveOption(OPTION_DEFAULT_RESOLUTION, valueIfMissing);
+ }
/**
* Retrieves the default resolution of the target intending to use from this configuration.
@@ -197,7 +214,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- Size getDefaultResolution();
+ default Size getDefaultResolution() {
+ return retrieveOption(OPTION_DEFAULT_RESOLUTION);
+ }
/**
* Retrieves the max resolution limitation of the target intending to use from this
@@ -208,7 +227,9 @@
* configuration.
*/
@Nullable
- Size getMaxResolution(@Nullable Size valueIfMissing);
+ default Size getMaxResolution(@Nullable Size valueIfMissing) {
+ return retrieveOption(OPTION_MAX_RESOLUTION, valueIfMissing);
+ }
/**
* Retrieves the max resolution limitation of the target intending to use from this
@@ -218,7 +239,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- Size getMaxResolution();
+ default Size getMaxResolution() {
+ return retrieveOption(OPTION_MAX_RESOLUTION);
+ }
/**
* Retrieves the supported resolutions can be used by the target from this configuration.
@@ -232,8 +255,10 @@
* configuration.
*/
@Nullable
- List<Pair<Integer, Size[]>> getSupportedResolutions(
- @Nullable List<Pair<Integer, Size[]>> valueIfMissing);
+ default List<Pair<Integer, Size[]>> getSupportedResolutions(
+ @Nullable List<Pair<Integer, Size[]>> valueIfMissing) {
+ return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS, valueIfMissing);
+ }
/**
* Retrieves the supported resolutions can be used by the target from this configuration.
@@ -246,7 +271,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- List<Pair<Integer, Size[]>> getSupportedResolutions();
+ default List<Pair<Integer, Size[]>> getSupportedResolutions() {
+ return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS);
+ }
/**
* Builder for a {@link ImageOutputConfig}.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java
index a16b700..de4e98c1 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java
@@ -16,23 +16,11 @@
package androidx.camera.core.impl;
-import android.util.Pair;
-import android.util.Rational;
-import android.util.Size;
-import android.view.Surface;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.camera.core.AspectRatio;
-import androidx.camera.core.CameraSelector;
import androidx.camera.core.Preview;
-import androidx.camera.core.UseCase;
import androidx.camera.core.internal.ThreadConfig;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-
/**
* Configuration for a {@link Preview} use case.
*/
@@ -54,373 +42,10 @@
mConfig = config;
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- @Override
- @NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
- @Override
- @Nullable
- public Class<Preview> getTargetClass(
- @Nullable Class<Preview> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<Preview> storedClass =
- (Class<Preview>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
- }
-
- @Override
- @NonNull
- public Class<Preview> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<Preview> storedClass =
- (Class<Preview>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
- // Implementations of ImageOutputConfig default methods
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Rational getTargetAspectRatioCustom(@Nullable Rational valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM, valueIfMissing);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
@NonNull
@Override
- public Rational getTargetAspectRatioCustom() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
- }
-
- @Override
- public boolean hasTargetAspectRatio() {
- return containsOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @AspectRatio.Ratio
- @Override
- public int getTargetAspectRatio() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * <p>Preview always set the rotation to device's nature orientation.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation(int valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ROTATION, valueIfMissing);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * <p>Preview always set the rotation to device's nature orientation.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation() {
- return retrieveOption(OPTION_TARGET_ROTATION);
- }
-
- /**
- * Retrieves the resolution of the target intending to use from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Size getTargetResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION, valueIfMissing);
- }
-
- /**
- * Retrieves the resolution of the target intending to use from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Size getTargetResolution() {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
- @Override
- public Size getDefaultResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(ImageOutputConfig.OPTION_DEFAULT_RESOLUTION, valueIfMissing);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @NonNull
- @Override
- public Size getDefaultResolution() {
- return retrieveOption(ImageOutputConfig.OPTION_DEFAULT_RESOLUTION);
- }
-
- @Override
- @Nullable
- public Size getMaxResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_MAX_RESOLUTION, valueIfMissing);
- }
-
- @Override
- @NonNull
- public Size getMaxResolution() {
- return retrieveOption(OPTION_MAX_RESOLUTION);
- }
-
- @Override
- @Nullable
- public List<Pair<Integer, Size[]>> getSupportedResolutions(
- @Nullable List<Pair<Integer, Size[]>> valueIfMissing) {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS, valueIfMissing);
- }
-
- @Override
- @NonNull
- public List<Pair<Integer, Size[]>> getSupportedResolutions() {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS);
- }
-
- // Implementations of ThreadConfig default methods
-
- /**
- * Returns the executor that will be used for background tasks.
- *
- * <p>Background executor not used in {@link Preview}.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Executor getBackgroundExecutor(@Nullable Executor valueIfMissing) {
- return retrieveOption(OPTION_BACKGROUND_EXECUTOR, valueIfMissing);
- }
-
- /**
- * Returns the executor that will be used for background tasks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Executor getBackgroundExecutor() {
- return retrieveOption(OPTION_BACKGROUND_EXECUTOR);
- }
-
- // Implementations of UseCaseConfig default methods
-
- @Override
- @Nullable
- public SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig getDefaultSessionConfig() {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
- }
-
- @Override
- @Nullable
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
- }
-
- @Override
- @Nullable
- public CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig getDefaultCaptureConfig() {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
- }
-
- @Override
- @Nullable
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
- }
-
- @Override
- public int getSurfaceOccupancyPriority(int valueIfMissing) {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, valueIfMissing);
- }
-
- @Override
- public int getSurfaceOccupancyPriority() {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
- }
-
- @Override
- @Nullable
- public CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
- return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CameraSelector getCameraSelector() {
- return retrieveOption(OPTION_CAMERA_SELECTOR);
- }
-
- @Override
- @Nullable
- public UseCase.EventCallback getUseCaseEventCallback(
- @Nullable UseCase.EventCallback valueIfMissing) {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
- }
-
- @Override
- @NonNull
- public UseCase.EventCallback getUseCaseEventCallback() {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
+ public Config getConfig() {
+ return mConfig;
}
/**
@@ -470,7 +95,4 @@
public int getInputFormat() {
return retrieveOption(OPTION_INPUT_FORMAT);
}
-
- // End of the default implementation of Config
- // *********************************************************************************************
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/ReadableConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/ReadableConfig.java
new file mode 100644
index 0000000..75b01b1
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/ReadableConfig.java
@@ -0,0 +1,68 @@
+/*
+ * 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.camera.core.impl;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Set;
+
+/**
+ * Interface that can be extended to create APIs for reading specific options.
+ *
+ * <p>ReadableConfig objects are also {@link Config} objects, so can be passed to any method that
+ * expects a {@link Config}.
+ */
+public interface ReadableConfig extends Config {
+
+ /**
+ * Returns the underlying immutable {@link Config} object.
+ *
+ * @return The underlying {@link Config} object.
+ */
+ @NonNull
+ Config getConfig();
+
+ @Override
+ default boolean containsOption(@NonNull Option<?> id) {
+ return getConfig().containsOption(id);
+ }
+
+ @Override
+ @Nullable
+ default <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
+ return getConfig().retrieveOption(id);
+ }
+
+ @Override
+ @Nullable
+ default <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
+ @Nullable ValueT valueIfMissing) {
+ return getConfig().retrieveOption(id, valueIfMissing);
+ }
+
+ @Override
+ default void findOptions(@NonNull String idSearchString, @NonNull OptionMatcher matcher) {
+ getConfig().findOptions(idSearchString, matcher);
+ }
+
+ @Override
+ @NonNull
+ default Set<Option<?>> listOptions() {
+ return getConfig().listOptions();
+ }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfig.java
index 859709f2..680d3f8 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfig.java
@@ -29,8 +29,8 @@
*
* @param <T> The use case being configured.
*/
-public interface UseCaseConfig<T extends UseCase> extends TargetConfig<T>, Config,
- UseCaseEventConfig , ImageInputConfig {
+public interface UseCaseConfig<T extends UseCase> extends TargetConfig<T>, UseCaseEventConfig,
+ ImageInputConfig {
// Option Declarations:
// *********************************************************************************************
@@ -86,7 +86,9 @@
* configuration.
*/
@Nullable
- SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing);
+ default SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
+ return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
+ }
/**
* Retrieves the default session configuration for this use case.
@@ -98,7 +100,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- SessionConfig getDefaultSessionConfig();
+ default SessionConfig getDefaultSessionConfig() {
+ return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
+ }
/**
* Retrieves the default capture configuration for this use case.
@@ -111,7 +115,9 @@
* configuration.
*/
@Nullable
- CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing);
+ default CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
+ return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
+ }
/**
* Retrieves the default capture configuration for this use case.
@@ -123,7 +129,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- CaptureConfig getDefaultCaptureConfig();
+ default CaptureConfig getDefaultCaptureConfig() {
+ return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
+ }
/**
* Retrieves the {@link SessionConfig.OptionUnpacker} for this use case.
@@ -138,8 +146,10 @@
* configuration.
*/
@Nullable
- SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing);
+ default SessionConfig.OptionUnpacker getSessionOptionUnpacker(
+ @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
+ return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
+ }
/**
* Retrieves the {@link SessionConfig.OptionUnpacker} for this use case.
@@ -153,7 +163,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- SessionConfig.OptionUnpacker getSessionOptionUnpacker();
+ default SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
+ return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
+ }
/**
* Retrieves the {@link CaptureConfig.OptionUnpacker} for this use case.
@@ -168,8 +180,10 @@
* configuration.
*/
@Nullable
- CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing);
+ default CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
+ @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
+ return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
+ }
/**
* Retrieves the {@link CaptureConfig.OptionUnpacker} for this use case.
@@ -183,7 +197,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- CaptureConfig.OptionUnpacker getCaptureOptionUnpacker();
+ default CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
+ return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
+ }
/**
* Retrieves the surface occupancy priority of the target intending to use from this
@@ -193,7 +209,9 @@
* @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
* configuration.
*/
- int getSurfaceOccupancyPriority(int valueIfMissing);
+ default int getSurfaceOccupancyPriority(int valueIfMissing) {
+ return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, valueIfMissing);
+ }
/**
* Retrieves the surface occupancy priority of the target intending to use from this
@@ -202,7 +220,9 @@
* @return The stored value, if it exists in this configuration.
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
- int getSurfaceOccupancyPriority();
+ default int getSurfaceOccupancyPriority() {
+ return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
+ }
/**
* Retrieves the camera selector that this use case requires.
@@ -212,7 +232,9 @@
* configuration.
*/
@Nullable
- CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing);
+ default CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
+ return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
+ }
/**
* Retrieves the camera selector that this use case requires.
@@ -221,7 +243,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- CameraSelector getCameraSelector();
+ default CameraSelector getCameraSelector() {
+ return retrieveOption(OPTION_CAMERA_SELECTOR);
+ }
/**
* Builder for a {@link UseCase}.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/VideoCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/VideoCaptureConfig.java
index 4dc69c0..732ffdf 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/VideoCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/VideoCaptureConfig.java
@@ -23,7 +23,6 @@
import android.view.Surface;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.camera.core.AspectRatio;
@@ -34,7 +33,6 @@
import androidx.camera.core.internal.ThreadConfig;
import java.util.List;
-import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
@@ -254,363 +252,12 @@
return ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE;
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- @Override
- @NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
- @Override
- @Nullable
- public Class<VideoCapture> getTargetClass(
- @Nullable Class<VideoCapture> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<VideoCapture> storedClass =
- (Class<VideoCapture>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
- }
-
- @Override
- @NonNull
- public Class<VideoCapture> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<VideoCapture> storedClass =
- (Class<VideoCapture>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- /**
- * Retrieves the name of the target object being configured.
- *
- * <p>The name should be a value that can uniquely identify an instance of the object being
- * configured.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
- // Implementations of ImageOutputConfig default methods
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Rational getTargetAspectRatioCustom(@Nullable Rational valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM, valueIfMissing);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * <p>This is the ratio of the target's width to the image's height, where the numerator of the
- * provided {@link Rational} corresponds to the width, and the denominator corresponds to the
- * height.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
@NonNull
@Override
- public Rational getTargetAspectRatioCustom() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
+ public Config getConfig() {
+ return mConfig;
}
- @Override
- public boolean hasTargetAspectRatio() {
- return containsOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @AspectRatio.Ratio
- @Override
- public int getTargetAspectRatio() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation(int valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ROTATION, valueIfMissing);
- }
-
- /**
- * Retrieves the rotation of the target intending to use images from this configuration.
- *
- * <p>This is one of four valid values: {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. Rotation values are relative to
- * the device's "natural" rotation, {@link Surface#ROTATION_0}.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @RotationValue
- public int getTargetRotation() {
- return retrieveOption(OPTION_TARGET_ROTATION);
- }
-
- @Override
- @Nullable
- public Size getTargetResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION, valueIfMissing);
- }
-
- @Override
- @NonNull
- public Size getTargetResolution() {
- return retrieveOption(ImageOutputConfig.OPTION_TARGET_RESOLUTION);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
- @Override
- public Size getDefaultResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(ImageOutputConfig.OPTION_DEFAULT_RESOLUTION, valueIfMissing);
- }
-
- /**
- * Retrieves the default resolution of the target intending to use from this configuration.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @NonNull
- @Override
- public Size getDefaultResolution() {
- return retrieveOption(ImageOutputConfig.OPTION_DEFAULT_RESOLUTION);
- }
-
- @Override
- @Nullable
- public Size getMaxResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_MAX_RESOLUTION, valueIfMissing);
- }
-
- @Override
- @NonNull
- public Size getMaxResolution() {
- return retrieveOption(OPTION_MAX_RESOLUTION);
- }
-
- @Override
- @Nullable
- public List<Pair<Integer, Size[]>> getSupportedResolutions(
- @Nullable List<Pair<Integer, Size[]>> valueIfMissing) {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS, valueIfMissing);
- }
-
- @Override
- @NonNull
- public List<Pair<Integer, Size[]>> getSupportedResolutions() {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS);
- }
-
- // Implementations of ThreadConfig default methods
-
- /**
- * Returns the executor that will be used for background tasks.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Override
- @Nullable
- public Executor getBackgroundExecutor(@Nullable Executor valueIfMissing) {
- return retrieveOption(OPTION_BACKGROUND_EXECUTOR, valueIfMissing);
- }
-
- /**
- * Returns the executor that will be used for background tasks.
- *
- * @return The stored value, if it exists in this configuration.
- * @throws IllegalArgumentException if the option does not exist in this configuration.
- */
- @Override
- @NonNull
- public Executor getBackgroundExecutor() {
- return retrieveOption(OPTION_BACKGROUND_EXECUTOR);
- }
-
- // Implementations of UseCaseConfig default methods
-
- @Override
- @Nullable
- public SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig getDefaultSessionConfig() {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
- }
-
- @Override
- @Nullable
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
- }
-
- @Override
- @Nullable
- public CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig getDefaultCaptureConfig() {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
- }
-
- @Override
- @Nullable
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
- }
-
- @Override
- public int getSurfaceOccupancyPriority(int valueIfMissing) {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, valueIfMissing);
- }
-
- @Override
- public int getSurfaceOccupancyPriority() {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY)
- @Override
- @Nullable
- public CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
- return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY)
- @Override
- @NonNull
- public CameraSelector getCameraSelector() {
- return retrieveOption(OPTION_CAMERA_SELECTOR);
- }
-
- @Override
- @Nullable
- public UseCase.EventCallback getUseCaseEventCallback(
- @Nullable UseCase.EventCallback valueIfMissing) {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
- }
-
- @Override
- @NonNull
- public UseCase.EventCallback getUseCaseEventCallback() {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
- }
-
- // End of the default implementation of Config
- // *********************************************************************************************
-
/** Builder for a {@link VideoCaptureConfig}. */
public static final class Builder
implements
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/IoConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/IoConfig.java
index b8c4712..7f283be 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/IoConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/IoConfig.java
@@ -18,14 +18,14 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.camera.core.impl.Config.Option;
+import androidx.camera.core.impl.ReadableConfig;
import java.util.concurrent.Executor;
/**
* Configuration containing IO related options.
*/
-public interface IoConfig {
+public interface IoConfig extends ReadableConfig {
// Option Declarations:
// *********************************************************************************************
@@ -46,7 +46,9 @@
* configuration.
*/
@Nullable
- Executor getIoExecutor(@Nullable Executor valueIfMissing);
+ default Executor getIoExecutor(@Nullable Executor valueIfMissing) {
+ return retrieveOption(OPTION_IO_EXECUTOR, valueIfMissing);
+ }
/**
@@ -56,7 +58,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- Executor getIoExecutor();
+ default Executor getIoExecutor() {
+ return retrieveOption(OPTION_IO_EXECUTOR);
+ }
/**
* Builder for a {@link IoConfig}.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/TargetConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/TargetConfig.java
index 2ddf24c..ad97e73 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/TargetConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/TargetConfig.java
@@ -20,14 +20,14 @@
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
-import androidx.camera.core.impl.Config.Option;
+import androidx.camera.core.impl.ReadableConfig;
/**
* Configuration containing options used to identify the target class and object being configured.
*
* @param <T> The type of the object being configured.
*/
-public interface TargetConfig<T> {
+public interface TargetConfig<T> extends ReadableConfig {
// Option Declarations:
// *********************************************************************************************
@@ -59,8 +59,11 @@
* @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
* configuration.
*/
+ @SuppressWarnings("unchecked")
@Nullable
- Class<T> getTargetClass(@Nullable Class<T> valueIfMissing);
+ default Class<T> getTargetClass(@Nullable Class<T> valueIfMissing) {
+ return (Class<T>) retrieveOption(OPTION_TARGET_CLASS, valueIfMissing);
+ }
/**
* Retrieves the class of the object being configured.
@@ -68,8 +71,11 @@
* @return The stored value, if it exists in this configuration.
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
+ @SuppressWarnings("unchecked")
@NonNull
- Class<T> getTargetClass();
+ default Class<T> getTargetClass() {
+ return (Class<T>) retrieveOption(OPTION_TARGET_CLASS);
+ }
/**
* Retrieves the name of the target object being configured.
@@ -82,7 +88,9 @@
* configuration.
*/
@Nullable
- String getTargetName(@Nullable String valueIfMissing);
+ default String getTargetName(@Nullable String valueIfMissing) {
+ return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
+ }
/**
* Retrieves the name of the target object being configured.
@@ -94,7 +102,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- String getTargetName();
+ default String getTargetName() {
+ return retrieveOption(OPTION_TARGET_NAME);
+ }
/**
* Builder for a {@link TargetConfig}.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/ThreadConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/ThreadConfig.java
index 05aaa5f..e31c0f4 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/ThreadConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/ThreadConfig.java
@@ -18,14 +18,14 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.camera.core.impl.Config.Option;
+import androidx.camera.core.impl.ReadableConfig;
import java.util.concurrent.Executor;
/**
* Configuration containing options pertaining to threads used by the configured object.
*/
-public interface ThreadConfig {
+public interface ThreadConfig extends ReadableConfig {
// Option Declarations:
// *********************************************************************************************
@@ -46,7 +46,9 @@
* configuration.
*/
@Nullable
- Executor getBackgroundExecutor(@Nullable Executor valueIfMissing);
+ default Executor getBackgroundExecutor(@Nullable Executor valueIfMissing) {
+ return retrieveOption(OPTION_BACKGROUND_EXECUTOR, valueIfMissing);
+ }
/**
@@ -56,7 +58,9 @@
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@NonNull
- Executor getBackgroundExecutor();
+ default Executor getBackgroundExecutor() {
+ return retrieveOption(OPTION_BACKGROUND_EXECUTOR);
+ }
/**
* Builder for a {@link ThreadConfig}.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseEventConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseEventConfig.java
index 1183cc4..729683e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseEventConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/UseCaseEventConfig.java
@@ -20,11 +20,12 @@
import androidx.annotation.Nullable;
import androidx.camera.core.UseCase;
import androidx.camera.core.impl.Config;
+import androidx.camera.core.impl.ReadableConfig;
/**
* Configuration containing options pertaining to EventCallback object.
*/
-public interface UseCaseEventConfig {
+public interface UseCaseEventConfig extends ReadableConfig {
/**
* Option: camerax.core.useCaseEventCallback
@@ -40,7 +41,10 @@
* configuration.
*/
@Nullable
- UseCase.EventCallback getUseCaseEventCallback(@Nullable UseCase.EventCallback valueIfMissing);
+ default UseCase.EventCallback getUseCaseEventCallback(
+ @Nullable UseCase.EventCallback valueIfMissing) {
+ return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
+ }
/**
* Returns the EventCallback.
@@ -48,7 +52,9 @@
* @return The stored value, if it exists in this configuration.
*/
@NonNull
- UseCase.EventCallback getUseCaseEventCallback();
+ default UseCase.EventCallback getUseCaseEventCallback() {
+ return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
+ }
// Option Declarations:
// *********************************************************************************************
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
index d213605..72fe289 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 The Android Open Source Project
+ * 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.
@@ -19,9 +19,12 @@
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
+import android.util.Rational;
+import android.view.Surface;
import androidx.camera.core.impl.CameraFactory;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
@@ -72,17 +75,18 @@
private List<ImageProxy> mImageProxiesReceived;
private ImageAnalysis mImageAnalysis;
private FakeImageReaderProxy mFakeImageReaderProxy;
+ private HandlerThread mBackgroundThread;
+ private HandlerThread mCallbackThread;
@Before
public void setUp() throws ExecutionException, InterruptedException {
- mFakeImageReaderProxy = new FakeImageReaderProxy(QUEUE_DEPTH);
- HandlerThread callbackThread = new HandlerThread("Callback");
- callbackThread.start();
- mCallbackHandler = new Handler(callbackThread.getLooper());
+ mCallbackThread = new HandlerThread("Callback");
+ mCallbackThread.start();
+ mCallbackHandler = new Handler(mCallbackThread.getLooper());
- HandlerThread backgroundThread = new HandlerThread("Background");
- backgroundThread.start();
- mBackgroundHandler = new Handler(backgroundThread.getLooper());
+ mBackgroundThread = new HandlerThread("Background");
+ mBackgroundThread.start();
+ mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
mBackgroundExecutor = CameraXExecutors.newHandlerExecutor(mBackgroundHandler);
mImageProxiesReceived = new ArrayList<>();
@@ -93,7 +97,6 @@
() -> new FakeCamera(ShadowCameraX.DEFAULT_CAMERA_ID));
return cameraFactory;
};
-
CameraXConfig cameraXConfig = CameraXConfig.Builder.fromConfig(
FakeAppConfig.create()).setCameraFactoryProvider(cameraFactoryProvider).build();
@@ -106,6 +109,68 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(CameraX::unbindAll);
mImageProxiesReceived.clear();
CameraX.shutdown().get();
+ if (mBackgroundThread != null) {
+ mBackgroundThread.quitSafely();
+ }
+ if (mCallbackThread != null) {
+ mCallbackThread.quitSafely();
+ }
+ }
+
+ @Test
+ public void largerThanBufferViewPortRect_cropRectIsBufferSize() throws InterruptedException {
+ // Arrange.
+ Rect largerThanBufferRect = new Rect(-1, -1, 10000, 10000);
+ setUpImageAnalysisWithStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST,
+ new ViewPort.Builder()
+ .setAspectRatio(new Rational(1, 1))
+ .setScaleType(ViewPort.FILL_CENTER)
+ .setRotation(Surface.ROTATION_0).build());
+ // Sets viewPortRect directly because Shadow#invert() doesn't work in unit test.
+ mImageAnalysis.setViewPortCropRect(largerThanBufferRect);
+
+ // Act.
+ mFakeImageReaderProxy.triggerImageAvailable(IMAGE_TAG, TIMESTAMP_1);
+ flushHandler(mBackgroundHandler);
+ flushHandler(mCallbackHandler);
+
+ // Assert.
+ ImageProxy imageProxyReceived = Iterables.getOnlyElement(mImageProxiesReceived);
+ assertThat(imageProxyReceived.getCropRect())
+ .isEqualTo(new Rect(0, 0, mFakeImageReaderProxy.getWidth(),
+ mFakeImageReaderProxy.getHeight()));
+ assertThat(imageProxyReceived.getViewPortRect()).isEqualTo(largerThanBufferRect);
+ }
+
+ @Test
+ public void bindViewPortWithFillStyle_returnsSameViewPortRectAndCropRect()
+ throws InterruptedException {
+ // Arrange.
+ setUpImageAnalysisWithStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST,
+ new ViewPort.Builder()
+ .setAspectRatio(new Rational(1, 1))
+ .setScaleType(ViewPort.FILL_CENTER)
+ .setRotation(Surface.ROTATION_0).build());
+
+ // Act.
+ mFakeImageReaderProxy.triggerImageAvailable(IMAGE_TAG, TIMESTAMP_1);
+ flushHandler(mBackgroundHandler);
+ flushHandler(mCallbackHandler);
+
+ // Assert: both
+ ImageProxy imageProxyReceived = Iterables.getOnlyElement(mImageProxiesReceived);
+ // The expected value is based on fitting the 1:1 view port into a rect with the size of
+ // the ImageReader.
+ int expectedPadding =
+ (mFakeImageReaderProxy.getWidth() - mFakeImageReaderProxy.getHeight()) / 2;
+ assertThat(imageProxyReceived.getCropRect())
+ .isEqualTo(new Rect(expectedPadding, 0,
+ mFakeImageReaderProxy.getWidth() - expectedPadding,
+ mFakeImageReaderProxy.getHeight()));
+ assertThat(imageProxyReceived.getViewPortRect())
+ .isEqualTo(new Rect(expectedPadding, 0,
+ mFakeImageReaderProxy.getWidth() - expectedPadding,
+ mFakeImageReaderProxy.getHeight()));
}
@Test
@@ -233,12 +298,22 @@
private void setUpImageAnalysisWithStrategy(
@ImageAnalysis.BackpressureStrategy int backpressureStrategy) {
+ setUpImageAnalysisWithStrategy(backpressureStrategy, null);
+ }
+
+ private void setUpImageAnalysisWithStrategy(
+ @ImageAnalysis.BackpressureStrategy int backpressureStrategy, ViewPort viewPort) {
mImageAnalysis = new ImageAnalysis.Builder()
.setBackgroundExecutor(mBackgroundExecutor)
+ .setTargetRotation(Surface.ROTATION_0)
.setImageQueueDepth(QUEUE_DEPTH)
.setBackpressureStrategy(backpressureStrategy)
.setImageReaderProxyProvider(
- (width, height, format, queueDepth, usage) -> mFakeImageReaderProxy)
+ (width, height, format, queueDepth, usage) -> {
+ mFakeImageReaderProxy = FakeImageReaderProxy.newInstance(width,
+ height, format, queueDepth, usage);
+ return mFakeImageReaderProxy;
+ })
.build();
mImageAnalysis.setAnalyzer(CameraXExecutors.newHandlerExecutor(mCallbackHandler),
@@ -250,7 +325,10 @@
FakeLifecycleOwner lifecycleOwner = new FakeLifecycleOwner();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- CameraX.bindToLifecycle(lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA,
+ CameraX.bindToLifecycle(
+ lifecycleOwner,
+ CameraSelector.DEFAULT_BACK_CAMERA,
+ viewPort,
mImageAnalysis);
lifecycleOwner.startAndResume();
});
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
new file mode 100644
index 0000000..75bcbe6
--- /dev/null
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageCaptureTest.kt
@@ -0,0 +1,228 @@
+/*
+ * 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.camera.core
+
+import android.content.Context
+import android.graphics.ImageFormat
+import android.graphics.Rect
+import android.os.Build
+import android.os.Handler
+import android.os.HandlerThread
+import android.util.Rational
+import android.view.Surface
+import androidx.camera.core.impl.CameraFactory
+import androidx.camera.core.impl.CameraThreadConfig
+import androidx.camera.core.impl.CaptureConfig
+import androidx.camera.core.impl.UseCaseConfig
+import androidx.camera.core.impl.utils.executor.CameraXExecutors
+import androidx.camera.testing.fakes.FakeAppConfig
+import androidx.camera.testing.fakes.FakeCamera
+import androidx.camera.testing.fakes.FakeCameraFactory
+import androidx.camera.testing.fakes.FakeImageReaderProxy
+import androidx.camera.testing.fakes.FakeLifecycleOwner
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.shadow.api.Shadow
+import org.robolectric.shadows.ShadowLooper
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.Executor
+
+/**
+ * Unit tests for [ImageCapture].
+ */
+@MediumTest
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP, shadows = [ShadowCameraX::class])
+class ImageCaptureTest {
+
+ private var executor: Executor? = null
+ private var callbackHandler: Handler? = null
+ private var fakeImageReaderProxy: FakeImageReaderProxy? = null
+ private var capturedImage: ImageProxy? = null
+ private val : ImageCapture.OnImageCapturedCallback() {
+ override fun onCaptureSuccess(image: ImageProxy) {
+ capturedImage = image
+ }
+
+ override fun onError(exception: ImageCaptureException) {
+ }
+ }
+
+ @Before
+ @Throws(ExecutionException::class, InterruptedException::class)
+ fun setUp() {
+ val cameraFactoryProvider =
+ CameraFactory.Provider { _: Context?, _: CameraThreadConfig? ->
+ val cameraFactory = FakeCameraFactory()
+ cameraFactory.insertDefaultBackCamera(ShadowCameraX.DEFAULT_CAMERA_ID) {
+ FakeCamera(ShadowCameraX.DEFAULT_CAMERA_ID)
+ }
+ cameraFactory
+ }
+ val cameraXConfig = CameraXConfig.Builder.fromConfig(
+ FakeAppConfig.create()
+ ).setCameraFactoryProvider(cameraFactoryProvider).build()
+ val context =
+ ApplicationProvider.getApplicationContext<Context>()
+ CameraX.initialize(context, cameraXConfig).get()
+ val callbackThread = HandlerThread("Callback")
+ callbackThread.start()
+ callbackHandler = Handler(callbackThread.looper)
+ executor = CameraXExecutors.newHandlerExecutor(callbackHandler!!)
+ }
+
+ @After
+ @Throws(ExecutionException::class, InterruptedException::class)
+ fun tearDown() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync { CameraX.unbindAll() }
+ CameraX.shutdown().get()
+ fakeImageReaderProxy = null
+ }
+
+ @Test
+ fun captureImageWithViewPortCropRectLargerThanBuffer_cropRectIsFullSize() {
+ // Arrange.
+ val imageCapture = bindImageCapture(
+ ViewPort.Builder()
+ .setAspectRatio(Rational(1, 1))
+ .setScaleType(ViewPort.FILL_CENTER)
+ .setRotation(Surface.ROTATION_0).build()
+ )
+ // Overwrites the view port crop rect to be larger than the surface. Cannot rely on the
+ // real code path to test this because ShadowMatrix#invert doesn't work.
+ val largerThanBufferRect = Rect(-1, -1, 10000, 10000)
+ imageCapture.viewPortCropRect = largerThanBufferRect
+
+ // Act
+ imageCapture.takePicture(executor!!, onImageCapturedCallback)
+ // Send fake image.
+ fakeImageReaderProxy?.triggerImageAvailable("tag", 0)
+ flushHandler(callbackHandler)
+
+ // Assert.
+ Truth.assertThat(capturedImage!!.viewPortRect).isEqualTo(largerThanBufferRect)
+ // When view port rect is larger, crop rect is full buffer size.
+ Truth.assertThat(capturedImage!!.cropRect).isEqualTo(
+ Rect(0, 0, fakeImageReaderProxy!!.width, fakeImageReaderProxy!!.height)
+ )
+ }
+
+ @Test
+ fun captureImageWithViewPort_isSet() {
+ // Arrange
+ val imageCapture = bindImageCapture(
+ ViewPort.Builder()
+ .setAspectRatio(Rational(1, 1))
+ .setScaleType(ViewPort.FILL_CENTER)
+ .setRotation(Surface.ROTATION_0).build()
+ )
+
+ // Act
+ imageCapture.takePicture(executor!!, onImageCapturedCallback)
+ // Send fake image.
+ fakeImageReaderProxy?.triggerImageAvailable("tag", 0)
+ flushHandler(callbackHandler)
+
+ // Assert.
+ // The expected value is based on fitting the 1:1 view port into a rect with the size of
+ // the ImageReader.
+ val expectedPadding = (fakeImageReaderProxy!!.width - fakeImageReaderProxy!!.height) / 2
+ Truth.assertThat(capturedImage!!.viewPortRect).isEqualTo(
+ Rect(
+ expectedPadding, 0, fakeImageReaderProxy!!.width - expectedPadding,
+ fakeImageReaderProxy!!.height
+ )
+ )
+ Truth.assertThat(capturedImage!!.cropRect).isEqualTo(
+ Rect(
+ expectedPadding, 0, fakeImageReaderProxy!!.width - expectedPadding,
+ fakeImageReaderProxy!!.height
+ )
+ )
+ }
+
+ @Test
+ fun capturedImageSize_isEqualToSurfaceSize() {
+ // Act/arrange.
+ val imageCapture = bindImageCapture()
+
+ // Act
+ imageCapture.takePicture(executor!!, onImageCapturedCallback)
+ // Send fake image.
+ fakeImageReaderProxy?.triggerImageAvailable("tag", 0)
+ flushHandler(callbackHandler)
+
+ // Assert.
+ Truth.assertThat(capturedImage!!.width).isEqualTo(fakeImageReaderProxy?.width)
+ Truth.assertThat(capturedImage!!.height).isEqualTo(fakeImageReaderProxy?.height)
+ }
+
+ private fun bindImageCapture(): ImageCapture {
+ return bindImageCapture(null)
+ }
+
+ private fun bindImageCapture(viewPort: ViewPort?): ImageCapture {
+ // Arrange.
+ val imageCapture = ImageCapture.Builder()
+ // Set non jpg format so it doesn't trigger the exif code path.
+ .setBufferFormat(ImageFormat.YUV_420_888)
+ .setTargetRotation(Surface.ROTATION_0)
+ .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
+ .setFlashMode(ImageCapture.FLASH_MODE_OFF)
+ .setCaptureOptionUnpacker { _: UseCaseConfig<*>?, _: CaptureConfig.Builder? -> }
+ .setImageReaderProxyProvider(getImageReaderProxyProvider())
+ .build()
+
+ // Act.
+ // Bind UseCase amd take picture.
+ val lifecycleOwner = FakeLifecycleOwner()
+ InstrumentationRegistry.getInstrumentation()
+ .runOnMainSync {
+ CameraX.bindToLifecycle(
+ lifecycleOwner,
+ CameraSelector.DEFAULT_BACK_CAMERA,
+ viewPort,
+ imageCapture
+ )
+ lifecycleOwner.startAndResume()
+ }
+ return imageCapture
+ }
+
+ private fun getImageReaderProxyProvider(): ImageReaderProxyProvider {
+ return ImageReaderProxyProvider { width, height, imageFormat, queueDepth, usage ->
+ fakeImageReaderProxy = FakeImageReaderProxy.newInstance(
+ width, height, imageFormat, queueDepth, usage
+ )
+ fakeImageReaderProxy!!
+ }
+ }
+
+ private fun flushHandler(handler: Handler?) {
+ (Shadow.extract<Any>(handler!!.looper) as ShadowLooper).idle()
+ }
+}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
new file mode 100644
index 0000000..5a5e072
--- /dev/null
+++ b/camera/camera-core/src/test/java/androidx/camera/core/PreviewTest.kt
@@ -0,0 +1,136 @@
+/*
+ * 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.camera.core
+
+import android.content.Context
+import android.graphics.Rect
+import android.os.Build
+import android.util.Rational
+import android.util.Size
+import android.view.Surface
+import androidx.camera.core.impl.CameraFactory
+import androidx.camera.core.impl.CameraThreadConfig
+import androidx.camera.testing.fakes.FakeAppConfig
+import androidx.camera.testing.fakes.FakeCamera
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager
+import androidx.camera.testing.fakes.FakeCameraFactory
+import androidx.camera.testing.fakes.FakeLifecycleOwner
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import java.util.concurrent.ExecutionException
+
+/**
+ * Unit tests for [Preview].
+ */
+@SmallTest
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP, shadows = [ShadowCameraX::class])
+class PreviewTest {
+
+ @Before
+ @Throws(ExecutionException::class, InterruptedException::class)
+ fun setUp() {
+ val cameraFactoryProvider =
+ CameraFactory.Provider { _: Context?, _: CameraThreadConfig? ->
+ val cameraFactory = FakeCameraFactory()
+ cameraFactory.insertDefaultBackCamera(
+ ShadowCameraX.DEFAULT_CAMERA_ID
+ ) { FakeCamera(ShadowCameraX.DEFAULT_CAMERA_ID) }
+ cameraFactory
+ }
+ val cameraXConfig = CameraXConfig.Builder.fromConfig(
+ FakeAppConfig.create()
+ ).setCameraFactoryProvider(cameraFactoryProvider).build()
+ val context = ApplicationProvider.getApplicationContext<Context>()
+ CameraX.initialize(context, cameraXConfig).get()
+ }
+
+ @After
+ @Throws(ExecutionException::class, InterruptedException::class)
+ fun tearDown() {
+ InstrumentationRegistry.getInstrumentation()
+ .runOnMainSync { CameraX.unbindAll() }
+ CameraX.shutdown().get()
+ }
+
+ @Test
+ fun viewPortCropSize() {
+ val expectedSurfaceRequest = bindToLifecycleAndGetSurfaceRequest(
+ ViewPort.Builder()
+ .setAspectRatio(Rational(1, 1))
+ .setScaleType(ViewPort.FILL_CENTER)
+ .setRotation(Surface.ROTATION_0).build()
+ )
+ // The expected value is based on fitting the 1:1 view port into a rect with the size of
+ // FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE.
+ val expectedPadding = (FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE.width -
+ FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE.height) / 2
+ Truth.assertThat(expectedSurfaceRequest.viewPortRect).isEqualTo(
+ Rect(
+ expectedPadding,
+ 0,
+ FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE.width - expectedPadding,
+ FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE.height
+ )
+ )
+ }
+
+ @Test
+ fun surfaceRequestSize_isSurfaceSize() {
+ Truth.assertThat(bindToLifecycleAndGetSurfaceRequest().resolution).isEqualTo(
+ Size(
+ FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE.width,
+ FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE.height
+ )
+ )
+ }
+
+ private fun bindToLifecycleAndGetSurfaceRequest(): SurfaceRequest {
+ return bindToLifecycleAndGetSurfaceRequest(null)
+ }
+
+ private fun bindToLifecycleAndGetSurfaceRequest(viewPort: ViewPort?): SurfaceRequest {
+ // Arrange.
+ val preview = Preview.Builder().setTargetRotation(Surface.ROTATION_0).build()
+ var surfaceRequest: SurfaceRequest? = null
+ preview.setSurfaceProvider { surfaceRequest = it }
+
+ // Act.
+ val lifecycleOwner = FakeLifecycleOwner()
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ CameraX.bindToLifecycle(
+ lifecycleOwner,
+ CameraSelector.DEFAULT_BACK_CAMERA,
+ viewPort,
+ preview
+ )
+ lifecycleOwner.startAndResume()
+ }
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ return surfaceRequest!!
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
index be14a98..ae9118a 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
@@ -17,6 +17,7 @@
package androidx.camera.testing.fakes;
import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
+import static androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager.MAX_OUTPUT_SIZE;
import android.graphics.Rect;
import android.util.Log;
@@ -146,6 +147,12 @@
}
}
+ @NonNull
+ @Override
+ public Rect getSensorRect() {
+ return new Rect(0, 0, MAX_OUTPUT_SIZE.getWidth(), MAX_OUTPUT_SIZE.getHeight());
+ }
+
private void updateSessionConfig() {
mControlUpdateCallback.onCameraControlUpdateSessionConfig(mSessionConfigBuilder.build());
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeConfig.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeConfig.java
index 978a65c..3723736 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeConfig.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeConfig.java
@@ -17,7 +17,6 @@
package androidx.camera.testing.fakes;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.camera.core.ExtendableBuilder;
@@ -25,8 +24,7 @@
import androidx.camera.core.impl.MutableConfig;
import androidx.camera.core.impl.MutableOptionsBundle;
import androidx.camera.core.impl.OptionsBundle;
-
-import java.util.Set;
+import androidx.camera.core.impl.ReadableConfig;
/**
* Wrapper for an empty Config
@@ -34,7 +32,7 @@
* @hide
*/
@RestrictTo(Scope.LIBRARY_GROUP)
-public final class FakeConfig implements Config {
+public final class FakeConfig implements ReadableConfig {
private final Config mConfig;
@@ -42,53 +40,12 @@
mConfig = config;
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config default methods
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- /** @hide */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- /** @hide */
@NonNull
- @RestrictTo(Scope.LIBRARY_GROUP)
@Override
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
+ public Config getConfig() {
+ return mConfig;
}
- // End of the default implementation of Config
- // *********************************************************************************************
-
/** Builder for an empty Config */
public static final class Builder implements ExtendableBuilder<FakeConfig> {
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java
index e57eede..7323432 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java
@@ -66,6 +66,21 @@
mImageProxyAcquisitionQueue = new LinkedBlockingQueue<>(maxImages);
}
+ /**
+ * Create a new {@link FakeImageReaderProxy} instance.
+ *
+ * @param maxImages The maximum number of images that can be acquired at once
+ */
+ @NonNull
+ public static FakeImageReaderProxy newInstance(int width, int height, int format,
+ int maxImages, long usage) {
+ FakeImageReaderProxy fakeImageReaderProxy = new FakeImageReaderProxy(maxImages);
+ fakeImageReaderProxy.mWidth = width;
+ fakeImageReaderProxy.mHeight = height;
+ fakeImageReaderProxy.setImageFormat(format);
+ return fakeImageReaderProxy;
+ }
+
@Override
public ImageProxy acquireLatestImage() {
ImageProxy imageProxy;
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java
index 3e3694c..3d2c5f7 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeUseCaseConfig.java
@@ -21,7 +21,6 @@
import android.util.Size;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.UseCase;
import androidx.camera.core.impl.CaptureConfig;
@@ -35,13 +34,10 @@
import androidx.camera.core.impl.UseCaseConfig;
import java.util.List;
-import java.util.Set;
import java.util.UUID;
/** A fake configuration for {@link FakeUseCase}. */
-public class FakeUseCaseConfig
- implements UseCaseConfig<FakeUseCase>,
- ImageOutputConfig {
+public class FakeUseCaseConfig implements UseCaseConfig<FakeUseCase>, ImageOutputConfig {
private final Config mConfig;
@@ -49,255 +45,17 @@
mConfig = config;
}
- // Start of the default implementation of Config
- // *********************************************************************************************
-
- // Implementations of Config.Reader default methods
-
- @Override
- public boolean containsOption(@NonNull Option<?> id) {
- return mConfig.containsOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id) {
- return mConfig.retrieveOption(id);
- }
-
- @Override
- @Nullable
- public <ValueT> ValueT retrieveOption(@NonNull Option<ValueT> id,
- @Nullable ValueT valueIfMissing) {
- return mConfig.retrieveOption(id, valueIfMissing);
- }
-
- @Override
- public void findOptions(@NonNull String idStem, @NonNull OptionMatcher matcher) {
- mConfig.findOptions(idStem, matcher);
- }
-
- @Override
- @NonNull
- public Set<Option<?>> listOptions() {
- return mConfig.listOptions();
- }
-
- // Implementations of TargetConfig default methods
-
- @Override
- @Nullable
- public Class<FakeUseCase> getTargetClass(
- @Nullable Class<FakeUseCase> valueIfMissing) {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<FakeUseCase> storedClass = (Class<FakeUseCase>) retrieveOption(
- OPTION_TARGET_CLASS,
- valueIfMissing);
- return storedClass;
- }
-
- @Override
- @NonNull
- public Class<FakeUseCase> getTargetClass() {
- @SuppressWarnings("unchecked") // Value should only be added via Builder#setTargetClass()
- Class<FakeUseCase> storedClass = (Class<FakeUseCase>) retrieveOption(
- OPTION_TARGET_CLASS);
- return storedClass;
- }
-
- @Override
- @Nullable
- public String getTargetName(@Nullable String valueIfMissing) {
- return retrieveOption(OPTION_TARGET_NAME, valueIfMissing);
- }
-
- @Override
- @NonNull
- public String getTargetName() {
- return retrieveOption(OPTION_TARGET_NAME);
- }
-
- // Implementations of UseCaseConfig default methods
-
- @Override
- @Nullable
- public SessionConfig getDefaultSessionConfig(@Nullable SessionConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig getDefaultSessionConfig() {
- return retrieveOption(OPTION_DEFAULT_SESSION_CONFIG);
- }
-
- @Override
- @Nullable
- public CaptureConfig getDefaultCaptureConfig(@Nullable CaptureConfig valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig getDefaultCaptureConfig() {
- return retrieveOption(OPTION_DEFAULT_CAPTURE_CONFIG);
- }
-
- @Override
- @Nullable
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker(
- @Nullable SessionConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public SessionConfig.OptionUnpacker getSessionOptionUnpacker() {
- return retrieveOption(OPTION_SESSION_CONFIG_UNPACKER);
- }
-
- @Override
- @Nullable
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker(
- @Nullable CaptureConfig.OptionUnpacker valueIfMissing) {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CaptureConfig.OptionUnpacker getCaptureOptionUnpacker() {
- return retrieveOption(OPTION_CAPTURE_CONFIG_UNPACKER);
- }
-
- @Override
- public int getSurfaceOccupancyPriority(int valueIfMissing) {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY, valueIfMissing);
- }
-
- @Override
- public int getSurfaceOccupancyPriority() {
- return retrieveOption(OPTION_SURFACE_OCCUPANCY_PRIORITY);
- }
-
- @Override
- @Nullable
- public CameraSelector getCameraSelector(@Nullable CameraSelector valueIfMissing) {
- return retrieveOption(OPTION_CAMERA_SELECTOR, valueIfMissing);
- }
-
- @Override
- @NonNull
- public CameraSelector getCameraSelector() {
- return retrieveOption(OPTION_CAMERA_SELECTOR);
- }
-
- @Override
- @Nullable
- public UseCase.EventCallback getUseCaseEventCallback(
- @Nullable UseCase.EventCallback valueIfMissing) {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK, valueIfMissing);
- }
-
- @Override
- @NonNull
- public UseCase.EventCallback getUseCaseEventCallback() {
- return retrieveOption(OPTION_USE_CASE_EVENT_CALLBACK);
- }
-
- // Implementations of ImageOutputConfig default methods
-
- @Nullable
- @Override
- public Rational getTargetAspectRatioCustom(@Nullable Rational valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM, valueIfMissing);
- }
-
@NonNull
@Override
- public Rational getTargetAspectRatioCustom() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
+ public Config getConfig() {
+ return mConfig;
}
@Override
- public boolean hasTargetAspectRatio() {
- return containsOption(OPTION_TARGET_ASPECT_RATIO);
- }
-
- @Override
- public int getTargetAspectRatio() {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO);
-
- }
-
- @Override
- public int getTargetRotation(int valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ROTATION, valueIfMissing);
- }
-
- @Override
- public int getTargetRotation() {
- return retrieveOption(OPTION_TARGET_ROTATION);
- }
-
- @Nullable
- @Override
- public Size getTargetResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_TARGET_RESOLUTION, valueIfMissing);
- }
-
- @NonNull
- @Override
- public Size getTargetResolution() {
- return retrieveOption(OPTION_TARGET_RESOLUTION);
- }
-
- @Nullable
- @Override
- public Size getDefaultResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_DEFAULT_RESOLUTION, valueIfMissing);
- }
-
- @NonNull
- @Override
- public Size getDefaultResolution() {
- return retrieveOption(OPTION_DEFAULT_RESOLUTION);
- }
-
- @Nullable
- @Override
- public Size getMaxResolution(@Nullable Size valueIfMissing) {
- return retrieveOption(OPTION_MAX_RESOLUTION, valueIfMissing);
- }
-
- @NonNull
- @Override
- public Size getMaxResolution() {
- return retrieveOption(OPTION_MAX_RESOLUTION);
- }
-
- @Nullable
- @Override
- public List<Pair<Integer, Size[]>> getSupportedResolutions(
- @Nullable List<Pair<Integer, Size[]>> valueIfMissing) {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS, valueIfMissing);
- }
-
- @NonNull
- @Override
- public List<Pair<Integer, Size[]>> getSupportedResolutions() {
- return retrieveOption(OPTION_SUPPORTED_RESOLUTIONS);
- }
-
- // Implementations of ImageInputConfig default methods
-
- @Override
public int getInputFormat() {
return ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE;
}
- // End of the default implementation of Config
- // *********************************************************************************************
-
/** Builder for an empty Config */
public static final class Builder implements
UseCaseConfig.Builder<FakeUseCase, FakeUseCaseConfig, FakeUseCaseConfig.Builder>,
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java
index 67f8abf..70e116c 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewTest.java
@@ -21,6 +21,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
@@ -30,6 +31,7 @@
import android.Manifest;
import android.content.Context;
+import android.os.Build;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.View;
@@ -106,7 +108,26 @@
@Test
@UiThreadTest
- public void usesSurfaceView_whenNonLegacyDevice_andPreferredImplModeSurfaceView() {
+ public void usesTextureView_whenAPILevelNotNewerThanN() {
+ assumeTrue(Build.VERSION.SDK_INT <= 24);
+ final CameraInfo cameraInfo = mock(CameraInfo.class);
+ when(cameraInfo.getImplementationType()).thenReturn(
+ CameraInfo.IMPLEMENTATION_TYPE_CAMERA2);
+
+ final PreviewView previewView = new PreviewView(mContext);
+ setContentView(previewView);
+ previewView.setPreferredImplementationMode(SURFACE_VIEW);
+ Preview.SurfaceProvider surfaceProvider = previewView.createSurfaceProvider();
+ mSurfaceRequest = createSurfaceRequest(cameraInfo);
+ surfaceProvider.onSurfaceRequested(mSurfaceRequest);
+
+ assertThat(previewView.mImplementation).isInstanceOf(TextureViewImplementation.class);
+ }
+
+ @Test
+ @UiThreadTest
+ public void usesSurfaceView_whenNonLegacyDevice_andAPILevelNewerThanN() {
+ assumeTrue(Build.VERSION.SDK_INT > 24);
final CameraInfo cameraInfo = mock(CameraInfo.class);
when(cameraInfo.getImplementationType()).thenReturn(
CameraInfo.IMPLEMENTATION_TYPE_CAMERA2);
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
index 96544c5..b4d0e76 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
@@ -123,7 +123,8 @@
* Specifies the preferred {@link ImplementationMode} to use for preview.
* <p>
* When the preferred {@link ImplementationMode} is {@link ImplementationMode#SURFACE_VIEW}
- * but the device doesn't support this mode (e.g. devices with a supported camera hardware level
+ * but the device doesn't support this mode (e.g. devices with API level not newer than
+ * Android 7.0 or a supported camera hardware level
* {@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY}),
* the actual implementation mode will be {@link ImplementationMode#TEXTURE_VIEW}.
*
@@ -223,9 +224,9 @@
}
@NonNull
- private ImplementationMode computeImplementationMode(@Nullable CameraInfo cameraInfo,
+ private ImplementationMode computeImplementationMode(@NonNull CameraInfo cameraInfo,
@NonNull final ImplementationMode preferredMode) {
- return cameraInfo == null || cameraInfo.getImplementationType().equals(
+ return Build.VERSION.SDK_INT <= 24 || cameraInfo.getImplementationType().equals(
CameraInfo.IMPLEMENTATION_TYPE_CAMERA2_LEGACY) ? ImplementationMode.TEXTURE_VIEW
: preferredMode;
}
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java
index 27cca3d..deb9ab6 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CaptureViewOnTouchListener.java
@@ -134,7 +134,7 @@
@Override
public void onError(@NonNull ImageCaptureException exception) {
- report("Failure: " + exception.getMessage());
+ report("Failure: " + exception.getMessage(), exception.getCause());
}
});
}
@@ -158,7 +158,7 @@
@Override
public void onError(int videoCaptureError, @NonNull String message,
@Nullable Throwable cause) {
- report("Failure: " + message);
+ report("Failure: " + message, cause);
}
});
}
@@ -225,16 +225,25 @@
}
private File createNewFile(String extension) {
+ File dirFile =
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
+ if (dirFile != null && !dirFile.exists()) {
+ dirFile.mkdirs();
+ }
// Use Locale.US to ensure we get ASCII digits
- return new File(
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
+ return new File(dirFile,
new SimpleDateFormat(FILENAME, Locale.US).format(System.currentTimeMillis())
+ extension);
}
@SuppressWarnings("WeakerAccess")
- void report(String msg) {
- Log.d(TAG, msg);
+ void report(@NonNull String msg) {
+ report(msg, null);
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ void report(@NonNull String msg, @Nullable Throwable cause) {
+ Log.d(TAG, msg, cause);
Toast.makeText(mCameraView.getContext(), msg, Toast.LENGTH_SHORT).show();
}
diff --git a/compose/compose-runtime/build.gradle b/compose/compose-runtime/build.gradle
index 0176276..cb04425 100644
--- a/compose/compose-runtime/build.gradle
+++ b/compose/compose-runtime/build.gradle
@@ -37,16 +37,10 @@
sourceSets {
commonMain.dependencies {
- implementation(KOTLIN_STDLIB)
- }
- commonTest.dependencies {
- implementation kotlin("test-junit")
- implementation project(":ui:ui-core")
- }
-
- jvmMain {
+ implementation(KOTLIN_STDLIB_COMMON)
}
jvmMain.dependencies {
+ implementation(KOTLIN_STDLIB)
api(KOTLIN_COROUTINES_CORE)
implementation "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:0.3"
}
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt
index fde1b1e..983800a9 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/ComposeBenchmark.kt
@@ -157,7 +157,11 @@
private val redBackground = background(Color.Red)
private val blackBackground = background(Color.Black)
private val yellowBackground = background(Color.Yellow)
-private val defaultBackground = yellowBackground
+
+private val redModifier = Modifier.fillMaxSize() + redBackground
+private val blackModifier = Modifier.fillMaxSize() + blackBackground
+private val yellowModifier = Modifier.fillMaxSize() + yellowBackground
+private val defaultModifier = yellowModifier
@Model
class ColorModel(private var color: Color = Color.Black) {
@@ -165,31 +169,31 @@
color = if (color == Color.Black) Color.Red else Color.Black
}
- val background
+ val modifier
get() = when (color) {
- Color.Red -> redBackground
- Color.Black -> blackBackground
- Color.Yellow -> yellowBackground
- else -> Modifier.drawBackground(color)
+ Color.Red -> redModifier
+ Color.Black -> blackModifier
+ Color.Yellow -> yellowModifier
+ else -> Modifier.fillMaxSize().drawBackground(color)
}
}
@Composable
fun OneRect(model: ColorModel) {
- Box(modifier = Modifier.fillMaxSize() + model.background)
+ Box(modifier = model.modifier)
}
@Composable
fun TenRects(model: ColorModel, narrow: Boolean = false) {
if (narrow) {
Observe {
- Box(modifier = Modifier.fillMaxSize() + model.background)
+ Box(modifier = model.modifier)
}
} else {
- Box(modifier = Modifier.fillMaxSize() + model.background)
+ Box(modifier = model.modifier)
}
repeat(9) {
- Box(modifier = Modifier.fillMaxSize() + defaultBackground)
+ Box(modifier = defaultModifier)
}
}
@@ -199,12 +203,12 @@
if (it % 10 == 0)
if (narrow) {
Observe {
- Box(modifier = Modifier.fillMaxSize() + model.background)
+ Box(modifier = model.modifier)
}
} else {
- Box(modifier = Modifier.fillMaxSize() + model.background)
+ Box(modifier = model.modifier)
}
else
- Box(modifier = Modifier.fillMaxSize() + defaultBackground)
+ Box(modifier = defaultModifier)
}
}
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/realworld4/RealWorld4_Widgets.kt b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/realworld4/RealWorld4_Widgets.kt
index 45422b0..21bf639 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/realworld4/RealWorld4_Widgets.kt
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/benchmark/realworld4/RealWorld4_Widgets.kt
@@ -31,7 +31,7 @@
import androidx.ui.layout.Column
import androidx.ui.layout.padding
import androidx.ui.foundation.Box
-import androidx.ui.foundation.DrawBackground
+import androidx.ui.foundation.drawBackground
import androidx.ui.layout.Row
import androidx.ui.layout.fillMaxSize
import androidx.ui.layout.fillMaxWidth
@@ -54,7 +54,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_001(
@@ -124,7 +124,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_002(
@@ -172,7 +172,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_003(
@@ -269,7 +269,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_004(
@@ -372,7 +372,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_005(
@@ -460,7 +460,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_133(
@@ -571,7 +571,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_070(
@@ -637,7 +637,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_071(
@@ -716,7 +716,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_012(
@@ -763,7 +763,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_123(
@@ -818,7 +818,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -856,7 +856,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -893,7 +893,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_091(
@@ -956,7 +956,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -995,7 +995,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1040,7 +1040,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_119(
@@ -1099,7 +1099,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_057(
@@ -1169,7 +1169,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1223,7 +1223,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_147(
@@ -1280,7 +1280,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1331,7 +1331,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1364,7 +1364,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1416,7 +1416,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_015(
@@ -1499,7 +1499,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_094(
@@ -1552,7 +1552,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_048(
@@ -1599,7 +1599,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_138(
@@ -1660,7 +1660,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1699,7 +1699,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1749,7 +1749,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1792,7 +1792,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_016(
@@ -1839,7 +1839,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_121(
@@ -1887,7 +1887,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1928,7 +1928,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -1967,7 +1967,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_063(
@@ -2022,7 +2022,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -2067,7 +2067,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -2106,7 +2106,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -2158,7 +2158,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_076(
@@ -2258,7 +2258,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_054(
@@ -2309,7 +2309,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_041(
@@ -2368,7 +2368,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_053(
@@ -2415,7 +2415,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_089(
@@ -2487,7 +2487,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -2545,7 +2545,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_097(
@@ -2611,7 +2611,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_124(
@@ -2697,7 +2697,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_105(
@@ -2744,7 +2744,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_103(
@@ -2785,7 +2785,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -2824,7 +2824,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -2863,7 +2863,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_107(
@@ -2924,7 +2924,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -2963,7 +2963,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3002,7 +3002,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3040,7 +3040,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3070,7 +3070,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_056(
@@ -3145,7 +3145,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_021(
@@ -3200,7 +3200,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_128(
@@ -3261,7 +3261,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3294,7 +3294,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_067(
@@ -3351,7 +3351,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3389,7 +3389,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3425,7 +3425,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3462,7 +3462,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_019(
@@ -3523,7 +3523,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3562,7 +3562,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3606,7 +3606,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3649,7 +3649,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3700,7 +3700,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -3750,7 +3750,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_140(
@@ -3815,7 +3815,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_092(
@@ -3879,7 +3879,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_029(
@@ -3950,7 +3950,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_073(
@@ -4019,7 +4019,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_118(
@@ -4066,7 +4066,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_074(
@@ -4112,7 +4112,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -4151,7 +4151,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_022(
@@ -4202,7 +4202,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_077(
@@ -4309,7 +4309,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_058(
@@ -4361,7 +4361,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_126(
@@ -4418,7 +4418,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -4458,7 +4458,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_112(
@@ -4538,7 +4538,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_083(
@@ -4609,7 +4609,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_084(
@@ -4664,7 +4664,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_042(
@@ -4707,7 +4707,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -4740,7 +4740,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_088(
@@ -4798,7 +4798,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_111(
@@ -4854,7 +4854,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -4891,7 +4891,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_011(
@@ -4938,7 +4938,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -4982,7 +4982,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5019,7 +5019,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5059,7 +5059,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_044(
@@ -5117,7 +5117,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_096(
@@ -5190,7 +5190,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_014(
@@ -5243,7 +5243,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5288,7 +5288,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_109(
@@ -5349,7 +5349,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_062(
@@ -5415,7 +5415,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_036(
@@ -5468,7 +5468,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5513,7 +5513,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_049(
@@ -5578,7 +5578,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_047(
@@ -5641,7 +5641,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5679,7 +5679,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5722,7 +5722,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5761,7 +5761,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_026(
@@ -5817,7 +5817,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5862,7 +5862,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5901,7 +5901,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5934,7 +5934,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -5985,7 +5985,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6028,7 +6028,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6061,7 +6061,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_116(
@@ -6120,7 +6120,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_114(
@@ -6191,7 +6191,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6242,7 +6242,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6281,7 +6281,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_117(
@@ -6328,7 +6328,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6367,7 +6367,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6406,7 +6406,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_130(
@@ -6449,7 +6449,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6494,7 +6494,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6549,7 +6549,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6594,7 +6594,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6639,7 +6639,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_125(
@@ -6686,7 +6686,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6725,7 +6725,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6758,7 +6758,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6803,7 +6803,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6842,7 +6842,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6875,7 +6875,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -6922,7 +6922,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_132(
@@ -6998,7 +6998,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_006(
@@ -7133,7 +7133,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_134(
@@ -7191,7 +7191,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_097(
@@ -7254,7 +7254,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_136(
@@ -7301,7 +7301,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_051(
@@ -7368,7 +7368,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -7401,7 +7401,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -7435,7 +7435,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_141(
@@ -7496,7 +7496,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_076(
@@ -7573,7 +7573,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_092(
@@ -7636,7 +7636,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_071(
@@ -7728,7 +7728,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_144(
@@ -7825,7 +7825,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_018(
@@ -7890,7 +7890,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_057(
@@ -7973,7 +7973,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_034(
@@ -8056,7 +8056,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp5 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2 + tmp3 + tmp4
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp5.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp5.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
Box(Modifier.fillMaxWidth().weight(1f), backgroundColor = model.toColor())
@@ -8094,7 +8094,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_041(
@@ -8161,7 +8161,7 @@
}.map { it.toString().reversed() }.joinToString("-"))
val tmp3 = "lkjzndgke84ts" + tmp0 + tmp1 + tmp2
WithConstraints(modifier) {
- Box(Modifier.padding(1.dp) + DrawBackground(color = tmp3.toColor())) {
+ Box(Modifier.padding(1.dp).drawBackground(color = tmp3.toColor())) {
if (constraints.maxHeight > constraints.maxWidth) {
Column {
RealWorld4_FancyWidget_087(
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
index 0b9634b..9a4ed0d 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
@@ -2197,8 +2197,24 @@
}
// Invalidation helpers
-private fun MutableList<Invalidation>.findLocation(location: Int): Int =
- binarySearch { it.location.compareTo(location) }
+private fun MutableList<Invalidation>.findLocation(location: Int): Int {
+ var low = 0
+ var high = size - 1
+
+ while (low <= high) {
+ val mid = (low + high).ushr(1) // safe from overflows
+ val midVal = get(mid)
+ val cmp = midVal.location.compareTo(location)
+
+ if (cmp < 0)
+ low = mid + 1
+ else if (cmp > 0)
+ high = mid - 1
+ else
+ return mid // key found
+ }
+ return -(low + 1) // key not found
+}
private fun MutableList<Invalidation>.insertIfMissing(location: Int, scope: RecomposeScope) {
val index = findLocation(location)
diff --git a/core/core-animation/api/api_lint.ignore b/core/core-animation/api/api_lint.ignore
index 3b4ea75..70743c5 100644
--- a/core/core-animation/api/api_lint.ignore
+++ b/core/core-animation/api/api_lint.ignore
@@ -1,3 +1,9 @@
// Baseline format: 1.0
+BuilderSetStyle: androidx.core.animation.AnimatorSet.Builder#after(androidx.core.animation.Animator):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.animation.AnimatorSet.Builder.after(androidx.core.animation.Animator)
+BuilderSetStyle: androidx.core.animation.AnimatorSet.Builder#after(long):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.animation.AnimatorSet.Builder.after(long)
+BuilderSetStyle: androidx.core.animation.AnimatorSet.Builder#before(androidx.core.animation.Animator):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.animation.AnimatorSet.Builder.before(androidx.core.animation.Animator)
BuilderSetStyle: androidx.core.animation.AnimatorSet.Builder#with(androidx.core.animation.Animator):
- Builder methods names should use setFoo() style: method androidx.core.animation.AnimatorSet.Builder.with(androidx.core.animation.Animator)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.animation.AnimatorSet.Builder.with(androidx.core.animation.Animator)
diff --git a/core/core/api/1.4.0-alpha01.txt b/core/core/api/1.4.0-alpha01.txt
index 31d0479..b8644ee 100644
--- a/core/core/api/1.4.0-alpha01.txt
+++ b/core/core/api/1.4.0-alpha01.txt
@@ -3069,6 +3069,15 @@
method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
}
+ public abstract class RichContentReceiverCompat<T extends android.view.View> {
+ ctor public RichContentReceiverCompat();
+ method public abstract java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public abstract boolean onReceive(T, android.content.ClipData, int, int);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_CLIPBOARD = 0; // 0x0
+ field public static final int SOURCE_INPUT_METHOD = 1; // 0x1
+ }
+
@Deprecated public final class ScrollerCompat {
method @Deprecated public void abortAnimation();
method @Deprecated public boolean computeScrollOffset();
@@ -3123,6 +3132,12 @@
field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
}
+ public abstract class TextViewRichContentReceiverCompat extends androidx.core.widget.RichContentReceiverCompat<android.widget.TextView> {
+ ctor public TextViewRichContentReceiverCompat();
+ method public java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public boolean onReceive(android.widget.TextView, android.content.ClipData, int, int);
+ }
+
public interface TintableCompoundButton {
method public android.content.res.ColorStateList? getSupportButtonTintList();
method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
diff --git a/core/core/api/api_lint.ignore b/core/core/api/api_lint.ignore
index 116fb6e..c20f29a 100644
--- a/core/core/api/api_lint.ignore
+++ b/core/core/api/api_lint.ignore
@@ -205,6 +205,30 @@
Methods must not mention RuntimeException subclasses in throws clauses (was `java.lang.IllegalArgumentException`)
+BuilderSetStyle: androidx.core.app.NotificationCompat.Action.Builder#extend(androidx.core.app.NotificationCompat.Action.Extender):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.NotificationCompat.Action.Builder.extend(androidx.core.app.NotificationCompat.Action.Extender)
+BuilderSetStyle: androidx.core.app.NotificationCompat.Builder#extend(androidx.core.app.NotificationCompat.Extender):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.NotificationCompat.Builder.extend(androidx.core.app.NotificationCompat.Extender)
+BuilderSetStyle: androidx.core.app.NotificationCompat.Builder#limitCharSequenceLength(CharSequence):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.NotificationCompat.Builder.limitCharSequenceLength(CharSequence)
+BuilderSetStyle: androidx.core.app.ShareCompat.IntentBuilder#createChooserIntent():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.ShareCompat.IntentBuilder.createChooserIntent()
+BuilderSetStyle: androidx.core.app.ShareCompat.IntentBuilder#from(android.app.Activity):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.ShareCompat.IntentBuilder.from(android.app.Activity)
+BuilderSetStyle: androidx.core.app.ShareCompat.IntentBuilder#startChooser():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.ShareCompat.IntentBuilder.startChooser()
+BuilderSetStyle: androidx.core.app.TaskStackBuilder#create(android.content.Context):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.TaskStackBuilder.create(android.content.Context)
+BuilderSetStyle: androidx.core.app.TaskStackBuilder#editIntentAt(int):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.TaskStackBuilder.editIntentAt(int)
+BuilderSetStyle: androidx.core.app.TaskStackBuilder#startActivities():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.TaskStackBuilder.startActivities()
+BuilderSetStyle: androidx.core.app.TaskStackBuilder#startActivities(android.os.Bundle):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.app.TaskStackBuilder.startActivities(android.os.Bundle)
+BuilderSetStyle: androidx.core.text.BidiFormatter.Builder#stereoReset(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.core.text.BidiFormatter.Builder.stereoReset(boolean)
+
+
ContextFirst: androidx.core.view.LayoutInflaterFactory#onCreateView(android.view.View, String, android.content.Context, android.util.AttributeSet) parameter #2:
Context is distinct, so it must be the first argument (method `onCreateView`)
ContextFirst: androidx.core.view.ViewConfigurationCompat#getScaledHorizontalScrollFactor(android.view.ViewConfiguration, android.content.Context) parameter #1:
@@ -2091,6 +2115,14 @@
Provide an explicit copy constructor instead of implementing `clone()`
+OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #0:
+ Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter icon in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
+OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #1:
+ Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter title in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
+OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #2:
+ Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter intent in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
+
+
PairedRegistration: androidx.core.view.OneShotPreDrawListener#removeListener():
Found removeListener but not addListener in androidx.core.view.OneShotPreDrawListener
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 31d0479..b8644ee 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -3069,6 +3069,15 @@
method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
}
+ public abstract class RichContentReceiverCompat<T extends android.view.View> {
+ ctor public RichContentReceiverCompat();
+ method public abstract java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public abstract boolean onReceive(T, android.content.ClipData, int, int);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_CLIPBOARD = 0; // 0x0
+ field public static final int SOURCE_INPUT_METHOD = 1; // 0x1
+ }
+
@Deprecated public final class ScrollerCompat {
method @Deprecated public void abortAnimation();
method @Deprecated public boolean computeScrollOffset();
@@ -3123,6 +3132,12 @@
field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
}
+ public abstract class TextViewRichContentReceiverCompat extends androidx.core.widget.RichContentReceiverCompat<android.widget.TextView> {
+ ctor public TextViewRichContentReceiverCompat();
+ method public java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public boolean onReceive(android.widget.TextView, android.content.ClipData, int, int);
+ }
+
public interface TintableCompoundButton {
method public android.content.res.ColorStateList? getSupportButtonTintList();
method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
diff --git a/core/core/api/public_plus_experimental_1.4.0-alpha01.txt b/core/core/api/public_plus_experimental_1.4.0-alpha01.txt
index b387d11..092bfc2 100644
--- a/core/core/api/public_plus_experimental_1.4.0-alpha01.txt
+++ b/core/core/api/public_plus_experimental_1.4.0-alpha01.txt
@@ -3067,6 +3067,15 @@
method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
}
+ public abstract class RichContentReceiverCompat<T extends android.view.View> {
+ ctor public RichContentReceiverCompat();
+ method public abstract java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public abstract boolean onReceive(T, android.content.ClipData, int, int);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_CLIPBOARD = 0; // 0x0
+ field public static final int SOURCE_INPUT_METHOD = 1; // 0x1
+ }
+
@Deprecated public final class ScrollerCompat {
method @Deprecated public void abortAnimation();
method @Deprecated public boolean computeScrollOffset();
@@ -3121,6 +3130,12 @@
field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
}
+ public abstract class TextViewRichContentReceiverCompat extends androidx.core.widget.RichContentReceiverCompat<android.widget.TextView> {
+ ctor public TextViewRichContentReceiverCompat();
+ method public java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public boolean onReceive(android.widget.TextView, android.content.ClipData, int, int);
+ }
+
public interface TintableCompoundButton {
method public android.content.res.ColorStateList? getSupportButtonTintList();
method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index b387d11..092bfc2 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -3067,6 +3067,15 @@
method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
}
+ public abstract class RichContentReceiverCompat<T extends android.view.View> {
+ ctor public RichContentReceiverCompat();
+ method public abstract java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public abstract boolean onReceive(T, android.content.ClipData, int, int);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_CLIPBOARD = 0; // 0x0
+ field public static final int SOURCE_INPUT_METHOD = 1; // 0x1
+ }
+
@Deprecated public final class ScrollerCompat {
method @Deprecated public void abortAnimation();
method @Deprecated public boolean computeScrollOffset();
@@ -3121,6 +3130,12 @@
field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
}
+ public abstract class TextViewRichContentReceiverCompat extends androidx.core.widget.RichContentReceiverCompat<android.widget.TextView> {
+ ctor public TextViewRichContentReceiverCompat();
+ method public java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public boolean onReceive(android.widget.TextView, android.content.ClipData, int, int);
+ }
+
public interface TintableCompoundButton {
method public android.content.res.ColorStateList? getSupportButtonTintList();
method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
diff --git a/core/core/api/restricted_1.4.0-alpha01.txt b/core/core/api/restricted_1.4.0-alpha01.txt
index 88d2713..7b3106b 100644
--- a/core/core/api/restricted_1.4.0-alpha01.txt
+++ b/core/core/api/restricted_1.4.0-alpha01.txt
@@ -3491,6 +3491,17 @@
method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
}
+ public abstract class RichContentReceiverCompat<T extends android.view.View> {
+ ctor public RichContentReceiverCompat();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final androidx.core.view.inputmethod.InputConnectionCompat.OnCommitContentListener buildOnCommitContentListener(T);
+ method public abstract java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public abstract boolean onReceive(T, android.content.ClipData, int, int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final void populateEditorInfoContentMimeTypes(android.view.inputmethod.InputConnection?, android.view.inputmethod.EditorInfo?);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_CLIPBOARD = 0; // 0x0
+ field public static final int SOURCE_INPUT_METHOD = 1; // 0x1
+ }
+
@Deprecated public final class ScrollerCompat {
method @Deprecated public void abortAnimation();
method @Deprecated public boolean computeScrollOffset();
@@ -3549,6 +3560,12 @@
@IntDef({androidx.core.widget.TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE, androidx.core.widget.TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface TextViewCompat.AutoSizeTextType {
}
+ public abstract class TextViewRichContentReceiverCompat extends androidx.core.widget.RichContentReceiverCompat<android.widget.TextView> {
+ ctor public TextViewRichContentReceiverCompat();
+ method public java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public boolean onReceive(android.widget.TextView, android.content.ClipData, int, int);
+ }
+
public interface TintableCompoundButton {
method public android.content.res.ColorStateList? getSupportButtonTintList();
method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 88d2713..7b3106b 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -3491,6 +3491,17 @@
method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
}
+ public abstract class RichContentReceiverCompat<T extends android.view.View> {
+ ctor public RichContentReceiverCompat();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final androidx.core.view.inputmethod.InputConnectionCompat.OnCommitContentListener buildOnCommitContentListener(T);
+ method public abstract java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public abstract boolean onReceive(T, android.content.ClipData, int, int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final void populateEditorInfoContentMimeTypes(android.view.inputmethod.InputConnection?, android.view.inputmethod.EditorInfo?);
+ field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
+ field public static final int SOURCE_CLIPBOARD = 0; // 0x0
+ field public static final int SOURCE_INPUT_METHOD = 1; // 0x1
+ }
+
@Deprecated public final class ScrollerCompat {
method @Deprecated public void abortAnimation();
method @Deprecated public boolean computeScrollOffset();
@@ -3549,6 +3560,12 @@
@IntDef({androidx.core.widget.TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE, androidx.core.widget.TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface TextViewCompat.AutoSizeTextType {
}
+ public abstract class TextViewRichContentReceiverCompat extends androidx.core.widget.RichContentReceiverCompat<android.widget.TextView> {
+ ctor public TextViewRichContentReceiverCompat();
+ method public java.util.Set<java.lang.String!> getSupportedMimeTypes();
+ method public boolean onReceive(android.widget.TextView, android.content.ClipData, int, int);
+ }
+
public interface TintableCompoundButton {
method public android.content.res.ColorStateList? getSupportButtonTintList();
method public android.graphics.PorterDuff.Mode? getSupportButtonTintMode();
diff --git a/core/core/src/androidTest/AndroidManifest.xml b/core/core/src/androidTest/AndroidManifest.xml
index b71482b..eebdc4d 100644
--- a/core/core/src/androidTest/AndroidManifest.xml
+++ b/core/core/src/androidTest/AndroidManifest.xml
@@ -34,6 +34,8 @@
<activity android:name="androidx.core.widget.TextViewTestActivity"/>
+ <activity android:name="androidx.core.widget.RichContentReceiverTestActivity"/>
+
<activity android:name="androidx.core.widget.TestContentViewActivity"/>
<activity android:name="androidx.core.view.VpaActivity"/>
diff --git a/core/core/src/androidTest/java/androidx/core/app/ActivityCompatTest.java b/core/core/src/androidTest/java/androidx/core/app/ActivityCompatTest.java
index 61e47ef..46f071a 100644
--- a/core/core/src/androidTest/java/androidx/core/app/ActivityCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/app/ActivityCompatTest.java
@@ -16,6 +16,8 @@
package androidx.core.app;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertSame;
import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.ArgumentMatchers.eq;
@@ -37,6 +39,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@LargeTest
public class ActivityCompatTest extends BaseInstrumentationTestCase<TestActivity> {
@@ -71,6 +75,32 @@
}
@Test
+ public void testPermissionNull() {
+ Activity activity = mActivityTestRule.getActivity();
+ String[] permissions = new String[]{null};
+
+ try {
+ ActivityCompat.requestPermissions(activity, permissions, 42);
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessageThat().contains("Permission request for permissions "
+ + Arrays.toString(permissions) + " must not contain null or empty values");
+ }
+ }
+
+ @Test
+ public void testPermissionEmpty() {
+ Activity activity = mActivityTestRule.getActivity();
+ String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION, ""};
+
+ try {
+ ActivityCompat.requestPermissions(activity, permissions, 42);
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessageThat().contains("Permission request for permissions "
+ + Arrays.toString(permissions) + " must not contain null or empty values");
+ }
+ }
+
+ @Test
public void testRequireViewByIdFound() {
View view = getActivity().findViewById(R.id.view);
assertSame(view, ActivityCompat.requireViewById(getActivity(), R.id.view));
diff --git a/core/core/src/androidTest/java/androidx/core/widget/RichContentReceiverCompatTest.java b/core/core/src/androidTest/java/androidx/core/widget/RichContentReceiverCompatTest.java
new file mode 100644
index 0000000..6310271
--- /dev/null
+++ b/core/core/src/androidTest/java/androidx/core/widget/RichContentReceiverCompatTest.java
@@ -0,0 +1,308 @@
+/*
+ * 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.core.widget;
+
+import static androidx.core.widget.RichContentReceiverCompat.FLAG_CONVERT_TO_PLAIN_TEXT;
+import static androidx.core.widget.RichContentReceiverCompat.SOURCE_CLIPBOARD;
+import static androidx.core.widget.RichContentReceiverCompat.SOURCE_INPUT_METHOD;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.util.Collections.singleton;
+
+import android.content.ClipData;
+import android.net.Uri;
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.UnderlineSpan;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.core.test.R;
+import androidx.core.view.inputmethod.EditorInfoCompat;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class RichContentReceiverCompatTest {
+
+ @Rule
+ public final ActivityTestRule<RichContentReceiverTestActivity> mActivityTestRule =
+ new ActivityTestRule<>(RichContentReceiverTestActivity.class);
+
+ private EditText mEditText;
+ private RichContentReceiverCompat<TextView> mReceiver;
+
+ @Before
+ public void before() {
+ RichContentReceiverTestActivity activity = mActivityTestRule.getActivity();
+ mEditText = activity.findViewById(R.id.edit_text_for_rich_content_receiver);
+ mReceiver = new TextViewRichContentReceiverCompat() {};
+ }
+
+ @UiThreadTest
+ @Test
+ public void testGetSupportedMimeTypes() throws Exception {
+ assertThat(mReceiver.getSupportedMimeTypes()).isEqualTo(singleton("text/*"));
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_text() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = ClipData.newPlainText("test", "y");
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, 0);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xyz", 2);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_styledText() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ UnderlineSpan underlineSpan = new UnderlineSpan();
+ SpannableStringBuilder ssb = new SpannableStringBuilder("hi world");
+ ssb.setSpan(underlineSpan, 3, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ClipData clip = ClipData.newPlainText("test", ssb);
+
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, 0);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xhi worldz", 9);
+ int spanStart = mEditText.getText().getSpanStart(underlineSpan);
+ assertThat(spanStart).isEqualTo(4);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_text_convertToPlainText() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = ClipData.newPlainText("test", "y");
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, FLAG_CONVERT_TO_PLAIN_TEXT);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xyz", 2);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_styledText_convertToPlainText() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ UnderlineSpan underlineSpan = new UnderlineSpan();
+ SpannableStringBuilder ssb = new SpannableStringBuilder("hi world");
+ ssb.setSpan(underlineSpan, 3, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ClipData clip = ClipData.newPlainText("test", ssb);
+
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, FLAG_CONVERT_TO_PLAIN_TEXT);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xhi worldz", 9);
+ int spanStart = mEditText.getText().getSpanStart(underlineSpan);
+ assertThat(spanStart).isEqualTo(-1);
+ }
+
+ @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
+ @UiThreadTest
+ @Test
+ public void testOnReceive_html() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = ClipData.newHtmlText("test", "*y*", "<b>y</b>");
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, 0);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xyz", 2);
+ }
+
+ @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
+ @UiThreadTest
+ @Test
+ public void testOnReceive_html_convertToPlainText() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = ClipData.newHtmlText("test", "*y*", "<b>y</b>");
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, FLAG_CONVERT_TO_PLAIN_TEXT);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("x*y*z", 4);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_multipleItemsInClipData() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = ClipData.newPlainText("test", "ONE");
+ clip.addItem(new ClipData.Item("TWO"));
+ clip.addItem(new ClipData.Item("THREE"));
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, 0);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xONE\nTWO\nTHREEz", 14);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_noSelectionPriorToPaste() throws Exception {
+ // Set the text and then clear the selection (ie, ensure that nothing is selected and
+ // that the cursor is not present).
+ setTextAndCursor("xz", 0);
+ Selection.removeSelection(mEditText.getText());
+ assertTextAndCursorPosition("xz", -1);
+
+ // Pasting should still work (should just insert the text at the beginning).
+ ClipData clip = ClipData.newPlainText("test", "y");
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, 0);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("yxz", 1);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_selectionStartAndEndSwapped() throws Exception {
+ // Set the text and then set the selection such that "end" is before "start".
+ setTextAndCursor("hey", 0);
+ Selection.setSelection(mEditText.getText(), 3, 1);
+ assertTextAndSelection("hey", 3, 1);
+
+ // Pasting should still work (should still successfully overwrite the selection).
+ ClipData clip = ClipData.newPlainText("test", "i");
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, 0);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("hi", 2);
+ }
+
+ @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
+ @UiThreadTest
+ @Test
+ public void testOnReceive_unsupportedMimeType_viaMenu() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = new ClipData("test", new String[]{"video/mp4"},
+ new ClipData.Item("text", "html", null, Uri.parse("content://com.example/path")));
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, 0);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xhtmlz", 5);
+ }
+
+ @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
+ @UiThreadTest
+ @Test
+ public void testOnReceive_unsupportedMimeType_viaMenu_convertToPlainText() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = new ClipData("test", new String[]{"video/mp4"},
+ new ClipData.Item("text", "html", null, Uri.parse("content://com.example/path")));
+ boolean result = onReceive(mReceiver, clip, SOURCE_CLIPBOARD, FLAG_CONVERT_TO_PLAIN_TEXT);
+
+ assertThat(result).isTrue();
+ assertTextAndCursorPosition("xtextz", 5);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnReceive_unsupportedMimeType_viaInputMethod() throws Exception {
+ setTextAndCursor("xz", 1);
+
+ ClipData clip = new ClipData("test", new String[]{"video/mp4"},
+ new ClipData.Item("text", null, Uri.parse("content://com.example/path")));
+ boolean result = onReceive(mReceiver, clip, SOURCE_INPUT_METHOD, 0);
+
+ assertThat(result).isFalse();
+ assertTextAndCursorPosition("xz", 1);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPopulateEditorInfoContentMimeTypes() throws Exception {
+ InputConnection ic = new BaseInputConnection(mEditText, true);
+ EditorInfo outAttrs = new EditorInfo();
+
+ // The field contentMimeTypes in outAttrs should be set to the MIME types of the receiver.
+ mReceiver.populateEditorInfoContentMimeTypes(ic, outAttrs);
+ assertThat(EditorInfoCompat.getContentMimeTypes(outAttrs)).isEqualTo(
+ new String[] {"text/*"});
+
+ // If the field contentMimeTypes in outAttrs already has a value assigned, it should be
+ // overwritten with the MIME types of the receiver.
+ EditorInfoCompat.setContentMimeTypes(outAttrs, new String[] {"video/mp4"});
+ mReceiver.populateEditorInfoContentMimeTypes(ic, outAttrs);
+ assertThat(EditorInfoCompat.getContentMimeTypes(outAttrs)).isEqualTo(
+ new String[] {"text/*"});
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPopulateEditorInfoContentMimeTypes_nulls() throws Exception {
+ InputConnection ic = new BaseInputConnection(mEditText, true);
+ EditorInfo outAttrs = new EditorInfo();
+
+ // If the ic arg is null, outAttrs should not be populated.
+ mReceiver.populateEditorInfoContentMimeTypes(null, outAttrs);
+ assertThat(EditorInfoCompat.getContentMimeTypes(outAttrs)).isEqualTo(new String[0]);
+
+ // If the outAttrs arg is null, it should not be populated.
+ mReceiver.populateEditorInfoContentMimeTypes(ic, null);
+ assertThat(EditorInfoCompat.getContentMimeTypes(outAttrs)).isEqualTo(new String[0]);
+ }
+
+ private boolean onReceive(final RichContentReceiverCompat<TextView> receiver,
+ final ClipData clip, @RichContentReceiverCompat.Source final int source,
+ final int flags) {
+ return receiver.onReceive(mEditText, clip, source, flags);
+ }
+
+ private void setTextAndCursor(final String text, final int cursorPosition) {
+ mEditText.requestFocus();
+ SpannableStringBuilder ssb = new SpannableStringBuilder(text);
+ mEditText.setText(ssb);
+ mEditText.setSelection(cursorPosition);
+ assertThat(mEditText.hasFocus()).isTrue();
+ assertTextAndCursorPosition(text, cursorPosition);
+ }
+
+ private void assertTextAndCursorPosition(String expectedText, int cursorPosition) {
+ assertTextAndSelection(expectedText, cursorPosition, cursorPosition);
+ }
+
+ private void assertTextAndSelection(String expectedText, int start, int end) {
+ assertThat(mEditText.getText().toString()).isEqualTo(expectedText);
+ assertThat(mEditText.getSelectionStart()).isEqualTo(start);
+ assertThat(mEditText.getSelectionEnd()).isEqualTo(end);
+ }
+}
diff --git a/core/core/src/androidTest/java/androidx/core/widget/RichContentReceiverTestActivity.java b/core/core/src/androidTest/java/androidx/core/widget/RichContentReceiverTestActivity.java
new file mode 100644
index 0000000..83a6ba0
--- /dev/null
+++ b/core/core/src/androidTest/java/androidx/core/widget/RichContentReceiverTestActivity.java
@@ -0,0 +1,28 @@
+/*
+ * 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.core.widget;
+
+import android.support.v4.BaseTestActivity;
+
+import androidx.core.test.R;
+
+public class RichContentReceiverTestActivity extends BaseTestActivity {
+ @Override
+ protected int getContentViewLayoutResId() {
+ return R.layout.rich_content_receiver_activity;
+ }
+}
diff --git a/core/core/src/androidTest/res/layout/rich_content_receiver_activity.xml b/core/core/src/androidTest/res/layout/rich_content_receiver_activity.xml
new file mode 100644
index 0000000..81b6479
--- /dev/null
+++ b/core/core/src/androidTest/res/layout/rich_content_receiver_activity.xml
@@ -0,0 +1,27 @@
+<?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.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <EditText
+ android:id="@+id/edit_text_for_rich_content_receiver"
+ android:layout_width="200dip"
+ android:layout_height="60dip" />
+</FrameLayout>
diff --git a/core/core/src/main/java/androidx/core/app/ActivityCompat.java b/core/core/src/main/java/androidx/core/app/ActivityCompat.java
index 523f70d..ae5d7ee 100644
--- a/core/core/src/main/java/androidx/core/app/ActivityCompat.java
+++ b/core/core/src/main/java/androidx/core/app/ActivityCompat.java
@@ -29,6 +29,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.view.DragEvent;
import android.view.View;
@@ -41,6 +42,7 @@
import androidx.core.content.ContextCompat;
import androidx.core.view.DragAndDropPermissionsCompat;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -494,6 +496,13 @@
return;
}
+ for (String permission : permissions) {
+ if (TextUtils.isEmpty(permission)) {
+ throw new IllegalArgumentException("Permission request for permissions "
+ + Arrays.toString(permissions) + " must not contain null or empty values");
+ }
+ }
+
if (Build.VERSION.SDK_INT >= 23) {
if (activity instanceof RequestPermissionsRequestCodeValidator) {
((RequestPermissionsRequestCodeValidator) activity)
diff --git a/core/core/src/main/java/androidx/core/widget/RichContentReceiverCompat.java b/core/core/src/main/java/androidx/core/widget/RichContentReceiverCompat.java
new file mode 100644
index 0000000..2a66954
--- /dev/null
+++ b/core/core/src/main/java/androidx/core/widget/RichContentReceiverCompat.java
@@ -0,0 +1,223 @@
+/*
+ * 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.core.widget;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.core.view.inputmethod.EditorInfoCompat;
+import androidx.core.view.inputmethod.InputConnectionCompat;
+import androidx.core.view.inputmethod.InputContentInfoCompat;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Set;
+
+/**
+ * Callback for apps to implement handling for insertion of rich content. "Rich content" here refers
+ * to both text and non-text content: plain text, styled text, HTML, images, videos, audio files,
+ * etc.
+ *
+ * <p>This callback can be attached to different types of UI components. For editable
+ * {@link android.widget.TextView} components, implementations should typically extend from
+ * {@link TextViewRichContentReceiverCompat}.
+ *
+ * <p>Example implementation:<br>
+ * <pre class="prettyprint">
+ * public class MyRichContentReceiver extends TextViewRichContentReceiverCompat {
+ *
+ * private static final Set<String> SUPPORTED_MIME_TYPES = Collections.unmodifiableSet(
+ * Set.of("text/*", "image/gif", "image/png", "image/jpg"));
+ *
+ * @NonNull
+ * @Override
+ * public Set<String> getSupportedMimeTypes() {
+ * return SUPPORTED_MIME_TYPES;
+ * }
+ *
+ * @Override
+ * public boolean onReceive(@NonNull TextView textView, @NonNull ClipData clip,
+ * int source, int flags) {
+ * if (clip.getDescription().hasMimeType("image/*")) {
+ * return receiveImage(textView, clip);
+ * }
+ * return super.onReceive(textView, clip, source);
+ * }
+ *
+ * private boolean receiveImage(@NonNull TextView textView, @NonNull ClipData clip) {
+ * // ... app-specific logic to handle the content URI in the clip ...
+ * }
+ * }
+ * </pre>
+ *
+ * @param <T> The type of {@link View} with which this receiver can be associated.
+ */
+public abstract class RichContentReceiverCompat<T extends View> {
+ private static final String TAG = "RichContentReceiver";
+
+ /**
+ * Specifies the UI through which content is being inserted.
+ */
+ @IntDef(value = {SOURCE_CLIPBOARD, SOURCE_INPUT_METHOD})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Source {}
+
+ /**
+ * Specifies that the operation was triggered by a paste from the clipboard (e.g. "Paste" or
+ * "Paste as plain text" action in the insertion/selection menu).
+ */
+ public static final int SOURCE_CLIPBOARD = 0;
+
+ /**
+ * Specifies that the operation was triggered from the soft keyboard (also known as input method
+ * editor or IME). See https://developer.android.com/guide/topics/text/image-keyboard for more
+ * info.
+ */
+ public static final int SOURCE_INPUT_METHOD = 1;
+
+ /**
+ * Flags to configure the insertion behavior.
+ */
+ @IntDef(flag = true, value = {FLAG_CONVERT_TO_PLAIN_TEXT})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Flags {}
+
+ /**
+ * Flag for {@link #onReceive} requesting that the content should be converted to plain text
+ * prior to inserting.
+ */
+ public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1 << 0;
+
+ /**
+ * Insert the given clip.
+ *
+ * <p>For a UI component where this callback is set, this function will be invoked in the
+ * following scenarios:
+ * <ol>
+ * <li>Paste from the clipboard (e.g. "Paste" or "Paste as plain text" action in the
+ * insertion/selection menu)
+ * <li>Content insertion from the keyboard ({@link InputConnection#commitContent})
+ * </ol>
+ *
+ * <p>For text, if the view has a selection, the selection should be overwritten by the
+ * clip; if there's no selection, this method should insert the content at the current
+ * cursor position.
+ *
+ * <p>For rich content (e.g. an image), this function may insert the content inline, or it may
+ * add the content as an attachment (could potentially go into a completely separate view).
+ *
+ * <p>This function may be invoked with a clip whose MIME type is not in the list of supported
+ * types returned by {@link #getSupportedMimeTypes()}. This provides the opportunity to
+ * implement custom fallback logic if desired.
+ *
+ * @param view The view where the content insertion was requested.
+ * @param clip The clip to insert.
+ * @param source The trigger of the operation.
+ * @param flags Optional flags to configure the insertion behavior. Use 0 for default
+ * behavior. See {@code FLAG_} constants on this class for other options.
+ * @return Returns true if the clip was inserted.
+ */
+ public abstract boolean onReceive(@NonNull T view, @NonNull ClipData clip, @Source int source,
+ @Flags int flags);
+
+ /**
+ * Returns the MIME types that can be handled by this callback.
+ *
+ * <p>Different platform features (e.g. pasting from the clipboard, inserting stickers from the
+ * keyboard, etc) may use this function to conditionally alter their behavior. For example, the
+ * keyboard may choose to hide its UI for inserting GIFs if the input field that has focus has
+ * a {@link RichContentReceiverCompat} set and the MIME types returned from this function
+ * don't include "image/gif".
+ *
+ * @return An immutable set with the MIME types supported by this callback. The returned
+ * MIME types may contain wildcards such as "text/*", "image/*", etc.
+ */
+ @NonNull
+ public abstract Set<String> getSupportedMimeTypes();
+
+ /**
+ * Returns true if the MIME type of the given clip is {@link #getSupportedMimeTypes() supported}
+ * by this receiver.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ public final boolean supports(@NonNull ClipDescription description) {
+ for (String supportedMimeType : getSupportedMimeTypes()) {
+ if (description.hasMimeType(supportedMimeType)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Populates {@code outAttrs.contentMimeTypes} with the supported MIME types of this receiver.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ public final void populateEditorInfoContentMimeTypes(@Nullable InputConnection ic,
+ @Nullable EditorInfo outAttrs) {
+ if (ic == null || outAttrs == null) {
+ return;
+ }
+ String[] mimeTypes = getSupportedMimeTypes().toArray(new String[0]);
+ EditorInfoCompat.setContentMimeTypes(outAttrs, mimeTypes);
+ }
+
+ /**
+ * Creates an {@link InputConnectionCompat.OnCommitContentListener} that uses this receiver
+ * to insert content. The object returned by this function should be passed to
+ * {@link InputConnectionCompat#createWrapper} when creating the {@link InputConnection} in
+ * {@link View#onCreateInputConnection}.
+ *
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @NonNull
+ public final InputConnectionCompat.OnCommitContentListener buildOnCommitContentListener(
+ @NonNull final T view) {
+ return new InputConnectionCompat.OnCommitContentListener() {
+ @Override
+ public boolean onCommitContent(InputContentInfoCompat content, int flags,
+ Bundle opts) {
+ ClipDescription description = content.getDescription();
+ if ((flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
+ try {
+ content.requestPermission();
+ } catch (Exception e) {
+ Log.w(TAG, "Can't insert from IME; requestPermission() failed: " + e);
+ return false; // Can't insert the content if we don't have permission
+ }
+ }
+ ClipData clip = new ClipData(description,
+ new ClipData.Item(content.getContentUri()));
+ return onReceive(view, clip, SOURCE_INPUT_METHOD, 0);
+ }
+ };
+ }
+}
diff --git a/core/core/src/main/java/androidx/core/widget/TextViewRichContentReceiverCompat.java b/core/core/src/main/java/androidx/core/widget/TextViewRichContentReceiverCompat.java
new file mode 100644
index 0000000..31c51b1
--- /dev/null
+++ b/core/core/src/main/java/androidx/core/widget/TextViewRichContentReceiverCompat.java
@@ -0,0 +1,104 @@
+/*
+ * 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.core.widget;
+
+import android.content.ClipData;
+import android.content.Context;
+import android.os.Build;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.Spanned;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Base implementation of {@link RichContentReceiverCompat} for editable {@link TextView}
+ * components.
+ *
+ * <p>This class handles insertion of text (plain text, styled text, HTML, etc) but not images or
+ * other rich content. It should be used as a base class when implementing a custom
+ * {@link RichContentReceiverCompat}, to provide consistent behavior for insertion of text while
+ * implementing custom behavior for insertion of other content (images, etc).
+ *
+ * <p>See {@link RichContentReceiverCompat} for an example of how to implement a custom receiver.
+ */
+public abstract class TextViewRichContentReceiverCompat extends
+ RichContentReceiverCompat<TextView> {
+
+ private static final Set<String> MIME_TYPES_ALL_TEXT = Collections.singleton("text/*");
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @NonNull
+ public Set<String> getSupportedMimeTypes() {
+ return MIME_TYPES_ALL_TEXT;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onReceive(@NonNull TextView textView, @NonNull ClipData clip,
+ @Source int source, @Flags int flags) {
+ if (source == SOURCE_INPUT_METHOD && !supports(clip.getDescription())) {
+ return false;
+ }
+
+ // The code here follows the platform logic in TextView:
+ // https://cs.android.com/android/_/android/platform/frameworks/base/+/9fefb65aa9e7beae9ca8306b925b9fbfaeffecc9:core/java/android/widget/TextView.java;l=12644
+ // In particular, multiple items within the given ClipData will trigger separate calls to
+ // replace/insert. This is to preserve the platform behavior with respect to TextWatcher
+ // notifications fired from SpannableStringBuilder when replace/insert is called.
+ final Editable editable = (Editable) textView.getText();
+ final Context context = textView.getContext();
+ boolean didFirst = false;
+ for (int i = 0; i < clip.getItemCount(); i++) {
+ CharSequence paste;
+ if ((flags & FLAG_CONVERT_TO_PLAIN_TEXT) != 0) {
+ paste = clip.getItemAt(i).coerceToText(context);
+ paste = (paste instanceof Spanned) ? paste.toString() : paste;
+ } else {
+ if (Build.VERSION.SDK_INT >= 16) {
+ paste = clip.getItemAt(i).coerceToStyledText(context);
+ } else {
+ paste = clip.getItemAt(i).coerceToText(context);
+ }
+ }
+ if (paste != null) {
+ if (!didFirst) {
+ final int selStart = Selection.getSelectionStart(editable);
+ final int selEnd = Selection.getSelectionEnd(editable);
+ final int start = Math.max(0, Math.min(selStart, selEnd));
+ final int end = Math.max(0, Math.max(selStart, selEnd));
+ Selection.setSelection(editable, end);
+ editable.replace(start, end, paste);
+ didFirst = true;
+ } else {
+ editable.insert(Selection.getSelectionEnd(editable), "\n");
+ editable.insert(Selection.getSelectionEnd(editable), paste);
+ }
+ }
+ }
+ return didFirst;
+ }
+}
diff --git a/customview/customview/api/api_lint.ignore b/customview/customview/api/api_lint.ignore
index e3d334f..ba85783 100644
--- a/customview/customview/api/api_lint.ignore
+++ b/customview/customview/api/api_lint.ignore
@@ -1,8 +1,4 @@
// Baseline format: 1.0
-CallbackMethodName: androidx.customview.widget.ViewDragHelper.Callback:
- Callback method names must follow the on<Something> style: getOrderedChildIndex
-
-
MissingNullability: androidx.customview.view.AbsSavedState#CREATOR:
Missing nullability on field `CREATOR` in class `class androidx.customview.view.AbsSavedState`
MissingNullability: androidx.customview.view.AbsSavedState#EMPTY_STATE:
diff --git a/datastore/datastore-preferences/api/api_lint.ignore b/datastore/datastore-preferences/api/api_lint.ignore
new file mode 100644
index 0000000..2890439
--- /dev/null
+++ b/datastore/datastore-preferences/api/api_lint.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+BuilderSetStyle: androidx.datastore.preferences.Preferences.Builder#remove(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.datastore.preferences.Preferences.Builder.remove(String)
diff --git a/fragment/fragment-ktx/api/1.3.0-alpha06.ignore b/fragment/fragment-ktx/api/1.3.0-alpha06.ignore
new file mode 100644
index 0000000..4da20b8
--- /dev/null
+++ b/fragment/fragment-ktx/api/1.3.0-alpha06.ignore
@@ -0,0 +1,21 @@
+// Baseline format: 1.0
+ChangedType: androidx.fragment.app.FragmentViewModelLazyKt#activityViewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Method androidx.fragment.app.FragmentViewModelLazyKt.activityViewModels has changed return type from kotlin.Lazy<VM> to kotlin.Lazy<? extends VM>
+ChangedType: androidx.fragment.app.FragmentViewModelLazyKt#viewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner>, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Method androidx.fragment.app.FragmentViewModelLazyKt.viewModels has changed return type from kotlin.Lazy<VM> to kotlin.Lazy<? extends VM>
+
+
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#add(androidx.fragment.app.FragmentTransaction, String, android.os.Bundle):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentTransactionKt.add(androidx.fragment.app.FragmentTransaction,String,android.os.Bundle)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#add(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentTransactionKt.add(androidx.fragment.app.FragmentTransaction,int,String,android.os.Bundle)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#add(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle) parameter #2:
+ Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter tag in androidx.fragment.app.FragmentTransactionKt.add(androidx.fragment.app.FragmentTransaction arg1, int containerViewId, String tag, android.os.Bundle args)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#replace(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentTransactionKt.replace(androidx.fragment.app.FragmentTransaction,int,String,android.os.Bundle)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#replace(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle) parameter #2:
+ Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter tag in androidx.fragment.app.FragmentTransactionKt.replace(androidx.fragment.app.FragmentTransaction arg1, int containerViewId, String tag, android.os.Bundle args)
+InvalidNullConversion: androidx.fragment.app.FragmentViewModelLazyKt#activityViewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentViewModelLazyKt.activityViewModels(androidx.fragment.app.Fragment,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>)
+InvalidNullConversion: androidx.fragment.app.FragmentViewModelLazyKt#viewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner>, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentViewModelLazyKt.viewModels(androidx.fragment.app.Fragment,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner>,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>)
diff --git a/fragment/fragment-ktx/api/1.3.0-alpha06.txt b/fragment/fragment-ktx/api/1.3.0-alpha06.txt
new file mode 100644
index 0000000..7fc1d63
--- /dev/null
+++ b/fragment/fragment-ktx/api/1.3.0-alpha06.txt
@@ -0,0 +1,38 @@
+// Signature format: 3.0
+package androidx.fragment.app {
+
+ public final class FragmentKt {
+ method public static void clearFragmentResult(androidx.fragment.app.Fragment, String requestKey);
+ method public static void clearFragmentResultListener(androidx.fragment.app.Fragment, String requestKey);
+ method public static void setFragmentResult(androidx.fragment.app.Fragment, String requestKey, android.os.Bundle result);
+ method public static inline void setFragmentResultListener(androidx.fragment.app.Fragment, String requestKey, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+ }
+
+ public final class FragmentManagerKt {
+ method public static inline void commit(androidx.fragment.app.FragmentManager, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ method public static inline void commitNow(androidx.fragment.app.FragmentManager, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ method @Deprecated public static inline void transaction(androidx.fragment.app.FragmentManager, boolean now = false, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ }
+
+ public final class FragmentResultOwnerKt {
+ method public static inline void setFragmentResultListener(androidx.fragment.app.FragmentResultOwner, String requestKey, androidx.lifecycle.LifecycleOwner lifecycleOwner, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+ }
+
+ public final class FragmentTransactionKt {
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! add(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, String tag = null, android.os.Bundle? args = null);
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! add(androidx.fragment.app.FragmentTransaction, String tag, android.os.Bundle? args = null);
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! replace(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, String tag = null, android.os.Bundle? args = null);
+ }
+
+ public final class FragmentViewModelLazyKt {
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! activityViewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! viewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer = { return this }, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ }
+
+ public final class ViewKt {
+ method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+ }
+
+}
+
diff --git a/fragment/fragment-ktx/api/public_plus_experimental_1.3.0-alpha06.txt b/fragment/fragment-ktx/api/public_plus_experimental_1.3.0-alpha06.txt
new file mode 100644
index 0000000..7fc1d63
--- /dev/null
+++ b/fragment/fragment-ktx/api/public_plus_experimental_1.3.0-alpha06.txt
@@ -0,0 +1,38 @@
+// Signature format: 3.0
+package androidx.fragment.app {
+
+ public final class FragmentKt {
+ method public static void clearFragmentResult(androidx.fragment.app.Fragment, String requestKey);
+ method public static void clearFragmentResultListener(androidx.fragment.app.Fragment, String requestKey);
+ method public static void setFragmentResult(androidx.fragment.app.Fragment, String requestKey, android.os.Bundle result);
+ method public static inline void setFragmentResultListener(androidx.fragment.app.Fragment, String requestKey, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+ }
+
+ public final class FragmentManagerKt {
+ method public static inline void commit(androidx.fragment.app.FragmentManager, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ method public static inline void commitNow(androidx.fragment.app.FragmentManager, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ method @Deprecated public static inline void transaction(androidx.fragment.app.FragmentManager, boolean now = false, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ }
+
+ public final class FragmentResultOwnerKt {
+ method public static inline void setFragmentResultListener(androidx.fragment.app.FragmentResultOwner, String requestKey, androidx.lifecycle.LifecycleOwner lifecycleOwner, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+ }
+
+ public final class FragmentTransactionKt {
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! add(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, String tag = null, android.os.Bundle? args = null);
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! add(androidx.fragment.app.FragmentTransaction, String tag, android.os.Bundle? args = null);
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! replace(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, String tag = null, android.os.Bundle? args = null);
+ }
+
+ public final class FragmentViewModelLazyKt {
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! activityViewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! viewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer = { return this }, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ }
+
+ public final class ViewKt {
+ method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+ }
+
+}
+
diff --git a/fragment/fragment-ktx/api/res-1.3.0-alpha06.txt b/fragment/fragment-ktx/api/res-1.3.0-alpha06.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment-ktx/api/res-1.3.0-alpha06.txt
diff --git a/fragment/fragment-ktx/api/restricted_1.3.0-alpha06.ignore b/fragment/fragment-ktx/api/restricted_1.3.0-alpha06.ignore
new file mode 100644
index 0000000..4da20b8
--- /dev/null
+++ b/fragment/fragment-ktx/api/restricted_1.3.0-alpha06.ignore
@@ -0,0 +1,21 @@
+// Baseline format: 1.0
+ChangedType: androidx.fragment.app.FragmentViewModelLazyKt#activityViewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Method androidx.fragment.app.FragmentViewModelLazyKt.activityViewModels has changed return type from kotlin.Lazy<VM> to kotlin.Lazy<? extends VM>
+ChangedType: androidx.fragment.app.FragmentViewModelLazyKt#viewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner>, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Method androidx.fragment.app.FragmentViewModelLazyKt.viewModels has changed return type from kotlin.Lazy<VM> to kotlin.Lazy<? extends VM>
+
+
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#add(androidx.fragment.app.FragmentTransaction, String, android.os.Bundle):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentTransactionKt.add(androidx.fragment.app.FragmentTransaction,String,android.os.Bundle)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#add(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentTransactionKt.add(androidx.fragment.app.FragmentTransaction,int,String,android.os.Bundle)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#add(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle) parameter #2:
+ Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter tag in androidx.fragment.app.FragmentTransactionKt.add(androidx.fragment.app.FragmentTransaction arg1, int containerViewId, String tag, android.os.Bundle args)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#replace(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentTransactionKt.replace(androidx.fragment.app.FragmentTransaction,int,String,android.os.Bundle)
+InvalidNullConversion: androidx.fragment.app.FragmentTransactionKt#replace(androidx.fragment.app.FragmentTransaction, int, String, android.os.Bundle) parameter #2:
+ Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter tag in androidx.fragment.app.FragmentTransactionKt.replace(androidx.fragment.app.FragmentTransaction arg1, int containerViewId, String tag, android.os.Bundle args)
+InvalidNullConversion: androidx.fragment.app.FragmentViewModelLazyKt#activityViewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentViewModelLazyKt.activityViewModels(androidx.fragment.app.Fragment,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>)
+InvalidNullConversion: androidx.fragment.app.FragmentViewModelLazyKt#viewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner>, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.FragmentViewModelLazyKt.viewModels(androidx.fragment.app.Fragment,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner>,kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>)
diff --git a/fragment/fragment-ktx/api/restricted_1.3.0-alpha06.txt b/fragment/fragment-ktx/api/restricted_1.3.0-alpha06.txt
new file mode 100644
index 0000000..7fc1d63
--- /dev/null
+++ b/fragment/fragment-ktx/api/restricted_1.3.0-alpha06.txt
@@ -0,0 +1,38 @@
+// Signature format: 3.0
+package androidx.fragment.app {
+
+ public final class FragmentKt {
+ method public static void clearFragmentResult(androidx.fragment.app.Fragment, String requestKey);
+ method public static void clearFragmentResultListener(androidx.fragment.app.Fragment, String requestKey);
+ method public static void setFragmentResult(androidx.fragment.app.Fragment, String requestKey, android.os.Bundle result);
+ method public static inline void setFragmentResultListener(androidx.fragment.app.Fragment, String requestKey, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+ }
+
+ public final class FragmentManagerKt {
+ method public static inline void commit(androidx.fragment.app.FragmentManager, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ method public static inline void commitNow(androidx.fragment.app.FragmentManager, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ method @Deprecated public static inline void transaction(androidx.fragment.app.FragmentManager, boolean now = false, boolean allowStateLoss = false, kotlin.jvm.functions.Function1<? super androidx.fragment.app.FragmentTransaction,kotlin.Unit> body);
+ }
+
+ public final class FragmentResultOwnerKt {
+ method public static inline void setFragmentResultListener(androidx.fragment.app.FragmentResultOwner, String requestKey, androidx.lifecycle.LifecycleOwner lifecycleOwner, kotlin.jvm.functions.Function2<? super java.lang.String,? super android.os.Bundle,kotlin.Unit> listener);
+ }
+
+ public final class FragmentTransactionKt {
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! add(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, String tag = null, android.os.Bundle? args = null);
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! add(androidx.fragment.app.FragmentTransaction, String tag, android.os.Bundle? args = null);
+ method public static inline <reified F> androidx.fragment.app.FragmentTransaction! replace(androidx.fragment.app.FragmentTransaction, @IdRes int containerViewId, String tag = null, android.os.Bundle? args = null);
+ }
+
+ public final class FragmentViewModelLazyKt {
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! activityViewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ method @MainThread public static inline <reified VM> kotlin.Lazy<? extends VM>! viewModels(androidx.fragment.app.Fragment, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer = { return this }, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer = null);
+ }
+
+ public final class ViewKt {
+ method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+ }
+
+}
+
diff --git a/fragment/fragment-testing/api/1.3.0-alpha06.ignore b/fragment/fragment-testing/api/1.3.0-alpha06.ignore
new file mode 100644
index 0000000..0c3c8e4
--- /dev/null
+++ b/fragment/fragment-testing/api/1.3.0-alpha06.ignore
@@ -0,0 +1,9 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragment(android.os.Bundle,int,androidx.fragment.app.FragmentFactory)
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragment(android.os.Bundle,int,kotlin.jvm.functions.Function0<? extends F>)
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragmentInContainer(android.os.Bundle,int,androidx.fragment.app.FragmentFactory)
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragmentInContainer(android.os.Bundle,int,kotlin.jvm.functions.Function0<? extends F>)
diff --git a/fragment/fragment-testing/api/1.3.0-alpha06.txt b/fragment/fragment-testing/api/1.3.0-alpha06.txt
new file mode 100644
index 0000000..7b33baa
--- /dev/null
+++ b/fragment/fragment-testing/api/1.3.0-alpha06.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.fragment.app.testing {
+
+ public final class FragmentScenario<F extends androidx.fragment.app.Fragment> {
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
+ }
+
+ public static interface FragmentScenario.FragmentAction<F extends androidx.fragment.app.Fragment> {
+ method public void perform(F);
+ }
+
+ public final class FragmentScenarioKt {
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ }
+
+}
+
diff --git a/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha06.txt b/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha06.txt
new file mode 100644
index 0000000..7b33baa
--- /dev/null
+++ b/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha06.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.fragment.app.testing {
+
+ public final class FragmentScenario<F extends androidx.fragment.app.Fragment> {
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
+ }
+
+ public static interface FragmentScenario.FragmentAction<F extends androidx.fragment.app.Fragment> {
+ method public void perform(F);
+ }
+
+ public final class FragmentScenarioKt {
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ }
+
+}
+
diff --git a/fragment/fragment-testing/api/res-1.3.0-alpha06.txt b/fragment/fragment-testing/api/res-1.3.0-alpha06.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment-testing/api/res-1.3.0-alpha06.txt
diff --git a/fragment/fragment-testing/api/restricted_1.3.0-alpha06.ignore b/fragment/fragment-testing/api/restricted_1.3.0-alpha06.ignore
new file mode 100644
index 0000000..0c3c8e4
--- /dev/null
+++ b/fragment/fragment-testing/api/restricted_1.3.0-alpha06.ignore
@@ -0,0 +1,9 @@
+// Baseline format: 1.0
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragment(android.os.Bundle,int,androidx.fragment.app.FragmentFactory)
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragment(android.os.Bundle,int,kotlin.jvm.functions.Function0<? extends F>)
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragmentInContainer(android.os.Bundle,int,androidx.fragment.app.FragmentFactory)
+InvalidNullConversion: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
+ Attempted to remove @NonNull annotation from method androidx.fragment.app.testing.FragmentScenarioKt.launchFragmentInContainer(android.os.Bundle,int,kotlin.jvm.functions.Function0<? extends F>)
diff --git a/fragment/fragment-testing/api/restricted_1.3.0-alpha06.txt b/fragment/fragment-testing/api/restricted_1.3.0-alpha06.txt
new file mode 100644
index 0000000..7b33baa
--- /dev/null
+++ b/fragment/fragment-testing/api/restricted_1.3.0-alpha06.txt
@@ -0,0 +1,30 @@
+// Signature format: 3.0
+package androidx.fragment.app.testing {
+
+ public final class FragmentScenario<F extends androidx.fragment.app.Fragment> {
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
+ method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
+ }
+
+ public static interface FragmentScenario.FragmentAction<F extends androidx.fragment.app.Fragment> {
+ method public void perform(F);
+ }
+
+ public final class FragmentScenarioKt {
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ }
+
+}
+
diff --git a/fragment/fragment/api/1.3.0-alpha06.txt b/fragment/fragment/api/1.3.0-alpha06.txt
new file mode 100644
index 0000000..d5b26f6
--- /dev/null
+++ b/fragment/fragment/api/1.3.0-alpha06.txt
@@ -0,0 +1,444 @@
+// Signature format: 3.0
+package androidx.fragment.app {
+
+ public class DialogFragment extends androidx.fragment.app.Fragment implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+ ctor public DialogFragment();
+ ctor public DialogFragment(@LayoutRes int);
+ method public void dismiss();
+ method public void dismissAllowingStateLoss();
+ method public android.app.Dialog? getDialog();
+ method public boolean getShowsDialog();
+ method @StyleRes public int getTheme();
+ method public boolean isCancelable();
+ method public void onCancel(android.content.DialogInterface);
+ method @MainThread public android.app.Dialog onCreateDialog(android.os.Bundle?);
+ method public void onDismiss(android.content.DialogInterface);
+ method public final android.app.Dialog requireDialog();
+ method public void setCancelable(boolean);
+ method public void setShowsDialog(boolean);
+ method public void setStyle(int, @StyleRes int);
+ method public void show(androidx.fragment.app.FragmentManager, String?);
+ method public int show(androidx.fragment.app.FragmentTransaction, String?);
+ method public void showNow(androidx.fragment.app.FragmentManager, String?);
+ field public static final int STYLE_NORMAL = 0; // 0x0
+ field public static final int STYLE_NO_FRAME = 2; // 0x2
+ field public static final int STYLE_NO_INPUT = 3; // 0x3
+ field public static final int STYLE_NO_TITLE = 1; // 0x1
+ }
+
+ public class Fragment implements androidx.activity.result.ActivityResultCaller android.content.ComponentCallbacks androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner android.view.View.OnCreateContextMenuListener androidx.lifecycle.ViewModelStoreOwner {
+ ctor public Fragment();
+ ctor @ContentView public Fragment(@LayoutRes int);
+ method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public final boolean equals(Object?);
+ method public final androidx.fragment.app.FragmentActivity? getActivity();
+ method public boolean getAllowEnterTransitionOverlap();
+ method public boolean getAllowReturnTransitionOverlap();
+ method public final android.os.Bundle? getArguments();
+ method public final androidx.fragment.app.FragmentManager getChildFragmentManager();
+ method public android.content.Context? getContext();
+ method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+ method public Object? getEnterTransition();
+ method public Object? getExitTransition();
+ method @Deprecated public final androidx.fragment.app.FragmentManager? getFragmentManager();
+ method public final Object? getHost();
+ method public final int getId();
+ method public final android.view.LayoutInflater getLayoutInflater();
+ method public androidx.lifecycle.Lifecycle getLifecycle();
+ method @Deprecated public androidx.loader.app.LoaderManager getLoaderManager();
+ method public final androidx.fragment.app.Fragment? getParentFragment();
+ method public final androidx.fragment.app.FragmentManager getParentFragmentManager();
+ method public Object? getReenterTransition();
+ method public final android.content.res.Resources getResources();
+ method @Deprecated public final boolean getRetainInstance();
+ method public Object? getReturnTransition();
+ method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+ method public Object? getSharedElementEnterTransition();
+ method public Object? getSharedElementReturnTransition();
+ method public final String getString(@StringRes int);
+ method public final String getString(@StringRes int, java.lang.Object!...);
+ method public final String? getTag();
+ method @Deprecated public final androidx.fragment.app.Fragment? getTargetFragment();
+ method @Deprecated public final int getTargetRequestCode();
+ method public final CharSequence getText(@StringRes int);
+ method @Deprecated public boolean getUserVisibleHint();
+ method public android.view.View? getView();
+ method @MainThread public androidx.lifecycle.LifecycleOwner getViewLifecycleOwner();
+ method public androidx.lifecycle.LiveData<androidx.lifecycle.LifecycleOwner!> getViewLifecycleOwnerLiveData();
+ method public androidx.lifecycle.ViewModelStore getViewModelStore();
+ method public final int hashCode();
+ method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String);
+ method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+ method public final boolean isAdded();
+ method public final boolean isDetached();
+ method public final boolean isHidden();
+ method public final boolean isInLayout();
+ method public final boolean isRemoving();
+ method public final boolean isResumed();
+ method public final boolean isStateSaved();
+ method public final boolean isVisible();
+ method @Deprecated @CallSuper @MainThread public void onActivityCreated(android.os.Bundle?);
+ method @Deprecated public void onActivityResult(int, int, android.content.Intent?);
+ method @CallSuper @MainThread public void onAttach(android.content.Context);
+ method @Deprecated @CallSuper @MainThread public void onAttach(android.app.Activity);
+ method @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+ method @CallSuper public void onConfigurationChanged(android.content.res.Configuration);
+ method @MainThread public boolean onContextItemSelected(android.view.MenuItem);
+ method @CallSuper @MainThread public void onCreate(android.os.Bundle?);
+ method @MainThread public android.view.animation.Animation? onCreateAnimation(int, boolean, int);
+ method @MainThread public android.animation.Animator? onCreateAnimator(int, boolean, int);
+ method @MainThread public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo?);
+ method @MainThread public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method @MainThread public android.view.View? onCreateView(android.view.LayoutInflater, android.view.ViewGroup?, android.os.Bundle?);
+ method @CallSuper @MainThread public void onDestroy();
+ method @MainThread public void onDestroyOptionsMenu();
+ method @CallSuper @MainThread public void onDestroyView();
+ method @CallSuper @MainThread public void onDetach();
+ method public android.view.LayoutInflater onGetLayoutInflater(android.os.Bundle?);
+ method @MainThread public void onHiddenChanged(boolean);
+ method @CallSuper @UiThread public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle?);
+ method @Deprecated @CallSuper @UiThread public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle?);
+ method @CallSuper @MainThread public void onLowMemory();
+ method public void onMultiWindowModeChanged(boolean);
+ method @MainThread public boolean onOptionsItemSelected(android.view.MenuItem);
+ method @MainThread public void onOptionsMenuClosed(android.view.Menu);
+ method @CallSuper @MainThread public void onPause();
+ method public void onPictureInPictureModeChanged(boolean);
+ method @MainThread public void onPrepareOptionsMenu(android.view.Menu);
+ method @MainThread public void onPrimaryNavigationFragmentChanged(boolean);
+ method @Deprecated public void onRequestPermissionsResult(int, String![], int[]);
+ method @CallSuper @MainThread public void onResume();
+ method @MainThread public void onSaveInstanceState(android.os.Bundle);
+ method @CallSuper @MainThread public void onStart();
+ method @CallSuper @MainThread public void onStop();
+ method @MainThread public void onViewCreated(android.view.View, android.os.Bundle?);
+ method @CallSuper @MainThread public void onViewStateRestored(android.os.Bundle?);
+ method public void postponeEnterTransition();
+ method public final void postponeEnterTransition(long, java.util.concurrent.TimeUnit);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ method public void registerForContextMenu(android.view.View);
+ method @Deprecated public final void requestPermissions(String![], int);
+ method public final androidx.fragment.app.FragmentActivity requireActivity();
+ method public final android.os.Bundle requireArguments();
+ method public final android.content.Context requireContext();
+ method @Deprecated public final androidx.fragment.app.FragmentManager requireFragmentManager();
+ method public final Object requireHost();
+ method public final androidx.fragment.app.Fragment requireParentFragment();
+ method public final android.view.View requireView();
+ method public void setAllowEnterTransitionOverlap(boolean);
+ method public void setAllowReturnTransitionOverlap(boolean);
+ method public void setArguments(android.os.Bundle?);
+ method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setEnterTransition(Object?);
+ method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setExitTransition(Object?);
+ method public void setHasOptionsMenu(boolean);
+ method public void setInitialSavedState(androidx.fragment.app.Fragment.SavedState?);
+ method public void setMenuVisibility(boolean);
+ method public void setReenterTransition(Object?);
+ method @Deprecated public void setRetainInstance(boolean);
+ method public void setReturnTransition(Object?);
+ method public void setSharedElementEnterTransition(Object?);
+ method public void setSharedElementReturnTransition(Object?);
+ method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
+ method @Deprecated public void setUserVisibleHint(boolean);
+ method public boolean shouldShowRequestPermissionRationale(String);
+ method public void startActivity(android.content.Intent!);
+ method public void startActivity(android.content.Intent!, android.os.Bundle?);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void startPostponedEnterTransition();
+ method public void unregisterForContextMenu(android.view.View);
+ }
+
+ public static class Fragment.InstantiationException extends java.lang.RuntimeException {
+ ctor public Fragment.InstantiationException(String, Exception?);
+ }
+
+ public static class Fragment.SavedState implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.fragment.app.Fragment.SavedState!> CREATOR;
+ }
+
+ public class FragmentActivity extends androidx.activity.ComponentActivity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback androidx.lifecycle.LifecycleOwner {
+ ctor public FragmentActivity();
+ ctor @ContentView public FragmentActivity(@LayoutRes int);
+ method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+ method @Deprecated public androidx.loader.app.LoaderManager getSupportLoaderManager();
+ method public void onAttachFragment(androidx.fragment.app.Fragment);
+ method @CallSuper public void onMultiWindowModeChanged(boolean);
+ method @CallSuper public void onPictureInPictureModeChanged(boolean);
+ method protected void onResumeFragments();
+ method public void onStateNotSaved();
+ method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
+ method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void supportFinishAfterTransition();
+ method @Deprecated public void supportInvalidateOptionsMenu();
+ method public void supportPostponeEnterTransition();
+ method public void supportStartPostponedEnterTransition();
+ method @Deprecated public final void validateRequestPermissionsRequestCode(int);
+ }
+
+ public abstract class FragmentContainer {
+ ctor public FragmentContainer();
+ method @Deprecated public androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+ method public abstract android.view.View? onFindViewById(@IdRes int);
+ method public abstract boolean onHasView();
+ }
+
+ public final class FragmentContainerView extends android.widget.FrameLayout {
+ ctor public FragmentContainerView(android.content.Context);
+ ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?);
+ ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?, int);
+ }
+
+ public class FragmentController {
+ method public void attachHost(androidx.fragment.app.Fragment?);
+ method public static androidx.fragment.app.FragmentController createController(androidx.fragment.app.FragmentHostCallback<?>);
+ method public void dispatchActivityCreated();
+ method public void dispatchConfigurationChanged(android.content.res.Configuration);
+ method public boolean dispatchContextItemSelected(android.view.MenuItem);
+ method public void dispatchCreate();
+ method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method public void dispatchDestroy();
+ method public void dispatchDestroyView();
+ method public void dispatchLowMemory();
+ method public void dispatchMultiWindowModeChanged(boolean);
+ method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+ method public void dispatchOptionsMenuClosed(android.view.Menu);
+ method public void dispatchPause();
+ method public void dispatchPictureInPictureModeChanged(boolean);
+ method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+ method @Deprecated public void dispatchReallyStop();
+ method public void dispatchResume();
+ method public void dispatchStart();
+ method public void dispatchStop();
+ method @Deprecated public void doLoaderDestroy();
+ method @Deprecated public void doLoaderRetain();
+ method @Deprecated public void doLoaderStart();
+ method @Deprecated public void doLoaderStop(boolean);
+ method @Deprecated public void dumpLoaders(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public boolean execPendingActions();
+ method public androidx.fragment.app.Fragment? findFragmentByWho(String);
+ method public java.util.List<androidx.fragment.app.Fragment!> getActiveFragments(java.util.List<androidx.fragment.app.Fragment!>!);
+ method public int getActiveFragmentsCount();
+ method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+ method @Deprecated public androidx.loader.app.LoaderManager! getSupportLoaderManager();
+ method public void noteStateNotSaved();
+ method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
+ method @Deprecated public void reportLoaderStart();
+ method @Deprecated public void restoreAllState(android.os.Parcelable?, java.util.List<androidx.fragment.app.Fragment!>?);
+ method @Deprecated public void restoreAllState(android.os.Parcelable?, androidx.fragment.app.FragmentManagerNonConfig?);
+ method @Deprecated public void restoreLoaderNonConfig(androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>!);
+ method public void restoreSaveState(android.os.Parcelable?);
+ method @Deprecated public androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>? retainLoaderNonConfig();
+ method @Deprecated public androidx.fragment.app.FragmentManagerNonConfig? retainNestedNonConfig();
+ method @Deprecated public java.util.List<androidx.fragment.app.Fragment!>? retainNonConfig();
+ method public android.os.Parcelable? saveAllState();
+ }
+
+ public class FragmentFactory {
+ ctor public FragmentFactory();
+ method public androidx.fragment.app.Fragment instantiate(ClassLoader, String);
+ method public static Class<? extends androidx.fragment.app.Fragment> loadFragmentClass(ClassLoader, String);
+ }
+
+ public abstract class FragmentHostCallback<E> extends androidx.fragment.app.FragmentContainer {
+ ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+ method public void onDump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public android.view.View? onFindViewById(int);
+ method public abstract E? onGetHost();
+ method public android.view.LayoutInflater onGetLayoutInflater();
+ method public int onGetWindowAnimations();
+ method public boolean onHasView();
+ method public boolean onHasWindowAnimations();
+ method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
+ method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
+ method public boolean onShouldShowRequestPermissionRationale(String);
+ method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
+ method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void onSupportInvalidateOptionsMenu();
+ }
+
+ public abstract class FragmentManager implements androidx.fragment.app.FragmentResultOwner {
+ ctor public FragmentManager();
+ method public void addOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+ method public androidx.fragment.app.FragmentTransaction beginTransaction();
+ method public final void clearFragmentResult(String);
+ method public final void clearFragmentResultListener(String);
+ method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method @Deprecated public static void enableDebugLogging(boolean);
+ method public boolean executePendingTransactions();
+ method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+ method public androidx.fragment.app.Fragment? findFragmentById(@IdRes int);
+ method public androidx.fragment.app.Fragment? findFragmentByTag(String?);
+ method public androidx.fragment.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
+ method public int getBackStackEntryCount();
+ method public androidx.fragment.app.Fragment? getFragment(android.os.Bundle, String);
+ method public androidx.fragment.app.FragmentFactory getFragmentFactory();
+ method public java.util.List<androidx.fragment.app.Fragment!> getFragments();
+ method public androidx.fragment.app.Fragment? getPrimaryNavigationFragment();
+ method public boolean isDestroyed();
+ method public boolean isStateSaved();
+ method public void popBackStack();
+ method public void popBackStack(String?, int);
+ method public void popBackStack(int, int);
+ method public boolean popBackStackImmediate();
+ method public boolean popBackStackImmediate(String?, int);
+ method public boolean popBackStackImmediate(int, int);
+ method public void putFragment(android.os.Bundle, String, androidx.fragment.app.Fragment);
+ method public void registerFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks, boolean);
+ method public void removeOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+ method public androidx.fragment.app.Fragment.SavedState? saveFragmentInstanceState(androidx.fragment.app.Fragment);
+ method public void setFragmentFactory(androidx.fragment.app.FragmentFactory);
+ method public final void setFragmentResult(String, android.os.Bundle);
+ method public final void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+ method public void unregisterFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks);
+ field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1
+ }
+
+ public static interface FragmentManager.BackStackEntry {
+ method @Deprecated public CharSequence? getBreadCrumbShortTitle();
+ method @Deprecated @StringRes public int getBreadCrumbShortTitleRes();
+ method @Deprecated public CharSequence? getBreadCrumbTitle();
+ method @Deprecated @StringRes public int getBreadCrumbTitleRes();
+ method public int getId();
+ method public String? getName();
+ }
+
+ public abstract static class FragmentManager.FragmentLifecycleCallbacks {
+ ctor public FragmentManager.FragmentLifecycleCallbacks();
+ method @Deprecated public void onFragmentActivityCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+ method public void onFragmentCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentDetached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentPaused(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentPreAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+ method public void onFragmentPreCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentResumed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentSaveInstanceState(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle);
+ method public void onFragmentStarted(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentStopped(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentViewCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.view.View, android.os.Bundle?);
+ method public void onFragmentViewDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ }
+
+ public static interface FragmentManager.OnBackStackChangedListener {
+ method @MainThread public void onBackStackChanged();
+ }
+
+ @Deprecated public class FragmentManagerNonConfig {
+ }
+
+ @Deprecated public abstract class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+ ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager);
+ ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager, int);
+ method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+ method @Deprecated public long getItemId(int);
+ method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+ field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+ }
+
+ public interface FragmentResultListener {
+ method public void onFragmentResult(String, android.os.Bundle);
+ }
+
+ public interface FragmentResultOwner {
+ method public void clearFragmentResult(String);
+ method public void clearFragmentResultListener(String);
+ method public void setFragmentResult(String, android.os.Bundle);
+ method public void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+ }
+
+ @Deprecated public abstract class FragmentStatePagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+ ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager);
+ ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager, int);
+ method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+ method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+ field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+ }
+
+ @Deprecated public class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
+ ctor @Deprecated public FragmentTabHost(android.content.Context);
+ ctor @Deprecated public FragmentTabHost(android.content.Context, android.util.AttributeSet?);
+ method @Deprecated public void addTab(android.widget.TabHost.TabSpec, Class<?>, android.os.Bundle?);
+ method @Deprecated public void onTabChanged(String?);
+ method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager);
+ method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager, int);
+ }
+
+ public abstract class FragmentTransaction {
+ ctor @Deprecated public FragmentTransaction();
+ method public final androidx.fragment.app.FragmentTransaction add(Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.Fragment, String?);
+ method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+ method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment, String?);
+ method public androidx.fragment.app.FragmentTransaction addSharedElement(android.view.View, String);
+ method public androidx.fragment.app.FragmentTransaction addToBackStack(String?);
+ method public androidx.fragment.app.FragmentTransaction attach(androidx.fragment.app.Fragment);
+ method public abstract int commit();
+ method public abstract int commitAllowingStateLoss();
+ method public abstract void commitNow();
+ method public abstract void commitNowAllowingStateLoss();
+ method public androidx.fragment.app.FragmentTransaction detach(androidx.fragment.app.Fragment);
+ method public androidx.fragment.app.FragmentTransaction disallowAddToBackStack();
+ method public androidx.fragment.app.FragmentTransaction hide(androidx.fragment.app.Fragment);
+ method public boolean isAddToBackStackAllowed();
+ method public boolean isEmpty();
+ method public androidx.fragment.app.FragmentTransaction remove(androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+ method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment, String?);
+ method public androidx.fragment.app.FragmentTransaction runOnCommit(Runnable);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setAllowOptimization(boolean);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(@StringRes int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(CharSequence?);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(@StringRes int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(CharSequence?);
+ method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+ method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+ method public androidx.fragment.app.FragmentTransaction setMaxLifecycle(androidx.fragment.app.Fragment, androidx.lifecycle.Lifecycle.State);
+ method public androidx.fragment.app.FragmentTransaction setPrimaryNavigationFragment(androidx.fragment.app.Fragment?);
+ method public androidx.fragment.app.FragmentTransaction setReorderingAllowed(boolean);
+ method public androidx.fragment.app.FragmentTransaction setTransition(int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setTransitionStyle(@StyleRes int);
+ method public androidx.fragment.app.FragmentTransaction show(androidx.fragment.app.Fragment);
+ field public static final int TRANSIT_ENTER_MASK = 4096; // 0x1000
+ field public static final int TRANSIT_EXIT_MASK = 8192; // 0x2000
+ field public static final int TRANSIT_FRAGMENT_CLOSE = 8194; // 0x2002
+ field public static final int TRANSIT_FRAGMENT_FADE = 4099; // 0x1003
+ field public static final int TRANSIT_FRAGMENT_OPEN = 4097; // 0x1001
+ field public static final int TRANSIT_NONE = 0; // 0x0
+ field public static final int TRANSIT_UNSET = -1; // 0xffffffff
+ }
+
+ public class ListFragment extends androidx.fragment.app.Fragment {
+ ctor public ListFragment();
+ method public android.widget.ListAdapter? getListAdapter();
+ method public android.widget.ListView getListView();
+ method public long getSelectedItemId();
+ method public int getSelectedItemPosition();
+ method public void onListItemClick(android.widget.ListView, android.view.View, int, long);
+ method public final android.widget.ListAdapter requireListAdapter();
+ method public void setEmptyText(CharSequence?);
+ method public void setListAdapter(android.widget.ListAdapter?);
+ method public void setListShown(boolean);
+ method public void setListShownNoAnimation(boolean);
+ method public void setSelection(int);
+ }
+
+}
+
diff --git a/fragment/fragment/api/api_lint.ignore b/fragment/fragment/api/api_lint.ignore
index 3f1f664..0268087 100644
--- a/fragment/fragment/api/api_lint.ignore
+++ b/fragment/fragment/api/api_lint.ignore
@@ -27,18 +27,10 @@
Missing nullability on parameter `intent` in method `startIntentSenderForResult`
MissingNullability: androidx.fragment.app.FragmentActivity#onNewIntent(android.content.Intent) parameter #0:
Missing nullability on parameter `intent` in method `onNewIntent`
-MissingNullability: androidx.fragment.app.FragmentActivity#startActivityForResult(android.content.Intent, int) parameter #0:
- Missing nullability on parameter `intent` in method `startActivityForResult`
-MissingNullability: androidx.fragment.app.FragmentActivity#startActivityForResult(android.content.Intent, int, android.os.Bundle) parameter #0:
- Missing nullability on parameter `intent` in method `startActivityForResult`
MissingNullability: androidx.fragment.app.FragmentActivity#startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int) parameter #1:
Missing nullability on parameter `intent` in method `startActivityFromFragment`
MissingNullability: androidx.fragment.app.FragmentActivity#startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle) parameter #1:
Missing nullability on parameter `intent` in method `startActivityFromFragment`
-MissingNullability: androidx.fragment.app.FragmentActivity#startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int) parameter #0:
- Missing nullability on parameter `intent` in method `startIntentSenderForResult`
-MissingNullability: androidx.fragment.app.FragmentActivity#startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) parameter #0:
- Missing nullability on parameter `intent` in method `startIntentSenderForResult`
MissingNullability: androidx.fragment.app.FragmentActivity#startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) parameter #1:
Missing nullability on parameter `intent` in method `startIntentSenderFromFragment`
MissingNullability: androidx.fragment.app.FragmentController#getActiveFragments(java.util.List<androidx.fragment.app.Fragment>) parameter #0:
diff --git a/fragment/fragment/api/public_plus_experimental_1.3.0-alpha06.txt b/fragment/fragment/api/public_plus_experimental_1.3.0-alpha06.txt
new file mode 100644
index 0000000..cce8158
--- /dev/null
+++ b/fragment/fragment/api/public_plus_experimental_1.3.0-alpha06.txt
@@ -0,0 +1,444 @@
+// Signature format: 3.0
+package androidx.fragment.app {
+
+ public class DialogFragment extends androidx.fragment.app.Fragment implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+ ctor public DialogFragment();
+ ctor public DialogFragment(@LayoutRes int);
+ method public void dismiss();
+ method public void dismissAllowingStateLoss();
+ method public android.app.Dialog? getDialog();
+ method public boolean getShowsDialog();
+ method @StyleRes public int getTheme();
+ method public boolean isCancelable();
+ method public void onCancel(android.content.DialogInterface);
+ method @MainThread public android.app.Dialog onCreateDialog(android.os.Bundle?);
+ method public void onDismiss(android.content.DialogInterface);
+ method public final android.app.Dialog requireDialog();
+ method public void setCancelable(boolean);
+ method public void setShowsDialog(boolean);
+ method public void setStyle(int, @StyleRes int);
+ method public void show(androidx.fragment.app.FragmentManager, String?);
+ method public int show(androidx.fragment.app.FragmentTransaction, String?);
+ method public void showNow(androidx.fragment.app.FragmentManager, String?);
+ field public static final int STYLE_NORMAL = 0; // 0x0
+ field public static final int STYLE_NO_FRAME = 2; // 0x2
+ field public static final int STYLE_NO_INPUT = 3; // 0x3
+ field public static final int STYLE_NO_TITLE = 1; // 0x1
+ }
+
+ public class Fragment implements androidx.activity.result.ActivityResultCaller android.content.ComponentCallbacks androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner android.view.View.OnCreateContextMenuListener androidx.lifecycle.ViewModelStoreOwner {
+ ctor public Fragment();
+ ctor @ContentView public Fragment(@LayoutRes int);
+ method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public final boolean equals(Object?);
+ method public final androidx.fragment.app.FragmentActivity? getActivity();
+ method public boolean getAllowEnterTransitionOverlap();
+ method public boolean getAllowReturnTransitionOverlap();
+ method public final android.os.Bundle? getArguments();
+ method public final androidx.fragment.app.FragmentManager getChildFragmentManager();
+ method public android.content.Context? getContext();
+ method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+ method public Object? getEnterTransition();
+ method public Object? getExitTransition();
+ method @Deprecated public final androidx.fragment.app.FragmentManager? getFragmentManager();
+ method public final Object? getHost();
+ method public final int getId();
+ method public final android.view.LayoutInflater getLayoutInflater();
+ method public androidx.lifecycle.Lifecycle getLifecycle();
+ method @Deprecated public androidx.loader.app.LoaderManager getLoaderManager();
+ method public final androidx.fragment.app.Fragment? getParentFragment();
+ method public final androidx.fragment.app.FragmentManager getParentFragmentManager();
+ method public Object? getReenterTransition();
+ method public final android.content.res.Resources getResources();
+ method @Deprecated public final boolean getRetainInstance();
+ method public Object? getReturnTransition();
+ method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+ method public Object? getSharedElementEnterTransition();
+ method public Object? getSharedElementReturnTransition();
+ method public final String getString(@StringRes int);
+ method public final String getString(@StringRes int, java.lang.Object!...);
+ method public final String? getTag();
+ method @Deprecated public final androidx.fragment.app.Fragment? getTargetFragment();
+ method @Deprecated public final int getTargetRequestCode();
+ method public final CharSequence getText(@StringRes int);
+ method @Deprecated public boolean getUserVisibleHint();
+ method public android.view.View? getView();
+ method @MainThread public androidx.lifecycle.LifecycleOwner getViewLifecycleOwner();
+ method public androidx.lifecycle.LiveData<androidx.lifecycle.LifecycleOwner!> getViewLifecycleOwnerLiveData();
+ method public androidx.lifecycle.ViewModelStore getViewModelStore();
+ method public final int hashCode();
+ method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String);
+ method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+ method public final boolean isAdded();
+ method public final boolean isDetached();
+ method public final boolean isHidden();
+ method public final boolean isInLayout();
+ method public final boolean isRemoving();
+ method public final boolean isResumed();
+ method public final boolean isStateSaved();
+ method public final boolean isVisible();
+ method @Deprecated @CallSuper @MainThread public void onActivityCreated(android.os.Bundle?);
+ method @Deprecated public void onActivityResult(int, int, android.content.Intent?);
+ method @CallSuper @MainThread public void onAttach(android.content.Context);
+ method @Deprecated @CallSuper @MainThread public void onAttach(android.app.Activity);
+ method @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+ method @CallSuper public void onConfigurationChanged(android.content.res.Configuration);
+ method @MainThread public boolean onContextItemSelected(android.view.MenuItem);
+ method @CallSuper @MainThread public void onCreate(android.os.Bundle?);
+ method @MainThread public android.view.animation.Animation? onCreateAnimation(int, boolean, int);
+ method @MainThread public android.animation.Animator? onCreateAnimator(int, boolean, int);
+ method @MainThread public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo?);
+ method @MainThread public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method @MainThread public android.view.View? onCreateView(android.view.LayoutInflater, android.view.ViewGroup?, android.os.Bundle?);
+ method @CallSuper @MainThread public void onDestroy();
+ method @MainThread public void onDestroyOptionsMenu();
+ method @CallSuper @MainThread public void onDestroyView();
+ method @CallSuper @MainThread public void onDetach();
+ method public android.view.LayoutInflater onGetLayoutInflater(android.os.Bundle?);
+ method @MainThread public void onHiddenChanged(boolean);
+ method @CallSuper @UiThread public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle?);
+ method @Deprecated @CallSuper @UiThread public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle?);
+ method @CallSuper @MainThread public void onLowMemory();
+ method public void onMultiWindowModeChanged(boolean);
+ method @MainThread public boolean onOptionsItemSelected(android.view.MenuItem);
+ method @MainThread public void onOptionsMenuClosed(android.view.Menu);
+ method @CallSuper @MainThread public void onPause();
+ method public void onPictureInPictureModeChanged(boolean);
+ method @MainThread public void onPrepareOptionsMenu(android.view.Menu);
+ method @MainThread public void onPrimaryNavigationFragmentChanged(boolean);
+ method @Deprecated public void onRequestPermissionsResult(int, String![], int[]);
+ method @CallSuper @MainThread public void onResume();
+ method @MainThread public void onSaveInstanceState(android.os.Bundle);
+ method @CallSuper @MainThread public void onStart();
+ method @CallSuper @MainThread public void onStop();
+ method @MainThread public void onViewCreated(android.view.View, android.os.Bundle?);
+ method @CallSuper @MainThread public void onViewStateRestored(android.os.Bundle?);
+ method public void postponeEnterTransition();
+ method public final void postponeEnterTransition(long, java.util.concurrent.TimeUnit);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ method public void registerForContextMenu(android.view.View);
+ method @Deprecated public final void requestPermissions(String![], int);
+ method public final androidx.fragment.app.FragmentActivity requireActivity();
+ method public final android.os.Bundle requireArguments();
+ method public final android.content.Context requireContext();
+ method @Deprecated public final androidx.fragment.app.FragmentManager requireFragmentManager();
+ method public final Object requireHost();
+ method public final androidx.fragment.app.Fragment requireParentFragment();
+ method public final android.view.View requireView();
+ method public void setAllowEnterTransitionOverlap(boolean);
+ method public void setAllowReturnTransitionOverlap(boolean);
+ method public void setArguments(android.os.Bundle?);
+ method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setEnterTransition(Object?);
+ method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setExitTransition(Object?);
+ method public void setHasOptionsMenu(boolean);
+ method public void setInitialSavedState(androidx.fragment.app.Fragment.SavedState?);
+ method public void setMenuVisibility(boolean);
+ method public void setReenterTransition(Object?);
+ method @Deprecated public void setRetainInstance(boolean);
+ method public void setReturnTransition(Object?);
+ method public void setSharedElementEnterTransition(Object?);
+ method public void setSharedElementReturnTransition(Object?);
+ method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
+ method @Deprecated public void setUserVisibleHint(boolean);
+ method public boolean shouldShowRequestPermissionRationale(String);
+ method public void startActivity(android.content.Intent!);
+ method public void startActivity(android.content.Intent!, android.os.Bundle?);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void startPostponedEnterTransition();
+ method public void unregisterForContextMenu(android.view.View);
+ }
+
+ public static class Fragment.InstantiationException extends java.lang.RuntimeException {
+ ctor public Fragment.InstantiationException(String, Exception?);
+ }
+
+ public static class Fragment.SavedState implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.fragment.app.Fragment.SavedState!> CREATOR;
+ }
+
+ public class FragmentActivity extends androidx.activity.ComponentActivity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback androidx.core.app.ActivityCompat.RequestPermissionsRequestCodeValidator {
+ ctor public FragmentActivity();
+ ctor @ContentView public FragmentActivity(@LayoutRes int);
+ method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+ method @Deprecated public androidx.loader.app.LoaderManager getSupportLoaderManager();
+ method public void onAttachFragment(androidx.fragment.app.Fragment);
+ method @CallSuper public void onMultiWindowModeChanged(boolean);
+ method @CallSuper public void onPictureInPictureModeChanged(boolean);
+ method protected void onResumeFragments();
+ method public void onStateNotSaved();
+ method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
+ method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void supportFinishAfterTransition();
+ method @Deprecated public void supportInvalidateOptionsMenu();
+ method public void supportPostponeEnterTransition();
+ method public void supportStartPostponedEnterTransition();
+ method @Deprecated public final void validateRequestPermissionsRequestCode(int);
+ }
+
+ public abstract class FragmentContainer {
+ ctor public FragmentContainer();
+ method @Deprecated public androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+ method public abstract android.view.View? onFindViewById(@IdRes int);
+ method public abstract boolean onHasView();
+ }
+
+ public final class FragmentContainerView extends android.widget.FrameLayout {
+ ctor public FragmentContainerView(android.content.Context);
+ ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?);
+ ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?, int);
+ }
+
+ public class FragmentController {
+ method public void attachHost(androidx.fragment.app.Fragment?);
+ method public static androidx.fragment.app.FragmentController createController(androidx.fragment.app.FragmentHostCallback<?>);
+ method public void dispatchActivityCreated();
+ method public void dispatchConfigurationChanged(android.content.res.Configuration);
+ method public boolean dispatchContextItemSelected(android.view.MenuItem);
+ method public void dispatchCreate();
+ method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method public void dispatchDestroy();
+ method public void dispatchDestroyView();
+ method public void dispatchLowMemory();
+ method public void dispatchMultiWindowModeChanged(boolean);
+ method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+ method public void dispatchOptionsMenuClosed(android.view.Menu);
+ method public void dispatchPause();
+ method public void dispatchPictureInPictureModeChanged(boolean);
+ method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+ method @Deprecated public void dispatchReallyStop();
+ method public void dispatchResume();
+ method public void dispatchStart();
+ method public void dispatchStop();
+ method @Deprecated public void doLoaderDestroy();
+ method @Deprecated public void doLoaderRetain();
+ method @Deprecated public void doLoaderStart();
+ method @Deprecated public void doLoaderStop(boolean);
+ method @Deprecated public void dumpLoaders(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public boolean execPendingActions();
+ method public androidx.fragment.app.Fragment? findFragmentByWho(String);
+ method public java.util.List<androidx.fragment.app.Fragment!> getActiveFragments(java.util.List<androidx.fragment.app.Fragment!>!);
+ method public int getActiveFragmentsCount();
+ method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+ method @Deprecated public androidx.loader.app.LoaderManager! getSupportLoaderManager();
+ method public void noteStateNotSaved();
+ method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
+ method @Deprecated public void reportLoaderStart();
+ method @Deprecated public void restoreAllState(android.os.Parcelable?, java.util.List<androidx.fragment.app.Fragment!>?);
+ method @Deprecated public void restoreAllState(android.os.Parcelable?, androidx.fragment.app.FragmentManagerNonConfig?);
+ method @Deprecated public void restoreLoaderNonConfig(androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>!);
+ method public void restoreSaveState(android.os.Parcelable?);
+ method @Deprecated public androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>? retainLoaderNonConfig();
+ method @Deprecated public androidx.fragment.app.FragmentManagerNonConfig? retainNestedNonConfig();
+ method @Deprecated public java.util.List<androidx.fragment.app.Fragment!>? retainNonConfig();
+ method public android.os.Parcelable? saveAllState();
+ }
+
+ public class FragmentFactory {
+ ctor public FragmentFactory();
+ method public androidx.fragment.app.Fragment instantiate(ClassLoader, String);
+ method public static Class<? extends androidx.fragment.app.Fragment> loadFragmentClass(ClassLoader, String);
+ }
+
+ public abstract class FragmentHostCallback<E> extends androidx.fragment.app.FragmentContainer {
+ ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+ method public void onDump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public android.view.View? onFindViewById(int);
+ method public abstract E? onGetHost();
+ method public android.view.LayoutInflater onGetLayoutInflater();
+ method public int onGetWindowAnimations();
+ method public boolean onHasView();
+ method public boolean onHasWindowAnimations();
+ method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
+ method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
+ method public boolean onShouldShowRequestPermissionRationale(String);
+ method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
+ method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void onSupportInvalidateOptionsMenu();
+ }
+
+ public abstract class FragmentManager implements androidx.fragment.app.FragmentResultOwner {
+ ctor public FragmentManager();
+ method public void addOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+ method public androidx.fragment.app.FragmentTransaction beginTransaction();
+ method public final void clearFragmentResult(String);
+ method public final void clearFragmentResultListener(String);
+ method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method @Deprecated public static void enableDebugLogging(boolean);
+ method public boolean executePendingTransactions();
+ method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+ method public androidx.fragment.app.Fragment? findFragmentById(@IdRes int);
+ method public androidx.fragment.app.Fragment? findFragmentByTag(String?);
+ method public androidx.fragment.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
+ method public int getBackStackEntryCount();
+ method public androidx.fragment.app.Fragment? getFragment(android.os.Bundle, String);
+ method public androidx.fragment.app.FragmentFactory getFragmentFactory();
+ method public java.util.List<androidx.fragment.app.Fragment!> getFragments();
+ method public androidx.fragment.app.Fragment? getPrimaryNavigationFragment();
+ method public boolean isDestroyed();
+ method public boolean isStateSaved();
+ method public void popBackStack();
+ method public void popBackStack(String?, int);
+ method public void popBackStack(int, int);
+ method public boolean popBackStackImmediate();
+ method public boolean popBackStackImmediate(String?, int);
+ method public boolean popBackStackImmediate(int, int);
+ method public void putFragment(android.os.Bundle, String, androidx.fragment.app.Fragment);
+ method public void registerFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks, boolean);
+ method public void removeOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+ method public androidx.fragment.app.Fragment.SavedState? saveFragmentInstanceState(androidx.fragment.app.Fragment);
+ method public void setFragmentFactory(androidx.fragment.app.FragmentFactory);
+ method public final void setFragmentResult(String, android.os.Bundle);
+ method public final void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+ method public void unregisterFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks);
+ field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1
+ }
+
+ public static interface FragmentManager.BackStackEntry {
+ method @Deprecated public CharSequence? getBreadCrumbShortTitle();
+ method @Deprecated @StringRes public int getBreadCrumbShortTitleRes();
+ method @Deprecated public CharSequence? getBreadCrumbTitle();
+ method @Deprecated @StringRes public int getBreadCrumbTitleRes();
+ method public int getId();
+ method public String? getName();
+ }
+
+ public abstract static class FragmentManager.FragmentLifecycleCallbacks {
+ ctor public FragmentManager.FragmentLifecycleCallbacks();
+ method @Deprecated public void onFragmentActivityCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+ method public void onFragmentCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentDetached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentPaused(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentPreAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+ method public void onFragmentPreCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentResumed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentSaveInstanceState(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle);
+ method public void onFragmentStarted(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentStopped(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentViewCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.view.View, android.os.Bundle?);
+ method public void onFragmentViewDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ }
+
+ public static interface FragmentManager.OnBackStackChangedListener {
+ method @MainThread public void onBackStackChanged();
+ }
+
+ @Deprecated public class FragmentManagerNonConfig {
+ }
+
+ @Deprecated public abstract class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+ ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager);
+ ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager, int);
+ method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+ method @Deprecated public long getItemId(int);
+ method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+ field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+ }
+
+ public interface FragmentResultListener {
+ method public void onFragmentResult(String, android.os.Bundle);
+ }
+
+ public interface FragmentResultOwner {
+ method public void clearFragmentResult(String);
+ method public void clearFragmentResultListener(String);
+ method public void setFragmentResult(String, android.os.Bundle);
+ method public void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+ }
+
+ @Deprecated public abstract class FragmentStatePagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+ ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager);
+ ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager, int);
+ method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+ method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+ field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+ }
+
+ @Deprecated public class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
+ ctor @Deprecated public FragmentTabHost(android.content.Context);
+ ctor @Deprecated public FragmentTabHost(android.content.Context, android.util.AttributeSet?);
+ method @Deprecated public void addTab(android.widget.TabHost.TabSpec, Class<?>, android.os.Bundle?);
+ method @Deprecated public void onTabChanged(String?);
+ method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager);
+ method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager, int);
+ }
+
+ public abstract class FragmentTransaction {
+ ctor @Deprecated public FragmentTransaction();
+ method public final androidx.fragment.app.FragmentTransaction add(Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.Fragment, String?);
+ method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+ method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment, String?);
+ method public androidx.fragment.app.FragmentTransaction addSharedElement(android.view.View, String);
+ method public androidx.fragment.app.FragmentTransaction addToBackStack(String?);
+ method public androidx.fragment.app.FragmentTransaction attach(androidx.fragment.app.Fragment);
+ method public abstract int commit();
+ method public abstract int commitAllowingStateLoss();
+ method public abstract void commitNow();
+ method public abstract void commitNowAllowingStateLoss();
+ method public androidx.fragment.app.FragmentTransaction detach(androidx.fragment.app.Fragment);
+ method public androidx.fragment.app.FragmentTransaction disallowAddToBackStack();
+ method public androidx.fragment.app.FragmentTransaction hide(androidx.fragment.app.Fragment);
+ method public boolean isAddToBackStackAllowed();
+ method public boolean isEmpty();
+ method public androidx.fragment.app.FragmentTransaction remove(androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+ method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment, String?);
+ method public androidx.fragment.app.FragmentTransaction runOnCommit(Runnable);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setAllowOptimization(boolean);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(@StringRes int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(CharSequence?);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(@StringRes int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(CharSequence?);
+ method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+ method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+ method public androidx.fragment.app.FragmentTransaction setMaxLifecycle(androidx.fragment.app.Fragment, androidx.lifecycle.Lifecycle.State);
+ method public androidx.fragment.app.FragmentTransaction setPrimaryNavigationFragment(androidx.fragment.app.Fragment?);
+ method public androidx.fragment.app.FragmentTransaction setReorderingAllowed(boolean);
+ method public androidx.fragment.app.FragmentTransaction setTransition(int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setTransitionStyle(@StyleRes int);
+ method public androidx.fragment.app.FragmentTransaction show(androidx.fragment.app.Fragment);
+ field public static final int TRANSIT_ENTER_MASK = 4096; // 0x1000
+ field public static final int TRANSIT_EXIT_MASK = 8192; // 0x2000
+ field public static final int TRANSIT_FRAGMENT_CLOSE = 8194; // 0x2002
+ field public static final int TRANSIT_FRAGMENT_FADE = 4099; // 0x1003
+ field public static final int TRANSIT_FRAGMENT_OPEN = 4097; // 0x1001
+ field public static final int TRANSIT_NONE = 0; // 0x0
+ field public static final int TRANSIT_UNSET = -1; // 0xffffffff
+ }
+
+ public class ListFragment extends androidx.fragment.app.Fragment {
+ ctor public ListFragment();
+ method public android.widget.ListAdapter? getListAdapter();
+ method public android.widget.ListView getListView();
+ method public long getSelectedItemId();
+ method public int getSelectedItemPosition();
+ method public void onListItemClick(android.widget.ListView, android.view.View, int, long);
+ method public final android.widget.ListAdapter requireListAdapter();
+ method public void setEmptyText(CharSequence?);
+ method public void setListAdapter(android.widget.ListAdapter?);
+ method public void setListShown(boolean);
+ method public void setListShownNoAnimation(boolean);
+ method public void setSelection(int);
+ }
+
+}
+
diff --git a/fragment/fragment/api/res-1.3.0-alpha06.txt b/fragment/fragment/api/res-1.3.0-alpha06.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment/api/res-1.3.0-alpha06.txt
diff --git a/fragment/fragment/api/restricted_1.3.0-alpha06.txt b/fragment/fragment/api/restricted_1.3.0-alpha06.txt
new file mode 100644
index 0000000..76caf91
--- /dev/null
+++ b/fragment/fragment/api/restricted_1.3.0-alpha06.txt
@@ -0,0 +1,474 @@
+// Signature format: 3.0
+package androidx.fragment.app {
+
+ public class DialogFragment extends androidx.fragment.app.Fragment implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
+ ctor public DialogFragment();
+ ctor public DialogFragment(@LayoutRes int);
+ method public void dismiss();
+ method public void dismissAllowingStateLoss();
+ method public android.app.Dialog? getDialog();
+ method public boolean getShowsDialog();
+ method @StyleRes public int getTheme();
+ method public boolean isCancelable();
+ method public void onCancel(android.content.DialogInterface);
+ method @MainThread public android.app.Dialog onCreateDialog(android.os.Bundle?);
+ method public void onDismiss(android.content.DialogInterface);
+ method public final android.app.Dialog requireDialog();
+ method public void setCancelable(boolean);
+ method public void setShowsDialog(boolean);
+ method public void setStyle(int, @StyleRes int);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setupDialog(android.app.Dialog, int);
+ method public void show(androidx.fragment.app.FragmentManager, String?);
+ method public int show(androidx.fragment.app.FragmentTransaction, String?);
+ method public void showNow(androidx.fragment.app.FragmentManager, String?);
+ field public static final int STYLE_NORMAL = 0; // 0x0
+ field public static final int STYLE_NO_FRAME = 2; // 0x2
+ field public static final int STYLE_NO_INPUT = 3; // 0x3
+ field public static final int STYLE_NO_TITLE = 1; // 0x1
+ }
+
+ public class Fragment implements androidx.activity.result.ActivityResultCaller android.content.ComponentCallbacks androidx.lifecycle.HasDefaultViewModelProviderFactory androidx.lifecycle.LifecycleOwner androidx.savedstate.SavedStateRegistryOwner android.view.View.OnCreateContextMenuListener androidx.lifecycle.ViewModelStoreOwner {
+ ctor public Fragment();
+ ctor @ContentView public Fragment(@LayoutRes int);
+ method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public final boolean equals(Object?);
+ method public final androidx.fragment.app.FragmentActivity? getActivity();
+ method public boolean getAllowEnterTransitionOverlap();
+ method public boolean getAllowReturnTransitionOverlap();
+ method public final android.os.Bundle? getArguments();
+ method public final androidx.fragment.app.FragmentManager getChildFragmentManager();
+ method public android.content.Context? getContext();
+ method public androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
+ method public Object? getEnterTransition();
+ method public Object? getExitTransition();
+ method @Deprecated public final androidx.fragment.app.FragmentManager? getFragmentManager();
+ method public final Object? getHost();
+ method public final int getId();
+ method public final android.view.LayoutInflater getLayoutInflater();
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public android.view.LayoutInflater getLayoutInflater(android.os.Bundle?);
+ method public androidx.lifecycle.Lifecycle getLifecycle();
+ method @Deprecated public androidx.loader.app.LoaderManager getLoaderManager();
+ method public final androidx.fragment.app.Fragment? getParentFragment();
+ method public final androidx.fragment.app.FragmentManager getParentFragmentManager();
+ method public Object? getReenterTransition();
+ method public final android.content.res.Resources getResources();
+ method @Deprecated public final boolean getRetainInstance();
+ method public Object? getReturnTransition();
+ method public final androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
+ method public Object? getSharedElementEnterTransition();
+ method public Object? getSharedElementReturnTransition();
+ method public final String getString(@StringRes int);
+ method public final String getString(@StringRes int, java.lang.Object!...);
+ method public final String? getTag();
+ method @Deprecated public final androidx.fragment.app.Fragment? getTargetFragment();
+ method @Deprecated public final int getTargetRequestCode();
+ method public final CharSequence getText(@StringRes int);
+ method @Deprecated public boolean getUserVisibleHint();
+ method public android.view.View? getView();
+ method @MainThread public androidx.lifecycle.LifecycleOwner getViewLifecycleOwner();
+ method public androidx.lifecycle.LiveData<androidx.lifecycle.LifecycleOwner!> getViewLifecycleOwnerLiveData();
+ method public androidx.lifecycle.ViewModelStore getViewModelStore();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final boolean hasOptionsMenu();
+ method public final int hashCode();
+ method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String);
+ method @Deprecated public static androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+ method public final boolean isAdded();
+ method public final boolean isDetached();
+ method public final boolean isHidden();
+ method public final boolean isInLayout();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final boolean isMenuVisible();
+ method public final boolean isRemoving();
+ method public final boolean isResumed();
+ method public final boolean isStateSaved();
+ method public final boolean isVisible();
+ method @Deprecated @CallSuper @MainThread public void onActivityCreated(android.os.Bundle?);
+ method @Deprecated public void onActivityResult(int, int, android.content.Intent?);
+ method @CallSuper @MainThread public void onAttach(android.content.Context);
+ method @Deprecated @CallSuper @MainThread public void onAttach(android.app.Activity);
+ method @MainThread public void onAttachFragment(androidx.fragment.app.Fragment);
+ method @CallSuper public void onConfigurationChanged(android.content.res.Configuration);
+ method @MainThread public boolean onContextItemSelected(android.view.MenuItem);
+ method @CallSuper @MainThread public void onCreate(android.os.Bundle?);
+ method @MainThread public android.view.animation.Animation? onCreateAnimation(int, boolean, int);
+ method @MainThread public android.animation.Animator? onCreateAnimator(int, boolean, int);
+ method @MainThread public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo?);
+ method @MainThread public void onCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method @MainThread public android.view.View? onCreateView(android.view.LayoutInflater, android.view.ViewGroup?, android.os.Bundle?);
+ method @CallSuper @MainThread public void onDestroy();
+ method @MainThread public void onDestroyOptionsMenu();
+ method @CallSuper @MainThread public void onDestroyView();
+ method @CallSuper @MainThread public void onDetach();
+ method public android.view.LayoutInflater onGetLayoutInflater(android.os.Bundle?);
+ method @MainThread public void onHiddenChanged(boolean);
+ method @CallSuper @UiThread public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle?);
+ method @Deprecated @CallSuper @UiThread public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle?);
+ method @CallSuper @MainThread public void onLowMemory();
+ method public void onMultiWindowModeChanged(boolean);
+ method @MainThread public boolean onOptionsItemSelected(android.view.MenuItem);
+ method @MainThread public void onOptionsMenuClosed(android.view.Menu);
+ method @CallSuper @MainThread public void onPause();
+ method public void onPictureInPictureModeChanged(boolean);
+ method @MainThread public void onPrepareOptionsMenu(android.view.Menu);
+ method @MainThread public void onPrimaryNavigationFragmentChanged(boolean);
+ method @Deprecated public void onRequestPermissionsResult(int, String![], int[]);
+ method @CallSuper @MainThread public void onResume();
+ method @MainThread public void onSaveInstanceState(android.os.Bundle);
+ method @CallSuper @MainThread public void onStart();
+ method @CallSuper @MainThread public void onStop();
+ method @MainThread public void onViewCreated(android.view.View, android.os.Bundle?);
+ method @CallSuper @MainThread public void onViewStateRestored(android.os.Bundle?);
+ method public void postponeEnterTransition();
+ method public final void postponeEnterTransition(long, java.util.concurrent.TimeUnit);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultCallback<O!>);
+ method public final <I, O> androidx.activity.result.ActivityResultLauncher<I!> registerForActivityResult(androidx.activity.result.contract.ActivityResultContract<I!,O!>, androidx.activity.result.ActivityResultRegistry, androidx.activity.result.ActivityResultCallback<O!>);
+ method public void registerForContextMenu(android.view.View);
+ method @Deprecated public final void requestPermissions(String![], int);
+ method public final androidx.fragment.app.FragmentActivity requireActivity();
+ method public final android.os.Bundle requireArguments();
+ method public final android.content.Context requireContext();
+ method @Deprecated public final androidx.fragment.app.FragmentManager requireFragmentManager();
+ method public final Object requireHost();
+ method public final androidx.fragment.app.Fragment requireParentFragment();
+ method public final android.view.View requireView();
+ method public void setAllowEnterTransitionOverlap(boolean);
+ method public void setAllowReturnTransitionOverlap(boolean);
+ method public void setArguments(android.os.Bundle?);
+ method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setEnterTransition(Object?);
+ method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setExitTransition(Object?);
+ method public void setHasOptionsMenu(boolean);
+ method public void setInitialSavedState(androidx.fragment.app.Fragment.SavedState?);
+ method public void setMenuVisibility(boolean);
+ method public void setReenterTransition(Object?);
+ method @Deprecated public void setRetainInstance(boolean);
+ method public void setReturnTransition(Object?);
+ method public void setSharedElementEnterTransition(Object?);
+ method public void setSharedElementReturnTransition(Object?);
+ method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
+ method @Deprecated public void setUserVisibleHint(boolean);
+ method public boolean shouldShowRequestPermissionRationale(String);
+ method public void startActivity(android.content.Intent!);
+ method public void startActivity(android.content.Intent!, android.os.Bundle?);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int);
+ method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void startPostponedEnterTransition();
+ method public void unregisterForContextMenu(android.view.View);
+ }
+
+ public static class Fragment.InstantiationException extends java.lang.RuntimeException {
+ ctor public Fragment.InstantiationException(String, Exception?);
+ }
+
+ public static class Fragment.SavedState implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<androidx.fragment.app.Fragment.SavedState!> CREATOR;
+ }
+
+ public class FragmentActivity extends androidx.activity.ComponentActivity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback androidx.core.app.ActivityCompat.RequestPermissionsRequestCodeValidator {
+ ctor public FragmentActivity();
+ ctor @ContentView public FragmentActivity(@LayoutRes int);
+ method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+ method @Deprecated public androidx.loader.app.LoaderManager getSupportLoaderManager();
+ method public void onAttachFragment(androidx.fragment.app.Fragment);
+ method @CallSuper public void onMultiWindowModeChanged(boolean);
+ method @CallSuper public void onPictureInPictureModeChanged(boolean);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) protected boolean onPrepareOptionsPanel(android.view.View?, android.view.Menu);
+ method protected void onResumeFragments();
+ method public void onStateNotSaved();
+ method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
+ method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
+ method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void supportFinishAfterTransition();
+ method @Deprecated public void supportInvalidateOptionsMenu();
+ method public void supportPostponeEnterTransition();
+ method public void supportStartPostponedEnterTransition();
+ method @Deprecated public final void validateRequestPermissionsRequestCode(int);
+ }
+
+ public abstract class FragmentContainer {
+ ctor public FragmentContainer();
+ method @Deprecated public androidx.fragment.app.Fragment instantiate(android.content.Context, String, android.os.Bundle?);
+ method public abstract android.view.View? onFindViewById(@IdRes int);
+ method public abstract boolean onHasView();
+ }
+
+ public final class FragmentContainerView extends android.widget.FrameLayout {
+ ctor public FragmentContainerView(android.content.Context);
+ ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?);
+ ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?, int);
+ }
+
+ public class FragmentController {
+ method public void attachHost(androidx.fragment.app.Fragment?);
+ method public static androidx.fragment.app.FragmentController createController(androidx.fragment.app.FragmentHostCallback<?>);
+ method public void dispatchActivityCreated();
+ method public void dispatchConfigurationChanged(android.content.res.Configuration);
+ method public boolean dispatchContextItemSelected(android.view.MenuItem);
+ method public void dispatchCreate();
+ method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method public void dispatchDestroy();
+ method public void dispatchDestroyView();
+ method public void dispatchLowMemory();
+ method public void dispatchMultiWindowModeChanged(boolean);
+ method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+ method public void dispatchOptionsMenuClosed(android.view.Menu);
+ method public void dispatchPause();
+ method public void dispatchPictureInPictureModeChanged(boolean);
+ method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+ method @Deprecated public void dispatchReallyStop();
+ method public void dispatchResume();
+ method public void dispatchStart();
+ method public void dispatchStop();
+ method @Deprecated public void doLoaderDestroy();
+ method @Deprecated public void doLoaderRetain();
+ method @Deprecated public void doLoaderStart();
+ method @Deprecated public void doLoaderStop(boolean);
+ method @Deprecated public void dumpLoaders(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public boolean execPendingActions();
+ method public androidx.fragment.app.Fragment? findFragmentByWho(String);
+ method public java.util.List<androidx.fragment.app.Fragment!> getActiveFragments(java.util.List<androidx.fragment.app.Fragment!>!);
+ method public int getActiveFragmentsCount();
+ method public androidx.fragment.app.FragmentManager getSupportFragmentManager();
+ method @Deprecated public androidx.loader.app.LoaderManager! getSupportLoaderManager();
+ method public void noteStateNotSaved();
+ method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
+ method @Deprecated public void reportLoaderStart();
+ method @Deprecated public void restoreAllState(android.os.Parcelable?, java.util.List<androidx.fragment.app.Fragment!>?);
+ method @Deprecated public void restoreAllState(android.os.Parcelable?, androidx.fragment.app.FragmentManagerNonConfig?);
+ method @Deprecated public void restoreLoaderNonConfig(androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>!);
+ method public void restoreSaveState(android.os.Parcelable?);
+ method @Deprecated public androidx.collection.SimpleArrayMap<java.lang.String!,androidx.loader.app.LoaderManager!>? retainLoaderNonConfig();
+ method @Deprecated public androidx.fragment.app.FragmentManagerNonConfig? retainNestedNonConfig();
+ method @Deprecated public java.util.List<androidx.fragment.app.Fragment!>? retainNonConfig();
+ method public android.os.Parcelable? saveAllState();
+ }
+
+ public class FragmentFactory {
+ ctor public FragmentFactory();
+ method public androidx.fragment.app.Fragment instantiate(ClassLoader, String);
+ method public static Class<? extends androidx.fragment.app.Fragment> loadFragmentClass(ClassLoader, String);
+ }
+
+ public abstract class FragmentHostCallback<E> extends androidx.fragment.app.FragmentContainer {
+ ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+ method public void onDump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method public android.view.View? onFindViewById(int);
+ method public abstract E? onGetHost();
+ method public android.view.LayoutInflater onGetLayoutInflater();
+ method public int onGetWindowAnimations();
+ method public boolean onHasView();
+ method public boolean onHasWindowAnimations();
+ method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
+ method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
+ method public boolean onShouldShowRequestPermissionRationale(String);
+ method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
+ method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
+ method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+ method public void onSupportInvalidateOptionsMenu();
+ }
+
+ public abstract class FragmentManager implements androidx.fragment.app.FragmentResultOwner {
+ ctor public FragmentManager();
+ method public void addOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+ method public androidx.fragment.app.FragmentTransaction beginTransaction();
+ method public final void clearFragmentResult(String);
+ method public final void clearFragmentResultListener(String);
+ method public void dump(String, java.io.FileDescriptor?, java.io.PrintWriter, String![]?);
+ method @Deprecated public static void enableDebugLogging(boolean);
+ method public boolean executePendingTransactions();
+ method public static <F extends androidx.fragment.app.Fragment> F findFragment(android.view.View);
+ method public androidx.fragment.app.Fragment? findFragmentById(@IdRes int);
+ method public androidx.fragment.app.Fragment? findFragmentByTag(String?);
+ method public androidx.fragment.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
+ method public int getBackStackEntryCount();
+ method public androidx.fragment.app.Fragment? getFragment(android.os.Bundle, String);
+ method public androidx.fragment.app.FragmentFactory getFragmentFactory();
+ method public java.util.List<androidx.fragment.app.Fragment!> getFragments();
+ method public androidx.fragment.app.Fragment? getPrimaryNavigationFragment();
+ method public boolean isDestroyed();
+ method public boolean isStateSaved();
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public androidx.fragment.app.FragmentTransaction openTransaction();
+ method public void popBackStack();
+ method public void popBackStack(String?, int);
+ method public void popBackStack(int, int);
+ method public boolean popBackStackImmediate();
+ method public boolean popBackStackImmediate(String?, int);
+ method public boolean popBackStackImmediate(int, int);
+ method public void putFragment(android.os.Bundle, String, androidx.fragment.app.Fragment);
+ method public void registerFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks, boolean);
+ method public void removeOnBackStackChangedListener(androidx.fragment.app.FragmentManager.OnBackStackChangedListener);
+ method public androidx.fragment.app.Fragment.SavedState? saveFragmentInstanceState(androidx.fragment.app.Fragment);
+ method public void setFragmentFactory(androidx.fragment.app.FragmentFactory);
+ method public final void setFragmentResult(String, android.os.Bundle);
+ method public final void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+ method public void unregisterFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks);
+ field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1
+ }
+
+ public static interface FragmentManager.BackStackEntry {
+ method @Deprecated public CharSequence? getBreadCrumbShortTitle();
+ method @Deprecated @StringRes public int getBreadCrumbShortTitleRes();
+ method @Deprecated public CharSequence? getBreadCrumbTitle();
+ method @Deprecated @StringRes public int getBreadCrumbTitleRes();
+ method public int getId();
+ method public String? getName();
+ }
+
+ public abstract static class FragmentManager.FragmentLifecycleCallbacks {
+ ctor public FragmentManager.FragmentLifecycleCallbacks();
+ method @Deprecated public void onFragmentActivityCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+ method public void onFragmentCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentDetached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentPaused(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentPreAttached(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.content.Context);
+ method public void onFragmentPreCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?);
+ method public void onFragmentResumed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentSaveInstanceState(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle);
+ method public void onFragmentStarted(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentStopped(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ method public void onFragmentViewCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.view.View, android.os.Bundle?);
+ method public void onFragmentViewDestroyed(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment);
+ }
+
+ public static interface FragmentManager.OnBackStackChangedListener {
+ method @MainThread public void onBackStackChanged();
+ }
+
+ @Deprecated public class FragmentManagerNonConfig {
+ }
+
+ @Deprecated public abstract class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+ ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager);
+ ctor @Deprecated public FragmentPagerAdapter(androidx.fragment.app.FragmentManager, int);
+ method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+ method @Deprecated public long getItemId(int);
+ method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+ field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+ }
+
+ public interface FragmentResultListener {
+ method public void onFragmentResult(String, android.os.Bundle);
+ }
+
+ public interface FragmentResultOwner {
+ method public void clearFragmentResult(String);
+ method public void clearFragmentResultListener(String);
+ method public void setFragmentResult(String, android.os.Bundle);
+ method public void setFragmentResultListener(String, androidx.lifecycle.LifecycleOwner, androidx.fragment.app.FragmentResultListener);
+ }
+
+ @Deprecated public abstract class FragmentStatePagerAdapter extends androidx.viewpager.widget.PagerAdapter {
+ ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager);
+ ctor @Deprecated public FragmentStatePagerAdapter(androidx.fragment.app.FragmentManager, int);
+ method @Deprecated public abstract androidx.fragment.app.Fragment getItem(int);
+ method @Deprecated public boolean isViewFromObject(android.view.View, Object);
+ field @Deprecated public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1; // 0x1
+ field @Deprecated public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0; // 0x0
+ }
+
+ @Deprecated public class FragmentTabHost extends android.widget.TabHost implements android.widget.TabHost.OnTabChangeListener {
+ ctor @Deprecated public FragmentTabHost(android.content.Context);
+ ctor @Deprecated public FragmentTabHost(android.content.Context, android.util.AttributeSet?);
+ method @Deprecated public void addTab(android.widget.TabHost.TabSpec, Class<?>, android.os.Bundle?);
+ method @Deprecated public void onTabChanged(String?);
+ method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager);
+ method @Deprecated public void setup(android.content.Context, androidx.fragment.app.FragmentManager, int);
+ }
+
+ public abstract class FragmentTransaction {
+ ctor @Deprecated public FragmentTransaction();
+ method public final androidx.fragment.app.FragmentTransaction add(Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction add(androidx.fragment.app.Fragment, String?);
+ method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+ method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction add(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction add(@IdRes int, androidx.fragment.app.Fragment, String?);
+ method public androidx.fragment.app.FragmentTransaction addSharedElement(android.view.View, String);
+ method public androidx.fragment.app.FragmentTransaction addToBackStack(String?);
+ method public androidx.fragment.app.FragmentTransaction attach(androidx.fragment.app.Fragment);
+ method public abstract int commit();
+ method public abstract int commitAllowingStateLoss();
+ method public abstract void commitNow();
+ method public abstract void commitNowAllowingStateLoss();
+ method public androidx.fragment.app.FragmentTransaction detach(androidx.fragment.app.Fragment);
+ method public androidx.fragment.app.FragmentTransaction disallowAddToBackStack();
+ method public androidx.fragment.app.FragmentTransaction hide(androidx.fragment.app.Fragment);
+ method public boolean isAddToBackStackAllowed();
+ method public boolean isEmpty();
+ method public androidx.fragment.app.FragmentTransaction remove(androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?);
+ method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment);
+ method public final androidx.fragment.app.FragmentTransaction replace(@IdRes int, Class<? extends androidx.fragment.app.Fragment>, android.os.Bundle?, String?);
+ method public androidx.fragment.app.FragmentTransaction replace(@IdRes int, androidx.fragment.app.Fragment, String?);
+ method public androidx.fragment.app.FragmentTransaction runOnCommit(Runnable);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setAllowOptimization(boolean);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(@StringRes int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbShortTitle(CharSequence?);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(@StringRes int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setBreadCrumbTitle(CharSequence?);
+ method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+ method public androidx.fragment.app.FragmentTransaction setCustomAnimations(@AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int, @AnimRes @AnimatorRes int);
+ method public androidx.fragment.app.FragmentTransaction setMaxLifecycle(androidx.fragment.app.Fragment, androidx.lifecycle.Lifecycle.State);
+ method public androidx.fragment.app.FragmentTransaction setPrimaryNavigationFragment(androidx.fragment.app.Fragment?);
+ method public androidx.fragment.app.FragmentTransaction setReorderingAllowed(boolean);
+ method public androidx.fragment.app.FragmentTransaction setTransition(int);
+ method @Deprecated public androidx.fragment.app.FragmentTransaction setTransitionStyle(@StyleRes int);
+ method public androidx.fragment.app.FragmentTransaction show(androidx.fragment.app.Fragment);
+ field public static final int TRANSIT_ENTER_MASK = 4096; // 0x1000
+ field public static final int TRANSIT_EXIT_MASK = 8192; // 0x2000
+ field public static final int TRANSIT_FRAGMENT_CLOSE = 8194; // 0x2002
+ field public static final int TRANSIT_FRAGMENT_FADE = 4099; // 0x1003
+ field public static final int TRANSIT_FRAGMENT_OPEN = 4097; // 0x1001
+ field public static final int TRANSIT_NONE = 0; // 0x0
+ field public static final int TRANSIT_UNSET = -1; // 0xffffffff
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class FragmentTransitionImpl {
+ ctor public FragmentTransitionImpl();
+ method public abstract void addTarget(Object!, android.view.View!);
+ method public abstract void addTargets(Object!, java.util.ArrayList<android.view.View!>!);
+ method public abstract void beginDelayedTransition(android.view.ViewGroup!, Object!);
+ method protected static void bfsAddViewChildren(java.util.List<android.view.View!>!, android.view.View!);
+ method public abstract boolean canHandle(Object!);
+ method public abstract Object! cloneTransition(Object!);
+ method protected void getBoundsOnScreen(android.view.View!, android.graphics.Rect!);
+ method protected static boolean isNullOrEmpty(java.util.List!);
+ method public abstract Object! mergeTransitionsInSequence(Object!, Object!, Object!);
+ method public abstract Object! mergeTransitionsTogether(Object!, Object!, Object!);
+ method public abstract void removeTarget(Object!, android.view.View!);
+ method public abstract void replaceTargets(Object!, java.util.ArrayList<android.view.View!>!, java.util.ArrayList<android.view.View!>!);
+ method public abstract void scheduleHideFragmentView(Object!, android.view.View!, java.util.ArrayList<android.view.View!>!);
+ method public abstract void scheduleRemoveTargets(Object!, Object!, java.util.ArrayList<android.view.View!>!, Object!, java.util.ArrayList<android.view.View!>!, Object!, java.util.ArrayList<android.view.View!>!);
+ method public abstract void setEpicenter(Object!, android.view.View!);
+ method public abstract void setEpicenter(Object!, android.graphics.Rect!);
+ method public void setListenerForTransitionEnd(androidx.fragment.app.Fragment, Object, androidx.core.os.CancellationSignal, Runnable);
+ method public abstract void setSharedElementTargets(Object!, android.view.View!, java.util.ArrayList<android.view.View!>!);
+ method public abstract void swapSharedElementTargets(Object!, java.util.ArrayList<android.view.View!>!, java.util.ArrayList<android.view.View!>!);
+ method public abstract Object! wrapTransitionInSet(Object!);
+ }
+
+ public class ListFragment extends androidx.fragment.app.Fragment {
+ ctor public ListFragment();
+ method public android.widget.ListAdapter? getListAdapter();
+ method public android.widget.ListView getListView();
+ method public long getSelectedItemId();
+ method public int getSelectedItemPosition();
+ method public void onListItemClick(android.widget.ListView, android.view.View, int, long);
+ method public final android.widget.ListAdapter requireListAdapter();
+ method public void setEmptyText(CharSequence?);
+ method public void setListAdapter(android.widget.ListAdapter?);
+ method public void setListShown(boolean);
+ method public void setListShownNoAnimation(boolean);
+ method public void setSelection(int);
+ }
+
+}
+
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt
index fd65a6f..5dfdb3d 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentReceiveResultTest.kt
@@ -22,6 +22,7 @@
import androidx.fragment.app.test.FragmentResultActivity
import androidx.fragment.app.test.FragmentTestActivity
import androidx.fragment.test.R
+import androidx.test.annotation.UiThreadTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
@@ -56,7 +57,10 @@
@Suppress("DEPRECATION")
@Test
+ @UiThreadTest
fun testNoFragmentOnActivityResult() {
+ activity.supportFragmentManager.saveAllState()
+
// 0xffff is the request code for the startActivityResult launcher in FragmentManager
activity.onActivityResult(0xffff, Activity.RESULT_OK, Intent())
}
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/test/FragmentTestActivity.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/test/FragmentTestActivity.kt
index 83c45c1..597ee6a 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/test/FragmentTestActivity.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/test/FragmentTestActivity.kt
@@ -38,6 +38,8 @@
@Suppress("DEPRECATION")
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
+ supportFragmentManager.beginTransaction()
+ .commitNow()
}
class ParentFragment : Fragment() {
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
index 6d8ff8c..194c9eb 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
@@ -119,6 +119,15 @@
// HOOKS INTO ACTIVITY
// ------------------------------------------------------------------------
+ @SuppressWarnings("deprecation")
+ @Override
+ @CallSuper
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ mFragments.noteStateNotSaved();
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+
/**
* Reverses the Activity Scene entry Transition and triggers the calling Activity
* to reverse its exit Transition. When the exit Transition completes,
@@ -561,6 +570,15 @@
@Deprecated
public final void validateRequestPermissionsRequestCode(int requestCode) { }
+ @SuppressWarnings("deprecation")
+ @CallSuper
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+ mFragments.noteStateNotSaved();
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+
/**
* Called by Fragment.startActivityForResult() to implement its behavior.
*
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index c06c661..da3933b 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -2768,7 +2768,6 @@
+ fragmentWho);
return;
}
- noteStateNotSaved();
fragment.onActivityResult(requestCode, result.getResultCode(),
result.getData());
}
@@ -2797,7 +2796,6 @@
+ fragmentWho);
return;
}
- noteStateNotSaved();
fragment.onActivityResult(requestCode, result.getResultCode(),
result.getData());
}
@@ -2833,7 +2831,6 @@
+ "Fragment " + fragmentWho);
return;
}
- noteStateNotSaved();
fragment.onRequestPermissionsResult(requestCode, permissions,
grantResults);
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 3a0fdf2..820c319 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -5,4 +5,4 @@
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=../../../../tools/external/gradle/gradle-6.3-bin.zip
+distributionUrl=../../../../tools/external/gradle/gradle-6.4-bin.zip
diff --git a/leanback/leanback/api/api_lint.ignore b/leanback/leanback/api/api_lint.ignore
index 32f2b54..1eea158 100644
--- a/leanback/leanback/api/api_lint.ignore
+++ b/leanback/leanback/api/api_lint.ignore
@@ -53,12 +53,18 @@
Must avoid boxed primitives (`java.lang.Number`)
-CallbackMethodName: androidx.leanback.widget.DiffCallback:
- Callback method names must follow the on<Something> style: areItemsTheSame
-CallbackMethodName: androidx.leanback.widget.GuidedActionDiffCallback:
- Callback method names must follow the on<Something> style: getInstance
-CallbackMethodName: androidx.leanback.widget.SearchBar.SearchBarPermissionListener:
- Listener method names must follow the on<Something> style: requestAudioPermission
+BuilderSetStyle: androidx.leanback.widget.ShadowOverlayHelper.Builder#keepForegroundDrawable(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.leanback.widget.ShadowOverlayHelper.Builder.keepForegroundDrawable(boolean)
+BuilderSetStyle: androidx.leanback.widget.ShadowOverlayHelper.Builder#needsOverlay(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.leanback.widget.ShadowOverlayHelper.Builder.needsOverlay(boolean)
+BuilderSetStyle: androidx.leanback.widget.ShadowOverlayHelper.Builder#needsRoundedCorner(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.leanback.widget.ShadowOverlayHelper.Builder.needsRoundedCorner(boolean)
+BuilderSetStyle: androidx.leanback.widget.ShadowOverlayHelper.Builder#needsShadow(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.leanback.widget.ShadowOverlayHelper.Builder.needsShadow(boolean)
+BuilderSetStyle: androidx.leanback.widget.ShadowOverlayHelper.Builder#options(androidx.leanback.widget.ShadowOverlayHelper.Options):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.leanback.widget.ShadowOverlayHelper.Builder.options(androidx.leanback.widget.ShadowOverlayHelper.Options)
+BuilderSetStyle: androidx.leanback.widget.ShadowOverlayHelper.Builder#preferZOrder(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.leanback.widget.ShadowOverlayHelper.Builder.preferZOrder(boolean)
CallbackName: androidx.leanback.widget.ObjectAdapter.DataObserver:
diff --git a/media/media/api/api_lint.ignore b/media/media/api/api_lint.ignore
index 6e997641..fe4b00a 100644
--- a/media/media/api/api_lint.ignore
+++ b/media/media/api/api_lint.ignore
@@ -21,8 +21,16 @@
Inconsistent extra value; expected `androidx.media.extra.SUGGESTED`, was `android.service.media.extra.SUGGESTED`
-CallbackMethodName: android.support.v4.media.session.MediaControllerCompat.Callback:
- Callback method names must follow the on<Something> style: binderDied
+BuilderSetStyle: android.support.v4.media.MediaMetadataCompat.Builder#putBitmap(String, android.graphics.Bitmap):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.support.v4.media.MediaMetadataCompat.Builder.putBitmap(String,android.graphics.Bitmap)
+BuilderSetStyle: android.support.v4.media.MediaMetadataCompat.Builder#putLong(String, long):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.support.v4.media.MediaMetadataCompat.Builder.putLong(String,long)
+BuilderSetStyle: android.support.v4.media.MediaMetadataCompat.Builder#putRating(String, android.support.v4.media.RatingCompat):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.support.v4.media.MediaMetadataCompat.Builder.putRating(String,android.support.v4.media.RatingCompat)
+BuilderSetStyle: android.support.v4.media.MediaMetadataCompat.Builder#putString(String, String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.support.v4.media.MediaMetadataCompat.Builder.putString(String,String)
+BuilderSetStyle: android.support.v4.media.MediaMetadataCompat.Builder#putText(String, CharSequence):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.support.v4.media.MediaMetadataCompat.Builder.putText(String,CharSequence)
ContextNameSuffix: androidx.media.MediaBrowserServiceCompat:
diff --git a/media2/common/api/api_lint.ignore b/media2/common/api/api_lint.ignore
index 35e4147..d2bb9aa 100644
--- a/media2/common/api/api_lint.ignore
+++ b/media2/common/api/api_lint.ignore
@@ -1,6 +1,16 @@
// Baseline format: 1.0
-CallbackMethodName: androidx.media2.common.DataSourceCallback:
- Callback method names must follow the on<Something> style: readAt
+BuilderSetStyle: androidx.media2.common.MediaMetadata.Builder#putBitmap(String, android.graphics.Bitmap):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putBitmap(String,android.graphics.Bitmap)
+BuilderSetStyle: androidx.media2.common.MediaMetadata.Builder#putFloat(String, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putFloat(String,float)
+BuilderSetStyle: androidx.media2.common.MediaMetadata.Builder#putLong(String, long):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putLong(String,long)
+BuilderSetStyle: androidx.media2.common.MediaMetadata.Builder#putRating(String, androidx.media2.common.Rating):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putRating(String,androidx.media2.common.Rating)
+BuilderSetStyle: androidx.media2.common.MediaMetadata.Builder#putString(String, String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putString(String,String)
+BuilderSetStyle: androidx.media2.common.MediaMetadata.Builder#putText(String, CharSequence):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putText(String,CharSequence)
GenericException: androidx.media2.common.SessionPlayer#close():
diff --git a/media2/session/api/api_lint.ignore b/media2/session/api/api_lint.ignore
index ac1c632..9ae568a 100644
--- a/media2/session/api/api_lint.ignore
+++ b/media2/session/api/api_lint.ignore
@@ -5,6 +5,10 @@
Use ListenableFuture (library), or a combination of Consumer<T>, Executor, and CancellationSignal (platform) instead of java.util.concurrent.Future (method androidx.media2.session.RemoteSessionPlayer.setVolume(int))
+BuilderSetStyle: androidx.media2.session.SessionCommandGroup.Builder#removeCommand(androidx.media2.session.SessionCommand):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.session.SessionCommandGroup.Builder.removeCommand(androidx.media2.session.SessionCommand)
+
+
MissingNullability: androidx.media2.session.MediaLibraryService#onBind(android.content.Intent):
Missing nullability on method `onBind` return
MissingNullability: androidx.media2.session.MediaSessionService#onStartCommand(android.content.Intent, int, int) parameter #0:
diff --git a/navigation/navigation-common-ktx/api/api_lint.ignore b/navigation/navigation-common-ktx/api/api_lint.ignore
index 6ba701d..82360c9 100644
--- a/navigation/navigation-common-ktx/api/api_lint.ignore
+++ b/navigation/navigation-common-ktx/api/api_lint.ignore
@@ -1,4 +1,20 @@
// Baseline format: 1.0
+BuilderSetStyle: androidx.navigation.NavActionBuilder#navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavActionBuilder.navOptions(kotlin.jvm.functions.Function1<? super androidx.navigation.NavOptionsBuilder,kotlin.Unit>)
+BuilderSetStyle: androidx.navigation.NavDestinationBuilder#action(int, kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDestinationBuilder.action(int,kotlin.jvm.functions.Function1<? super androidx.navigation.NavActionBuilder,kotlin.Unit>)
+BuilderSetStyle: androidx.navigation.NavDestinationBuilder#argument(String, kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDestinationBuilder.argument(String,kotlin.jvm.functions.Function1<? super androidx.navigation.NavArgumentBuilder,kotlin.Unit>)
+BuilderSetStyle: androidx.navigation.NavDestinationBuilder#deepLink(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDestinationBuilder.deepLink(String)
+BuilderSetStyle: androidx.navigation.NavDestinationBuilder#deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDestinationBuilder.deepLink(kotlin.jvm.functions.Function1<? super androidx.navigation.NavDeepLinkDslBuilder,kotlin.Unit>)
+BuilderSetStyle: androidx.navigation.NavOptionsBuilder#anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavOptionsBuilder.anim(kotlin.jvm.functions.Function1<? super androidx.navigation.AnimBuilder,kotlin.Unit>)
+BuilderSetStyle: androidx.navigation.NavOptionsBuilder#popUpTo(int, kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavOptionsBuilder.popUpTo(int,kotlin.jvm.functions.Function1<? super androidx.navigation.PopUpToBuilder,kotlin.Unit>)
+
+
DocumentExceptions: androidx.navigation.NavArgumentBuilder#getType():
Method NavArgumentBuilder.getType appears to be throwing java.lang.IllegalStateException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions
DocumentExceptions: androidx.navigation.NavGraphBuilder#build():
diff --git a/navigation/navigation-common/api/api_lint.ignore b/navigation/navigation-common/api/api_lint.ignore
index 9c1799e7..50d8eb6 100644
--- a/navigation/navigation-common/api/api_lint.ignore
+++ b/navigation/navigation-common/api/api_lint.ignore
@@ -13,5 +13,19 @@
Method parameter should be Collection<D> (or subclass) instead of raw array; was `D[]`
+BuilderSetStyle: androidx.navigation.NavDeepLink.Builder#fromAction(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLink.Builder.fromAction(String)
+BuilderSetStyle: androidx.navigation.NavDeepLink.Builder#fromMimeType(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLink.Builder.fromMimeType(String)
+BuilderSetStyle: androidx.navigation.NavDeepLink.Builder#fromUriPattern(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLink.Builder.fromUriPattern(String)
+BuilderSetStyle: androidx.navigation.NavDeepLinkRequest.Builder#fromAction(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLinkRequest.Builder.fromAction(String)
+BuilderSetStyle: androidx.navigation.NavDeepLinkRequest.Builder#fromMimeType(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLinkRequest.Builder.fromMimeType(String)
+BuilderSetStyle: androidx.navigation.NavDeepLinkRequest.Builder#fromUri(android.net.Uri):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLinkRequest.Builder.fromUri(android.net.Uri)
+
+
KotlinOperator: androidx.navigation.NavType#get(android.os.Bundle, String):
Method can be invoked with an indexing operator from Kotlin: `get` (this is usually desirable; just make sure it makes sense for this type of object)
diff --git a/navigation/navigation-fragment/src/androidTest/AndroidManifest.xml b/navigation/navigation-fragment/src/androidTest/AndroidManifest.xml
index d40a782..c51701b 100644
--- a/navigation/navigation-fragment/src/androidTest/AndroidManifest.xml
+++ b/navigation/navigation-fragment/src/androidTest/AndroidManifest.xml
@@ -21,6 +21,7 @@
<activity android:name="androidx.navigation.fragment.test.NavigationActivity"/>
<activity
android:name="androidx.navigation.fragment.test.NavigationActivityWithFragmentTag"/>
+ <activity android:name="androidx.navigation.fragment.test.NavigationActivityMultiNavHost"/>
<activity android:name="androidx.navigation.fragment.XmlNavigationActivity" />
<activity android:name="androidx.navigation.fragment.DynamicNavigationActivity" />
<activity android:name="androidx.navigation.fragment.EmbeddedXmlActivity" />
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/MultiNavHostFragmentTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/MultiNavHostFragmentTest.kt
new file mode 100644
index 0000000..c895377
--- /dev/null
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/MultiNavHostFragmentTest.kt
@@ -0,0 +1,142 @@
+/*
+ * 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.navigation.fragment
+
+import android.os.Bundle
+import androidx.navigation.findNavController
+import androidx.navigation.fragment.test.NavigationActivityMultiNavHost
+import androidx.navigation.fragment.test.R
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class MultiNavHostFragmentTest {
+
+ @Test
+ fun testFragmentToNavHost() {
+ with(ActivityScenario.launch(NavigationActivityMultiNavHost::class.java)) {
+ val navController = withActivity {
+ findNavController(R.id.nav_host_fragment)
+ }
+
+ navController.setGraph(R.navigation.nav_nav_host)
+ navController.navigate(R.id.nav_host_1)
+
+ val rootNavController = withActivity {
+ val navHostFragment = supportFragmentManager
+ .findFragmentById(R.id.nav_host_fragment)!!
+ navHostFragment.requireView().findNavController()
+ }
+ assertWithMessage("Child should have changed the NavController")
+ .that(rootNavController)
+ .isNotEqualTo(navController)
+ }
+ }
+
+ @Test
+ fun testNavHostToFragment() {
+ with(ActivityScenario.launch(NavigationActivityMultiNavHost::class.java)) {
+ val navController = withActivity {
+ findNavController(R.id.nav_host_fragment)
+ }
+
+ navController.setGraph(R.navigation.nav_nav_host)
+ navController.navigate(R.id.nav_host_1)
+
+ val childFragment = withActivity {
+ supportFragmentManager.findFragmentById(R.id.nav_host_fragment)
+ ?.childFragmentManager?.findFragmentById(R.id.nav_host_fragment) as
+ BasicNavHostFragment
+ }
+
+ navController.popBackStack()
+
+ val returnNavController = withActivity {
+ val navHostFragment =
+ supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
+ navHostFragment.requireView().findNavController()
+ }
+
+ assertThat(childFragment.destroyViewCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
+ .isTrue()
+
+ assertWithMessage("NavController should not have changed")
+ .that(returnNavController)
+ .isSameInstanceAs(navController)
+ }
+ }
+
+ @Test
+ fun testNavHostToNavHost() {
+ with(ActivityScenario.launch(NavigationActivityMultiNavHost::class.java)) {
+ val navController = withActivity {
+ findNavController(R.id.nav_host_fragment)
+ }
+
+ navController.setGraph(R.navigation.nav_nav_host)
+ navController.navigate(R.id.nav_host_1)
+
+ val firstChildNavController = withActivity {
+ val navHostFragment =
+ supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
+ navHostFragment.requireView().findNavController()
+ }
+ assertWithMessage("child should have changed the NavController")
+ .that(firstChildNavController)
+ .isNotEqualTo(navController)
+
+ navController.navigate(R.id.nav_host_2)
+
+ val secondChildNavController = withActivity {
+ val navHostFragment =
+ supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
+ navHostFragment.requireView().findNavController()
+ }
+
+ assertWithMessage("Second child should have changed the NavController")
+ .that(secondChildNavController)
+ .isNotEqualTo(firstChildNavController)
+
+ assertWithMessage("the second child navHost should be different from the parent")
+ .that(secondChildNavController)
+ .isNotEqualTo(navController)
+ }
+ }
+}
+
+class BasicNavHostFragment : NavHostFragment() {
+ val destroyViewCountDownLatch = CountDownLatch(1)
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ navController.setGraph(R.navigation.nav_nav_host)
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ destroyViewCountDownLatch.countDown()
+ }
+}
\ No newline at end of file
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/test/NavigationActivity.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/test/NavigationActivity.kt
index 460f906..a4de7e6 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/test/NavigationActivity.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/test/NavigationActivity.kt
@@ -26,6 +26,8 @@
R.layout.navigation_activity_fragment_tag
)
+class NavigationActivityMultiNavHost : NavigationBaseActivity(R.layout.navigation_activity_nav_host)
+
open class NavigationBaseActivity(contentLayoutId: Int) : FragmentActivity(contentLayoutId) {
val navController get() = findNavController(R.id.nav_host)
diff --git a/navigation/navigation-fragment/src/androidTest/res/layout/navigation_activity_nav_host.xml b/navigation/navigation-fragment/src/androidTest/res/layout/navigation_activity_nav_host.xml
new file mode 100644
index 0000000..ef4772d
--- /dev/null
+++ b/navigation/navigation-fragment/src/androidTest/res/layout/navigation_activity_nav_host.xml
@@ -0,0 +1,27 @@
+<?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.
+ -->
+
+<androidx.fragment.app.FragmentContainerView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/nav_host_fragment"
+ android:name="androidx.navigation.fragment.NavHostFragment"
+ app:navGraph="@navigation/nav_nav_host"
+ app:defaultNavHost="true"
+/>
\ No newline at end of file
diff --git a/navigation/navigation-fragment/src/androidTest/res/navigation/nav_nav_host.xml b/navigation/navigation-fragment/src/androidTest/res/navigation/nav_nav_host.xml
new file mode 100644
index 0000000..d9c1a03
--- /dev/null
+++ b/navigation/navigation-fragment/src/androidTest/res/navigation/nav_nav_host.xml
@@ -0,0 +1,30 @@
+<?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.
+ -->
+
+<navigation xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_nav_host"
+ app:startDestination="@+id/start_fragment">
+ <fragment
+ android:id="@+id/start_fragment"
+ android:name="androidx.navigation.fragment.test.EmptyFragment"/>
+ <fragment
+ android:id="@+id/nav_host_1"
+ android:name="androidx.navigation.fragment.BasicNavHostFragment"/>
+ <fragment
+ android:id="@+id/nav_host_2"
+ android:name="androidx.navigation.fragment.BasicNavHostFragment"/>
+</navigation>
\ No newline at end of file
diff --git a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.java b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.java
index aab2ef5..ba0c6a2 100644
--- a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.java
+++ b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.java
@@ -123,6 +123,7 @@
private NavHostController mNavController;
private Boolean mIsPrimaryBeforeOnCreate = null;
+ private View mViewParent;
// State that will be saved and restored
private int mGraphId;
@@ -335,9 +336,9 @@
// When added programmatically, we need to set the NavController on the parent - i.e.,
// the View that has the ID matching this NavHostFragment.
if (view.getParent() != null) {
- View rootView = (View) view.getParent();
- if (rootView.getId() == getId()) {
- Navigation.setViewNavController(rootView, mNavController);
+ mViewParent = (View) view.getParent();
+ if (mViewParent.getId() == getId()) {
+ Navigation.setViewNavController(mViewParent, mNavController);
}
}
}
@@ -380,4 +381,13 @@
outState.putInt(KEY_GRAPH_ID, mGraphId);
}
}
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (mViewParent != null && Navigation.findNavController(mViewParent) == mNavController) {
+ Navigation.setViewNavController(mViewParent, null);
+ }
+ mViewParent = null;
+ }
}
diff --git a/navigation/navigation-runtime/api/api_lint.ignore b/navigation/navigation-runtime/api/api_lint.ignore
index 12f82c6..8005e78 100644
--- a/navigation/navigation-runtime/api/api_lint.ignore
+++ b/navigation/navigation-runtime/api/api_lint.ignore
@@ -1,4 +1,10 @@
// Baseline format: 1.0
+BuilderSetStyle: androidx.navigation.NavDeepLinkBuilder#createPendingIntent():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLinkBuilder.createPendingIntent()
+BuilderSetStyle: androidx.navigation.NavDeepLinkBuilder#createTaskStackBuilder():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.navigation.NavDeepLinkBuilder.createTaskStackBuilder()
+
+
MissingBuildMethod: androidx.navigation.NavDeepLinkBuilder:
androidx.navigation.NavDeepLinkBuilder does not declare a `build()` method, but builder classes are expected to
diff --git a/paging/rxjava2/api/api_lint.ignore b/paging/rxjava2/api/api_lint.ignore
index 20c6bba..153d977 100644
--- a/paging/rxjava2/api/api_lint.ignore
+++ b/paging/rxjava2/api/api_lint.ignore
@@ -1,4 +1,10 @@
// Baseline format: 1.0
+BuilderSetStyle: androidx.paging.RxPagedListBuilder#buildFlowable(io.reactivex.BackpressureStrategy):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.paging.RxPagedListBuilder.buildFlowable(io.reactivex.BackpressureStrategy)
+BuilderSetStyle: androidx.paging.RxPagedListBuilder#buildObservable():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.paging.RxPagedListBuilder.buildObservable()
+
+
MissingBuildMethod: androidx.paging.RxPagedListBuilder:
androidx.paging.RxPagedListBuilder does not declare a `build()` method, but builder classes are expected to
diff --git a/palette/palette/api/api_lint.ignore b/palette/palette/api/api_lint.ignore
index b8c8876..162d7eb 100644
--- a/palette/palette/api/api_lint.ignore
+++ b/palette/palette/api/api_lint.ignore
@@ -1,3 +1,13 @@
// Baseline format: 1.0
+BuilderSetStyle: androidx.palette.graphics.Palette.Builder#generate():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.generate()
+BuilderSetStyle: androidx.palette.graphics.Palette.Builder#generate(androidx.palette.graphics.Palette.PaletteAsyncListener):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.generate(androidx.palette.graphics.Palette.PaletteAsyncListener)
+BuilderSetStyle: androidx.palette.graphics.Palette.Builder#maximumColorCount(int):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.maximumColorCount(int)
+BuilderSetStyle: androidx.palette.graphics.Palette.Builder#resizeBitmapArea(int):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.resizeBitmapArea(int)
+
+
MissingBuildMethod: androidx.palette.graphics.Palette.Builder:
androidx.palette.graphics.Palette.Builder does not declare a `build()` method, but builder classes are expected to
diff --git a/preference/preference/api/api_lint.ignore b/preference/preference/api/api_lint.ignore
index de479d5..8cd2bf7 100644
--- a/preference/preference/api/api_lint.ignore
+++ b/preference/preference/api/api_lint.ignore
@@ -19,12 +19,6 @@
Method parameter should be Collection<CharSequence> (or subclass) instead of raw array; was `java.lang.CharSequence[]`
-CallbackMethodName: androidx.preference.PreferenceManager.PreferenceComparisonCallback:
- Callback method names must follow the on<Something> style: arePreferenceItemsTheSame
-CallbackMethodName: androidx.preference.PreferenceManager.SimplePreferenceComparisonCallback:
- Callback method names must follow the on<Something> style: arePreferenceItemsTheSame
-
-
InternalField: androidx.preference.TwoStatePreference#mChecked:
Internal field mChecked must not be exposed
diff --git a/recyclerview/recyclerview-selection/api/api_lint.ignore b/recyclerview/recyclerview-selection/api/api_lint.ignore
index a607d9e..82e97e9 100644
--- a/recyclerview/recyclerview-selection/api/api_lint.ignore
+++ b/recyclerview/recyclerview-selection/api/api_lint.ignore
@@ -6,21 +6,21 @@
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withBandOverlay(int):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withBandOverlay(int)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withBandOverlay(int)
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withBandPredicate(androidx.recyclerview.selection.BandPredicate):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withBandPredicate(androidx.recyclerview.selection.BandPredicate)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withBandPredicate(androidx.recyclerview.selection.BandPredicate)
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withFocusDelegate(androidx.recyclerview.selection.FocusDelegate<K>):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withFocusDelegate(androidx.recyclerview.selection.FocusDelegate<K>)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withFocusDelegate(androidx.recyclerview.selection.FocusDelegate<K>)
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withOnContextClickListener(androidx.recyclerview.selection.OnContextClickListener):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOnContextClickListener(androidx.recyclerview.selection.OnContextClickListener)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOnContextClickListener(androidx.recyclerview.selection.OnContextClickListener)
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withOnDragInitiatedListener(androidx.recyclerview.selection.OnDragInitiatedListener):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOnDragInitiatedListener(androidx.recyclerview.selection.OnDragInitiatedListener)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOnDragInitiatedListener(androidx.recyclerview.selection.OnDragInitiatedListener)
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withOnItemActivatedListener(androidx.recyclerview.selection.OnItemActivatedListener<K>):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOnItemActivatedListener(androidx.recyclerview.selection.OnItemActivatedListener<K>)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOnItemActivatedListener(androidx.recyclerview.selection.OnItemActivatedListener<K>)
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withOperationMonitor(androidx.recyclerview.selection.OperationMonitor):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOperationMonitor(androidx.recyclerview.selection.OperationMonitor)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withOperationMonitor(androidx.recyclerview.selection.OperationMonitor)
BuilderSetStyle: androidx.recyclerview.selection.SelectionTracker.Builder#withSelectionPredicate(androidx.recyclerview.selection.SelectionTracker.SelectionPredicate<K>):
- Builder methods names should use setFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withSelectionPredicate(androidx.recyclerview.selection.SelectionTracker.SelectionPredicate<K>)
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.recyclerview.selection.SelectionTracker.Builder.withSelectionPredicate(androidx.recyclerview.selection.SelectionTracker.SelectionPredicate<K>)
CallbackName: androidx.recyclerview.selection.SelectionTracker.SelectionObserver:
diff --git a/recyclerview/recyclerview/api/api_lint.ignore b/recyclerview/recyclerview/api/api_lint.ignore
index 2510713..bd0ba08 100644
--- a/recyclerview/recyclerview/api/api_lint.ignore
+++ b/recyclerview/recyclerview/api/api_lint.ignore
@@ -23,26 +23,6 @@
Methods must not mention RuntimeException subclasses in throws clauses (was `java.lang.IndexOutOfBoundsException`)
-CallbackMethodName: androidx.recyclerview.widget.AsyncListUtil.DataCallback:
- Callback method names must follow the on<Something> style: refreshData
-CallbackMethodName: androidx.recyclerview.widget.AsyncListUtil.ViewCallback:
- Callback method names must follow the on<Something> style: getItemRangeInto
-CallbackMethodName: androidx.recyclerview.widget.BatchingListUpdateCallback:
- Callback method names must follow the on<Something> style: dispatchLastEvent
-CallbackMethodName: androidx.recyclerview.widget.DiffUtil.Callback:
- Callback method names must follow the on<Something> style: getOldListSize
-CallbackMethodName: androidx.recyclerview.widget.DiffUtil.ItemCallback:
- Callback method names must follow the on<Something> style: areItemsTheSame
-CallbackMethodName: androidx.recyclerview.widget.ItemTouchHelper.Callback:
- Callback method names must follow the on<Something> style: getDefaultUIUtil
-CallbackMethodName: androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback:
- Callback method names must follow the on<Something> style: setDefaultSwipeDirs
-CallbackMethodName: androidx.recyclerview.widget.SortedList.BatchedCallback:
- Callback method names must follow the on<Something> style: compare
-CallbackMethodName: androidx.recyclerview.widget.SortedList.Callback:
- Callback method names must follow the on<Something> style: compare
-
-
CallbackName: androidx.recyclerview.widget.RecyclerView.AdapterDataObserver:
Class should be named AdapterDataCallback
diff --git a/remotecallback/remotecallback/api/api_lint.ignore b/remotecallback/remotecallback/api/api_lint.ignore
index 732332e..277ff92 100644
--- a/remotecallback/remotecallback/api/api_lint.ignore
+++ b/remotecallback/remotecallback/api/api_lint.ignore
@@ -1,8 +1,4 @@
// Baseline format: 1.0
-CallbackMethodName: androidx.remotecallback.RemoteCallback:
- Callback method names must follow the on<Something> style: getType
-
-
ContextFirst: androidx.remotecallback.RemoteCallback#create(Class<T>, android.content.Context) parameter #1:
Context is distinct, so it must be the first argument (method `create`)
diff --git a/room/runtime/api/api_lint.ignore b/room/runtime/api/api_lint.ignore
index 49e0dbf..8c2f59a 100644
--- a/room/runtime/api/api_lint.ignore
+++ b/room/runtime/api/api_lint.ignore
@@ -3,6 +3,24 @@
Method parameter should be Collection<Object> (or subclass) instead of raw array; was `java.lang.Object[]`
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#allowMainThreadQueries():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.allowMainThreadQueries()
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#createFromAsset(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.createFromAsset(String)
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#createFromFile(java.io.File):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.createFromFile(java.io.File)
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#enableMultiInstanceInvalidation():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.enableMultiInstanceInvalidation()
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#fallbackToDestructiveMigration():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.fallbackToDestructiveMigration()
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#fallbackToDestructiveMigrationFrom(int...):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.fallbackToDestructiveMigrationFrom(int...)
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#fallbackToDestructiveMigrationOnDowngrade():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.fallbackToDestructiveMigrationOnDowngrade()
+BuilderSetStyle: androidx.room.RoomDatabase.Builder#openHelperFactory(androidx.sqlite.db.SupportSQLiteOpenHelper.Factory):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.room.RoomDatabase.Builder.openHelperFactory(androidx.sqlite.db.SupportSQLiteOpenHelper.Factory)
+
+
CallbackName: androidx.room.InvalidationTracker.Observer:
Class should be named Callback
diff --git a/samples/Support7Demos/src/main/AndroidManifest.xml b/samples/Support7Demos/src/main/AndroidManifest.xml
index fd36e80..0433f43 100644
--- a/samples/Support7Demos/src/main/AndroidManifest.xml
+++ b/samples/Support7Demos/src/main/AndroidManifest.xml
@@ -731,6 +731,16 @@
<category android:name="com.example.android.supportv7.SAMPLE_CODE"/>
</intent-filter>
</activity>
+
+ <!-- Custom drawable activity -->
+ <activity android:name=".drawable.CustomDrawableActivity"
+ android:label="@string/custom_drawable"
+ android:theme="@style/Theme.AppCompat.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.example.android.supportv7.SAMPLE_CODE"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/samples/Support7Demos/src/main/java/com/example/android/supportv7/drawable/CustomDrawableActivity.java b/samples/Support7Demos/src/main/java/com/example/android/supportv7/drawable/CustomDrawableActivity.java
new file mode 100644
index 0000000..196a768
--- /dev/null
+++ b/samples/Support7Demos/src/main/java/com/example/android/supportv7/drawable/CustomDrawableActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 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 com.example.android.supportv7.drawable;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.example.android.supportv7.R;
+
+/**
+ * This demonstrates usage of a custom <drawable>
+ */
+public class CustomDrawableActivity extends AppCompatActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.custom_drawable_image);
+ }
+}
diff --git a/samples/Support7Demos/src/main/java/com/example/android/supportv7/drawable/MyDrawable.java b/samples/Support7Demos/src/main/java/com/example/android/supportv7/drawable/MyDrawable.java
new file mode 100644
index 0000000..ecab1b2
--- /dev/null
+++ b/samples/Support7Demos/src/main/java/com/example/android/supportv7/drawable/MyDrawable.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.example.android.supportv7.drawable;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+
+/**
+ * Simple custom drawable.
+ */
+public class MyDrawable extends Drawable {
+ private final Paint mPaint;
+
+ public MyDrawable() {
+ mPaint = new Paint();
+ mPaint.setARGB(255, 255, 0, 0);
+ mPaint.setAntiAlias(true);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ // Get the drawable's bounds
+ int width = getBounds().width();
+ int height = getBounds().height();
+ float radius = Math.min(width, height) / 2;
+
+ // Draw a red circle in the center
+ canvas.drawCircle(width / 2, height / 2, radius, mPaint);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // This method is required
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // This method is required
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
+}
diff --git a/samples/Support7Demos/src/main/res/drawable/my_drawable.xml b/samples/Support7Demos/src/main/res/drawable/my_drawable.xml
new file mode 100644
index 0000000..8eb5c46
--- /dev/null
+++ b/samples/Support7Demos/src/main/res/drawable/my_drawable.xml
@@ -0,0 +1,20 @@
+<?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.
+ -->
+
+<drawable xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.example.android.supportv7.drawable.MyDrawable"
+ android:color="#ffff0000" />
diff --git a/samples/Support7Demos/src/main/res/layout/custom_drawable_image.xml b/samples/Support7Demos/src/main/res/layout/custom_drawable_image.xml
new file mode 100644
index 0000000..4baca82
--- /dev/null
+++ b/samples/Support7Demos/src/main/res/layout/custom_drawable_image.xml
@@ -0,0 +1,35 @@
+<?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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="8dp">
+
+ <ImageView
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ app:srcCompat="@drawable/my_drawable" />
+
+ <ImageView
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginTop="8dp"
+ app:srcCompat="@drawable/my_drawable" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/Support7Demos/src/main/res/values/strings.xml b/samples/Support7Demos/src/main/res/values/strings.xml
index 86faac1..a6922ae 100644
--- a/samples/Support7Demos/src/main/res/values/strings.xml
+++ b/samples/Support7Demos/src/main/res/values/strings.xml
@@ -280,4 +280,6 @@
<string name="webview">WebView</string>
<string name="launch_activity">Launch Activity</string>
+
+ <string name="custom_drawable">Drawable/Custom drawable</string>
</resources>
diff --git a/sqlite/sqlite/api/api_lint.ignore b/sqlite/sqlite/api/api_lint.ignore
index fa0a8dd..a9d0891 100644
--- a/sqlite/sqlite/api/api_lint.ignore
+++ b/sqlite/sqlite/api/api_lint.ignore
@@ -35,6 +35,32 @@
Method parameter should be Collection<Object> (or subclass) instead of raw array; was `java.lang.Object[]`
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder#callback(androidx.sqlite.db.SupportSQLiteOpenHelper.Callback):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder.callback(androidx.sqlite.db.SupportSQLiteOpenHelper.Callback)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder#name(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder.name(String)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder#noBackupDirectory(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder.noBackupDirectory(boolean)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#builder(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.builder(String)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#columns(String[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.columns(String[])
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#create():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.create()
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#distinct():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.distinct()
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#groupBy(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.groupBy(String)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#having(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.having(String)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#limit(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.limit(String)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#orderBy(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.orderBy(String)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#selection(String, Object[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.selection(String,Object[])
+
+
MissingBuildMethod: androidx.sqlite.db.SupportSQLiteQueryBuilder:
androidx.sqlite.db.SupportSQLiteQueryBuilder does not declare a `build()` method, but builder classes are expected to
diff --git a/textclassifier/textclassifier/api/api_lint.ignore b/textclassifier/textclassifier/api/api_lint.ignore
index fe3256c..b4fcb1d 100644
--- a/textclassifier/textclassifier/api/api_lint.ignore
+++ b/textclassifier/textclassifier/api/api_lint.ignore
@@ -15,6 +15,10 @@
Must avoid boxed primitives (`java.lang.Long`)
+BuilderSetStyle: androidx.textclassifier.TextClassifier.EntityConfig.Builder#includeTypesFromTextClassifier(boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.textclassifier.TextClassifier.EntityConfig.Builder.includeTypesFromTextClassifier(boolean)
+
+
MissingNullability: androidx.textclassifier.TextClassification#getConfidenceScore(String) parameter #0:
Missing nullability on parameter `entity` in method `getConfidenceScore`
MissingNullability: androidx.textclassifier.TextClassification.Builder#setEntityType(String, float):
diff --git a/tv-provider/tv-provider/api/api_lint.ignore b/tv-provider/tv-provider/api/api_lint.ignore
index c2050f2..7c43e2f 100644
--- a/tv-provider/tv-provider/api/api_lint.ignore
+++ b/tv-provider/tv-provider/api/api_lint.ignore
@@ -273,10 +273,6 @@
Missing nullability on method `setAppLinkIntentUri` return
MissingNullability: androidx.tvprovider.media.tv.PreviewChannel.Builder#setAppLinkIntentUri(android.net.Uri) parameter #0:
Missing nullability on parameter `appLinkIntentUri` in method `setAppLinkIntentUri`
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannel.Builder#setDescription(CharSequence):
- Missing nullability on method `setDescription` return
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannel.Builder#setDescription(CharSequence) parameter #0:
- Missing nullability on parameter `description` in method `setDescription`
MissingNullability: androidx.tvprovider.media.tv.PreviewChannel.Builder#setDisplayName(CharSequence):
Missing nullability on method `setDisplayName` return
MissingNullability: androidx.tvprovider.media.tv.PreviewChannel.Builder#setDisplayName(CharSequence) parameter #0:
diff --git a/ui/gradle/wrapper/gradle-wrapper.properties b/ui/gradle/wrapper/gradle-wrapper.properties
index a0c65fe..2bec472 100644
--- a/ui/gradle/wrapper/gradle-wrapper.properties
+++ b/ui/gradle/wrapper/gradle-wrapper.properties
@@ -5,4 +5,4 @@
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=../../../../../tools/external/gradle/gradle-6.3-bin.zip
+distributionUrl=../../../../../tools/external/gradle/gradle-6.4-bin.zip
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/RectsInColumnBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/RectsInColumnBenchmark.kt
index 1c742d3..fc82db8 100644
--- a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/RectsInColumnBenchmark.kt
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/RectsInColumnBenchmark.kt
@@ -44,7 +44,7 @@
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{0}")
- fun initParameters(): Array<Any> = arrayOf(1, 10)
+ fun initParameters(): Array<Any> = arrayOf(10, 100)
}
@get:Rule
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/TextInColumnBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/TextInColumnBenchmark.kt
new file mode 100644
index 0000000..25ce2fd
--- /dev/null
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/TextInColumnBenchmark.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.ui.benchmark.test
+
+import androidx.test.filters.LargeTest
+import androidx.ui.benchmark.ComposeBenchmarkRule
+import androidx.ui.benchmark.benchmarkDrawPerf
+import androidx.ui.benchmark.benchmarkFirstCompose
+import androidx.ui.benchmark.benchmarkFirstDraw
+import androidx.ui.benchmark.benchmarkFirstLayout
+import androidx.ui.benchmark.benchmarkFirstMeasure
+import androidx.ui.benchmark.benchmarkLayoutPerf
+import androidx.ui.benchmark.toggleStateBenchmarkDraw
+import androidx.ui.benchmark.toggleStateBenchmarkLayout
+import androidx.ui.benchmark.toggleStateBenchmarkMeasure
+import androidx.ui.benchmark.toggleStateBenchmarkRecompose
+import androidx.ui.integration.test.foundation.RectsInColumnTestCase
+import androidx.ui.integration.test.foundation.TextInColumnTestCase
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Benchmark that runs [RectsInColumnTestCase].
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+class TextInColumnBenchmark(private val numberOfTexts: Int) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun initParameters(): Array<Any> = arrayOf(10, 100)
+ }
+
+ @get:Rule
+ val benchmarkRule = ComposeBenchmarkRule()
+
+ private val textInColumnCaseFactory = { TextInColumnTestCase(numberOfTexts) }
+
+ @Test
+ fun first_compose() {
+ benchmarkRule.benchmarkFirstCompose(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun first_measure() {
+ benchmarkRule.benchmarkFirstMeasure(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun first_layout() {
+ benchmarkRule.benchmarkFirstLayout(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun first_draw() {
+ benchmarkRule.benchmarkFirstDraw(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun toggleRectangleColor_recompose() {
+ benchmarkRule.toggleStateBenchmarkRecompose(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun toggleRectangleColor_measure() {
+ benchmarkRule.toggleStateBenchmarkMeasure(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun toggleRectangleColor_layout() {
+ benchmarkRule.toggleStateBenchmarkLayout(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun toggleRectangleColor_draw() {
+ benchmarkRule.toggleStateBenchmarkDraw(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun layout() {
+ benchmarkRule.benchmarkLayoutPerf(textInColumnCaseFactory)
+ }
+
+ @Test
+ fun draw() {
+ benchmarkRule.benchmarkDrawPerf(textInColumnCaseFactory)
+ }
+}
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidRectsInLinearLayoutBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidRectsInLinearLayoutBenchmark.kt
new file mode 100644
index 0000000..de8bcff
--- /dev/null
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidRectsInLinearLayoutBenchmark.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.ui.benchmark.test.view
+
+import androidx.test.filters.LargeTest
+import androidx.ui.benchmark.AndroidBenchmarkRule
+import androidx.ui.benchmark.benchmarkDrawPerf
+import androidx.ui.benchmark.benchmarkFirstDraw
+import androidx.ui.benchmark.benchmarkFirstLayout
+import androidx.ui.benchmark.benchmarkFirstMeasure
+import androidx.ui.benchmark.benchmarkFirstSetContent
+import androidx.ui.benchmark.benchmarkLayoutPerf
+import androidx.ui.integration.test.view.AndroidCheckboxesInLinearLayoutTestCase
+import androidx.ui.integration.test.view.AndroidRectsInLinearLayoutTestCase
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Benchmark that runs [AndroidCheckboxesInLinearLayoutTestCase].
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+class AndroidRectsInLinearLayoutBenchmark(private val numberOfRectangles: Int) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun initParameters(): Array<Any> = arrayOf(10, 100)
+ }
+
+ @get:Rule
+ val benchmarkRule = AndroidBenchmarkRule()
+
+ private val rectanglesCaseFactory = {
+ AndroidRectsInLinearLayoutTestCase(numberOfRectangles)
+ }
+
+ @Test
+ fun first_setContent() {
+ benchmarkRule.benchmarkFirstSetContent(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun first_measure() {
+ benchmarkRule.benchmarkFirstMeasure(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun first_layout() {
+ benchmarkRule.benchmarkFirstLayout(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun first_draw() {
+ benchmarkRule.benchmarkFirstDraw(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun layout() {
+ benchmarkRule.benchmarkLayoutPerf(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun draw() {
+ benchmarkRule.benchmarkDrawPerf(rectanglesCaseFactory)
+ }
+}
\ No newline at end of file
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidTextViewsInLinearLayoutBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidTextViewsInLinearLayoutBenchmark.kt
new file mode 100644
index 0000000..c85a7fa
--- /dev/null
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/view/AndroidTextViewsInLinearLayoutBenchmark.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.ui.benchmark.test.view
+
+import androidx.test.filters.LargeTest
+import androidx.ui.benchmark.AndroidBenchmarkRule
+import androidx.ui.benchmark.benchmarkDrawPerf
+import androidx.ui.benchmark.benchmarkFirstDraw
+import androidx.ui.benchmark.benchmarkFirstLayout
+import androidx.ui.benchmark.benchmarkFirstMeasure
+import androidx.ui.benchmark.benchmarkFirstSetContent
+import androidx.ui.benchmark.benchmarkLayoutPerf
+import androidx.ui.integration.test.view.AndroidCheckboxesInLinearLayoutTestCase
+import androidx.ui.integration.test.view.AndroidTextViewsInLinearLayoutTestCase
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Benchmark that runs [AndroidCheckboxesInLinearLayoutTestCase].
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+class AndroidTextViewsInLinearLayoutBenchmark(private val numberOfTexts: Int) {
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun initParameters(): Array<Any> = arrayOf(10, 100)
+ }
+
+ @get:Rule
+ val benchmarkRule = AndroidBenchmarkRule()
+
+ private val rectanglesCaseFactory = {
+ AndroidTextViewsInLinearLayoutTestCase(numberOfTexts)
+ }
+
+ @Test
+ fun first_setContent() {
+ benchmarkRule.benchmarkFirstSetContent(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun first_measure() {
+ benchmarkRule.benchmarkFirstMeasure(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun first_layout() {
+ benchmarkRule.benchmarkFirstLayout(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun first_draw() {
+ benchmarkRule.benchmarkFirstDraw(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun layout() {
+ benchmarkRule.benchmarkLayoutPerf(rectanglesCaseFactory)
+ }
+
+ @Test
+ fun draw() {
+ benchmarkRule.benchmarkDrawPerf(rectanglesCaseFactory)
+ }
+}
\ No newline at end of file
diff --git a/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoFilter.kt b/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoFilter.kt
index 3398a9c..7d10c55 100644
--- a/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoFilter.kt
+++ b/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoFilter.kt
@@ -22,7 +22,7 @@
import androidx.ui.core.Alignment
import androidx.ui.core.Modifier
import androidx.ui.demos.common.Demo
-import androidx.ui.focus.FocusModifier
+import androidx.ui.core.focus.FocusModifier
import androidx.ui.foundation.Icon
import androidx.ui.foundation.Text
import androidx.ui.foundation.TextField
diff --git a/ui/integration-tests/src/main/java/androidx/ui/integration/test/foundation/TextInColumnTestCase.kt b/ui/integration-tests/src/main/java/androidx/ui/integration/test/foundation/TextInColumnTestCase.kt
new file mode 100644
index 0000000..ddd6c47
--- /dev/null
+++ b/ui/integration-tests/src/main/java/androidx/ui/integration/test/foundation/TextInColumnTestCase.kt
@@ -0,0 +1,66 @@
+/*
+ * 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.ui.integration.test.foundation
+
+import androidx.compose.Composable
+import androidx.compose.mutableStateOf
+import androidx.ui.foundation.Text
+import androidx.ui.integration.test.ToggleableTestCase
+import androidx.ui.layout.Column
+import androidx.ui.material.MaterialTheme
+import androidx.ui.material.Surface
+import androidx.ui.test.ComposeTestCase
+import androidx.ui.text.TextStyle
+import androidx.ui.unit.sp
+
+/**
+ * Test case that puts the given amount of rectangles into a column layout and makes changes by
+ * modifying the color used in the model.
+ *
+ * Note: Each rectangle has its own model so changes should always affect only the first one.
+ */
+class TextInColumnTestCase(
+ private val numberOfTexts: Int
+) : ComposeTestCase, ToggleableTestCase {
+
+ private val fontSize = mutableStateOf(20.sp)
+
+ @Composable
+ override fun emitContent() {
+ MaterialTheme {
+ Surface {
+ Column {
+ repeat(numberOfTexts) {
+ // 32-character text to match dashboards
+ Text(
+ "Hello World Hello World Hello W",
+ style = TextStyle(fontSize = fontSize.value)
+ )
+ }
+ }
+ }
+ }
+ }
+
+ override fun toggleState() {
+ fontSize.value = if (fontSize.value == 20.sp) {
+ 15.sp
+ } else {
+ 20.sp
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidRectsInLinearLayoutTestCase.kt b/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidRectsInLinearLayoutTestCase.kt
new file mode 100644
index 0000000..b816715
--- /dev/null
+++ b/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidRectsInLinearLayoutTestCase.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.ui.integration.test.view
+
+import android.app.Activity
+import android.graphics.Color
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import androidx.ui.benchmark.android.AndroidTestCase
+import androidx.ui.integration.test.material.CheckboxesInRowsTestCase
+
+/**
+ * Version of [CheckboxesInRowsTestCase] using Android views.
+ */
+class AndroidRectsInLinearLayoutTestCase(
+ private val numberOfRectangles: Int
+) : AndroidTestCase {
+
+ private val rectangles = mutableListOf<View>()
+ var isBlue = true
+
+ override fun getContent(activity: Activity): ViewGroup {
+ val column = LinearLayout(activity)
+ column.orientation = LinearLayout.VERTICAL
+ column.layoutParams = ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ repeat(numberOfRectangles) {
+ val rectangle = View(activity)
+ rectangle.setBackgroundColor(Color.BLUE)
+ rectangle.layoutParams = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+
+ column.addView(rectangle)
+ rectangles += rectangle
+ }
+ return column
+ }
+
+ fun toggleState() {
+ rectangles.forEach {
+ isBlue = !isBlue
+ val color = if (isBlue) Color.BLUE else Color.RED
+ it.setBackgroundColor(color)
+ }
+ }
+}
diff --git a/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidTextViewsInLinearLayoutTestCase.kt b/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidTextViewsInLinearLayoutTestCase.kt
new file mode 100644
index 0000000..8d4769d
--- /dev/null
+++ b/ui/integration-tests/src/main/java/androidx/ui/integration/test/view/AndroidTextViewsInLinearLayoutTestCase.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.ui.integration.test.view
+
+import android.app.Activity
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.ui.benchmark.android.AndroidTestCase
+import androidx.ui.integration.test.material.CheckboxesInRowsTestCase
+
+/**
+ * Version of [CheckboxesInRowsTestCase] using Android views.
+ */
+class AndroidTextViewsInLinearLayoutTestCase(
+ private val amountOfCheckboxes: Int
+) : AndroidTestCase {
+
+ private val textViews = mutableListOf<TextView>()
+ private var fontSize = 20f
+
+ override fun getContent(activity: Activity): ViewGroup {
+ val column = LinearLayout(activity)
+ column.orientation = LinearLayout.VERTICAL
+ column.layoutParams = ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ repeat(amountOfCheckboxes) {
+ val text = TextView(activity)
+ text.text = "Hello World Hello World Hello W"
+ text.layoutParams = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ text.setTextSize(fontSize)
+ column.addView(text)
+ textViews += text
+ }
+ return column
+ }
+
+ fun toggleState() {
+ fontSize = if (fontSize == 20f) 15f else 20f
+ textViews.forEach {
+ it.textSize = fontSize
+ }
+ }
+}
diff --git a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt b/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt
index b9a83b6..ce0c1e3a 100644
--- a/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt
+++ b/ui/ui-animation-core/src/main/java/androidx/animation/TransitionDefinition.kt
@@ -16,6 +16,7 @@
package androidx.animation
+import androidx.ui.util.fastFirstOrNull
import kotlin.experimental.ExperimentalTypeInference
/**
@@ -269,10 +270,10 @@
}
internal fun getSpec(fromState: T, toState: T): TransitionSpec<T> {
- return transitionSpecs.firstOrNull { it.defines(fromState, toState) }
- ?: transitionSpecs.firstOrNull { it.defines(fromState, null) }
- ?: transitionSpecs.firstOrNull { it.defines(null, toState) }
- ?: transitionSpecs.firstOrNull { it.defines(null, null) }
+ return transitionSpecs.fastFirstOrNull { it.defines(fromState, toState) }
+ ?: transitionSpecs.fastFirstOrNull { it.defines(fromState, null) }
+ ?: transitionSpecs.fastFirstOrNull { it.defines(null, toState) }
+ ?: transitionSpecs.fastFirstOrNull { it.defines(null, null) }
?: defaultTransitionSpec
}
diff --git a/ui/ui-core/OWNERS b/ui/ui-core/OWNERS
index 4ccb43c..8abcc5f 100644
--- a/ui/ui-core/OWNERS
+++ b/ui/ui-core/OWNERS
@@ -4,6 +4,7 @@
ryanmentley@google.com
njawad@google.com
popam@google.com
+soboleva@google.com
# For text related files
qqd@google.com
diff --git a/ui/ui-core/api/0.1.0-dev12.txt b/ui/ui-core/api/0.1.0-dev12.txt
index 65cd94e..1996b5b 100644
--- a/ui/ui-core/api/0.1.0-dev12.txt
+++ b/ui/ui-core/api/0.1.0-dev12.txt
@@ -716,10 +716,6 @@
method public static androidx.ui.core.Modifier paint(androidx.ui.core.Modifier, androidx.ui.graphics.painter.Painter painter, boolean sizeToIntrinsics = true, androidx.ui.core.Alignment alignment = Alignment.Center, androidx.ui.core.ContentScale contentScale = ContentScale.Inside, float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, boolean rtl = false);
}
- public final class ParentDataKt {
- method @Deprecated public static inline void ParentData(Object data, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- }
-
public interface ParentDataModifier extends androidx.ui.core.Modifier.Element {
method public default Object? modifyParentData(androidx.ui.unit.Density, Object? parentData);
}
@@ -935,7 +931,6 @@
method public static androidx.compose.ProvidableAmbient<androidx.ui.core.texttoolbar.TextToolbar> getTextToolbarAmbient();
method public static androidx.compose.ProvidableAmbient<androidx.ui.platform.UriHandler> getUriHandlerAmbient();
method public static androidx.compose.Composition setContent(androidx.activity.ComponentActivity, androidx.compose.Recomposer recomposer = Recomposer.current(), kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @Deprecated public static androidx.compose.Composition setContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setContent(android.view.ViewGroup, androidx.compose.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
@@ -969,13 +964,48 @@
package androidx.ui.core.focus {
- public final class FocusModifierImplKt {
- method public static androidx.ui.focus.FocusModifier createFocusModifier(androidx.ui.focus.FocusDetailedState focusDetailedState);
+ public enum FocusDetailedState {
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Disabled;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Inactive;
+ }
+
+ public interface FocusModifier extends androidx.ui.core.Modifier.Element {
+ method public boolean captureFocus();
+ method public boolean freeFocus();
+ method public androidx.ui.core.focus.FocusDetailedState getFocusDetailedState();
+ method public void requestFocus();
+ property public abstract androidx.ui.core.focus.FocusDetailedState focusDetailedState;
+ }
+
+ public final class FocusModifierKt {
+ method public static androidx.ui.core.focus.FocusModifier FocusModifier();
+ method public static androidx.ui.core.focus.FocusState getFocusState(androidx.ui.core.focus.FocusModifier);
}
public final class FocusNodeUtilsKt {
}
+ @Deprecated public final class FocusOperator {
+ ctor @Deprecated public FocusOperator();
+ }
+
+ public enum FocusState {
+ enum_constant public static final androidx.ui.core.focus.FocusState Focused;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
+ }
+
+ public final class FocusStateKt {
+ method public static androidx.ui.core.focus.FocusState focusState(androidx.ui.core.focus.FocusDetailedState);
+ }
+
+ public final class FocusableKt {
+ method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
+ }
+
}
package androidx.ui.core.gesture {
@@ -1933,49 +1963,6 @@
}
-package androidx.ui.focus {
-
- public enum FocusDetailedState {
- enum_constant public static final androidx.ui.focus.FocusDetailedState Active;
- enum_constant public static final androidx.ui.focus.FocusDetailedState ActiveParent;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Captured;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Disabled;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Inactive;
- }
-
- public interface FocusModifier extends androidx.ui.core.Modifier.Element {
- method public boolean captureFocus();
- method public boolean freeFocus();
- method public androidx.ui.focus.FocusDetailedState getFocusDetailedState();
- method public void requestFocus();
- property public abstract androidx.ui.focus.FocusDetailedState focusDetailedState;
- }
-
- public final class FocusModifierProviderKt {
- method public static androidx.ui.focus.FocusModifier FocusModifier();
- method public static androidx.ui.focus.FocusState getFocusState(androidx.ui.focus.FocusModifier);
- }
-
- @Deprecated public final class FocusOperator {
- ctor @Deprecated public FocusOperator();
- }
-
- public enum FocusState {
- enum_constant public static final androidx.ui.focus.FocusState Focused;
- enum_constant public static final androidx.ui.focus.FocusState NotFocusable;
- enum_constant public static final androidx.ui.focus.FocusState NotFocused;
- }
-
- public final class FocusStateKt {
- method public static androidx.ui.focus.FocusState focusState(androidx.ui.focus.FocusDetailedState);
- }
-
- public final class FocusableKt {
- method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
- }
-
-}
-
package androidx.ui.graphics.vector {
public final class VectorAsset {
diff --git a/ui/ui-core/api/api_lint.ignore b/ui/ui-core/api/api_lint.ignore
index f6b8aeb..5bf293e 100644
--- a/ui/ui-core/api/api_lint.ignore
+++ b/ui/ui-core/api/api_lint.ignore
@@ -1,6 +1,8 @@
// Baseline format: 1.0
AcronymName: androidx.ui.core.AlignmentLineKt#merge-CBRbNzc(androidx.ui.core.AlignmentLine, int, int):
Acronyms should not be capitalized in method names: was `merge-CBRbNzc`, should this be `merge-CbRbNzc`?
+AcronymName: androidx.ui.core.ContentScaleKt#scale-iWWM28M(androidx.ui.core.ContentScale, long, long):
+ Acronyms should not be capitalized in method names: was `scale-iWWM28M`, should this be `scale-iWwM28M`?
AcronymName: androidx.ui.core.DrawShadowKt#drawShadow-xWKVMPI(androidx.ui.core.Modifier, float, androidx.ui.graphics.Shape, boolean, float):
Acronyms should not be capitalized in method names: was `drawShadow-xWKVMPI`, should this be `drawShadow-xWkvmpi`?
AcronymName: androidx.ui.core.IntrinsicMeasureScope#maxIntrinsicHeight-e0m06WU(androidx.ui.core.IntrinsicMeasurable, int):
@@ -31,17 +33,33 @@
Method parameter should be Collection<PointerInputChange> (or subclass) instead of raw array; was `androidx.ui.core.PointerInputChange[]`
+BuilderSetStyle: androidx.ui.graphics.vector.VectorAssetBuilder#popGroup():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.VectorAssetBuilder.popGroup()
+BuilderSetStyle: androidx.ui.graphics.vector.VectorAssetBuilder#pushGroup(String, float, float, float, float, float, float, float, java.util.List<? extends androidx.ui.graphics.vector.PathNode>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.VectorAssetBuilder.pushGroup(String,float,float,float,float,float,float,float,java.util.List<? extends androidx.ui.graphics.vector.PathNode>)
+
+
+CallbackName: androidx.ui.core.ModelObserver:
+ Class should be named ModelCallback
+CallbackName: androidx.ui.core.gesture.DragObserver:
+ Class should be named DragCallback
+CallbackName: androidx.ui.core.gesture.LongPressDragObserver:
+ Class should be named LongPressDragCallback
+CallbackName: androidx.ui.core.gesture.RawScaleObserver:
+ Class should be named RawScaleCallback
+CallbackName: androidx.ui.core.gesture.ScaleObserver:
+ Class should be named ScaleCallback
+
+
ContextFirst: androidx.ui.core.WrapperKt#subcomposeInto(androidx.ui.core.ComponentNode, android.content.Context, androidx.compose.CompositionReference, kotlin.jvm.functions.Function0<kotlin.Unit>) parameter #1:
Context is distinct, so it must be the first argument (method `subcomposeInto`)
-TopLevelBuilder: androidx.ui.graphics.vector.VectorAssetBuilder:
- Builder should be defined as inner class: androidx.ui.graphics.vector.VectorAssetBuilder
-
-
-MissingNullability: androidx.ui.core.Constraints2#toString-impl(long):
- Missing nullability on method `toString-impl` return
MissingNullability: androidx.ui.core.PointerId#toString-impl(long):
Missing nullability on method `toString-impl` return
MissingNullability: androidx.ui.core.TransformOrigin#toString-impl(long):
Missing nullability on method `toString-impl` return
+
+
+TopLevelBuilder: androidx.ui.graphics.vector.VectorAssetBuilder:
+ Builder should be defined as inner class: androidx.ui.graphics.vector.VectorAssetBuilder
diff --git a/ui/ui-core/api/current.txt b/ui/ui-core/api/current.txt
index 65cd94e..1996b5b 100644
--- a/ui/ui-core/api/current.txt
+++ b/ui/ui-core/api/current.txt
@@ -716,10 +716,6 @@
method public static androidx.ui.core.Modifier paint(androidx.ui.core.Modifier, androidx.ui.graphics.painter.Painter painter, boolean sizeToIntrinsics = true, androidx.ui.core.Alignment alignment = Alignment.Center, androidx.ui.core.ContentScale contentScale = ContentScale.Inside, float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, boolean rtl = false);
}
- public final class ParentDataKt {
- method @Deprecated public static inline void ParentData(Object data, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- }
-
public interface ParentDataModifier extends androidx.ui.core.Modifier.Element {
method public default Object? modifyParentData(androidx.ui.unit.Density, Object? parentData);
}
@@ -935,7 +931,6 @@
method public static androidx.compose.ProvidableAmbient<androidx.ui.core.texttoolbar.TextToolbar> getTextToolbarAmbient();
method public static androidx.compose.ProvidableAmbient<androidx.ui.platform.UriHandler> getUriHandlerAmbient();
method public static androidx.compose.Composition setContent(androidx.activity.ComponentActivity, androidx.compose.Recomposer recomposer = Recomposer.current(), kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @Deprecated public static androidx.compose.Composition setContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setContent(android.view.ViewGroup, androidx.compose.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
@@ -969,13 +964,48 @@
package androidx.ui.core.focus {
- public final class FocusModifierImplKt {
- method public static androidx.ui.focus.FocusModifier createFocusModifier(androidx.ui.focus.FocusDetailedState focusDetailedState);
+ public enum FocusDetailedState {
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Disabled;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Inactive;
+ }
+
+ public interface FocusModifier extends androidx.ui.core.Modifier.Element {
+ method public boolean captureFocus();
+ method public boolean freeFocus();
+ method public androidx.ui.core.focus.FocusDetailedState getFocusDetailedState();
+ method public void requestFocus();
+ property public abstract androidx.ui.core.focus.FocusDetailedState focusDetailedState;
+ }
+
+ public final class FocusModifierKt {
+ method public static androidx.ui.core.focus.FocusModifier FocusModifier();
+ method public static androidx.ui.core.focus.FocusState getFocusState(androidx.ui.core.focus.FocusModifier);
}
public final class FocusNodeUtilsKt {
}
+ @Deprecated public final class FocusOperator {
+ ctor @Deprecated public FocusOperator();
+ }
+
+ public enum FocusState {
+ enum_constant public static final androidx.ui.core.focus.FocusState Focused;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
+ }
+
+ public final class FocusStateKt {
+ method public static androidx.ui.core.focus.FocusState focusState(androidx.ui.core.focus.FocusDetailedState);
+ }
+
+ public final class FocusableKt {
+ method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
+ }
+
}
package androidx.ui.core.gesture {
@@ -1933,49 +1963,6 @@
}
-package androidx.ui.focus {
-
- public enum FocusDetailedState {
- enum_constant public static final androidx.ui.focus.FocusDetailedState Active;
- enum_constant public static final androidx.ui.focus.FocusDetailedState ActiveParent;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Captured;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Disabled;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Inactive;
- }
-
- public interface FocusModifier extends androidx.ui.core.Modifier.Element {
- method public boolean captureFocus();
- method public boolean freeFocus();
- method public androidx.ui.focus.FocusDetailedState getFocusDetailedState();
- method public void requestFocus();
- property public abstract androidx.ui.focus.FocusDetailedState focusDetailedState;
- }
-
- public final class FocusModifierProviderKt {
- method public static androidx.ui.focus.FocusModifier FocusModifier();
- method public static androidx.ui.focus.FocusState getFocusState(androidx.ui.focus.FocusModifier);
- }
-
- @Deprecated public final class FocusOperator {
- ctor @Deprecated public FocusOperator();
- }
-
- public enum FocusState {
- enum_constant public static final androidx.ui.focus.FocusState Focused;
- enum_constant public static final androidx.ui.focus.FocusState NotFocusable;
- enum_constant public static final androidx.ui.focus.FocusState NotFocused;
- }
-
- public final class FocusStateKt {
- method public static androidx.ui.focus.FocusState focusState(androidx.ui.focus.FocusDetailedState);
- }
-
- public final class FocusableKt {
- method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
- }
-
-}
-
package androidx.ui.graphics.vector {
public final class VectorAsset {
diff --git a/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt
index 312c643..e4965f4 100644
--- a/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt
@@ -718,10 +718,6 @@
method public static androidx.ui.core.Modifier paint(androidx.ui.core.Modifier, androidx.ui.graphics.painter.Painter painter, boolean sizeToIntrinsics = true, androidx.ui.core.Alignment alignment = Alignment.Center, androidx.ui.core.ContentScale contentScale = ContentScale.Inside, float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, boolean rtl = false);
}
- public final class ParentDataKt {
- method @Deprecated public static inline void ParentData(Object data, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- }
-
public interface ParentDataModifier extends androidx.ui.core.Modifier.Element {
method public default Object? modifyParentData(androidx.ui.unit.Density, Object? parentData);
}
@@ -937,7 +933,6 @@
method public static androidx.compose.ProvidableAmbient<androidx.ui.core.texttoolbar.TextToolbar> getTextToolbarAmbient();
method public static androidx.compose.ProvidableAmbient<androidx.ui.platform.UriHandler> getUriHandlerAmbient();
method public static androidx.compose.Composition setContent(androidx.activity.ComponentActivity, androidx.compose.Recomposer recomposer = Recomposer.current(), kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @Deprecated public static androidx.compose.Composition setContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setContent(android.view.ViewGroup, androidx.compose.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
@@ -971,13 +966,48 @@
package androidx.ui.core.focus {
- public final class FocusModifierImplKt {
- method public static androidx.ui.focus.FocusModifier createFocusModifier(androidx.ui.focus.FocusDetailedState focusDetailedState);
+ public enum FocusDetailedState {
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Disabled;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Inactive;
+ }
+
+ public interface FocusModifier extends androidx.ui.core.Modifier.Element {
+ method public boolean captureFocus();
+ method public boolean freeFocus();
+ method public androidx.ui.core.focus.FocusDetailedState getFocusDetailedState();
+ method public void requestFocus();
+ property public abstract androidx.ui.core.focus.FocusDetailedState focusDetailedState;
+ }
+
+ public final class FocusModifierKt {
+ method public static androidx.ui.core.focus.FocusModifier FocusModifier();
+ method public static androidx.ui.core.focus.FocusState getFocusState(androidx.ui.core.focus.FocusModifier);
}
public final class FocusNodeUtilsKt {
}
+ @Deprecated public final class FocusOperator {
+ ctor @Deprecated public FocusOperator();
+ }
+
+ public enum FocusState {
+ enum_constant public static final androidx.ui.core.focus.FocusState Focused;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
+ }
+
+ public final class FocusStateKt {
+ method public static androidx.ui.core.focus.FocusState focusState(androidx.ui.core.focus.FocusDetailedState);
+ }
+
+ public final class FocusableKt {
+ method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
+ }
+
}
package androidx.ui.core.gesture {
@@ -1935,49 +1965,6 @@
}
-package androidx.ui.focus {
-
- public enum FocusDetailedState {
- enum_constant public static final androidx.ui.focus.FocusDetailedState Active;
- enum_constant public static final androidx.ui.focus.FocusDetailedState ActiveParent;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Captured;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Disabled;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Inactive;
- }
-
- public interface FocusModifier extends androidx.ui.core.Modifier.Element {
- method public boolean captureFocus();
- method public boolean freeFocus();
- method public androidx.ui.focus.FocusDetailedState getFocusDetailedState();
- method public void requestFocus();
- property public abstract androidx.ui.focus.FocusDetailedState focusDetailedState;
- }
-
- public final class FocusModifierProviderKt {
- method public static androidx.ui.focus.FocusModifier FocusModifier();
- method public static androidx.ui.focus.FocusState getFocusState(androidx.ui.focus.FocusModifier);
- }
-
- @Deprecated public final class FocusOperator {
- ctor @Deprecated public FocusOperator();
- }
-
- public enum FocusState {
- enum_constant public static final androidx.ui.focus.FocusState Focused;
- enum_constant public static final androidx.ui.focus.FocusState NotFocusable;
- enum_constant public static final androidx.ui.focus.FocusState NotFocused;
- }
-
- public final class FocusStateKt {
- method public static androidx.ui.focus.FocusState focusState(androidx.ui.focus.FocusDetailedState);
- }
-
- public final class FocusableKt {
- method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
- }
-
-}
-
package androidx.ui.graphics.vector {
public final class VectorAsset {
diff --git a/ui/ui-core/api/public_plus_experimental_current.txt b/ui/ui-core/api/public_plus_experimental_current.txt
index 312c643..e4965f4 100644
--- a/ui/ui-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-core/api/public_plus_experimental_current.txt
@@ -718,10 +718,6 @@
method public static androidx.ui.core.Modifier paint(androidx.ui.core.Modifier, androidx.ui.graphics.painter.Painter painter, boolean sizeToIntrinsics = true, androidx.ui.core.Alignment alignment = Alignment.Center, androidx.ui.core.ContentScale contentScale = ContentScale.Inside, float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, boolean rtl = false);
}
- public final class ParentDataKt {
- method @Deprecated public static inline void ParentData(Object data, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- }
-
public interface ParentDataModifier extends androidx.ui.core.Modifier.Element {
method public default Object? modifyParentData(androidx.ui.unit.Density, Object? parentData);
}
@@ -937,7 +933,6 @@
method public static androidx.compose.ProvidableAmbient<androidx.ui.core.texttoolbar.TextToolbar> getTextToolbarAmbient();
method public static androidx.compose.ProvidableAmbient<androidx.ui.platform.UriHandler> getUriHandlerAmbient();
method public static androidx.compose.Composition setContent(androidx.activity.ComponentActivity, androidx.compose.Recomposer recomposer = Recomposer.current(), kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @Deprecated public static androidx.compose.Composition setContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setContent(android.view.ViewGroup, androidx.compose.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
@@ -971,13 +966,48 @@
package androidx.ui.core.focus {
- public final class FocusModifierImplKt {
- method public static androidx.ui.focus.FocusModifier createFocusModifier(androidx.ui.focus.FocusDetailedState focusDetailedState);
+ public enum FocusDetailedState {
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Disabled;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Inactive;
+ }
+
+ public interface FocusModifier extends androidx.ui.core.Modifier.Element {
+ method public boolean captureFocus();
+ method public boolean freeFocus();
+ method public androidx.ui.core.focus.FocusDetailedState getFocusDetailedState();
+ method public void requestFocus();
+ property public abstract androidx.ui.core.focus.FocusDetailedState focusDetailedState;
+ }
+
+ public final class FocusModifierKt {
+ method public static androidx.ui.core.focus.FocusModifier FocusModifier();
+ method public static androidx.ui.core.focus.FocusState getFocusState(androidx.ui.core.focus.FocusModifier);
}
public final class FocusNodeUtilsKt {
}
+ @Deprecated public final class FocusOperator {
+ ctor @Deprecated public FocusOperator();
+ }
+
+ public enum FocusState {
+ enum_constant public static final androidx.ui.core.focus.FocusState Focused;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
+ }
+
+ public final class FocusStateKt {
+ method public static androidx.ui.core.focus.FocusState focusState(androidx.ui.core.focus.FocusDetailedState);
+ }
+
+ public final class FocusableKt {
+ method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
+ }
+
}
package androidx.ui.core.gesture {
@@ -1935,49 +1965,6 @@
}
-package androidx.ui.focus {
-
- public enum FocusDetailedState {
- enum_constant public static final androidx.ui.focus.FocusDetailedState Active;
- enum_constant public static final androidx.ui.focus.FocusDetailedState ActiveParent;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Captured;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Disabled;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Inactive;
- }
-
- public interface FocusModifier extends androidx.ui.core.Modifier.Element {
- method public boolean captureFocus();
- method public boolean freeFocus();
- method public androidx.ui.focus.FocusDetailedState getFocusDetailedState();
- method public void requestFocus();
- property public abstract androidx.ui.focus.FocusDetailedState focusDetailedState;
- }
-
- public final class FocusModifierProviderKt {
- method public static androidx.ui.focus.FocusModifier FocusModifier();
- method public static androidx.ui.focus.FocusState getFocusState(androidx.ui.focus.FocusModifier);
- }
-
- @Deprecated public final class FocusOperator {
- ctor @Deprecated public FocusOperator();
- }
-
- public enum FocusState {
- enum_constant public static final androidx.ui.focus.FocusState Focused;
- enum_constant public static final androidx.ui.focus.FocusState NotFocusable;
- enum_constant public static final androidx.ui.focus.FocusState NotFocused;
- }
-
- public final class FocusStateKt {
- method public static androidx.ui.focus.FocusState focusState(androidx.ui.focus.FocusDetailedState);
- }
-
- public final class FocusableKt {
- method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
- }
-
-}
-
package androidx.ui.graphics.vector {
public final class VectorAsset {
diff --git a/ui/ui-core/api/restricted_0.1.0-dev12.txt b/ui/ui-core/api/restricted_0.1.0-dev12.txt
index bded631..f09213b 100644
--- a/ui/ui-core/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-core/api/restricted_0.1.0-dev12.txt
@@ -726,10 +726,6 @@
method public static androidx.ui.core.Modifier paint(androidx.ui.core.Modifier, androidx.ui.graphics.painter.Painter painter, boolean sizeToIntrinsics = true, androidx.ui.core.Alignment alignment = Alignment.Center, androidx.ui.core.ContentScale contentScale = ContentScale.Inside, float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, boolean rtl = false);
}
- public final class ParentDataKt {
- method @Deprecated public static inline void ParentData(Object data, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- }
-
public interface ParentDataModifier extends androidx.ui.core.Modifier.Element {
method public default Object? modifyParentData(androidx.ui.unit.Density, Object? parentData);
}
@@ -945,7 +941,6 @@
method public static androidx.compose.ProvidableAmbient<androidx.ui.core.texttoolbar.TextToolbar> getTextToolbarAmbient();
method public static androidx.compose.ProvidableAmbient<androidx.ui.platform.UriHandler> getUriHandlerAmbient();
method public static androidx.compose.Composition setContent(androidx.activity.ComponentActivity, androidx.compose.Recomposer recomposer = Recomposer.current(), kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @Deprecated public static androidx.compose.Composition setContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setContent(android.view.ViewGroup, androidx.compose.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
@@ -979,13 +974,48 @@
package androidx.ui.core.focus {
- public final class FocusModifierImplKt {
- method public static androidx.ui.focus.FocusModifier createFocusModifier(androidx.ui.focus.FocusDetailedState focusDetailedState);
+ public enum FocusDetailedState {
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Disabled;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Inactive;
+ }
+
+ public interface FocusModifier extends androidx.ui.core.Modifier.Element {
+ method public boolean captureFocus();
+ method public boolean freeFocus();
+ method public androidx.ui.core.focus.FocusDetailedState getFocusDetailedState();
+ method public void requestFocus();
+ property public abstract androidx.ui.core.focus.FocusDetailedState focusDetailedState;
+ }
+
+ public final class FocusModifierKt {
+ method public static androidx.ui.core.focus.FocusModifier FocusModifier();
+ method public static androidx.ui.core.focus.FocusState getFocusState(androidx.ui.core.focus.FocusModifier);
}
public final class FocusNodeUtilsKt {
}
+ @Deprecated public final class FocusOperator {
+ ctor @Deprecated public FocusOperator();
+ }
+
+ public enum FocusState {
+ enum_constant public static final androidx.ui.core.focus.FocusState Focused;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
+ }
+
+ public final class FocusStateKt {
+ method public static androidx.ui.core.focus.FocusState focusState(androidx.ui.core.focus.FocusDetailedState);
+ }
+
+ public final class FocusableKt {
+ method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
+ }
+
}
package androidx.ui.core.gesture {
@@ -1943,49 +1973,6 @@
}
-package androidx.ui.focus {
-
- public enum FocusDetailedState {
- enum_constant public static final androidx.ui.focus.FocusDetailedState Active;
- enum_constant public static final androidx.ui.focus.FocusDetailedState ActiveParent;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Captured;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Disabled;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Inactive;
- }
-
- public interface FocusModifier extends androidx.ui.core.Modifier.Element {
- method public boolean captureFocus();
- method public boolean freeFocus();
- method public androidx.ui.focus.FocusDetailedState getFocusDetailedState();
- method public void requestFocus();
- property public abstract androidx.ui.focus.FocusDetailedState focusDetailedState;
- }
-
- public final class FocusModifierProviderKt {
- method public static androidx.ui.focus.FocusModifier FocusModifier();
- method public static androidx.ui.focus.FocusState getFocusState(androidx.ui.focus.FocusModifier);
- }
-
- @Deprecated public final class FocusOperator {
- ctor @Deprecated public FocusOperator();
- }
-
- public enum FocusState {
- enum_constant public static final androidx.ui.focus.FocusState Focused;
- enum_constant public static final androidx.ui.focus.FocusState NotFocusable;
- enum_constant public static final androidx.ui.focus.FocusState NotFocused;
- }
-
- public final class FocusStateKt {
- method public static androidx.ui.focus.FocusState focusState(androidx.ui.focus.FocusDetailedState);
- }
-
- public final class FocusableKt {
- method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
- }
-
-}
-
package androidx.ui.graphics.vector {
public final class VectorAsset {
diff --git a/ui/ui-core/api/restricted_current.txt b/ui/ui-core/api/restricted_current.txt
index bded631..f09213b 100644
--- a/ui/ui-core/api/restricted_current.txt
+++ b/ui/ui-core/api/restricted_current.txt
@@ -726,10 +726,6 @@
method public static androidx.ui.core.Modifier paint(androidx.ui.core.Modifier, androidx.ui.graphics.painter.Painter painter, boolean sizeToIntrinsics = true, androidx.ui.core.Alignment alignment = Alignment.Center, androidx.ui.core.ContentScale contentScale = ContentScale.Inside, float alpha = 1.0f, androidx.ui.graphics.ColorFilter? colorFilter = null, boolean rtl = false);
}
- public final class ParentDataKt {
- method @Deprecated public static inline void ParentData(Object data, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- }
-
public interface ParentDataModifier extends androidx.ui.core.Modifier.Element {
method public default Object? modifyParentData(androidx.ui.unit.Density, Object? parentData);
}
@@ -945,7 +941,6 @@
method public static androidx.compose.ProvidableAmbient<androidx.ui.core.texttoolbar.TextToolbar> getTextToolbarAmbient();
method public static androidx.compose.ProvidableAmbient<androidx.ui.platform.UriHandler> getUriHandlerAmbient();
method public static androidx.compose.Composition setContent(androidx.activity.ComponentActivity, androidx.compose.Recomposer recomposer = Recomposer.current(), kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @Deprecated public static androidx.compose.Composition setContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setContent(android.view.ViewGroup, androidx.compose.Recomposer recomposer, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
@@ -979,13 +974,48 @@
package androidx.ui.core.focus {
- public final class FocusModifierImplKt {
- method public static androidx.ui.focus.FocusModifier createFocusModifier(androidx.ui.focus.FocusDetailedState focusDetailedState);
+ public enum FocusDetailedState {
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Disabled;
+ enum_constant public static final androidx.ui.core.focus.FocusDetailedState Inactive;
+ }
+
+ public interface FocusModifier extends androidx.ui.core.Modifier.Element {
+ method public boolean captureFocus();
+ method public boolean freeFocus();
+ method public androidx.ui.core.focus.FocusDetailedState getFocusDetailedState();
+ method public void requestFocus();
+ property public abstract androidx.ui.core.focus.FocusDetailedState focusDetailedState;
+ }
+
+ public final class FocusModifierKt {
+ method public static androidx.ui.core.focus.FocusModifier FocusModifier();
+ method public static androidx.ui.core.focus.FocusState getFocusState(androidx.ui.core.focus.FocusModifier);
}
public final class FocusNodeUtilsKt {
}
+ @Deprecated public final class FocusOperator {
+ ctor @Deprecated public FocusOperator();
+ }
+
+ public enum FocusState {
+ enum_constant public static final androidx.ui.core.focus.FocusState Focused;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
+ enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
+ }
+
+ public final class FocusStateKt {
+ method public static androidx.ui.core.focus.FocusState focusState(androidx.ui.core.focus.FocusDetailedState);
+ }
+
+ public final class FocusableKt {
+ method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
+ }
+
}
package androidx.ui.core.gesture {
@@ -1943,49 +1973,6 @@
}
-package androidx.ui.focus {
-
- public enum FocusDetailedState {
- enum_constant public static final androidx.ui.focus.FocusDetailedState Active;
- enum_constant public static final androidx.ui.focus.FocusDetailedState ActiveParent;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Captured;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Disabled;
- enum_constant public static final androidx.ui.focus.FocusDetailedState Inactive;
- }
-
- public interface FocusModifier extends androidx.ui.core.Modifier.Element {
- method public boolean captureFocus();
- method public boolean freeFocus();
- method public androidx.ui.focus.FocusDetailedState getFocusDetailedState();
- method public void requestFocus();
- property public abstract androidx.ui.focus.FocusDetailedState focusDetailedState;
- }
-
- public final class FocusModifierProviderKt {
- method public static androidx.ui.focus.FocusModifier FocusModifier();
- method public static androidx.ui.focus.FocusState getFocusState(androidx.ui.focus.FocusModifier);
- }
-
- @Deprecated public final class FocusOperator {
- ctor @Deprecated public FocusOperator();
- }
-
- public enum FocusState {
- enum_constant public static final androidx.ui.focus.FocusState Focused;
- enum_constant public static final androidx.ui.focus.FocusState NotFocusable;
- enum_constant public static final androidx.ui.focus.FocusState NotFocused;
- }
-
- public final class FocusStateKt {
- method public static androidx.ui.focus.FocusState focusState(androidx.ui.focus.FocusDetailedState);
- }
-
- public final class FocusableKt {
- method @Deprecated public static void Focusable(Object focusOperator, kotlin.jvm.functions.Function1<java.lang.Object,kotlin.Unit> children);
- }
-
-}
-
package androidx.ui.graphics.vector {
public final class VectorAsset {
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/focus/FocusableDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/focus/FocusableDemo.kt
index d7b5433..386580e 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/focus/FocusableDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/focus/FocusableDemo.kt
@@ -19,11 +19,11 @@
import androidx.compose.Composable
import androidx.ui.core.Modifier
import androidx.ui.core.gesture.tapGestureFilter
-import androidx.ui.focus.FocusModifier
-import androidx.ui.focus.FocusState.Focused
-import androidx.ui.focus.FocusState.NotFocusable
-import androidx.ui.focus.FocusState.NotFocused
-import androidx.ui.focus.focusState
+import androidx.ui.core.focus.FocusModifier
+import androidx.ui.core.focus.FocusState.Focused
+import androidx.ui.core.focus.FocusState.NotFocusable
+import androidx.ui.core.focus.FocusState.NotFocused
+import androidx.ui.core.focus.focusState
import androidx.ui.foundation.Text
import androidx.ui.graphics.Color
import androidx.ui.layout.Arrangement
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/keyinput/KeyInputDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/keyinput/KeyInputDemo.kt
index 482ca25..642005a 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/keyinput/KeyInputDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/keyinput/KeyInputDemo.kt
@@ -21,11 +21,11 @@
import androidx.compose.state
import androidx.ui.core.Modifier
import androidx.ui.core.gesture.tapGestureFilter
-import androidx.ui.focus.FocusModifier
-import androidx.ui.focus.FocusState.Focused
-import androidx.ui.focus.FocusState.NotFocusable
-import androidx.ui.focus.FocusState.NotFocused
-import androidx.ui.focus.focusState
+import androidx.ui.core.focus.FocusModifier
+import androidx.ui.core.focus.FocusState.Focused
+import androidx.ui.core.focus.FocusState.NotFocusable
+import androidx.ui.core.focus.FocusState.NotFocused
+import androidx.ui.core.focus.focusState
import androidx.ui.foundation.Text
import androidx.ui.graphics.Color
import androidx.ui.layout.Arrangement
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/CaptureFocusTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/CaptureFocusTest.kt
index 63ac2d2..792fd1c 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/CaptureFocusTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/CaptureFocusTest.kt
@@ -17,15 +17,15 @@
package androidx.ui.core.focus
import androidx.test.filters.SmallTest
-import androidx.ui.focus.FocusDetailedState.Active
-import androidx.ui.focus.FocusDetailedState.ActiveParent
-import androidx.ui.focus.FocusDetailedState.Captured
-import androidx.ui.focus.FocusDetailedState.Disabled
-import androidx.ui.focus.FocusDetailedState.Inactive
+import androidx.ui.core.focus.FocusDetailedState.Active
+import androidx.ui.core.focus.FocusDetailedState.ActiveParent
+import androidx.ui.core.focus.FocusDetailedState.Captured
+import androidx.ui.core.focus.FocusDetailedState.Disabled
+import androidx.ui.core.focus.FocusDetailedState.Inactive
import androidx.ui.foundation.Box
import androidx.ui.test.createComposeRule
-import androidx.ui.test.runOnUiThread
-import com.google.common.truth.Truth
+import androidx.ui.test.runOnIdleCompose
+import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -39,86 +39,106 @@
@Test
fun active_captureFocus_changesStateToCaptured() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(Active).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(Active)
+ Box(modifier = focusModifier)
+ }
- // Act.
- val success = focusModifier.captureFocus()
+ // Act.
+ val success = runOnIdleCompose {
+ focusModifier.captureFocus()
+ }
- // Assert.
- Truth.assertThat(success).isTrue()
- Truth.assertThat(focusModifier.focusDetailedState).isEqualTo(Captured)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(success).isTrue()
+ assertThat(focusModifier.focusDetailedState).isEqualTo(Captured)
}
}
@Test
fun activeParent_captureFocus_retainsStateAsActiveParent() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(ActiveParent).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(ActiveParent)
+ Box(modifier = focusModifier)
+ }
- // Act.
- val success = focusModifier.captureFocus()
+ // Act.
+ val success = runOnIdleCompose {
+ focusModifier.captureFocus()
+ }
- // Assert.
- Truth.assertThat(success).isFalse()
- Truth.assertThat(focusModifier.focusDetailedState).isEqualTo(ActiveParent)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(success).isFalse()
+ assertThat(focusModifier.focusDetailedState).isEqualTo(ActiveParent)
}
}
@Test
fun captured_captureFocus_retainsStateAsCaptured() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(Captured).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(Captured)
+ Box(modifier = focusModifier)
+ }
- // Act.
- val success = focusModifier.captureFocus()
+ // Act.
+ val success = runOnIdleCompose {
+ focusModifier.captureFocus()
+ }
- // Assert.
- Truth.assertThat(success).isTrue()
- Truth.assertThat(focusModifier.focusDetailedState).isEqualTo(Captured)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(success).isTrue()
+ assertThat(focusModifier.focusDetailedState).isEqualTo(Captured)
}
}
@Test
fun disabled_captureFocus_retainsStateAsDisabled() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(Disabled).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(Disabled)
+ Box(modifier = focusModifier)
+ }
- // Act.
- val success = focusModifier.captureFocus()
+ // Act.
+ val success = runOnIdleCompose {
+ focusModifier.captureFocus()
+ }
- // Assert.
- Truth.assertThat(success).isFalse()
- Truth.assertThat(focusModifier.focusDetailedState).isEqualTo(Disabled)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(success).isFalse()
+ assertThat(focusModifier.focusDetailedState).isEqualTo(Disabled)
}
}
@Test
fun inactive_captureFocus_retainsStateAsInactive() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(Inactive).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = focusModifier)
+ }
- // Act.
- val success = focusModifier.captureFocus()
+ // Act.
+ val success = runOnIdleCompose {
+ focusModifier.captureFocus()
+ }
- // Assert.
- Truth.assertThat(success).isFalse()
- Truth.assertThat(focusModifier.focusDetailedState).isEqualTo(Inactive)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(success).isFalse()
+ assertThat(focusModifier.focusDetailedState).isEqualTo(Inactive)
}
}
-}
\ No newline at end of file
+}
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindFocusableChildrenTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindFocusableChildrenTest.kt
index f630a48..4774df6 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindFocusableChildrenTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindFocusableChildrenTest.kt
@@ -18,13 +18,12 @@
import androidx.test.filters.SmallTest
import androidx.ui.core.Modifier
-import androidx.ui.focus.FocusDetailedState
import androidx.ui.foundation.Box
import androidx.ui.foundation.drawBackground
import androidx.ui.graphics.Color.Companion.Red
import androidx.ui.test.createComposeRule
-import androidx.ui.test.runOnUiThread
-import com.google.common.truth.Truth
+import androidx.ui.test.runOnIdleCompose
+import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -38,68 +37,84 @@
@Test
fun returnsFirstFocusNodeInModifierChain() {
- runOnUiThread {
- // Arrange.
- // layoutNode--focusNode1--focusNode2--focusNode3
- val focusModifier1 = createFocusModifier(FocusDetailedState.Inactive)
- val focusModifier2 = createFocusModifier(FocusDetailedState.Inactive)
- val focusModifier3 = createFocusModifier(FocusDetailedState.Inactive)
- composeTestRule.setContent {
- Box(modifier = focusModifier1 + focusModifier2 + focusModifier3)
- }
+ lateinit var focusModifier1: FocusModifier
+ lateinit var focusModifier2: FocusModifier
+ lateinit var focusModifier3: FocusModifier
+ // Arrange.
+ // layoutNode--focusNode1--focusNode2--focusNode3
+ composeTestRule.setContent {
+ focusModifier1 = FocusModifier()
+ focusModifier2 = FocusModifier()
+ focusModifier3 = FocusModifier()
+ Box(modifier = focusModifier1 + focusModifier2 + focusModifier3)
+ }
- // Act.
- val focusableChildren = focusModifier1.focusNode.focusableChildren()
+ // Act.
+ val focusableChildren = runOnIdleCompose {
+ focusModifier1.focusNode.focusableChildren()
+ }
- // Assert.
- Truth.assertThat(focusableChildren).containsExactly(focusModifier2.focusNode)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(focusableChildren).containsExactly(focusModifier2.focusNode)
}
}
@Test
fun skipsNonFocusNodesAndReturnsFirstFocusNodeInModifierChain() {
- runOnUiThread {
- // Arrange.
- // layoutNode--focusNode1--nonFocusNode--focusNode2
- val focusModifier1 = createFocusModifier(FocusDetailedState.Inactive)
- val focusModifier2 = createFocusModifier(FocusDetailedState.Inactive)
- composeTestRule.setContent {
- Box(modifier = focusModifier1 + Modifier.drawBackground(Red) + focusModifier2)
- }
+ lateinit var focusModifier1: FocusModifier
+ lateinit var focusModifier2: FocusModifier
+ // Arrange.
+ // layoutNode--focusNode1--nonFocusNode--focusNode2
+ composeTestRule.setContent {
+ focusModifier1 = FocusModifier()
+ focusModifier2 = FocusModifier()
+ Box(modifier = focusModifier1 + Modifier.drawBackground(Red) + focusModifier2)
+ }
- // Act.
- val focusableChildren = focusModifier1.focusNode.focusableChildren()
+ // Act.
+ val focusableChildren = runOnIdleCompose {
+ focusModifier1.focusNode.focusableChildren()
+ }
- // Assert.
- Truth.assertThat(focusableChildren).containsExactly(focusModifier2.focusNode)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(focusableChildren).containsExactly(focusModifier2.focusNode)
}
}
@Test
fun returnsFirstFocusChildOfEachChildLayoutNode() {
- runOnUiThread {
- // Arrange.
- // parentLayoutNode--parentFocusNode
- // |___________________________________
- // | |
- // childLayoutNode1--focusNode1 childLayoutNode2--focusNode2--focusNode3
- val parentFocusModifier = createFocusModifier(FocusDetailedState.Inactive)
- val focusModifier1 = createFocusModifier(FocusDetailedState.Inactive)
- val focusModifier2 = createFocusModifier(FocusDetailedState.Inactive)
- val focusModifier3 = createFocusModifier(FocusDetailedState.Inactive)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier1)
- Box(modifier = focusModifier2 + focusModifier3)
- }
+ // Arrange.
+ // parentLayoutNode--parentFocusNode
+ // |___________________________________
+ // | |
+ // childLayoutNode1--focusNode1 childLayoutNode2--focusNode2--focusNode3
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier1: FocusModifier
+ lateinit var focusModifier2: FocusModifier
+ lateinit var focusModifier3: FocusModifier
+ composeTestRule.setContent {
+ parentFocusModifier = FocusModifier()
+ focusModifier1 = FocusModifier()
+ focusModifier2 = FocusModifier()
+ focusModifier3 = FocusModifier()
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier1)
+ Box(modifier = focusModifier2 + focusModifier3)
}
+ }
- // Act.
- val focusableChildren = parentFocusModifier.focusNode.focusableChildren()
+ // Act.
+ val focusableChildren = runOnIdleCompose {
+ parentFocusModifier.focusNode.focusableChildren()
+ }
- // Assert.
- Truth.assertThat(focusableChildren)
- .containsExactly(focusModifier1.focusNode, focusModifier2.focusNode)
+ // Assert.
+ runOnIdleCompose {
+ assertThat(focusableChildren).containsExactly(
+ focusModifier1.focusNode, focusModifier2.focusNode
+ )
}
}
}
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindParentFocusNodeTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindParentFocusNodeTest.kt
index 5bb81b2..2548c47 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindParentFocusNodeTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FindParentFocusNodeTest.kt
@@ -18,13 +18,11 @@
import androidx.test.filters.SmallTest
import androidx.ui.core.Modifier
-import androidx.ui.focus.FocusDetailedState
-import androidx.ui.focus.FocusDetailedState.Inactive
import androidx.ui.foundation.Box
import androidx.ui.foundation.drawBackground
import androidx.ui.graphics.Color.Companion.Red
import androidx.ui.test.createComposeRule
-import androidx.ui.test.runOnUiThread
+import androidx.ui.test.runOnIdleCompose
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -39,138 +37,167 @@
@Test
fun noParentReturnsNull() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(FocusDetailedState.Inactive).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifier()
+ Box(modifier = focusModifier)
+ }
- // Act.
- val rootFocusNode = focusModifier.focusNode.findParentFocusNode()!!
- .findParentFocusNode()
+ // Act.
+ val rootFocusNode = runOnIdleCompose {
+ focusModifier.focusNode.findParentFocusNode()!!.findParentFocusNode()
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(rootFocusNode).isNull()
}
}
@Test
fun returnsImmediateParentFromModifierChain() {
- runOnUiThread {
- // Arrange.
- // focusNode1--focusNode2--focusNode3--focusNode4--focusNode5
- val modifier1 = createFocusModifier(Inactive)
- val modifier2 = createFocusModifier(Inactive)
- val modifier3 = createFocusModifier(Inactive)
- val modifier4 = createFocusModifier(Inactive)
- val modifier5 = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = modifier1 + modifier2 + modifier3 + modifier4 + modifier5) {}
- }
+ // Arrange.
+ // focusNode1--focusNode2--focusNode3--focusNode4--focusNode5
+ lateinit var modifier1: FocusModifier
+ lateinit var modifier2: FocusModifier
+ lateinit var modifier3: FocusModifier
+ lateinit var modifier4: FocusModifier
+ lateinit var modifier5: FocusModifier
+ composeTestRule.setFocusableContent {
+ modifier1 = FocusModifier()
+ modifier2 = FocusModifier()
+ modifier3 = FocusModifier()
+ modifier4 = FocusModifier()
+ modifier5 = FocusModifier()
+ Box(modifier = modifier1 + modifier2 + modifier3 + modifier4 + modifier5) {}
+ }
- // Act.
- val parent = modifier3.focusNode.findParentFocusNode()
+ // Act.
+ val parent = runOnIdleCompose {
+ modifier3.focusNode.findParentFocusNode()
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parent).isEqualTo(modifier2.focusNode)
}
}
@Test
fun returnsImmediateParentFromModifierChain_ignoresNonFocusModifiers() {
- runOnUiThread {
- // Arrange.
- // focusNode1--focusNode2--nonFocusNode--focusNode3
- val modifier1 = createFocusModifier(Inactive)
- val modifier2 = createFocusModifier(Inactive)
- val modifier3 = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = modifier1 + modifier2 + Modifier.drawBackground(Red) + modifier3)
- }
+ // Arrange.
+ // focusNode1--focusNode2--nonFocusNode--focusNode3
+ lateinit var modifier1: FocusModifier
+ lateinit var modifier2: FocusModifier
+ lateinit var modifier3: FocusModifier
+ composeTestRule.setFocusableContent {
+ modifier1 = FocusModifier()
+ modifier2 = FocusModifier()
+ modifier3 = FocusModifier()
+ Box(modifier = modifier1 + modifier2 + Modifier.drawBackground(Red) + modifier3)
+ }
- // Act.
- val parent = modifier3.focusNode.findParentFocusNode()
+ // Act.
+ val parent = runOnIdleCompose {
+ modifier3.focusNode.findParentFocusNode()
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parent).isEqualTo(modifier2.focusNode)
}
}
@Test
fun returnsLastFocusParentFromParentLayoutNode() {
- runOnUiThread {
- // Arrange.
- // parentLayoutNode--parentFocusNode1--parentFocusNode2
- // |
- // layoutNode--focusNode
- val parentFocusModifier1 = createFocusModifier(Inactive)
- val parentFocusModifier2 = createFocusModifier(Inactive)
- val focusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier1 + parentFocusModifier2) {
- Box(modifier = focusModifier)
- }
+ // Arrange.
+ // parentLayoutNode--parentFocusNode1--parentFocusNode2
+ // |
+ // layoutNode--focusNode
+ lateinit var parentFocusModifier1: FocusModifier
+ lateinit var parentFocusModifier2: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ parentFocusModifier1 = FocusModifier()
+ parentFocusModifier2 = FocusModifier()
+ focusModifier = FocusModifier()
+ Box(modifier = parentFocusModifier1 + parentFocusModifier2) {
+ Box(modifier = focusModifier)
}
+ }
- // Act.
- val parent = focusModifier.focusNode.findParentFocusNode()
+ // Act.
+ val parent = runOnIdleCompose {
+ focusModifier.focusNode.findParentFocusNode()
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parent).isEqualTo(parentFocusModifier2.focusNode)
}
}
@Test
fun returnsImmediateParent() {
- runOnUiThread {
- // Arrange.
- // grandparentLayoutNode--grandparentFocusNode
- // |
- // parentLayoutNode--parentFocusNode
- // |
- // layoutNode--focusNode
- val grandparentFocusModifier = createFocusModifier(Inactive)
- val parentFocusModifier = createFocusModifier(Inactive)
- val focusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = grandparentFocusModifier) {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier)
- }
+ // Arrange.
+ // grandparentLayoutNode--grandparentFocusNode
+ // |
+ // parentLayoutNode--parentFocusNode
+ // |
+ // layoutNode--focusNode
+ lateinit var grandparentFocusModifier: FocusModifier
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ grandparentFocusModifier = FocusModifier()
+ parentFocusModifier = FocusModifier()
+ focusModifier = FocusModifier()
+ Box(modifier = grandparentFocusModifier) {
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier)
}
}
+ }
- // Act.
- val parent = focusModifier.focusNode.findParentFocusNode()
+ // Act.
+ val parent = runOnIdleCompose {
+ focusModifier.focusNode.findParentFocusNode()
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parent).isEqualTo(parentFocusModifier.focusNode)
}
}
@Test
fun ignoresIntermediateLayoutNodesThatDontHaveFocusNodes() {
- runOnUiThread {
- // Arrange.
- // grandparentLayoutNode--grandparentFocusNode
- // |
- // parentLayoutNode
- // |
- // layoutNode--focusNode
- val grandparentFocusModifier = createFocusModifier(Inactive)
- val focusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = grandparentFocusModifier) {
- Box {
- Box(modifier = focusModifier)
- }
+ // Arrange.
+ // grandparentLayoutNode--grandparentFocusNode
+ // |
+ // parentLayoutNode
+ // |
+ // layoutNode--focusNode
+ lateinit var grandparentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ grandparentFocusModifier = FocusModifier()
+ focusModifier = FocusModifier()
+ Box(modifier = grandparentFocusModifier) {
+ Box {
+ Box(modifier = focusModifier)
}
}
+ }
- // Act.
- val parent = focusModifier.focusNode.findParentFocusNode()
+ // Act.
+ val parent = runOnIdleCompose {
+ focusModifier.focusNode.findParentFocusNode()
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parent).isEqualTo(grandparentFocusModifier.focusNode)
}
}
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FocusTestUtils.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FocusTestUtils.kt
index f470758..db6d410 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FocusTestUtils.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FocusTestUtils.kt
@@ -16,7 +16,12 @@
package androidx.ui.core.focus
-import androidx.ui.focus.FocusModifier
+import androidx.compose.Composable
+import androidx.ui.core.Modifier
+import androidx.ui.foundation.Box
+import androidx.ui.layout.size
+import androidx.ui.test.ComposeTestRule
+import androidx.ui.unit.dp
internal val FocusModifier.focusNode get() = (this as FocusModifierImpl).focusNode!!
@@ -24,4 +29,14 @@
get() = (this as FocusModifierImpl).focusedChild
set(value) {
(this as FocusModifierImpl).focusedChild = value
- }
\ No newline at end of file
+ }
+
+/**
+ * This function adds a parent composable which has size. [View.requestFocus()][android.view.View
+ * .requestFocus] will not take focus if the view has no size.
+ */
+internal fun ComposeTestRule.setFocusableContent(children: @Composable () -> Unit) {
+ setContent {
+ Box(modifier = Modifier.size(10.dp, 10.dp), children = children)
+ }
+}
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FreeFocusTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FreeFocusTest.kt
index 2913959..77e4e76 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FreeFocusTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/FreeFocusTest.kt
@@ -17,11 +17,11 @@
package androidx.ui.core.focus
import androidx.test.filters.SmallTest
-import androidx.ui.focus.FocusDetailedState.Active
-import androidx.ui.focus.FocusDetailedState.ActiveParent
-import androidx.ui.focus.FocusDetailedState.Captured
-import androidx.ui.focus.FocusDetailedState.Disabled
-import androidx.ui.focus.FocusDetailedState.Inactive
+import androidx.ui.core.focus.FocusDetailedState.Active
+import androidx.ui.core.focus.FocusDetailedState.ActiveParent
+import androidx.ui.core.focus.FocusDetailedState.Captured
+import androidx.ui.core.focus.FocusDetailedState.Disabled
+import androidx.ui.core.focus.FocusDetailedState.Inactive
import androidx.ui.foundation.Box
import androidx.ui.test.createComposeRule
import androidx.ui.test.runOnUiThread
@@ -41,8 +41,8 @@
fun active_freeFocus_retainFocusAsActive() {
runOnUiThread {
// Arrange.
- val focusModifier = createFocusModifier(Active).also {
- composeTestRule.setContent { Box(modifier = it) }
+ val focusModifier = FocusModifierImpl(Active).also {
+ composeTestRule.setFocusableContent { Box(modifier = it) }
}
// Act.
@@ -58,8 +58,8 @@
fun activeParent_freeFocus_retainFocusAsActiveParent() {
runOnUiThread {
// Arrange.
- val focusModifier = createFocusModifier(ActiveParent).also {
- composeTestRule.setContent { Box(modifier = it) }
+ val focusModifier = FocusModifierImpl(ActiveParent).also {
+ composeTestRule.setFocusableContent { Box(modifier = it) }
}
// Act.
@@ -75,8 +75,8 @@
fun captured_freeFocus_changesStateToActive() {
runOnUiThread {
// Arrange.
- val focusModifier = createFocusModifier(Captured).also {
- composeTestRule.setContent { Box(modifier = it) }
+ val focusModifier = FocusModifierImpl(Captured).also {
+ composeTestRule.setFocusableContent { Box(modifier = it) }
}
// Act.
@@ -92,8 +92,8 @@
fun disabled_freeFocus_retainFocusAsDisabled() {
runOnUiThread {
// Arrange.
- val focusModifier = createFocusModifier(Disabled).also {
- composeTestRule.setContent { Box(modifier = it) }
+ val focusModifier = FocusModifierImpl(Disabled).also {
+ composeTestRule.setFocusableContent { Box(modifier = it) }
}
// Act.
@@ -109,8 +109,8 @@
fun inactive_freeFocus_retainFocusAsInactive() {
runOnUiThread {
// Arrange.
- val focusModifier = createFocusModifier(Inactive).also {
- composeTestRule.setContent { Box(modifier = it) }
+ val focusModifier = FocusModifierImpl(Inactive).also {
+ composeTestRule.setFocusableContent { Box(modifier = it) }
}
// Act.
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/RequestFocusTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/RequestFocusTest.kt
index 8f72d8fb..19ff7db 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/RequestFocusTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/focus/RequestFocusTest.kt
@@ -17,14 +17,14 @@
package androidx.ui.core.focus
import androidx.test.filters.SmallTest
-import androidx.ui.focus.FocusDetailedState.Active
-import androidx.ui.focus.FocusDetailedState.ActiveParent
-import androidx.ui.focus.FocusDetailedState.Captured
-import androidx.ui.focus.FocusDetailedState.Disabled
-import androidx.ui.focus.FocusDetailedState.Inactive
+import androidx.ui.core.focus.FocusDetailedState.Active
+import androidx.ui.core.focus.FocusDetailedState.ActiveParent
+import androidx.ui.core.focus.FocusDetailedState.Captured
+import androidx.ui.core.focus.FocusDetailedState.Disabled
+import androidx.ui.core.focus.FocusDetailedState.Inactive
import androidx.ui.foundation.Box
import androidx.ui.test.createComposeRule
-import androidx.ui.test.runOnUiThread
+import androidx.ui.test.runOnIdleCompose
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
@@ -46,82 +46,104 @@
@Test
fun active_isUnchanged() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(Active).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(Active)
+ Box(modifier = focusModifier)
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(focusModifier.focusDetailedState).isEqualTo(Active)
}
}
@Test
fun captured_isUnchanged() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(Captured).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
- // Act.
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(Captured)
+ Box(modifier = focusModifier)
+ }
+
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(focusModifier.focusDetailedState).isEqualTo(Captured)
}
}
@Test
fun disabled_isUnchanged() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(Disabled).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(Disabled)
+ Box(modifier = focusModifier)
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(focusModifier.focusDetailedState).isEqualTo(Disabled)
}
}
@Test(expected = IllegalArgumentException::class)
fun activeParent_withNoFocusedChild_throwsException() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(ActiveParent).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(ActiveParent)
+ Box(modifier = focusModifier)
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
}
}
@Test
fun activeParent_propagateFocus() {
- runOnUiThread {
- // Arrange.
- val focusModifier = createFocusModifier(ActiveParent)
- val childFocusModifier = createFocusModifier(Active)
- composeTestRule.setContent {
- Box(modifier = focusModifier) {
- Box(modifier = childFocusModifier)
- }
+ // Arrange.
+ lateinit var focusModifier: FocusModifier
+ lateinit var childFocusModifier: FocusModifier
+
+ composeTestRule.setFocusableContent {
+ focusModifier = FocusModifierImpl(ActiveParent)
+ childFocusModifier = FocusModifierImpl(Active)
+ Box(modifier = focusModifier) {
+ Box(modifier = childFocusModifier)
}
+ }
+ runOnIdleCompose {
focusModifier.focusedChild = childFocusModifier.focusNode
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
when (propagateFocus) {
true -> {
// Unchanged.
@@ -139,36 +161,44 @@
@Test
fun inactiveRoot_propagateFocusSendsRequestToOwner_systemCanGrantFocus() {
- runOnUiThread {
- // Arrange.
- val rootFocusModifier = createFocusModifier(Inactive).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var rootFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ rootFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = rootFocusModifier)
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
rootFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(rootFocusModifier.focusDetailedState).isEqualTo(Active)
}
}
@Test
fun inactiveRootWithChildren_propagateFocusSendsRequestToOwner_systemCanGrantFocus() {
- runOnUiThread {
- // Arrange.
- val rootFocusModifier = createFocusModifier(Inactive)
- val childFocusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = rootFocusModifier) {
- Box(modifier = childFocusModifier)
- }
+ // Arrange.
+ lateinit var rootFocusModifier: FocusModifier
+ lateinit var childFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ rootFocusModifier = FocusModifierImpl(Inactive)
+ childFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = rootFocusModifier) {
+ Box(modifier = childFocusModifier)
}
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
rootFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
when (propagateFocus) {
true -> {
// Unchanged.
@@ -185,23 +215,28 @@
@Test
fun inactiveNonRootWithChilcren() {
- runOnUiThread {
- // Arrange.
- val parentFocusModifier = createFocusModifier(Active)
- val focusModifier = createFocusModifier(Inactive)
- val childFocusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier) {
- Box(modifier = childFocusModifier)
- }
+ // Arrange.
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ lateinit var childFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ parentFocusModifier = FocusModifierImpl(Active)
+ focusModifier = FocusModifierImpl(Inactive)
+ childFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier) {
+ Box(modifier = childFocusModifier)
}
}
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
when (propagateFocus) {
true -> {
assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
@@ -219,36 +254,44 @@
@Test
fun rootNode() {
- runOnUiThread {
- // Arrange.
- val rootFocusModifier = createFocusModifier(Inactive).also {
- composeTestRule.setContent { Box(modifier = it) }
- }
+ // Arrange.
+ lateinit var rootFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ rootFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = rootFocusModifier)
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
rootFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(rootFocusModifier.focusDetailedState).isEqualTo(Active)
}
}
@Test
fun rootNodeWithChildren() {
- runOnUiThread {
- // Arrange.
- val rootFocusModifier = createFocusModifier(Inactive)
- val childFocusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = rootFocusModifier) {
- Box(modifier = childFocusModifier)
- }
+ // Arrange.
+ lateinit var rootFocusModifier: FocusModifier
+ lateinit var childFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ rootFocusModifier = FocusModifierImpl(Inactive)
+ childFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = rootFocusModifier) {
+ Box(modifier = childFocusModifier)
}
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
rootFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
when (propagateFocus) {
true -> assertThat(rootFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
false -> assertThat(rootFocusModifier.focusDetailedState).isEqualTo(Active)
@@ -258,23 +301,28 @@
@Test
fun parentNodeWithNoFocusedAncestor() {
- runOnUiThread {
- // Arrange.
- val grandParentFocusModifier = createFocusModifier(Inactive)
- val parentFocusModifier = createFocusModifier(Inactive)
- val childFocusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = grandParentFocusModifier) {
- Box(modifier = parentFocusModifier) {
- Box(modifier = childFocusModifier)
- }
+ // Arrange.
+ lateinit var grandParentFocusModifier: FocusModifier
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var childFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ grandParentFocusModifier = FocusModifierImpl(Inactive)
+ parentFocusModifier = FocusModifierImpl(Inactive)
+ childFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = grandParentFocusModifier) {
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = childFocusModifier)
}
}
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
parentFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
when (propagateFocus) {
true -> assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
false -> assertThat(parentFocusModifier.focusDetailedState).isEqualTo(Active)
@@ -284,66 +332,79 @@
@Test
fun parentNodeWithNoFocusedAncestor_childRequestsFocus() {
- runOnUiThread {
- // Arrange.
- val grandParentFocusModifier = createFocusModifier(Inactive)
- val parentFocusModifier = createFocusModifier(Inactive)
- val childFocusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = grandParentFocusModifier) {
- Box(modifier = parentFocusModifier) {
- Box(modifier = childFocusModifier)
- }
+ // Arrange.
+ lateinit var grandParentFocusModifier: FocusModifier
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var childFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ grandParentFocusModifier = FocusModifierImpl(Inactive)
+ parentFocusModifier = FocusModifierImpl(Inactive)
+ childFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = grandParentFocusModifier) {
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = childFocusModifier)
}
}
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
childFocusModifier.focusNode.requestFocus(propagateFocus)
-
- // Assert.
+ }
+ // Assert.
+ runOnIdleCompose {
assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
}
}
@Test
fun childNodeWithNoFocusedAncestor() {
- runOnUiThread {
- // Arrange.
- val grandParentFocusModifier = createFocusModifier(Inactive)
- val parentFocusModifier = createFocusModifier(Inactive)
- val childFocusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = grandParentFocusModifier) {
- Box(modifier = parentFocusModifier) {
- Box(modifier = childFocusModifier)
- }
+ // Arrange.
+ lateinit var grandParentFocusModifier: FocusModifier
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var childFocusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ grandParentFocusModifier = FocusModifierImpl(Inactive)
+ parentFocusModifier = FocusModifierImpl(Inactive)
+ childFocusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = grandParentFocusModifier) {
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = childFocusModifier)
}
}
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
childFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(childFocusModifier.focusDetailedState).isEqualTo(Active)
}
}
@Test
fun requestFocus_parentIsFocused() {
- runOnUiThread {
- // Arrange.
- val parentFocusModifier = createFocusModifier(Active)
- val focusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier)
- }
+ // Arrange.
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ parentFocusModifier = FocusModifierImpl(Active)
+ focusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier)
}
+ }
- // After executing requestFocus, siblingNode will be 'Active'.
+ // After executing requestFocus, siblingNode will be 'Active'.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
assertThat(focusModifier.focusDetailedState).isEqualTo(Active)
}
@@ -351,21 +412,27 @@
@Test
fun requestFocus_childIsFocused() {
- runOnUiThread {
- // Arrange.
- val parentFocusModifier = createFocusModifier(ActiveParent)
- val focusModifier = createFocusModifier(Active)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier)
- }
+ // Arrange.
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ parentFocusModifier = FocusModifierImpl(ActiveParent)
+ focusModifier = FocusModifierImpl(Active)
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier)
}
+ }
+ runOnIdleCompose {
parentFocusModifier.focusedChild = focusModifier.focusNode
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
parentFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
when (propagateFocus) {
true -> {
assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
@@ -381,21 +448,27 @@
@Test
fun requestFocus_childHasCapturedFocus() {
- runOnUiThread {
- // Arrange.
- val parentFocusModifier = createFocusModifier(ActiveParent)
- val focusModifier = createFocusModifier(Captured)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier)
- }
+ // Arrange.
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ parentFocusModifier = FocusModifierImpl(ActiveParent)
+ focusModifier = FocusModifierImpl(Captured)
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier)
}
+ }
+ runOnIdleCompose {
parentFocusModifier.focusedChild = focusModifier.focusNode
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
parentFocusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
assertThat(focusModifier.focusDetailedState).isEqualTo(Captured)
}
@@ -403,23 +476,30 @@
@Test
fun requestFocus_siblingIsFocused() {
- runOnUiThread {
- // Arrange.
- val parentFocusModifier = createFocusModifier(ActiveParent)
- val focusModifier = createFocusModifier(Inactive)
- val siblingModifier = createFocusModifier(Active)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier)
- Box(modifier = siblingModifier)
- }
+ // Arrange.
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ lateinit var siblingModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ parentFocusModifier = FocusModifierImpl(ActiveParent)
+ focusModifier = FocusModifierImpl(Inactive)
+ siblingModifier = FocusModifierImpl(Active)
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier)
+ Box(modifier = siblingModifier)
}
+ }
+ runOnIdleCompose {
parentFocusModifier.focusedChild = siblingModifier.focusNode
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
assertThat(focusModifier.focusDetailedState).isEqualTo(Active)
assertThat(siblingModifier.focusDetailedState).isEqualTo(Inactive)
@@ -428,23 +508,30 @@
@Test
fun requestFocus_siblingHasCapturedFocused() {
- runOnUiThread {
- // Arrange.
- val parentFocusModifier = createFocusModifier(ActiveParent)
- val focusModifier = createFocusModifier(Inactive)
- val siblingModifier = createFocusModifier(Captured)
- composeTestRule.setContent {
- Box(modifier = parentFocusModifier) {
- Box(modifier = focusModifier)
- Box(modifier = siblingModifier)
- }
+ // Arrange.
+ lateinit var parentFocusModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ lateinit var siblingModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ parentFocusModifier = FocusModifierImpl(ActiveParent)
+ focusModifier = FocusModifierImpl(Inactive)
+ siblingModifier = FocusModifierImpl(Captured)
+ Box(modifier = parentFocusModifier) {
+ Box(modifier = focusModifier)
+ Box(modifier = siblingModifier)
}
+ }
+ runOnIdleCompose {
parentFocusModifier.focusedChild = siblingModifier.focusNode
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(parentFocusModifier.focusDetailedState).isEqualTo(ActiveParent)
assertThat(focusModifier.focusDetailedState).isEqualTo(Inactive)
assertThat(siblingModifier.focusDetailedState).isEqualTo(Captured)
@@ -453,34 +540,45 @@
@Test
fun requestFocus_cousinIsFocused() {
- runOnUiThread {
- // Arrange.
- val grandParentModifier = createFocusModifier(ActiveParent)
- val parentModifier = createFocusModifier(Inactive)
- val focusModifier = createFocusModifier(Inactive)
- val auntModifier = createFocusModifier(ActiveParent)
- val cousinModifier = createFocusModifier(Active)
- composeTestRule.setContent {
- Box(modifier = grandParentModifier) {
- Box(modifier = parentModifier) {
- Box(modifier = focusModifier)
- }
- Box(modifier = auntModifier) {
- Box(modifier = cousinModifier)
- }
+ // Arrange.
+ lateinit var grandParentModifier: FocusModifier
+ lateinit var parentModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ lateinit var auntModifier: FocusModifier
+ lateinit var cousinModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ grandParentModifier = FocusModifierImpl(ActiveParent)
+ parentModifier = FocusModifierImpl(Inactive)
+ focusModifier = FocusModifierImpl(Inactive)
+ auntModifier = FocusModifierImpl(ActiveParent)
+ cousinModifier = FocusModifierImpl(Active)
+ Box(modifier = grandParentModifier) {
+ Box(modifier = parentModifier) {
+ Box(modifier = focusModifier)
+ }
+ Box(modifier = auntModifier) {
+ Box(modifier = cousinModifier)
}
}
+ }
+ runOnIdleCompose {
grandParentModifier.focusedChild = auntModifier.focusNode
auntModifier.focusedChild = cousinModifier.focusNode
+ }
- // Verify Setup.
+ // Verify Setup.
+ runOnIdleCompose {
assertThat(cousinModifier.focusDetailedState).isEqualTo(Active)
assertThat(focusModifier.focusDetailedState).isEqualTo(Inactive)
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(cousinModifier.focusDetailedState).isEqualTo(Inactive)
assertThat(focusModifier.focusDetailedState).isEqualTo(Active)
}
@@ -488,23 +586,28 @@
@Test
fun requestFocus_grandParentIsFocused() {
- runOnUiThread {
- // Arrange.
- val grandParentModifier = createFocusModifier(Active)
- val parentModifier = createFocusModifier(Inactive)
- val focusModifier = createFocusModifier(Inactive)
- composeTestRule.setContent {
- Box(modifier = grandParentModifier) {
- Box(modifier = parentModifier) {
- Box(modifier = focusModifier)
- }
+ // Arrange.
+ lateinit var grandParentModifier: FocusModifier
+ lateinit var parentModifier: FocusModifier
+ lateinit var focusModifier: FocusModifier
+ composeTestRule.setFocusableContent {
+ grandParentModifier = FocusModifierImpl(Active)
+ parentModifier = FocusModifierImpl(Inactive)
+ focusModifier = FocusModifierImpl(Inactive)
+ Box(modifier = grandParentModifier) {
+ Box(modifier = parentModifier) {
+ Box(modifier = focusModifier)
}
}
+ }
- // Act.
+ // Act.
+ runOnIdleCompose {
focusModifier.focusNode.requestFocus(propagateFocus)
+ }
- // Assert.
+ // Assert.
+ runOnIdleCompose {
assertThat(grandParentModifier.focusDetailedState).isEqualTo(ActiveParent)
assertThat(parentModifier.focusDetailedState).isEqualTo(ActiveParent)
assertThat(focusModifier.focusDetailedState).isEqualTo(Active)
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
index 7b1e8ab..114bcfa 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/test/AndroidLayoutDrawTest.kt
@@ -52,7 +52,6 @@
import androidx.ui.core.MeasureScope
import androidx.ui.core.Modifier
import androidx.ui.core.Owner
-import androidx.ui.core.ParentData
import androidx.ui.core.ParentDataModifier
import androidx.ui.core.PassThroughLayout
import androidx.ui.core.Ref
@@ -2338,30 +2337,10 @@
PassThroughLayout {
FixedSize(50.ipx, LayoutTag("1"))
}
- PassThroughLayout {
- ParentData(LayoutTag("2")) {
- FixedSize(50.ipx, LayoutTag("1"))
- }
- }
- ParentData(LayoutTag("3")) {
- PassThroughLayout {
- ParentData(LayoutTag("2")) {
- FixedSize(50.ipx, LayoutTag("1"))
- }
- }
- }
- PassThroughLayout(LayoutTag("4")) {
- ParentData(LayoutTag("2")) {
- FixedSize(50.ipx, LayoutTag("1"))
- }
- }
}) { measurables, constraints, _ ->
assertEquals("1", measurables[0].tag)
val placeable = measurables[0].measure(constraints)
assertEquals(50.ipx, placeable.width)
- assertEquals("2", measurables[1].tag)
- assertEquals("3", measurables[2].tag)
- assertEquals("4", measurables[3].tag)
latch.countDown()
layout(0.ipx, 0.ipx) {}
}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/AndroidOwner.kt b/ui/ui-core/src/main/java/androidx/ui/core/AndroidOwner.kt
index c82e74b..9a63d23 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/AndroidOwner.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/AndroidOwner.kt
@@ -63,8 +63,8 @@
import androidx.ui.core.text.AndroidFontResourceLoader
import androidx.ui.core.texttoolbar.AndroidTextToolbar
import androidx.ui.core.texttoolbar.TextToolbar
-import androidx.ui.focus.FocusDetailedState.Active
-import androidx.ui.focus.FocusDetailedState.Inactive
+import androidx.ui.core.focus.FocusDetailedState.Active
+import androidx.ui.core.focus.FocusDetailedState.Inactive
import androidx.ui.geometry.Size
import androidx.ui.graphics.Canvas
import androidx.ui.graphics.painter.drawCanvas
@@ -133,6 +133,7 @@
}
}
}
+
override val semanticsOwner: SemanticsOwner = SemanticsOwner(root)
private var semanticsNodes: MutableMap<Int, SemanticsNodeCopy> = mutableMapOf()
private var semanticsRoot = SemanticsNodeCopy(semanticsOwner.rootSemanticsNode)
@@ -687,7 +688,8 @@
override fun dispatchDraw(canvas: android.graphics.Canvas) {
// TODO(b/154633012): move this to a proper place
if ((context.getSystemService(Context.ACCESSIBILITY_SERVICE)
- as AccessibilityManager).isEnabled) {
+ as AccessibilityManager).isEnabled
+ ) {
checkForSemanticsChanges()
}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt b/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt
index 75fd646..32f1d67 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/ComponentNodes.kt
@@ -21,7 +21,7 @@
import androidx.ui.core.pointerinput.PointerInputModifier
import androidx.ui.core.semantics.SemanticsModifier
import androidx.ui.core.semantics.SemanticsWrapper
-import androidx.ui.focus.FocusModifier
+import androidx.ui.core.focus.FocusModifier
import androidx.ui.graphics.Canvas
import androidx.ui.unit.Density
import androidx.ui.unit.IntPx
@@ -336,7 +336,7 @@
* TODO(b/154633015): Deprecated in Dev11. Delete for Dev12.
*/
@Deprecated(
- message = "FocusNode is deprecated. Use androidx.ui.focus.FocusModifier instead.",
+ message = "FocusNode is deprecated. Use androidx.ui.core.focus.FocusModifier instead.",
level = DeprecationLevel.ERROR
)
class FocusNode : ComponentNode()
@@ -658,37 +658,9 @@
return _layoutChildren
}
- /**
- * `true` when parentDataNode has to be rediscovered. This is when the
- * LayoutNode has been attached.
- */
- private var parentDataDirty = false
-
override val parentData: Any?
get() = layoutNodeWrapper.parentData
- /**
- * The parentData [DataNode] for this LayoutNode.
- */
- internal var parentDataNode: DataNode<*>? = null
- get() {
- if (parentDataDirty) {
- // walk up to find ParentData
- field = null
- var node = parent
- val parentLayoutNode = parentLayoutNode
- while (node != null && node !== parentLayoutNode) {
- if (node is DataNode<*> && node.key === ParentDataKey) {
- field = node
- break
- }
- node = node.parent
- }
- parentDataDirty = false
- }
- return field
- }
-
internal val innerLayoutNodeWrapper: LayoutNodeWrapper = InnerPlaceable(this)
internal var layoutNodeWrapper = innerLayoutNodeWrapper
@@ -708,6 +680,19 @@
private var outerZIndexModifier: ZIndexModifier? = null
/**
+ * The inner-most layer wrapper. Used for performance for LayoutNodeWrapper.findLayer().
+ */
+ internal var innerLayerWrapper: LayerWrapper? = null
+
+ /**
+ * Returns the inner-most layer as part of this LayoutNode or from the containing LayoutNode.
+ * This is added for performance so that LayoutNodeWrapper.findLayer() can be faster.
+ */
+ internal fun findLayer(): OwnedLayer? {
+ return innerLayerWrapper?.layer ?: parentLayoutNode?.findLayer()
+ }
+
+ /**
* The [Modifier] currently applied to this node.
*/
var modifier: Modifier = Modifier
@@ -721,6 +706,7 @@
onPositionedCallbacks.clear()
onChildPositionedCallbacks.clear()
outerZIndexModifier = null
+ innerLayerWrapper = null
layoutNodeWrapper = modifier.foldOut(innerLayoutNodeWrapper) { mod, toWrap ->
var wrapper = toWrap
// The order in which the following blocks occur matters. For example, the
@@ -737,7 +723,11 @@
wrapper = ModifiedDrawNode(wrapper, mod)
}
if (mod is DrawLayerModifier) {
- wrapper = LayerWrapper(wrapper, mod)
+ val layerWrapper = LayerWrapper(wrapper, mod)
+ wrapper = layerWrapper
+ if (innerLayerWrapper == null) {
+ innerLayerWrapper = layerWrapper
+ }
}
if (mod is FocusModifier) {
require(mod is FocusModifierImpl)
@@ -792,7 +782,6 @@
override fun attach(owner: Owner) {
super.attach(owner)
requestRemeasure()
- parentDataDirty = true
parentLayoutNode?.layoutChildrenDirty = true
layoutNodeWrapper.attach()
onAttach?.invoke(owner)
@@ -811,7 +800,6 @@
parentLayoutNode.layoutChildrenDirty = true
parentLayoutNode.requestRemeasure()
}
- parentDataDirty = true
alignmentLinesQueryOwner = null
onDetach?.invoke(owner)
layoutNodeWrapper.detach()
@@ -1185,7 +1173,6 @@
* for all ancestors.
*/
fun ComponentNode.findClosestParentNode(selector: (ComponentNode) -> Boolean): ComponentNode? {
- // TODO(b/143866294): move this to the testing side after the hierarchy isn't flattened anymore
var currentParent = parent
while (currentParent != null) {
if (selector(currentParent)) {
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt b/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
index 5da930c..0e6d8ca 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/InnerPlaceable.kt
@@ -28,6 +28,7 @@
import androidx.ui.unit.PxPosition
import androidx.ui.unit.toPxSize
import androidx.ui.util.fastAny
+import androidx.ui.util.fastFirstOrNull
import androidx.ui.util.fastForEach
internal class InnerPlaceable(
@@ -59,11 +60,10 @@
override val parentData: Any?
@Suppress("DEPRECATION")
get() = if (layoutNode.handlesParentData) {
- layoutNode.parentDataNode?.value
+ null
} else {
- layoutNode.parentDataNode?.value
- ?: layoutNode.layoutChildren
- .firstOrNull { it.layoutNodeWrapper.parentData != null }?.parentData
+ layoutNode.layoutChildren
+ .fastFirstOrNull { it.parentData != null }?.parentData
}
override fun findFocusWrapperWrappingThisWrapper() =
@@ -187,4 +187,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt b/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
index 16b05d0..47c2b40 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Layout.kt
@@ -36,6 +36,7 @@
import androidx.ui.unit.ipx
import androidx.ui.unit.max
import androidx.ui.unit.min
+import androidx.ui.util.fastForEach
/**
* [Layout] is the main core component for layout. It can be used to measure and position
@@ -199,7 +200,7 @@
val width = placeables.maxBy { it.width }?.width ?: constraints.minWidth
val height = placeables.maxBy { it.height }?.height ?: constraints.minHeight
layout(width, height) {
- placeables.forEach { it.place(IntPx.Zero, IntPx.Zero) }
+ placeables.fastForEach { it.place(IntPx.Zero, IntPx.Zero) }
}
}
MeasuringIntrinsicsMeasureBlocks(measureBlock)
@@ -207,8 +208,7 @@
LayoutNode(
modifier = currentComposer.materialize(modifier),
measureBlocks = measureBlocks,
- handlesParentData =
- false
+ handlesParentData = false
) {
children()
}
@@ -569,7 +569,7 @@
val layoutChildren = root.layoutChildren
var maxWidth: IntPx = constraints.minWidth
var maxHeight: IntPx = constraints.minHeight
- layoutChildren.forEach {
+ layoutChildren.fastForEach {
it.measure(constraints, layoutDirection)
maxWidth = max(maxWidth, it.width)
maxHeight = max(maxHeight, it.height)
@@ -578,7 +578,7 @@
maxHeight = min(maxHeight, constraints.maxHeight)
return measureScope.layout(maxWidth, maxHeight) {
- layoutChildren.forEach { it.place(IntPx.Zero, IntPx.Zero) }
+ layoutChildren.fastForEach { it.place(IntPx.Zero, IntPx.Zero) }
}
}
}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
index bc2fe55..b660d948 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
@@ -290,7 +290,13 @@
/**
* Returns the layer that this wrapper will draw into.
*/
- open fun findLayer(): OwnedLayer? = wrappedBy?.findLayer()
+ open fun findLayer(): OwnedLayer? {
+ return if (layoutNode.innerLayerWrapper != null) {
+ wrappedBy?.findLayer()
+ } else {
+ layoutNode.findLayer()
+ }
+ }
/**
* Returns the first [ModifiedFocusNode] in the wrapper list that wraps this
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/ModifiedParentDataNode.kt b/ui/ui-core/src/main/java/androidx/ui/core/ModifiedParentDataNode.kt
index 5d3f681..44e2e86 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/ModifiedParentDataNode.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/ModifiedParentDataNode.kt
@@ -26,7 +26,6 @@
* ParentData provided through the parentData node will override the data provided
* through a modifier
*/
- layoutNode.parentDataNode?.value
- ?: layoutNode.measureScope.modifyParentData(wrapped.parentData)
+ layoutNode.measureScope.modifyParentData(wrapped.parentData)
}
}
\ No newline at end of file
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/ParentData.kt b/ui/ui-core/src/main/java/androidx/ui/core/ParentData.kt
deleted file mode 100644
index 1767efb..0000000
--- a/ui/ui-core/src/main/java/androidx/ui/core/ParentData.kt
+++ /dev/null
@@ -1,42 +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.ui.core
-
-import androidx.compose.Composable
-
-/**
- * Provide data for the parent of a [Layout], which can then be read from the
- * corresponding [Measurable].
- *
- * A containing [Layout] sometimes needs to mark children with attributes that can later
- * be read during layout. [data] is assigned to the [Measurable.parentData] to be read.
- * Normally [ParentData] is completely controlled by the containing Layout. For example,
- * Row and Column layout models use parent data to access the flex value of their children
- * during measurement (though that is achieved using the Inflexible and Flexible modifiers,
- * rather than using this widget).
- *
- */
-@Deprecated(
- "ParentData composable is deprecated. You should either create a modifier which implements " +
- "ParentDataModifier interface, or use LayoutTag modifier if you simply need to tag " +
- "layout children to recognize them inside the measure block."
-)
-@Composable
-inline fun ParentData(data: Any, crossinline children: @Composable () -> Unit) {
- DataNode(key = ParentDataKey, value = data) {
- children()
- }
-}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt b/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt
index 93bdff0..b75aac0 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Wrapper.kt
@@ -148,32 +148,12 @@
// on the main thread.
recomposer: Recomposer = Recomposer.current(),
content: @Composable () -> Unit
-): Composition = setContent(this, recomposer, content)
-
-/**
- * Composes the given composable into the given activity. The composable will become the root view
- * of the given activity.
- *
- * @param content Composable that will be the content of the activity.
- */
-@Deprecated(
- "Your activity should extend androidx.activity.ComponentActivity " +
- "or AppCompatActivity"
-)
-fun Activity.setContent(
- content: @Composable () -> Unit
-): Composition = setContent(null, Recomposer.current(), content)
-
-private fun Activity.setContent(
- lifecycleOwner: LifecycleOwner?,
- recomposer: Recomposer,
- content: @Composable () -> Unit
): Composition {
FrameManager.ensureStarted()
val composeView: AndroidOwner = window.decorView
.findViewById<ViewGroup>(android.R.id.content)
.getChildAt(0) as? AndroidOwner
- ?: createOwner(this, lifecycleOwner).also {
+ ?: createOwner(this, this).also {
setContentView(it.view, DefaultLayoutParams)
}
return doSetContent(this, composeView, recomposer, content)
diff --git a/ui/ui-core/src/main/java/androidx/ui/focus/FocusModifier.kt b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusModifier.kt
similarity index 80%
rename from ui/ui-core/src/main/java/androidx/ui/focus/FocusModifier.kt
rename to ui/ui-core/src/main/java/androidx/ui/core/focus/FocusModifier.kt
index f5cc7ea..281627c 100644
--- a/ui/ui-core/src/main/java/androidx/ui/focus/FocusModifier.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusModifier.kt
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-package androidx.ui.focus
+package androidx.ui.core.focus
+import androidx.compose.Composable
+import androidx.compose.remember
import androidx.ui.core.Modifier
/**
@@ -56,4 +58,16 @@
* @return true if the focus was successfully released. false otherwise.
*/
fun freeFocus(): Boolean
-}
\ No newline at end of file
+}
+
+/**
+ * Use this function to create an instance of [FocusModifier]. Adding a [FocusModifier] to a
+ * [Composable] makes it focusable.
+ */
+@Composable
+fun FocusModifier(): FocusModifier = remember { FocusModifierImpl(FocusDetailedState.Inactive) }
+
+/**
+ * This function returns the [FocusState] for the component wrapped by this [FocusModifier].
+ */
+val FocusModifier.focusState: FocusState get() = focusDetailedState.focusState()
\ No newline at end of file
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusModifierImpl.kt b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusModifierImpl.kt
index 7e49169..dc207f1 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusModifierImpl.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusModifierImpl.kt
@@ -17,11 +17,6 @@
package androidx.ui.core.focus
import androidx.compose.Model
-import androidx.ui.focus.FocusDetailedState
-import androidx.ui.focus.FocusModifier
-
-fun createFocusModifier(focusDetailedState: FocusDetailedState): FocusModifier =
- FocusModifierImpl(focusDetailedState)
@Model
internal class FocusModifierImpl(
diff --git a/ui/ui-core/src/main/java/androidx/ui/focus/FocusState.kt b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusState.kt
similarity index 96%
rename from ui/ui-core/src/main/java/androidx/ui/focus/FocusState.kt
rename to ui/ui-core/src/main/java/androidx/ui/core/focus/FocusState.kt
index e2cae0c..bc5ec1b 100644
--- a/ui/ui-core/src/main/java/androidx/ui/focus/FocusState.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/focus/FocusState.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.ui.focus
+package androidx.ui.core.focus
/**
* Different states of the focus system.
diff --git a/ui/ui-core/src/main/java/androidx/ui/focus/Focusable.kt b/ui/ui-core/src/main/java/androidx/ui/core/focus/Focusable.kt
similarity index 89%
rename from ui/ui-core/src/main/java/androidx/ui/focus/Focusable.kt
rename to ui/ui-core/src/main/java/androidx/ui/core/focus/Focusable.kt
index a5c081d..9bdea93 100644
--- a/ui/ui-core/src/main/java/androidx/ui/focus/Focusable.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/focus/Focusable.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.ui.focus
+package androidx.ui.core.focus
import androidx.compose.Composable
@@ -36,7 +36,7 @@
*/
@Suppress("UNUSED_PARAMETER")
@Deprecated(
- message = "Focusable is deprecated. Use androidx.ui.focus.FocusModifier instead.",
+ message = "Focusable is deprecated. Use androidx.ui.core.focus.FocusModifier instead.",
level = DeprecationLevel.ERROR
)
@Composable
@@ -51,7 +51,7 @@
*/
@Deprecated(
message = "FocusOperator is used along with a Focusable. Focusable is deprecated in favor of " +
- "androidx.ui.focus.FocusModifier.",
+ "androidx.ui.core.focus.FocusModifier.",
level = DeprecationLevel.ERROR
)
class FocusOperator
\ No newline at end of file
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt b/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt
index c4bdf20..395348d 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/focus/ModifiedFocusNode.kt
@@ -17,11 +17,11 @@
import androidx.ui.core.DelegatingLayoutNodeWrapper
import androidx.ui.core.LayoutNodeWrapper
-import androidx.ui.focus.FocusDetailedState.Active
-import androidx.ui.focus.FocusDetailedState.ActiveParent
-import androidx.ui.focus.FocusDetailedState.Captured
-import androidx.ui.focus.FocusDetailedState.Disabled
-import androidx.ui.focus.FocusDetailedState.Inactive
+import androidx.ui.core.focus.FocusDetailedState.Active
+import androidx.ui.core.focus.FocusDetailedState.ActiveParent
+import androidx.ui.core.focus.FocusDetailedState.Captured
+import androidx.ui.core.focus.FocusDetailedState.Disabled
+import androidx.ui.core.focus.FocusDetailedState.Inactive
internal class ModifiedFocusNode(
wrapped: LayoutNodeWrapper,
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt b/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt
index 0140972..cc555e0 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/semantics/SemanticsNode.kt
@@ -344,7 +344,6 @@
* for all ancestors.
*/
fun SemanticsNode.findClosestParentNode(selector: (SemanticsNode) -> Boolean): SemanticsNode? {
- // TODO(b/143866294): move this to the testing side after the hierarchy isn't flattened anymore
var currentParent = parent
while (currentParent != null) {
if (currentParent.isSemanticBoundary && selector(currentParent)) {
diff --git a/ui/ui-core/src/main/java/androidx/ui/focus/FocusModifierProvider.kt b/ui/ui-core/src/main/java/androidx/ui/focus/FocusModifierProvider.kt
deleted file mode 100644
index 53e1f6a..0000000
--- a/ui/ui-core/src/main/java/androidx/ui/focus/FocusModifierProvider.kt
+++ /dev/null
@@ -1,33 +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.ui.focus
-
-import androidx.compose.Composable
-import androidx.compose.remember
-import androidx.ui.core.focus.createFocusModifier
-
-/**
- * Use this function to create an instance of [FocusModifier]. Adding a [FocusModifier] to a
- * [Composable] makes it focusable.
- */
-@Composable
-fun FocusModifier(): FocusModifier = remember { createFocusModifier(FocusDetailedState.Inactive) }
-
-/**
- * This function returns the [FocusState] for the component wrapped by this [FocusModifier].
- */
-val FocusModifier.focusState: FocusState get() = focusDetailedState.focusState()
\ No newline at end of file
diff --git a/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt b/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt
index 8985b93..7bd8279 100644
--- a/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/node/ViewInterop.kt
@@ -32,6 +32,7 @@
import androidx.ui.unit.IntPx
import androidx.ui.unit.ipx
import androidx.ui.unit.isFinite
+import androidx.ui.util.fastFirstOrNull
import androidx.ui.viewinterop.AndroidViewHolder
/**
@@ -157,7 +158,7 @@
inline fun <T : ViewAdapter> get(id: Int, factory: () -> T): T {
@Suppress("UNCHECKED_CAST")
- val existing = adapters.firstOrNull { it.id == id } as? T
+ val existing = adapters.fastFirstOrNull { it.id == id } as? T
if (existing != null) return existing
val next = factory()
adapters.add(next)
diff --git a/ui/ui-desktop/.gitignore b/ui/ui-desktop/.gitignore
new file mode 100644
index 0000000..7f0f0e2
--- /dev/null
+++ b/ui/ui-desktop/.gitignore
@@ -0,0 +1 @@
+compose-libs
diff --git a/ui/ui-desktop/android-emu/build.gradle b/ui/ui-desktop/android-emu/build.gradle
index 82dc30c..31dbd9a 100644
--- a/ui/ui-desktop/android-emu/build.gradle
+++ b/ui/ui-desktop/android-emu/build.gradle
@@ -22,14 +22,13 @@
import static androidx.build.dependencies.DependenciesKt.*
plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("AndroidXUiPlugin")
id("kotlin-multiplatform")
}
kotlin {
- jvm("desktop")
+ jvm("desktop") {
+ withJava()
+ }
sourceSets {
commonMain.dependencies {
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/IntRange.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/IntRange.java
new file mode 100644
index 0000000..a7ba1b4
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/IntRange.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 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 android.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated element should be an int or long in the given range
+ * <p>
+ * Example:
+ * <pre><code>
+ * @IntRange(from=0,to=255)
+ * public int getAlpha() {
+ * ...
+ * }
+ * </code></pre>
+ *
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE})
+public @interface IntRange {
+ /** Smallest value, inclusive */
+ long from() default Long.MIN_VALUE;
+
+ /** Largest value, inclusive */
+ long to() default Long.MAX_VALUE;
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/NonNull.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/NonNull.java
new file mode 100644
index 0000000..ff38cfe
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/NonNull.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 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 android.annotation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can never be null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value must never be {@code null}.
+ * @returnDoc This value will never be {@code null}.
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface NonNull {
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/Nullable.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/Nullable.java
new file mode 100644
index 0000000..1b3cb94
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/annotation/Nullable.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 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 android.annotation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can be null.
+ * <p>
+ * When decorating a method call parameter, this denotes that the parameter can
+ * legitimately be null and the method will gracefully deal with it. Typically
+ * used on optional parameters.
+ * <p>
+ * When decorating a method, this denotes the method might legitimately return
+ * null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value may be {@code null}.
+ * @returnDoc This value may be {@code null}.
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface Nullable {
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/compat/annotation/UnsupportedAppUsage.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/compat/annotation/UnsupportedAppUsage.java
new file mode 100644
index 0000000..079816d
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/compat/annotation/UnsupportedAppUsage.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 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 android.compat.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that this non-SDK interface is used by apps. A non-SDK interface is a
+ * class member (field or method) that is not part of the public SDK. Since the
+ * member is not part of the SDK, usage by apps is not supported.
+ *
+ * <h2>If you are an Android App developer</h2>
+ *
+ * This annotation indicates that you may be able to access the member at runtime, but that
+ * this access is discouraged and not supported by Android. If there is a value
+ * for {@link #maxTargetSdk()} on the annotation, access will be restricted based
+ * on the {@code targetSdkVersion} value set in your manifest.
+ *
+ * <p>Fields and methods annotated with this are likely to be restricted, changed
+ * or removed in future Android releases. If you rely on these members for
+ * functionality that is not otherwise supported by Android, consider filing a
+ * <a href="http://g.co/dev/appcompat">feature request</a>.
+ *
+ * <h2>If you are an Android OS developer</h2>
+ *
+ * This annotation acts as a heads up that changing a given method or field
+ * may affect apps, potentially breaking them when the next Android version is
+ * released. In some cases, for members that are heavily used, this annotation
+ * may imply restrictions on changes to the member.
+ *
+ * <p>This annotation also results in access to the member being permitted by the
+ * runtime, with a warning being generated in debug builds. Which apps can access
+ * the member is determined by the value of {@link #maxTargetSdk()}.
+ *
+ * <p>For more details, see go/UnsupportedAppUsage.
+ *
+ * {@hide}
+ */
+@Retention(CLASS)
+@Target({CONSTRUCTOR, METHOD, FIELD, TYPE})
+@Repeatable(UnsupportedAppUsage.Container.class)
+public @interface UnsupportedAppUsage {
+
+ /**
+ * Associates a bug tracking the work to add a public alternative to this API. Optional.
+ *
+ * @return ID of the associated tracking bug
+ */
+ long trackingBug() default 0;
+
+ /**
+ * Indicates that usage of this API is limited to apps based on their target SDK version.
+ *
+ * <p>Access to the API is allowed if the targetSdkVersion in the apps manifest is no greater
+ * than this value. Access checks are performed at runtime.
+ *
+ * <p>This is used to give app developers a grace period to migrate off a non-SDK interface.
+ * When making Android version N, existing APIs can have a maxTargetSdk of N-1 added to them.
+ * Developers must then migrate off the API when their app is updated in future, but it will
+ * continue working in the meantime.
+ *
+ * <p>Possible values are:
+ * <ul>
+ * <li>
+ * An API level like {@link VersionCodes#O} - in which case the API is available up to
+ * and including the specified release. Or, in other words, the API is blacklisted
+ * (unavailable) from the next API level from the one specified.
+ * </li>
+ * <li>
+ * absent (default value) - All apps can access this API, but doing so may result in
+ * warnings in the log, UI warnings (on developer builds) and/or strictmode violations.
+ * The API is likely to be further restricted in future.
+ * </li>
+ *
+ * </ul>
+ *
+ * @return The maximum value for an apps targetSdkVersion in order to access this API.
+ */
+ int maxTargetSdk() default Integer.MAX_VALUE;
+
+ /**
+ * The signature of an implicit (not present in the source) member that forms part of the
+ * hiddenapi.
+ *
+ * <p>Allows access to non-SDK API elements that are not represented in the input source to be
+ * managed.
+ *
+ * <p>This must only be used when applying the annotation to a type, using it in any other
+ * situation is an error.
+ *
+ * @return A dex API signature.
+ */
+ String implicitMember() default "";
+
+ /**
+ * Public API alternatives to this API.
+ *
+ * <p>If non-empty, the string must be a description of the public API alternative(s) to this
+ * API. The explanation must contain at least one Javadoc link tag to public API methods or
+ * fields. e.g.:
+ * {@literal @UnsupportedAppUsage(publicAlternatives="Use {@link foo.bar.Baz#bat()} instead.")}
+ *
+ * <p>Any elements that can be deduced can be omitted, e.g.:
+ * <ul>
+ * <li>
+ * the class, if it's the same as for the annotated element.
+ * </li>
+ * <li>
+ * the package name, if it's the same as for the annotated element.
+ * </li>
+ * <li>
+ * the method parameters, if there is only one method with that name in the given
+ * package and class.
+ * </li>
+ * </ul>
+ * @return A Javadoc-formatted string.
+ */
+ @SuppressWarnings("JavadocReference")
+ String publicAlternatives() default "";
+
+ /**
+ * Container for {@link UnsupportedAppUsage} that allows it to be applied repeatedly to types.
+ */
+ @Retention(CLASS)
+ @Target(TYPE)
+ @interface Container {
+ UnsupportedAppUsage[] value();
+ }
+
+ /**
+ * Internal usage only.
+ *
+ * Override the default source position when generating an index of the annotations.
+ *
+ * <p>This is intended for use by tools that generate java source code, to point to the
+ * original source position of the annotation, rather than the position within the generated
+ * code. It should never be set manually.
+ *
+ * <p>The format of the value is "path/to/file:startline:startcol:endline:endcol" indicating
+ * the position of the annotation itself.
+ */
+ String overrideSourcePosition() default "";
+
+ /**
+ * Internal usage only.
+ *
+ * For debug use only. The expected dex signature to be generated for this API, used to verify
+ * parts of the build process.
+ *
+ * @return A dex API signature.
+ */
+ String expectedSignature() default "";
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/BoringLayout.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/BoringLayout.java
new file mode 100644
index 0000000..dd442d5
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/BoringLayout.java
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+import android.compat.annotation.UnsupportedAppUsage;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.text.style.ParagraphStyle;
+
+/**
+ * A BoringLayout is a very simple Layout implementation for text that
+ * fits on a single line and is all left-to-right characters.
+ * You will probably never want to make one of these yourself;
+ * if you do, be sure to call {@link #isBoring} first to make sure
+ * the text meets the criteria.
+ * <p>This class is used by widgets to control text layout. You should not need
+ * to use this class directly unless you are implementing your own widget
+ * or custom display object, in which case
+ * you are encouraged to use a Layout instead of calling
+ * {@link android.graphics.Canvas#drawText(
+ * java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
+ * Canvas.drawText()} directly.</p>
+ */
+public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback {
+
+ /**
+ * Utility function to construct a BoringLayout instance.
+ *
+ * @param source the text to render
+ * @param paint the default paint for the layout
+ * @param outerWidth the wrapping width for the text
+ * @param align whether to left, right, or center the text
+ * @param spacingMult this value is no longer used by BoringLayout
+ * @param spacingAdd this value is no longer used by BoringLayout
+ * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
+ * line width
+ * @param includePad set whether to include extra space beyond font ascent and descent which is
+ * needed to avoid clipping in some scripts
+ */
+ public static BoringLayout make(CharSequence source, TextPaint paint, int outerWidth,
+ Alignment align, float spacingMult, float spacingAdd, BoringLayout.Metrics metrics,
+ boolean includePad) {
+ return new BoringLayout(source, paint, outerWidth, align, spacingMult, spacingAdd, metrics,
+ includePad);
+ }
+
+ /**
+ * Utility function to construct a BoringLayout instance.
+ *
+ * @param source the text to render
+ * @param paint the default paint for the layout
+ * @param outerWidth the wrapping width for the text
+ * @param align whether to left, right, or center the text
+ * @param spacingmult this value is no longer used by BoringLayout
+ * @param spacingadd this value is no longer used by BoringLayout
+ * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
+ * line width
+ * @param includePad set whether to include extra space beyond font ascent and descent which is
+ * needed to avoid clipping in some scripts
+ * @param ellipsize whether to ellipsize the text if width of the text is longer than the
+ * requested width
+ * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
+ * {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
+ * not used, {@code outerWidth} is used instead
+ */
+ public static BoringLayout make(CharSequence source, TextPaint paint, int outerWidth,
+ Alignment align, float spacingmult, float spacingadd, BoringLayout.Metrics metrics,
+ boolean includePad, TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+ return new BoringLayout(source, paint, outerWidth, align, spacingmult, spacingadd, metrics,
+ includePad, ellipsize, ellipsizedWidth);
+ }
+
+ /**
+ * Returns a BoringLayout for the specified text, potentially reusing
+ * this one if it is already suitable. The caller must make sure that
+ * no one is still using this Layout.
+ *
+ * @param source the text to render
+ * @param paint the default paint for the layout
+ * @param outerwidth the wrapping width for the text
+ * @param align whether to left, right, or center the text
+ * @param spacingMult this value is no longer used by BoringLayout
+ * @param spacingAdd this value is no longer used by BoringLayout
+ * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
+ * line width
+ * @param includePad set whether to include extra space beyond font ascent and descent which is
+ * needed to avoid clipping in some scripts
+ */
+ public BoringLayout replaceOrMake(CharSequence source, TextPaint paint, int outerwidth,
+ Alignment align, float spacingMult, float spacingAdd, BoringLayout.Metrics metrics,
+ boolean includePad) {
+ replaceWith(source, paint, outerwidth, align, spacingMult, spacingAdd);
+
+ mEllipsizedWidth = outerwidth;
+ mEllipsizedStart = 0;
+ mEllipsizedCount = 0;
+
+ init(source, paint, align, metrics, includePad, true);
+ return this;
+ }
+
+ /**
+ * Returns a BoringLayout for the specified text, potentially reusing
+ * this one if it is already suitable. The caller must make sure that
+ * no one is still using this Layout.
+ *
+ * @param source the text to render
+ * @param paint the default paint for the layout
+ * @param outerWidth the wrapping width for the text
+ * @param align whether to left, right, or center the text
+ * @param spacingMult this value is no longer used by BoringLayout
+ * @param spacingAdd this value is no longer used by BoringLayout
+ * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
+ * line width
+ * @param includePad set whether to include extra space beyond font ascent and descent which is
+ * needed to avoid clipping in some scripts
+ * @param ellipsize whether to ellipsize the text if width of the text is longer than the
+ * requested width
+ * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
+ * {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
+ * not used, {@code outerwidth} is used instead
+ */
+ public BoringLayout replaceOrMake(CharSequence source, TextPaint paint, int outerWidth,
+ Alignment align, float spacingMult, float spacingAdd, BoringLayout.Metrics metrics,
+ boolean includePad, TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+ boolean trust;
+
+ if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
+ replaceWith(source, paint, outerWidth, align, spacingMult, spacingAdd);
+
+ mEllipsizedWidth = outerWidth;
+ mEllipsizedStart = 0;
+ mEllipsizedCount = 0;
+ trust = true;
+ } else {
+ replaceWith(TextUtils.ellipsize(source, paint, ellipsizedWidth, ellipsize, true, this),
+ paint, outerWidth, align, spacingMult, spacingAdd);
+
+ mEllipsizedWidth = ellipsizedWidth;
+ trust = false;
+ }
+
+ init(getText(), paint, align, metrics, includePad, trust);
+ return this;
+ }
+
+ /**
+ * @param source the text to render
+ * @param paint the default paint for the layout
+ * @param outerwidth the wrapping width for the text
+ * @param align whether to left, right, or center the text
+ * @param spacingMult this value is no longer used by BoringLayout
+ * @param spacingAdd this value is no longer used by BoringLayout
+ * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
+ * line width
+ * @param includePad set whether to include extra space beyond font ascent and descent which is
+ * needed to avoid clipping in some scripts
+ */
+ public BoringLayout(CharSequence source, TextPaint paint, int outerwidth, Alignment align,
+ float spacingMult, float spacingAdd, BoringLayout.Metrics metrics, boolean includePad) {
+ super(source, paint, outerwidth, align, spacingMult, spacingAdd);
+
+ mEllipsizedWidth = outerwidth;
+ mEllipsizedStart = 0;
+ mEllipsizedCount = 0;
+
+ init(source, paint, align, metrics, includePad, true);
+ }
+
+ /**
+ *
+ * @param source the text to render
+ * @param paint the default paint for the layout
+ * @param outerWidth the wrapping width for the text
+ * @param align whether to left, right, or center the text
+ * @param spacingMult this value is no longer used by BoringLayout
+ * @param spacingAdd this value is no longer used by BoringLayout
+ * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
+ * line width
+ * @param includePad set whether to include extra space beyond font ascent and descent which is
+ * needed to avoid clipping in some scripts
+ * @param ellipsize whether to ellipsize the text if width of the text is longer than the
+ * requested {@code outerwidth}
+ * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
+ * {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
+ * not used, {@code outerwidth} is used instead
+ */
+ public BoringLayout(CharSequence source, TextPaint paint, int outerWidth, Alignment align,
+ float spacingMult, float spacingAdd, BoringLayout.Metrics metrics, boolean includePad,
+ TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+ /*
+ * It is silly to have to call super() and then replaceWith(),
+ * but we can't use "this" for the callback until the call to
+ * super() finishes.
+ */
+ super(source, paint, outerWidth, align, spacingMult, spacingAdd);
+
+ boolean trust;
+
+ if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
+ mEllipsizedWidth = outerWidth;
+ mEllipsizedStart = 0;
+ mEllipsizedCount = 0;
+ trust = true;
+ } else {
+ replaceWith(TextUtils.ellipsize(source, paint, ellipsizedWidth, ellipsize, true, this),
+ paint, outerWidth, align, spacingMult, spacingAdd);
+
+ mEllipsizedWidth = ellipsizedWidth;
+ trust = false;
+ }
+
+ init(getText(), paint, align, metrics, includePad, trust);
+ }
+
+ /* package */ void init(CharSequence source, TextPaint paint, Alignment align,
+ BoringLayout.Metrics metrics, boolean includePad, boolean trustWidth) {
+ int spacing;
+
+ if (source instanceof String && align == Layout.Alignment.ALIGN_NORMAL) {
+ mDirect = source.toString();
+ } else {
+ mDirect = null;
+ }
+
+ mPaint = paint;
+
+ if (includePad) {
+ spacing = metrics.bottom - metrics.top;
+ mDesc = metrics.bottom;
+ } else {
+ spacing = metrics.descent - metrics.ascent;
+ mDesc = metrics.descent;
+ }
+
+ mBottom = spacing;
+
+ if (trustWidth) {
+ mMax = metrics.width;
+ } else {
+ /*
+ * If we have ellipsized, we have to actually calculate the
+ * width because the width that was passed in was for the
+ * full text, not the ellipsized form.
+ */
+ TextLine line = TextLine.obtain();
+ line.set(paint, source, 0, source.length(), Layout.DIR_LEFT_TO_RIGHT,
+ Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null,
+ mEllipsizedStart, mEllipsizedStart + mEllipsizedCount);
+ mMax = (int) Math.ceil(line.metrics(null));
+ TextLine.recycle(line);
+ }
+
+ if (includePad) {
+ mTopPadding = metrics.top - metrics.ascent;
+ mBottomPadding = metrics.bottom - metrics.descent;
+ }
+ }
+
+ /**
+ * Determine and compute metrics if given text can be handled by BoringLayout.
+ *
+ * @param text a text
+ * @param paint a paint
+ * @return layout metric for the given text. null if given text is unable to be handled by
+ * BoringLayout.
+ */
+ public static Metrics isBoring(CharSequence text, TextPaint paint) {
+ return isBoring(text, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR, null);
+ }
+
+ /**
+ * Determine and compute metrics if given text can be handled by BoringLayout.
+ *
+ * @param text a text
+ * @param paint a paint
+ * @param metrics a metrics object to be recycled. If null is passed, this function creat new
+ * object.
+ * @return layout metric for the given text. If metrics is not null, this method fills values
+ * to given metrics object instead of allocating new metrics object. null if given text
+ * is unable to be handled by BoringLayout.
+ */
+ public static Metrics isBoring(CharSequence text, TextPaint paint, Metrics metrics) {
+ return isBoring(text, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR, metrics);
+ }
+
+ /**
+ * Returns true if the text contains any RTL characters, bidi format characters, or surrogate
+ * code units.
+ */
+ private static boolean hasAnyInterestingChars(CharSequence text, int textLength) {
+ final int maxBufLen = 500;
+ final char[] buffer = TextUtils.obtain(maxBufLen);
+ try {
+ for (int start = 0; start < textLength; start += maxBufLen) {
+ final int end = Math.min(start + maxBufLen, textLength);
+
+ // No need to worry about getting half codepoints, since we consider surrogate code
+ // units "interesting" as soon we see one.
+ TextUtils.getChars(text, start, end, buffer, 0);
+
+ final int len = end - start;
+ for (int i = 0; i < len; i++) {
+ final char c = buffer[i];
+ if (c == '\n' || c == '\t' || TextUtils.couldAffectRtl(c)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ } finally {
+ TextUtils.recycle(buffer);
+ }
+ }
+
+ /**
+ * Returns null if not boring; the width, ascent, and descent in the
+ * provided Metrics object (or a new one if the provided one was null)
+ * if boring.
+ */
+ @UnsupportedAppUsage
+ public static Metrics isBoring(CharSequence text, TextPaint paint,
+ TextDirectionHeuristic textDir, Metrics metrics) {
+ final int textLength = text.length();
+ if (hasAnyInterestingChars(text, textLength)) {
+ return null; // There are some interesting characters. Not boring.
+ }
+ if (textDir != null && textDir.isRtl(text, 0, textLength)) {
+ return null; // The heuristic considers the whole text RTL. Not boring.
+ }
+ if (text instanceof Spanned) {
+ Spanned sp = (Spanned) text;
+ Object[] styles = sp.getSpans(0, textLength, ParagraphStyle.class);
+ if (styles.length > 0) {
+ return null; // There are some ParagraphStyle spans. Not boring.
+ }
+ }
+
+ Metrics fm = metrics;
+ if (fm == null) {
+ fm = new Metrics();
+ } else {
+ fm.reset();
+ }
+
+ TextLine line = TextLine.obtain();
+ line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
+ Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null,
+ 0 /* ellipsisStart, 0 since text has not been ellipsized at this point */,
+ 0 /* ellipsisEnd, 0 since text has not been ellipsized at this point */);
+ fm.width = (int) Math.ceil(line.metrics(fm));
+ TextLine.recycle(line);
+
+ return fm;
+ }
+
+ @Override
+ public int getHeight() {
+ return mBottom;
+ }
+
+ @Override
+ public int getLineCount() {
+ return 1;
+ }
+
+ @Override
+ public int getLineTop(int line) {
+ if (line == 0) {
+ return 0;
+ } else {
+ return mBottom;
+ }
+ }
+
+ @Override
+ public int getLineDescent(int line) {
+ return mDesc;
+ }
+
+ @Override
+ public int getLineStart(int line) {
+ if (line == 0) {
+ return 0;
+ } else {
+ return getText().length();
+ }
+ }
+
+ @Override
+ public int getParagraphDirection(int line) {
+ return DIR_LEFT_TO_RIGHT;
+ }
+
+ @Override
+ public boolean getLineContainsTab(int line) {
+ return false;
+ }
+
+ @Override
+ public float getLineMax(int line) {
+ return mMax;
+ }
+
+ @Override
+ public float getLineWidth(int line) {
+ return (line == 0 ? mMax : 0);
+ }
+
+ @Override
+ public final Directions getLineDirections(int line) {
+ return Layout.DIRS_ALL_LEFT_TO_RIGHT;
+ }
+
+ @Override
+ public int getTopPadding() {
+ return mTopPadding;
+ }
+
+ @Override
+ public int getBottomPadding() {
+ return mBottomPadding;
+ }
+
+ @Override
+ public int getEllipsisCount(int line) {
+ return mEllipsizedCount;
+ }
+
+ @Override
+ public int getEllipsisStart(int line) {
+ return mEllipsizedStart;
+ }
+
+ @Override
+ public int getEllipsizedWidth() {
+ return mEllipsizedWidth;
+ }
+
+ // Override draw so it will be faster.
+ @Override
+ public void draw(Canvas c, Path highlight, Paint highlightpaint,
+ int cursorOffset) {
+ if (mDirect != null && highlight == null) {
+ c.drawText(mDirect, 0, mBottom - mDesc, mPaint);
+ } else {
+ super.draw(c, highlight, highlightpaint, cursorOffset);
+ }
+ }
+
+ /**
+ * Callback for the ellipsizer to report what region it ellipsized.
+ */
+ public void ellipsized(int start, int end) {
+ mEllipsizedStart = start;
+ mEllipsizedCount = end - start;
+ }
+
+ private String mDirect;
+ private Paint mPaint;
+
+ /* package */ int mBottom, mDesc; // for Direct
+ private int mTopPadding, mBottomPadding;
+ private float mMax;
+ private int mEllipsizedWidth, mEllipsizedStart, mEllipsizedCount;
+
+ /**
+ * Metrics.
+ */
+ public static class Metrics extends Paint.FontMetricsInt {
+ public int width;
+
+ @Override public String toString() {
+ return super.toString() + " width=" + width;
+ }
+
+ private void reset() {
+ top = 0;
+ bottom = 0;
+ ascent = 0;
+ descent = 0;
+ width = 0;
+ leading = 0;
+ }
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/GetChars.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/GetChars.java
new file mode 100644
index 0000000..7a7d5be
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/GetChars.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+/**
+ * Please implement this interface if your CharSequence has a
+ * getChars() method like the one in String that is faster than
+ * calling charAt() multiple times.
+ */
+public interface GetChars extends CharSequence {
+ /**
+ * Exactly like String.getChars(): copy chars <code>start</code>
+ * through <code>end - 1</code> from this CharSequence into <code>dest</code>
+ * beginning at offset <code>destoff</code>.
+ */
+ void getChars(int start, int end, char[] dest, int destoff);
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/NoCopySpan.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/NoCopySpan.java
new file mode 100644
index 0000000..4cbe062
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/NoCopySpan.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2009 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 android.text;
+
+/**
+ * This interface should be added to a span object that should not be copied
+ * into a new Spanned when performing a slice or copy operation on the original
+ * Spanned it was placed in.
+ */
+public interface NoCopySpan {
+ /**
+ * Convenience equivalent for when you would just want a new Object() for
+ * a span but want it to be no-copy. Use this instead.
+ */
+ class Concrete implements NoCopySpan {
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpanWatcher.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpanWatcher.java
new file mode 100644
index 0000000..e1eee36
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpanWatcher.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+/**
+ * When an object of this type is attached to a Spannable, its methods
+ * will be called to notify it that other markup objects have been
+ * added, changed, or removed.
+ */
+public interface SpanWatcher extends NoCopySpan {
+ /**
+ * This method is called to notify you that the specified object
+ * has been attached to the specified range of the text.
+ */
+ void onSpanAdded(Spannable text, Object what, int start, int end);
+ /**
+ * This method is called to notify you that the specified object
+ * has been detached from the specified range of the text.
+ */
+ void onSpanRemoved(Spannable text, Object what, int start, int end);
+ /**
+ * This method is called to notify you that the specified object
+ * has been relocated from the range <code>ostart…oend</code>
+ * to the new range <code>nstart…nend</code> of the text.
+ */
+ void onSpanChanged(Spannable text, Object what, int ostart, int oend,
+ int nstart, int nend);
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/Spannable.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/Spannable.java
new file mode 100644
index 0000000..e374fba
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/Spannable.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+/**
+ * This is the interface for text to which markup objects can be
+ * attached and detached. Not all Spannable classes have mutable text;
+ * see {@link Editable} for that.
+ */
+public interface Spannable extends Spanned {
+ /**
+ * Attach the specified markup object to the range <code>start…end</code>
+ * of the text, or move the object to that range if it was already
+ * attached elsewhere. See {@link Spanned} for an explanation of
+ * what the flags mean. The object can be one that has meaning only
+ * within your application, or it can be one that the text system will
+ * use to affect text display or behavior. Some noteworthy ones are
+ * the subclasses of {@link android.text.style.CharacterStyle} and
+ * {@link android.text.style.ParagraphStyle}, and
+ * {@link android.text.TextWatcher} and
+ * {@link android.text.SpanWatcher}.
+ */
+ void setSpan(Object what, int start, int end, int flags);
+
+ /**
+ * Remove the specified object from the range of text to which it
+ * was attached, if any. It is OK to remove an object that was never
+ * attached in the first place.
+ */
+ void removeSpan(Object what);
+
+ /**
+ * Remove the specified object from the range of text to which it
+ * was attached, if any. It is OK to remove an object tShat was never
+ * attached in the first place.
+ *
+ * See {@link Spanned} for an explanation of what the flags mean.
+ *
+ */
+ default void removeSpan(Object what, int flags) {
+ removeSpan(what);
+ }
+
+ /**
+ * Factory used by TextView to create new {@link Spannable Spannables}. You can subclass
+ * it to provide something other than {@link SpannableString}.
+ *
+ * @see android.widget.TextView#setSpannableFactory(Factory)
+ */
+ class Factory {
+ private static Spannable.Factory sInstance = new Spannable.Factory();
+
+ /**
+ * Returns the standard Spannable Factory.
+ */
+ public static Spannable.Factory getInstance() {
+ return sInstance;
+ }
+
+ /**
+ * Returns a new SpannableString from the specified CharSequence.
+ * You can override this to provide a different kind of Spannable.
+ */
+ public Spannable newSpannable(CharSequence source) {
+ return new SpannableString(source);
+ }
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpannableString.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpannableString.java
new file mode 100644
index 0000000..49484e7
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpannableString.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+/**
+ * This is the class for text whose content is immutable but to which
+ * markup objects can be attached and detached.
+ * For mutable text, see {@link SpannableStringBuilder}.
+ */
+public class SpannableString
+ extends SpannableStringInternal
+ implements CharSequence, GetChars, Spannable {
+
+ /**
+ * @param source source object to copy from
+ * @param ignoreNoCopySpan whether to copy NoCopySpans in the {@code source}
+ */
+ public SpannableString(CharSequence source, boolean ignoreNoCopySpan) {
+ super(source, 0, source.length(), ignoreNoCopySpan);
+ }
+
+ /**
+ * For the backward compatibility reasons, this constructor copies all spans including {@link
+ * android.text.NoCopySpan}.
+ *
+ * @param source source text
+ */
+ public SpannableString(CharSequence source) {
+ this(source, false /* ignoreNoCopySpan */); // preserve existing NoCopySpan behavior
+ }
+
+ /**
+ * Ctor.
+ */
+ private SpannableString(CharSequence source, int start, int end) {
+ // preserve existing NoCopySpan behavior
+ super(source, start, end, false /* ignoreNoCopySpan */);
+ }
+
+ /**
+ * valueOf.
+ */
+ public static SpannableString valueOf(CharSequence source) {
+ if (source instanceof SpannableString) {
+ return (SpannableString) source;
+ } else {
+ return new SpannableString(source);
+ }
+ }
+
+ /**
+ * setSpan.
+ */
+ public void setSpan(Object what, int start, int end, int flags) {
+ super.setSpan(what, start, end, flags);
+ }
+
+ /**
+ * removeSpan.
+ */
+ public void removeSpan(Object what) {
+ super.removeSpan(what);
+ }
+
+ /**
+ * subSequence.
+ */
+ public final CharSequence subSequence(int start, int end) {
+ return new SpannableString(this, start, end);
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpannableStringInternal.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpannableStringInternal.java
new file mode 100644
index 0000000..f327845
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/SpannableStringInternal.java
@@ -0,0 +1,588 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
+
+import java.lang.reflect.Array;
+
+/* package */ abstract class SpannableStringInternal {
+ /* package */ SpannableStringInternal(CharSequence source,
+ int start, int end, boolean ignoreNoCopySpan) {
+ if (start == 0 && end == source.length()) {
+ mText = source.toString();
+ } else {
+ mText = source.toString().substring(start, end);
+ }
+ mSpans = EmptyArray.OBJECT;
+ // Invariant: mSpanData.length = mSpans.length * COLUMNS
+ mSpanData = EmptyArray.INT;
+
+ if (source instanceof Spanned) {
+ if (source instanceof SpannableStringInternal) {
+ copySpans((SpannableStringInternal) source, start, end, ignoreNoCopySpan);
+ } else {
+ copySpans((Spanned) source, start, end, ignoreNoCopySpan);
+ }
+ }
+ }
+
+ /**
+ * This unused method is left since this is listed in hidden api list.
+ *
+ * Due to backward compatibility reasons, we copy even NoCopySpan by default
+ */
+ @UnsupportedAppUsage
+ /* package */ SpannableStringInternal(CharSequence source, int start, int end) {
+ this(source, start, end, false /* ignoreNoCopySpan */);
+ }
+
+ /**
+ * Copies another {@link Spanned} object's spans between [start, end] into this object.
+ *
+ * @param src Source object to copy from.
+ * @param start Start index in the source object.
+ * @param end End index in the source object.
+ * @param ignoreNoCopySpan whether to copy NoCopySpans in the {@code source}
+ */
+ private void copySpans(Spanned src, int start, int end, boolean ignoreNoCopySpan) {
+ Object[] spans = src.getSpans(start, end, Object.class);
+
+ for (int i = 0; i < spans.length; i++) {
+ if (ignoreNoCopySpan && spans[i] instanceof NoCopySpan) {
+ continue;
+ }
+ int st = src.getSpanStart(spans[i]);
+ int en = src.getSpanEnd(spans[i]);
+ int fl = src.getSpanFlags(spans[i]);
+
+ if (st < start) st = start;
+ if (en > end) en = end;
+
+ setSpan(spans[i], st - start, en - start, fl, false/*enforceParagraph*/);
+ }
+ }
+
+ /**
+ * Copies a {@link SpannableStringInternal} object's spans between [start, end] into this
+ * object.
+ *
+ * @param src Source object to copy from.
+ * @param start Start index in the source object.
+ * @param end End index in the source object.
+ * @param ignoreNoCopySpan copy NoCopySpan for backward compatible reasons.
+ */
+ private void copySpans(SpannableStringInternal src, int start, int end,
+ boolean ignoreNoCopySpan) {
+ int count = 0;
+ final int[] srcData = src.mSpanData;
+ final Object[] srcSpans = src.mSpans;
+ final int limit = src.mSpanCount;
+ boolean hasNoCopySpan = false;
+
+ for (int i = 0; i < limit; i++) {
+ int spanStart = srcData[i * COLUMNS + START];
+ int spanEnd = srcData[i * COLUMNS + END];
+ if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
+ if (srcSpans[i] instanceof NoCopySpan) {
+ hasNoCopySpan = true;
+ if (ignoreNoCopySpan) {
+ continue;
+ }
+ }
+ count++;
+ }
+
+ if (count == 0) return;
+
+ if (!hasNoCopySpan && start == 0 && end == src.length()) {
+ mSpans = ArrayUtils.newUnpaddedObjectArray(src.mSpans.length);
+ mSpanData = new int[src.mSpanData.length];
+ mSpanCount = src.mSpanCount;
+ System.arraycopy(src.mSpans, 0, mSpans, 0, src.mSpans.length);
+ System.arraycopy(src.mSpanData, 0, mSpanData, 0, mSpanData.length);
+ } else {
+ mSpanCount = count;
+ mSpans = ArrayUtils.newUnpaddedObjectArray(mSpanCount);
+ mSpanData = new int[mSpans.length * COLUMNS];
+ for (int i = 0, j = 0; i < limit; i++) {
+ int spanStart = srcData[i * COLUMNS + START];
+ int spanEnd = srcData[i * COLUMNS + END];
+ if (isOutOfCopyRange(start, end, spanStart, spanEnd)
+ || (ignoreNoCopySpan && srcSpans[i] instanceof NoCopySpan)) {
+ continue;
+ }
+ if (spanStart < start) spanStart = start;
+ if (spanEnd > end) spanEnd = end;
+
+ mSpans[j] = srcSpans[i];
+ mSpanData[j * COLUMNS + START] = spanStart - start;
+ mSpanData[j * COLUMNS + END] = spanEnd - start;
+ mSpanData[j * COLUMNS + FLAGS] = srcData[i * COLUMNS + FLAGS];
+ j++;
+ }
+ }
+ }
+
+ /**
+ * Checks if [spanStart, spanEnd] interval is excluded from [start, end].
+ *
+ * @return True if excluded, false if included.
+ */
+ @UnsupportedAppUsage
+ private boolean isOutOfCopyRange(int start, int end, int spanStart, int spanEnd) {
+ if (spanStart > end || spanEnd < start) return true;
+ if (spanStart != spanEnd && start != end) {
+ if (spanStart == end || spanEnd == start) return true;
+ }
+ return false;
+ }
+
+ public final int length() {
+ return mText.length();
+ }
+
+ public final char charAt(int i) {
+ return mText.charAt(i);
+ }
+
+ public final String toString() {
+ return mText;
+ }
+
+ /* subclasses must do subSequence() to preserve type */
+
+ public final void getChars(int start, int end, char[] dest, int off) {
+ mText.getChars(start, end, dest, off);
+ }
+
+ @UnsupportedAppUsage
+ /* package */ void setSpan(Object what, int start, int end, int flags) {
+ setSpan(what, start, end, flags, true/*enforceParagraph*/);
+ }
+
+ @UnsupportedAppUsage
+ private boolean isIndexFollowsNextLine(int index) {
+ return index != 0 && index != length() && charAt(index - 1) != '\n';
+ }
+
+ @UnsupportedAppUsage
+ private void setSpan(Object what, int start, int end, int flags, boolean enforceParagraph) {
+ int nstart = start;
+ int nend = end;
+
+ checkRange("setSpan", start, end);
+
+ if ((flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPH) {
+ if (isIndexFollowsNextLine(start)) {
+ if (!enforceParagraph) {
+ // do not set the span
+ return;
+ }
+ throw new RuntimeException("PARAGRAPH span must start at paragraph boundary"
+ + " (" + start + " follows " + charAt(start - 1) + ")");
+ }
+
+ if (isIndexFollowsNextLine(end)) {
+ if (!enforceParagraph) {
+ // do not set the span
+ return;
+ }
+ throw new RuntimeException("PARAGRAPH span must end at paragraph boundary"
+ + " (" + end + " follows " + charAt(end - 1) + ")");
+ }
+ }
+
+ int count = mSpanCount;
+ Object[] spans = mSpans;
+ int[] data = mSpanData;
+
+ for (int i = 0; i < count; i++) {
+ if (spans[i] == what) {
+ int ostart = data[i * COLUMNS + START];
+ int oend = data[i * COLUMNS + END];
+
+ data[i * COLUMNS + START] = start;
+ data[i * COLUMNS + END] = end;
+ data[i * COLUMNS + FLAGS] = flags;
+
+ sendSpanChanged(what, ostart, oend, nstart, nend);
+ return;
+ }
+ }
+
+ if (mSpanCount + 1 >= mSpans.length) {
+ Object[] newtags = ArrayUtils.newUnpaddedObjectArray(
+ GrowingArrayUtils.growSize(mSpanCount));
+ int[] newdata = new int[newtags.length * 3];
+
+ System.arraycopy(mSpans, 0, newtags, 0, mSpanCount);
+ System.arraycopy(mSpanData, 0, newdata, 0, mSpanCount * 3);
+
+ mSpans = newtags;
+ mSpanData = newdata;
+ }
+
+ mSpans[mSpanCount] = what;
+ mSpanData[mSpanCount * COLUMNS + START] = start;
+ mSpanData[mSpanCount * COLUMNS + END] = end;
+ mSpanData[mSpanCount * COLUMNS + FLAGS] = flags;
+ mSpanCount++;
+
+ if (this instanceof Spannable) {
+ sendSpanAdded(what, nstart, nend);
+ }
+ }
+
+ @UnsupportedAppUsage
+ /* package */ void removeSpan(Object what) {
+ removeSpan(what, 0 /* flags */);
+ }
+
+ /**
+ * removeSpan
+ */
+ public void removeSpan(Object what, int flags) {
+ int count = mSpanCount;
+ Object[] spans = mSpans;
+ int[] data = mSpanData;
+
+ for (int i = count - 1; i >= 0; i--) {
+ if (spans[i] == what) {
+ int ostart = data[i * COLUMNS + START];
+ int oend = data[i * COLUMNS + END];
+
+ int c = count - (i + 1);
+
+ System.arraycopy(spans, i + 1, spans, i, c);
+ System.arraycopy(data, (i + 1) * COLUMNS,
+ data, i * COLUMNS, c * COLUMNS);
+
+ mSpanCount--;
+
+ if ((flags & Spanned.SPAN_INTERMEDIATE) == 0) {
+ sendSpanRemoved(what, ostart, oend);
+ }
+ return;
+ }
+ }
+ }
+
+ @UnsupportedAppUsage
+ public int getSpanStart(Object what) {
+ int count = mSpanCount;
+ Object[] spans = mSpans;
+ int[] data = mSpanData;
+
+ for (int i = count - 1; i >= 0; i--) {
+ if (spans[i] == what) {
+ return data[i * COLUMNS + START];
+ }
+ }
+
+ return -1;
+ }
+
+ @UnsupportedAppUsage
+ public int getSpanEnd(Object what) {
+ int count = mSpanCount;
+ Object[] spans = mSpans;
+ int[] data = mSpanData;
+
+ for (int i = count - 1; i >= 0; i--) {
+ if (spans[i] == what) {
+ return data[i * COLUMNS + END];
+ }
+ }
+
+ return -1;
+ }
+
+ @UnsupportedAppUsage
+ public int getSpanFlags(Object what) {
+ int count = mSpanCount;
+ Object[] spans = mSpans;
+ int[] data = mSpanData;
+
+ for (int i = count - 1; i >= 0; i--) {
+ if (spans[i] == what) {
+ return data[i * COLUMNS + FLAGS];
+ }
+ }
+
+ return 0;
+ }
+
+ @UnsupportedAppUsage
+ public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
+ int count = 0;
+
+ int spanCount = mSpanCount;
+ Object[] spans = mSpans;
+ int[] data = mSpanData;
+ Object[] ret = null;
+ Object ret1 = null;
+
+ for (int i = 0; i < spanCount; i++) {
+ int spanStart = data[i * COLUMNS + START];
+ int spanEnd = data[i * COLUMNS + END];
+
+ if (spanStart > queryEnd) {
+ continue;
+ }
+ if (spanEnd < queryStart) {
+ continue;
+ }
+
+ if (spanStart != spanEnd && queryStart != queryEnd) {
+ if (spanStart == queryEnd) {
+ continue;
+ }
+ if (spanEnd == queryStart) {
+ continue;
+ }
+ }
+
+ // verify span class as late as possible, since it is expensive
+ if (kind != null && kind != Object.class && !kind.isInstance(spans[i])) {
+ continue;
+ }
+
+ if (count == 0) {
+ ret1 = spans[i];
+ count++;
+ } else {
+ if (count == 1) {
+ ret = (Object[]) Array.newInstance(kind, spanCount - i + 1);
+ ret[0] = ret1;
+ }
+
+ int prio = data[i * COLUMNS + FLAGS] & Spanned.SPAN_PRIORITY;
+ if (prio != 0) {
+ int j;
+
+ for (j = 0; j < count; j++) {
+ int p = getSpanFlags(ret[j]) & Spanned.SPAN_PRIORITY;
+
+ if (prio > p) {
+ break;
+ }
+ }
+
+ System.arraycopy(ret, j, ret, j + 1, count - j);
+ ret[j] = spans[i];
+ count++;
+ } else {
+ ret[count++] = spans[i];
+ }
+ }
+ }
+
+ if (count == 0) {
+ return (T[]) ArrayUtils.emptyArray(kind);
+ }
+ if (count == 1) {
+ ret = (Object[]) Array.newInstance(kind, 1);
+ ret[0] = ret1;
+ return (T[]) ret;
+ }
+ if (count == ret.length) {
+ return (T[]) ret;
+ }
+
+ Object[] nret = (Object[]) Array.newInstance(kind, count);
+ System.arraycopy(ret, 0, nret, 0, count);
+ return (T[]) nret;
+ }
+
+ @UnsupportedAppUsage
+ public int nextSpanTransition(int start, int limit, Class kind) {
+ int count = mSpanCount;
+ Object[] spans = mSpans;
+ int[] data = mSpanData;
+
+ if (kind == null) {
+ kind = Object.class;
+ }
+
+ for (int i = 0; i < count; i++) {
+ int st = data[i * COLUMNS + START];
+ int en = data[i * COLUMNS + END];
+
+ if (st > start && st < limit && kind.isInstance(spans[i])) {
+ limit = st;
+ }
+ if (en > start && en < limit && kind.isInstance(spans[i])) {
+ limit = en;
+ }
+ }
+
+ return limit;
+ }
+
+ @UnsupportedAppUsage
+ private void sendSpanAdded(Object what, int start, int end) {
+ SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
+ int n = recip.length;
+
+ for (int i = 0; i < n; i++) {
+ recip[i].onSpanAdded((Spannable) this, what, start, end);
+ }
+ }
+
+ @UnsupportedAppUsage
+ private void sendSpanRemoved(Object what, int start, int end) {
+ SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
+ int n = recip.length;
+
+ for (int i = 0; i < n; i++) {
+ recip[i].onSpanRemoved((Spannable) this, what, start, end);
+ }
+ }
+
+ @UnsupportedAppUsage
+ private void sendSpanChanged(Object what, int s, int e, int st, int en) {
+ SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
+ SpanWatcher.class);
+ int n = recip.length;
+
+ for (int i = 0; i < n; i++) {
+ recip[i].onSpanChanged((Spannable) this, what, s, e, st, en);
+ }
+ }
+
+ @UnsupportedAppUsage
+ private static String region(int start, int end) {
+ return "(" + start + " ... " + end + ")";
+ }
+
+ @UnsupportedAppUsage
+ private void checkRange(final String operation, int start, int end) {
+ if (end < start) {
+ throw new IndexOutOfBoundsException(operation + " "
+ + region(start, end)
+ + " has end before start");
+ }
+
+ int len = length();
+
+ if (start > len || end > len) {
+ throw new IndexOutOfBoundsException(operation + " "
+ + region(start, end)
+ + " ends beyond length " + len);
+ }
+
+ if (start < 0 || end < 0) {
+ throw new IndexOutOfBoundsException(operation + " "
+ + region(start, end)
+ + " starts before 0");
+ }
+ }
+
+ // Same as SpannableStringBuilder
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Spanned
+ && toString().equals(o.toString())) {
+ final Spanned other = (Spanned) o;
+ // Check span data
+ final Object[] otherSpans = other.getSpans(0, other.length(), Object.class);
+ final Object[] thisSpans = getSpans(0, length(), Object.class);
+ if (mSpanCount == otherSpans.length) {
+ for (int i = 0; i < mSpanCount; ++i) {
+ final Object thisSpan = thisSpans[i];
+ final Object otherSpan = otherSpans[i];
+ if (thisSpan == this) {
+ if (other != otherSpan
+ || getSpanStart(thisSpan) != other.getSpanStart(otherSpan)
+ || getSpanEnd(thisSpan) != other.getSpanEnd(otherSpan)
+ || getSpanFlags(thisSpan) != other.getSpanFlags(otherSpan)) {
+ return false;
+ }
+ } else if (!thisSpan.equals(otherSpan)
+ || getSpanStart(thisSpan) != other.getSpanStart(otherSpan)
+ || getSpanEnd(thisSpan) != other.getSpanEnd(otherSpan)
+ || getSpanFlags(thisSpan) != other.getSpanFlags(otherSpan)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Same as SpannableStringBuilder
+ @Override
+ public int hashCode() {
+ int hash = toString().hashCode();
+ hash = hash * 31 + mSpanCount;
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object span = mSpans[i];
+ if (span != this) {
+ hash = hash * 31 + span.hashCode();
+ }
+ hash = hash * 31 + getSpanStart(span);
+ hash = hash * 31 + getSpanEnd(span);
+ hash = hash * 31 + getSpanFlags(span);
+ }
+ return hash;
+ }
+
+ /**
+ * Following two unused methods are left since these are listed in hidden api list.
+ *
+ * Due to backward compatibility reasons, we copy even NoCopySpan by default
+ */
+ @UnsupportedAppUsage
+ private void copySpans(Spanned src, int start, int end) {
+ copySpans(src, start, end, false);
+ }
+
+ @UnsupportedAppUsage
+ private void copySpans(SpannableStringInternal src, int start, int end) {
+ copySpans(src, start, end, false);
+ }
+
+
+
+ @UnsupportedAppUsage
+ private String mText;
+ @UnsupportedAppUsage
+ private Object[] mSpans;
+ @UnsupportedAppUsage
+ private int[] mSpanData;
+ @UnsupportedAppUsage
+ private int mSpanCount;
+
+ @UnsupportedAppUsage
+ /* package */ static final Object[] EMPTY = new Object[0];
+
+ @UnsupportedAppUsage
+ private static final int START = 0;
+ @UnsupportedAppUsage
+ private static final int END = 1;
+ @UnsupportedAppUsage
+ private static final int FLAGS = 2;
+ @UnsupportedAppUsage
+ private static final int COLUMNS = 3;
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/Spanned.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/Spanned.java
new file mode 100644
index 0000000..998b8b0
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/Spanned.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+/**
+ * This is the interface for text that has markup objects attached to
+ * ranges of it. Not all text classes have mutable markup or text;
+ * see {@link Spannable} for mutable markup and {@link Editable} for
+ * mutable text.
+ */
+public interface Spanned extends CharSequence {
+ /**
+ * Bitmask of bits that are relevant for controlling point/mark behavior
+ * of spans.
+ *
+ * MARK and POINT are conceptually located <i>between</i> two adjacent characters.
+ * A MARK is "attached" to the character before, while a POINT will stick to the character
+ * after. The insertion cursor is conceptually located between the MARK and the POINT.
+ *
+ * As a result, inserting a new character between a MARK and a POINT will leave the MARK
+ * unchanged, while the POINT will be shifted, now located after the inserted character and
+ * still glued to the same character after it.
+ *
+ * Depending on whether the insertion happens at the beginning or the end of a span, the span
+ * will hence be expanded to <i>include</i> the new character (when the span is using a MARK at
+ * its beginning or a POINT at its end) or it will be <i>excluded</i>.
+ *
+ * Note that <i>before</i> and <i>after</i> here refer to offsets in the String, which are
+ * independent from the visual representation of the text (left-to-right or right-to-left).
+ */
+ int SPAN_POINT_MARK_MASK = 0x33;
+
+ /**
+ * 0-length spans with type SPAN_MARK_MARK behave like text marks:
+ * they remain at their original offset when text is inserted
+ * at that offset. Conceptually, the text is added after the mark.
+ */
+ int SPAN_MARK_MARK = 0x11;
+
+ /**
+ * SPAN_MARK_POINT is a synonym for {@link #SPAN_INCLUSIVE_INCLUSIVE}.
+ */
+ int SPAN_MARK_POINT = 0x12;
+
+ /**
+ * SPAN_POINT_MARK is a synonym for {@link #SPAN_EXCLUSIVE_EXCLUSIVE}.
+ */
+ int SPAN_POINT_MARK = 0x21;
+
+ /**
+ * 0-length spans with type SPAN_POINT_POINT behave like cursors:
+ * they are pushed forward by the length of the insertion when text
+ * is inserted at their offset.
+ * The text is conceptually inserted before the point.
+ */
+ int SPAN_POINT_POINT = 0x22;
+
+ /**
+ * SPAN_PARAGRAPH behaves like SPAN_INCLUSIVE_EXCLUSIVE
+ * (SPAN_MARK_MARK), except that if either end of the span is
+ * at the end of the buffer, that end behaves like _POINT
+ * instead (so SPAN_INCLUSIVE_INCLUSIVE if it starts in the
+ * middle and ends at the end, or SPAN_EXCLUSIVE_INCLUSIVE
+ * if it both starts and ends at the end).
+ * <p>
+ * Its endpoints must be the start or end of the buffer or
+ * immediately after a \n character, and if the \n
+ * that anchors it is deleted, the endpoint is pulled to the
+ * next \n that follows in the buffer (or to the end of
+ * the buffer). If a span with SPAN_PARAGRAPH flag is pasted
+ * into another text and the paragraph boundary constraint
+ * is not satisfied, the span is discarded.
+ */
+ int SPAN_PARAGRAPH = 0x33;
+
+ /**
+ * Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand
+ * to include text inserted at their starting point but not at their
+ * ending point. When 0-length, they behave like marks.
+ */
+ int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;
+
+ /**
+ * Spans of type SPAN_INCLUSIVE_INCLUSIVE expand
+ * to include text inserted at either their starting or ending point.
+ */
+ int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;
+
+ /**
+ * Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand
+ * to include text inserted at either their starting or ending point.
+ * They can never have a length of 0 and are automatically removed
+ * from the buffer if all the text they cover is removed.
+ */
+ int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;
+
+ /**
+ * Non-0-length spans of type SPAN_EXCLUSIVE_INCLUSIVE expand
+ * to include text inserted at their ending point but not at their
+ * starting point. When 0-length, they behave like points.
+ */
+ int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;
+
+ /**
+ * This flag is set on spans that are being used to apply temporary
+ * styling information on the composing text of an input method, so that
+ * they can be found and removed when the composing text is being
+ * replaced.
+ */
+ int SPAN_COMPOSING = 0x100;
+
+ /**
+ * This flag will be set for intermediate span changes, meaning there
+ * is guaranteed to be another change following it. Typically it is
+ * used for {@link Selection} which automatically uses this with the first
+ * offset it sets when updating the selection.
+ */
+ int SPAN_INTERMEDIATE = 0x200;
+
+ /**
+ * The bits numbered SPAN_USER_SHIFT and above are available
+ * for callers to use to store scalar data associated with their
+ * span object.
+ */
+ int SPAN_USER_SHIFT = 24;
+
+ /**
+ * The bits specified by the SPAN_USER bitfield are available
+ * for callers to use to store scalar data associated with their
+ * span object.
+ */
+ int SPAN_USER = 0xFFFFFFFF << SPAN_USER_SHIFT;
+
+ /**
+ * The bits numbered just above SPAN_PRIORITY_SHIFT determine the order
+ * of change notifications -- higher numbers go first. You probably
+ * don't need to set this; it is used so that when text changes, the
+ * text layout gets the chance to update itself before any other
+ * callbacks can inquire about the layout of the text.
+ */
+ int SPAN_PRIORITY_SHIFT = 16;
+
+ /**
+ * The bits specified by the SPAN_PRIORITY bitmap determine the order
+ * of change notifications -- higher numbers go first. You probably
+ * don't need to set this; it is used so that when text changes, the
+ * text layout gets the chance to update itself before any other
+ * callbacks can inquire about the layout of the text.
+ */
+ int SPAN_PRIORITY = 0xFF << SPAN_PRIORITY_SHIFT;
+
+ /**
+ * Return an array of the markup objects attached to the specified
+ * slice of this CharSequence and whose type is the specified type
+ * or a subclass of it. Specify Object.class for the type if you
+ * want all the objects regardless of type.
+ */
+ <T> T[] getSpans(int start, int end, Class<T> type);
+
+ /**
+ * Return the beginning of the range of text to which the specified
+ * markup object is attached, or -1 if the object is not attached.
+ */
+ int getSpanStart(Object tag);
+
+ /**
+ * Return the end of the range of text to which the specified
+ * markup object is attached, or -1 if the object is not attached.
+ */
+ int getSpanEnd(Object tag);
+
+ /**
+ * Return the flags that were specified when {@link Spannable#setSpan} was
+ * used to attach the specified markup object, or 0 if the specified
+ * object has not been attached.
+ */
+ int getSpanFlags(Object tag);
+
+ /**
+ * Return the first offset greater than <code>start</code> where a markup
+ * object of class <code>type</code> begins or ends, or <code>limit</code>
+ * if there are no starts or ends greater than <code>start</code> but less
+ * than <code>limit</code>. Specify <code>null</code> or Object.class for
+ * the type if you want every transition regardless of type.
+ */
+ int nextSpanTransition(int start, int limit, Class type);
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextDirectionHeuristic.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextDirectionHeuristic.java
new file mode 100644
index 0000000..88a35c1
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextDirectionHeuristic.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 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 android.text;
+
+/**
+ * Interface for objects that use a heuristic for guessing at the paragraph direction
+ * by examining text.
+ */
+public interface TextDirectionHeuristic {
+ /**
+ * Guess if a chars array is in the RTL direction or not.
+ *
+ * @param array the char array.
+ * @param start start index, inclusive.
+ * @param count the length to check, must not be negative and not greater than
+ * {@code array.length - start}.
+ * @return true if all chars in the range are to be considered in a RTL direction,
+ * false otherwise.
+ */
+ boolean isRtl(char[] array, int start, int count);
+
+ /**
+ * Guess if a {@code CharSequence} is in the RTL direction or not.
+ *
+ * @param cs the CharSequence.
+ * @param start start index, inclusive.
+ * @param count the length to check, must not be negative and not greater than
+ * {@code CharSequence.length() - start}.
+ * @return true if all chars in the range are to be considered in a RTL direction,
+ * false otherwise.
+ */
+ boolean isRtl(CharSequence cs, int start, int count);
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextDirectionHeuristics.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextDirectionHeuristics.java
new file mode 100644
index 0000000..4feab0d
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextDirectionHeuristics.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2011 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 android.text;
+
+
+import android.view.View;
+
+import java.nio.CharBuffer;
+
+/**
+ * Some objects that implement {@link TextDirectionHeuristic}. Use these with
+ * the {@link BidiFormatter#unicodeWrap unicodeWrap()} methods in {@link BidiFormatter}.
+ * Also notice that these direction heuristics correspond to the same types of constants
+ * provided in the {@link android.view.View} class for {@link android.view.View#setTextDirection
+ * setTextDirection()}, such as {@link android.view.View#TEXT_DIRECTION_RTL}.
+ * <p>To support versions lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
+ * you can use the support library's {@link android.support.v4.text.TextDirectionHeuristicsCompat}
+ * class.
+ */
+public class TextDirectionHeuristics {
+
+ /**
+ * Always decides that the direction is left to right.
+ */
+ public static final TextDirectionHeuristic LTR =
+ new TextDirectionHeuristicInternal(null /* no algorithm */, false);
+
+ /**
+ * Always decides that the direction is right to left.
+ */
+ public static final TextDirectionHeuristic RTL =
+ new TextDirectionHeuristicInternal(null /* no algorithm */, true);
+
+ /**
+ * Determines the direction based on the first strong directional character, including bidi
+ * format chars, falling back to left to right if it finds none. This is the default behavior
+ * of the Unicode Bidirectional Algorithm.
+ */
+ public static final TextDirectionHeuristic FIRSTSTRONG_LTR =
+ new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, false);
+
+ /**
+ * Determines the direction based on the first strong directional character, including bidi
+ * format chars, falling back to right to left if it finds none. This is similar to the default
+ * behavior of the Unicode Bidirectional Algorithm, just with different fallback behavior.
+ */
+ public static final TextDirectionHeuristic FIRSTSTRONG_RTL =
+ new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, true);
+
+ /**
+ * If the text contains any strong right to left non-format character, determines that the
+ * direction is right to left, falling back to left to right if it finds none.
+ */
+ public static final TextDirectionHeuristic ANYRTL_LTR =
+ new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
+
+ /**
+ * Force the paragraph direction to the Locale direction. Falls back to left to right.
+ */
+ public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
+
+ /**
+ * State constants for taking care about true / false / unknown
+ */
+ private static final int STATE_TRUE = 0;
+ private static final int STATE_FALSE = 1;
+ private static final int STATE_UNKNOWN = 2;
+
+ /* Returns STATE_TRUE for strong RTL characters, STATE_FALSE for strong LTR characters, and
+ * STATE_UNKNOWN for everything else.
+ */
+ private static int isRtlCodePoint(int codePoint) {
+ switch (Character.getDirectionality(codePoint)) {
+ case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
+ return STATE_FALSE;
+ case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
+ case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
+ return STATE_TRUE;
+ case Character.DIRECTIONALITY_UNDEFINED:
+ // Unassigned characters still have bidi direction, defined at:
+ // http://www.unicode.org/Public/UCD/latest/ucd/extracted/DerivedBidiClass.txt
+
+ if ((0x0590 <= codePoint && codePoint <= 0x08FF)
+ || (0xFB1D <= codePoint && codePoint <= 0xFDCF)
+ || (0xFDF0 <= codePoint && codePoint <= 0xFDFF)
+ || (0xFE70 <= codePoint && codePoint <= 0xFEFF)
+ || (0x10800 <= codePoint && codePoint <= 0x10FFF)
+ || (0x1E800 <= codePoint && codePoint <= 0x1EFFF)) {
+ // Unassigned RTL character
+ return STATE_TRUE;
+ } else if (
+ // Potentially-unassigned Default_Ignorable. Ranges are from unassigned
+ // characters that have Unicode property Other_Default_Ignorable_Code_Point
+ // plus some enlargening to cover bidi isolates and simplify checks.
+ (0x2065 <= codePoint && codePoint <= 0x2069)
+ || (0xFFF0 <= codePoint && codePoint <= 0xFFF8)
+ || (0xE0000 <= codePoint && codePoint <= 0xE0FFF)
+ // Non-character
+ || (0xFDD0 <= codePoint && codePoint <= 0xFDEF)
+ || ((codePoint & 0xFFFE) == 0xFFFE)
+ // Currency symbol
+ || (0x20A0 <= codePoint && codePoint <= 0x20CF)
+ // Unpaired surrogate
+ || (0xD800 <= codePoint && codePoint <= 0xDFFF)) {
+ return STATE_UNKNOWN;
+ } else {
+ // Unassigned LTR character
+ return STATE_FALSE;
+ }
+ default:
+ return STATE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Computes the text direction based on an algorithm. Subclasses implement
+ * {@link #defaultIsRtl} to handle cases where the algorithm cannot determine the
+ * direction from the text alone.
+ */
+ private abstract static class TextDirectionHeuristicImpl implements TextDirectionHeuristic {
+ private final TextDirectionAlgorithm mAlgorithm;
+
+ TextDirectionHeuristicImpl(TextDirectionAlgorithm algorithm) {
+ mAlgorithm = algorithm;
+ }
+
+ /**
+ * Return true if the default text direction is rtl.
+ */
+ protected abstract boolean defaultIsRtl();
+
+ @Override
+ public boolean isRtl(char[] array, int start, int count) {
+ return isRtl(CharBuffer.wrap(array), start, count);
+ }
+
+ @Override
+ public boolean isRtl(CharSequence cs, int start, int count) {
+ if (cs == null || start < 0 || count < 0 || cs.length() - count < start) {
+ throw new IllegalArgumentException();
+ }
+ if (mAlgorithm == null) {
+ return defaultIsRtl();
+ }
+ return doCheck(cs, start, count);
+ }
+
+ private boolean doCheck(CharSequence cs, int start, int count) {
+ switch (mAlgorithm.checkRtl(cs, start, count)) {
+ case STATE_TRUE:
+ return true;
+ case STATE_FALSE:
+ return false;
+ default:
+ return defaultIsRtl();
+ }
+ }
+ }
+
+ private static class TextDirectionHeuristicInternal extends TextDirectionHeuristicImpl {
+ private final boolean mDefaultIsRtl;
+
+ private TextDirectionHeuristicInternal(TextDirectionAlgorithm algorithm,
+ boolean defaultIsRtl) {
+ super(algorithm);
+ mDefaultIsRtl = defaultIsRtl;
+ }
+
+ @Override
+ protected boolean defaultIsRtl() {
+ return mDefaultIsRtl;
+ }
+ }
+
+ /**
+ * Interface for an algorithm to guess the direction of a paragraph of text.
+ */
+ private interface TextDirectionAlgorithm {
+ /**
+ * Returns whether the range of text is RTL according to the algorithm.
+ */
+ int checkRtl(CharSequence cs, int start, int count);
+ }
+
+ /**
+ * Algorithm that uses the first strong directional character to determine the paragraph
+ * direction. This is the standard Unicode Bidirectional Algorithm (steps P2 and P3), with the
+ * exception that if no strong character is found, UNKNOWN is returned.
+ */
+ private static class FirstStrong implements TextDirectionAlgorithm {
+ @Override
+ public int checkRtl(CharSequence cs, int start, int count) {
+ int result = STATE_UNKNOWN;
+ int openIsolateCount = 0;
+ for (int cp, i = start, end = start + count;
+ i < end && result == STATE_UNKNOWN;
+ i += Character.charCount(cp)) {
+ cp = Character.codePointAt(cs, i);
+ if (0x2066 <= cp && cp <= 0x2068) { // Opening isolates
+ openIsolateCount += 1;
+ } else if (cp == 0x2069) { // POP DIRECTIONAL ISOLATE (PDI)
+ if (openIsolateCount > 0) openIsolateCount -= 1;
+ } else if (openIsolateCount == 0) {
+ // Only consider the characters outside isolate pairs
+ result = isRtlCodePoint(cp);
+ }
+ }
+ return result;
+ }
+
+ private FirstStrong() {
+ }
+
+ public static final FirstStrong INSTANCE = new FirstStrong();
+ }
+
+ /**
+ * Algorithm that uses the presence of any strong directional character of the type indicated
+ * in the constructor parameter to determine the direction of text.
+ *
+ * Characters inside isolate pairs are skipped.
+ */
+ private static class AnyStrong implements TextDirectionAlgorithm {
+ private final boolean mLookForRtl;
+
+ @Override
+ public int checkRtl(CharSequence cs, int start, int count) {
+ boolean haveUnlookedFor = false;
+ int openIsolateCount = 0;
+ for (int cp, i = start, end = start + count; i < end; i += Character.charCount(cp)) {
+ cp = Character.codePointAt(cs, i);
+ if (0x2066 <= cp && cp <= 0x2068) { // Opening isolates
+ openIsolateCount += 1;
+ } else if (cp == 0x2069) { // POP DIRECTIONAL ISOLATE (PDI)
+ if (openIsolateCount > 0) openIsolateCount -= 1;
+ } else if (openIsolateCount == 0) {
+ // Only consider the characters outside isolate pairs
+ switch (isRtlCodePoint(cp)) {
+ case STATE_TRUE:
+ if (mLookForRtl) {
+ return STATE_TRUE;
+ }
+ haveUnlookedFor = true;
+ break;
+ case STATE_FALSE:
+ if (!mLookForRtl) {
+ return STATE_FALSE;
+ }
+ haveUnlookedFor = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if (haveUnlookedFor) {
+ return mLookForRtl ? STATE_FALSE : STATE_TRUE;
+ }
+ return STATE_UNKNOWN;
+ }
+
+ private AnyStrong(boolean lookForRtl) {
+ this.mLookForRtl = lookForRtl;
+ }
+
+ public static final AnyStrong INSTANCE_RTL = new AnyStrong(true);
+ public static final AnyStrong INSTANCE_LTR = new AnyStrong(false);
+ }
+
+ /**
+ * Algorithm that uses the Locale direction to force the direction of a paragraph.
+ */
+ private static class TextDirectionHeuristicLocale extends TextDirectionHeuristicImpl {
+
+ TextDirectionHeuristicLocale() {
+ super(null);
+ }
+
+ @Override
+ protected boolean defaultIsRtl() {
+ // TODO: fix me!
+ final int dir =
+ View.LAYOUT_DIRECTION_LTR; // TextUtils.getLayoutDirectionFromLocale(java
+ // .util.Locale.getDefault());
+ return (dir == View.LAYOUT_DIRECTION_RTL);
+ }
+
+ public static final TextDirectionHeuristicLocale INSTANCE =
+ new TextDirectionHeuristicLocale();
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextUtils.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextUtils.java
new file mode 100644
index 0000000..33f69ba
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/TextUtils.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2006 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 android.text;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+import com.android.internal.util.ArrayUtils;
+
+/**
+ * TextUtils.
+ */
+public class TextUtils {
+ private static final String ELLIPSIS_NORMAL = "\u2026"; // HORIZONTAL ELLIPSIS (…)
+ private static final String ELLIPSIS_TWO_DOTS = "\u2025"; // TWO DOT LEADER (‥)
+
+ /**
+ * getChars
+ */
+ public static void getChars(CharSequence s, int start, int end,
+ char[] dest, int destoff) {
+ Class<? extends CharSequence> c = s.getClass();
+ if (c == String.class) {
+ ((String) s).getChars(start, end, dest, destoff);
+ } else if (c == StringBuffer.class) {
+ ((StringBuffer) s).getChars(start, end, dest, destoff);
+ } else if (c == StringBuilder.class) {
+ ((StringBuilder) s).getChars(start, end, dest, destoff);
+ } else if (s instanceof GetChars) {
+ ((GetChars) s).getChars(start, end, dest, destoff);
+ } else {
+ for (int i = start; i < end; i++) {
+ dest[destoff++] = s.charAt(i);
+ }
+ }
+ }
+
+ /**
+ * ellipsize.
+ */
+ public static CharSequence ellipsize(CharSequence text,
+ TextPaint p,
+ float avail, TruncateAt where) {
+ return ellipsize(text, p, avail, where, false, null);
+ }
+
+ /**
+ * ellipsize.
+ */
+ public static CharSequence ellipsize(CharSequence text,
+ TextPaint paint,
+ float avail, TruncateAt where,
+ boolean preserveLength,
+ EllipsizeCallback callback) {
+ return ellipsize(text, paint, avail, where, preserveLength, callback,
+ TextDirectionHeuristics.FIRSTSTRONG_LTR,
+ getEllipsisString(where));
+ }
+
+ /**
+ * ellipsize
+ */
+ public static CharSequence ellipsize(
+ CharSequence text,
+ TextPaint paint,
+ float avail, TruncateAt where,
+ boolean preserveLength,
+ EllipsizeCallback callback,
+ TextDirectionHeuristic textDir, String ellipsis) {
+ // TODO: incorrect
+ return text;
+ }
+
+ /**
+ * getEllipsisString
+ */
+ public static String getEllipsisString(TextUtils.TruncateAt method) {
+ return (method == TextUtils.TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL;
+ }
+
+ /**
+ * obtain
+ */
+ static char[] obtain(int len) {
+ return ArrayUtils.newUnpaddedCharArray(len);
+ }
+
+ /**
+ * recycle
+ */
+ static void recycle(char[] temp) {
+ }
+
+ /**
+ * couldAffectRtl
+ */
+ static boolean couldAffectRtl(char c) {
+ return (0x0590 <= c && c <= 0x08FF) || // RTL scripts
+ c == 0x200E || // Bidi format character
+ c == 0x200F || // Bidi format character
+ (0x202A <= c && c <= 0x202E) || // Bidi format characters
+ (0x2066 <= c && c <= 0x2069) || // Bidi format characters
+ (0xD800 <= c && c <= 0xDFFF) || // Surrogate pairs
+ (0xFB1D <= c && c <= 0xFDFF) || // Hebrew and Arabic presentation forms
+ (0xFE70 <= c && c <= 0xFEFE); // Arabic presentation forms
+ }
+
+ /**
+ * TruncateAt.
+ */
+ public enum TruncateAt {
+ START,
+ MIDDLE,
+ END,
+ MARQUEE,
+ @UnsupportedAppUsage
+ END_SMALL
+ }
+
+ /**
+ * EllipsizeCallback
+ */
+ public interface EllipsizeCallback {
+ /**
+ * This method is called to report that the specified region of
+ * text was ellipsized away by a call to {@link #ellipsize}.
+ */
+ void ellipsized(int start, int end);
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/CharacterStyle.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/CharacterStyle.java
new file mode 100644
index 0000000..19be4be8
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/CharacterStyle.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2006 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 android.text.style;
+
+import android.text.TextPaint;
+
+/**
+ * The classes that affect character-level text formatting extend this
+ * class. Most extend its subclass {@link MetricAffectingSpan}, but simple
+ * ones may just implement {@link UpdateAppearance}.
+ */
+public abstract class CharacterStyle {
+ abstract void updateDrawState(TextPaint tp);
+
+ /**
+ * A given CharacterStyle can only applied to a single region of a given
+ * Spanned. If you need to attach the same CharacterStyle to multiple
+ * regions, you can use this method to wrap it with a new object that
+ * will have the same effect but be a distinct object so that it can
+ * also be attached without conflict.
+ */
+ public static CharacterStyle wrap(CharacterStyle cs) {
+ if (cs instanceof MetricAffectingSpan) {
+ return new MetricAffectingSpan.Passthrough((MetricAffectingSpan) cs);
+ } else {
+ return new Passthrough(cs);
+ }
+ }
+
+ /**
+ * Returns "this" for most CharacterStyles, but for CharacterStyles
+ * that were generated by {@link #wrap}, returns the underlying
+ * CharacterStyle.
+ */
+ public CharacterStyle getUnderlying() {
+ return this;
+ }
+
+ /**
+ * A Passthrough CharacterStyle is one that
+ * passes {@link #updateDrawState} calls through to the
+ * specified CharacterStyle while still being a distinct object,
+ * and is therefore able to be attached to the same Spannable
+ * to which the specified CharacterStyle is already attached.
+ */
+ private static class Passthrough extends CharacterStyle {
+ private CharacterStyle mStyle;
+
+ /**
+ * Creates a new Passthrough of the specfied CharacterStyle.
+ */
+ Passthrough(CharacterStyle cs) {
+ mStyle = cs;
+ }
+
+ /**
+ * Passes updateDrawState through to the underlying CharacterStyle.
+ */
+ @Override
+ public void updateDrawState(TextPaint tp) {
+ mStyle.updateDrawState(tp);
+ }
+
+ /**
+ * Returns the CharacterStyle underlying this one, or the one
+ * underlying it if it too is a Passthrough.
+ */
+ @Override
+ public CharacterStyle getUnderlying() {
+ return mStyle.getUnderlying();
+ }
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/MetricAffectingSpan.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/MetricAffectingSpan.java
new file mode 100644
index 0000000..61b7947
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/MetricAffectingSpan.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 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 android.text.style;
+
+import android.annotation.NonNull;
+import android.text.TextPaint;
+
+/**
+ * The classes that affect character-level text formatting in a way that
+ * changes the width or height of characters extend this class.
+ */
+public abstract class MetricAffectingSpan
+ extends CharacterStyle
+ implements UpdateLayout {
+
+ /**
+ * Classes that extend MetricAffectingSpan implement this method to update the text formatting
+ * in a way that can change the width or height of characters.
+ *
+ * @param textPaint the paint used for drawing the text
+ */
+ public abstract void updateMeasureState(@NonNull TextPaint textPaint);
+
+ /**
+ * Returns "this" for most MetricAffectingSpans, but for
+ * MetricAffectingSpans that were generated by {@link #wrap},
+ * returns the underlying MetricAffectingSpan.
+ */
+ @Override
+ public MetricAffectingSpan getUnderlying() {
+ return this;
+ }
+
+ /**
+ * A Passthrough MetricAffectingSpan is one that
+ * passes {@link #updateDrawState} and {@link #updateMeasureState}
+ * calls through to the specified MetricAffectingSpan
+ * while still being a distinct object,
+ * and is therefore able to be attached to the same Spannable
+ * to which the specified MetricAffectingSpan is already attached.
+ */
+ /* package */ static class Passthrough extends MetricAffectingSpan {
+ private MetricAffectingSpan mStyle;
+
+ /**
+ * Creates a new Passthrough of the specfied MetricAffectingSpan.
+ */
+ Passthrough(@NonNull MetricAffectingSpan cs) {
+ mStyle = cs;
+ }
+
+ /**
+ * Passes updateDrawState through to the underlying MetricAffectingSpan.
+ */
+ @Override
+ public void updateDrawState(@NonNull TextPaint tp) {
+ mStyle.updateDrawState(tp);
+ }
+
+ /**
+ * Passes updateMeasureState through to the underlying MetricAffectingSpan.
+ */
+ @Override
+ public void updateMeasureState(@NonNull TextPaint tp) {
+ mStyle.updateMeasureState(tp);
+ }
+
+ /**
+ * Returns the MetricAffectingSpan underlying this one, or the one
+ * underlying it if it too is a Passthrough.
+ */
+ @Override
+ public MetricAffectingSpan getUnderlying() {
+ return mStyle.getUnderlying();
+ }
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/ParagraphStyle.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/ParagraphStyle.java
new file mode 100644
index 0000000..c213f96
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/ParagraphStyle.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 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 android.text.style;
+
+/**
+ * The classes that affect paragraph-level text formatting implement
+ * this interface.
+ */
+public interface ParagraphStyle {
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/ReplacementSpan.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/ReplacementSpan.java
new file mode 100644
index 0000000..e1b9ee1
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/ReplacementSpan.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2006 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 android.text.style;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.text.TextPaint;
+
+/**
+ * Replacement span.
+ */
+public abstract class ReplacementSpan extends MetricAffectingSpan {
+
+ /**
+ * Returns the width of the span. Extending classes can set the height of the span by updating
+ * attributes of {@link android.graphics.Paint.FontMetricsInt}. If the span covers the whole
+ * text, and the height is not set,
+ * {@link #draw(Canvas, CharSequence, int, int, float, int, int, int, Paint)} will not be
+ * called for the span.
+ *
+ * @param paint Paint instance.
+ * @param text Current text.
+ * @param start Start character index for span.
+ * @param end End character index for span.
+ * @param fm Font metrics, can be null.
+ * @return Width of the span.
+ */
+ public abstract int getSize(@NonNull Paint paint, CharSequence text,
+ @IntRange(from = 0) int start, @IntRange(from = 0) int end,
+ @Nullable Paint.FontMetricsInt fm);
+
+ /**
+ * Draws the span into the canvas.
+ *
+ * @param canvas Canvas into which the span should be rendered.
+ * @param text Current text.
+ * @param start Start character index for span.
+ * @param end End character index for span.
+ * @param x Edge of the replacement closest to the leading margin.
+ * @param top Top of the line.
+ * @param y Baseline.
+ * @param bottom Bottom of the line.
+ * @param paint Paint instance.
+ */
+ public abstract void draw(@NonNull Canvas canvas, CharSequence text,
+ @IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,
+ int top, int y, int bottom, @NonNull Paint paint);
+
+ /**
+ * This method does nothing, since ReplacementSpans are measured
+ * explicitly instead of affecting Paint properties.
+ */
+ public void updateMeasureState(TextPaint p) { }
+
+ /**
+ * This method does nothing, since ReplacementSpans are drawn
+ * explicitly instead of affecting Paint properties.
+ */
+ public void updateDrawState(TextPaint ds) { }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/UpdateAppearance.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/UpdateAppearance.java
new file mode 100644
index 0000000..7112347
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/UpdateAppearance.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2008 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 android.text.style;
+
+/**
+ * The classes that affect character-level text in a way that modifies their
+ * appearance when one is added or removed must implement this interface. Note
+ * that if the class also impacts size or other metrics, it should instead
+ * implement {@link UpdateLayout}.
+ */
+public interface UpdateAppearance {
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/UpdateLayout.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/UpdateLayout.java
new file mode 100644
index 0000000..591075e
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/text/style/UpdateLayout.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006 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 android.text.style;
+
+/**
+ * The classes that affect character-level text formatting in a way that
+ * triggers a text layout update when one is added or removed must implement
+ * this interface. This interface also includes {@link UpdateAppearance}
+ * since such a change implicitly also impacts the appearance.
+ */
+public interface UpdateLayout extends UpdateAppearance { }
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/android/util/LayoutDirection.java b/ui/ui-desktop/android-emu/src/desktopMain/java/android/util/LayoutDirection.java
new file mode 100644
index 0000000..5dfdad0
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/android/util/LayoutDirection.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 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 android.util;
+
+/**
+ * A class for defining layout directions. A layout direction can be left-to-right (LTR)
+ * or right-to-left (RTL). It can also be inherited (from a parent) or deduced from the default
+ * language script of a locale.
+ */
+public final class LayoutDirection {
+
+ // No instantiation
+ private LayoutDirection() {}
+
+ /**
+ * An undefined layout direction.
+ */
+ public static final int UNDEFINED = -1;
+
+ /**
+ * Horizontal layout direction is from Left to Right.
+ */
+ public static final int LTR = 0;
+
+ /**
+ * Horizontal layout direction is from Right to Left.
+ */
+ public static final int RTL = 1;
+
+ /**
+ * Horizontal layout direction is inherited.
+ */
+ public static final int INHERIT = 2;
+
+ /**
+ * Horizontal layout direction is deduced from the default language script for the locale.
+ */
+ public static final int LOCALE = 3;
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/com/android/internal/util/ArrayUtils.java b/ui/ui-desktop/android-emu/src/desktopMain/java/com/android/internal/util/ArrayUtils.java
new file mode 100644
index 0000000..04fab97
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/com/android/internal/util/ArrayUtils.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2006 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 com.android.internal.util;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+import java.lang.reflect.Array;
+
+/**
+ * ArrayUtils contains some methods that you can call to find out
+ * the most efficient increments by which to grow arrays.
+ */
+public class ArrayUtils {
+ private ArrayUtils() { /* cannot be instantiated */ }
+
+ /**
+ * newUnpaddedObjectArray
+ */
+ public static Object[] newUnpaddedObjectArray(int minLen) {
+ return new Object[minLen];
+ }
+
+ /**
+ * newUnpaddedArray
+ */
+ @UnsupportedAppUsage
+ @SuppressWarnings("unchecked")
+ public static <T> T[] newUnpaddedArray(Class<T> clazz, int minLen) {
+ return (T[]) Array.newInstance(clazz, minLen);
+ }
+
+ /**
+ * newUnpaddedIntArray
+ */
+ public static int[] newUnpaddedIntArray(int minLen) {
+ return new int[minLen];
+ }
+
+ /**
+ * newUnpaddedLongArray
+ */
+ public static long[] newUnpaddedLongArray(int minLen) {
+ return new long[minLen];
+ }
+
+ /**
+ * newUnpaddedFloatArray
+ */
+ public static float[] newUnpaddedFloatArray(int minLen) {
+ return new float[minLen];
+ }
+
+ /**
+ * newUnpaddedBooleanArray
+ */
+ public static boolean[] newUnpaddedBooleanArray(int minLen) {
+ return new boolean[minLen];
+ }
+
+ /**
+ * newUnpaddedCharArray
+ */
+ public static char[] newUnpaddedCharArray(int minLen) {
+ return new char[minLen];
+ }
+
+ /**
+ * emptyArray
+ */
+ public static <T> T[] emptyArray(Class<T> kind) {
+ return (T[]) Array.newInstance(kind, 0);
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/com/android/internal/util/GrowingArrayUtils.java b/ui/ui-desktop/android-emu/src/desktopMain/java/com/android/internal/util/GrowingArrayUtils.java
new file mode 100644
index 0000000..ffe6de7
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/com/android/internal/util/GrowingArrayUtils.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2014 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 com.android.internal.util;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
+/**
+ * A helper class that aims to provide comparable growth performance to ArrayList, but on primitive
+ * arrays. Common array operations are implemented for efficient use in dynamic containers.
+ *
+ * All methods in this class assume that the length of an array is equivalent to its capacity and
+ * NOT the number of elements in the array. The current size of the array is always passed in as a
+ * parameter.
+ *
+ */
+public final class GrowingArrayUtils {
+
+ /**
+ * Appends an element to the end of the array, growing the array if there is no more room.
+ * @param array The array to which to append the element. This must NOT be null.
+ * @param currentSize The number of elements in the array. Must be less than or equal to
+ * array.length.
+ * @param element The element to append.
+ * @return the array to which the element was appended. This may be different than the given
+ * array.
+ */
+ @UnsupportedAppUsage
+ public static <T> T[] append(T[] array, int currentSize, T element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ @SuppressWarnings("unchecked")
+ T[] newArray = ArrayUtils.newUnpaddedArray(
+ (Class<T>) array.getClass().getComponentType(), growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive int version of {@link #append(Object[], int, Object)}.
+ */
+ @UnsupportedAppUsage
+ public static int[] append(int[] array, int currentSize, int element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive long version of {@link #append(Object[], int, Object)}.
+ */
+ public static long[] append(long[] array, int currentSize, long element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive boolean version of {@link #append(Object[], int, Object)}.
+ */
+ public static boolean[] append(boolean[] array, int currentSize, boolean element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive float version of {@link #append(Object[], int, Object)}.
+ */
+ public static float[] append(float[] array, int currentSize, float element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ float[] newArray = ArrayUtils.newUnpaddedFloatArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Inserts an element into the array at the specified index, growing the array if there is no
+ * more room.
+ *
+ * @param array The array to which to append the element. Must NOT be null.
+ * @param currentSize The number of elements in the array. Must be less than or equal to
+ * array.length.
+ * @param element The element to insert.
+ * @return the array to which the element was appended. This may be different than the given
+ * array.
+ */
+ public static <T> T[] insert(T[] array, int currentSize, int index, T element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ @SuppressWarnings("unchecked")
+ T[] newArray = ArrayUtils.newUnpaddedArray((Class<T>) array.getClass().getComponentType(),
+ growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive int version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static int[] insert(int[] array, int currentSize, int index, int element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive long version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static long[] insert(long[] array, int currentSize, int index, long element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive boolean version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static boolean[] insert(boolean[] array, int currentSize, int index, boolean element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Given the current size of an array, returns an ideal size to which the array should grow.
+ * This is typically double the given size, but should not be relied upon to do so in the
+ * future.
+ */
+ public static int growSize(int currentSize) {
+ return currentSize <= 4 ? 8 : currentSize * 2;
+ }
+
+ // Uninstantiable
+ private GrowingArrayUtils() {}
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/java/libcore/util/EmptyArray.java b/ui/ui-desktop/android-emu/src/desktopMain/java/libcore/util/EmptyArray.java
new file mode 100644
index 0000000..df47d6e
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/java/libcore/util/EmptyArray.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 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 libcore.util;
+
+/**
+ * Empty primitive arrays.
+ */
+public final class EmptyArray {
+ private EmptyArray() {}
+
+ public static final boolean[] BOOLEAN = new boolean[0];
+ public static final byte[] BYTE = new byte[0];
+ public static final char[] CHAR = new char[0];
+ public static final double[] DOUBLE = new double[0];
+ public static final float[] FLOAT = new float[0];
+ public static final int[] INT = new int[0];
+ public static final long[] LONG = new long[0];
+
+ public static final Class<?>[] CLASS = new Class[0];
+ public static final Object[] OBJECT = new Object[0];
+ public static final String[] STRING = new String[0];
+ public static final Throwable[] THROWABLE = new Throwable[0];
+ public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0];
+ public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0];
+ public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE =
+ new java.lang.reflect.TypeVariable[0];
+}
+
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt
index 54f7b9d..6a991eb 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Canvas.kt
@@ -18,15 +18,123 @@
import org.jetbrains.skija.Canvas
import org.jetbrains.skija.Rect
+import org.jetbrains.skija.RoundedRect
-public class Canvas(private val canvas: org.jetbrains.skija.Canvas) {
+public class Canvas(val skijaCanvas: org.jetbrains.skija.Canvas) {
+ var skijaFont = org.jetbrains.skija.Font(Typeface.DEFAULT.skijaTypeface, 30f)
fun translate(x: Float, y: Float) {
- canvas.translate(x, y)
+ skijaCanvas.translate(x, y)
+ }
+
+ fun drawLine(
+ startX: Float,
+ startY: Float,
+ stopX: Float,
+ stopY: Float,
+ paint: Paint
+ ) {
+ skijaCanvas.drawLine(
+ startX,
+ startY,
+ stopX,
+ stopY,
+ paint.skijaPaint
+ )
}
fun drawRect(rect: android.graphics.RectF, paint: android.graphics.Paint) {
val skijaRect = Rect.makeLTRB(rect.left, rect.top, rect.right, rect.bottom)
- canvas.drawRect(skijaRect, paint.skijaPaint)
+ skijaCanvas.drawRect(skijaRect, paint.skijaPaint)
+ }
+
+ fun drawRect(
+ left: Float,
+ top: Float,
+ right: Float,
+ bottom: Float,
+ paint: android.graphics.Paint
+ ) {
+ val skijaRect = Rect.makeLTRB(left, top, right, bottom)
+ skijaCanvas.drawRect(skijaRect, paint.skijaPaint)
+ }
+
+ fun drawArc(
+ left: Float,
+ top: Float,
+ right: Float,
+ bottom: Float,
+ startAngle: Float,
+ sweepAngle: Float,
+ useCenter: Boolean,
+ paint: Paint
+ ) {
+ skijaCanvas.drawArc(
+ left,
+ top,
+ right,
+ bottom,
+ startAngle,
+ sweepAngle,
+ !useCenter,
+ paint.skijaPaint
+ )
+ }
+
+ fun drawText(
+ text: CharSequence,
+ start: Int,
+ end: Int,
+ x: Float,
+ y: Float,
+ paint: Paint
+ ) {
+ val buffer = skijaFont.hbFont.shape(text.toString(), org.jetbrains.skija.FontFeature.EMPTY)
+ skijaCanvas.drawTextBuffer(buffer, x, y, skijaFont.skFont, paint.skijaPaint)
+ }
+
+ fun drawText(
+ text: String,
+ x: Float,
+ y: Float,
+ paint: Paint
+ ) {
+ drawText(text, 0, text.length, x, y, paint)
+ }
+
+ fun drawRoundRect(
+ left: Float,
+ top: Float,
+ right: Float,
+ bottom: Float,
+ rx: Float,
+ ry: Float,
+ paint: android.graphics.Paint
+ ) {
+ val skijaRoundedRect = RoundedRect.makeLTRB(left, top, right, bottom, rx, ry)
+ skijaCanvas.drawRoundedRect(skijaRoundedRect, paint.skijaPaint)
+ }
+
+ fun clipRect(left: Float, top: Float, right: Float, bottom: Float, op: Region.Op): Boolean {
+ val skijaRect = Rect.makeLTRB(left, top, right, bottom)
+ skijaCanvas.clipRect(skijaRect, op.skija)
+ return true
+ }
+
+ fun clipPath(path: Path, op: Region.Op): Boolean {
+ skijaCanvas.clipPath(path.skijaPath, op.skija)
+ return true
+ }
+
+ fun scale(sx: Float, sy: Float) {
+ skijaCanvas.scale(sx, sy)
+ }
+
+ fun save(): Int {
+ return skijaCanvas.save()
+ }
+
+ fun restore() {
+ skijaCanvas.restore()
}
}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Outline.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Outline.kt
new file mode 100644
index 0000000..9f4d6f8
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Outline.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 android.graphics
+
+class Outline {
+ var alpha: Float = 1f
+
+ var rect: Rect? = null
+ var radius: Float? = null
+ var path: Path? = null
+
+ fun set(outline: Outline) {
+ rect = outline.rect
+ radius = outline.radius
+ path = outline.path
+ }
+
+ fun isEmpty() = rect == null && radius == null && path == null
+
+ fun canClip() = true
+
+ fun setEmpty() {
+ rect = null
+ radius = null
+ path = null
+ }
+
+ fun setRect(left: Int, top: Int, right: Int, bottom: Int) {
+ rect = Rect(left, top, right, bottom)
+ radius = null
+ path = null
+ }
+
+ fun setRoundRect(left: Int, top: Int, right: Int, bottom: Int, radius: Float) {
+ rect = Rect(left, top, right, bottom)
+ this.radius = radius
+ path = null
+ }
+
+ fun setConvexPath(convexPath: Path) {
+ path = convexPath
+ rect = null
+ radius = null
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Paint.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Paint.kt
index d9e25f7..08cebc6 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Paint.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Paint.kt
@@ -16,35 +16,109 @@
package android.graphics
-class Paint {
- enum class Style {
- FILL,
- FILL_AND_STROKE,
- STROKE
+open class Paint {
+ enum class Style(val skija: org.jetbrains.skija.Paint.Style) {
+ FILL(org.jetbrains.skija.Paint.Style.FILL),
+ FILL_AND_STROKE(org.jetbrains.skija.Paint.Style.STROKE_AND_FILL),
+ STROKE(org.jetbrains.skija.Paint.Style.STROKE)
}
- enum class Cap {
- BUTT,
- ROUND,
- SQUARE
+ enum class Cap(val skija: org.jetbrains.skija.Paint.Cap) {
+ BUTT(org.jetbrains.skija.Paint.Cap.BUTT),
+ ROUND(org.jetbrains.skija.Paint.Cap.ROUND),
+ SQUARE(org.jetbrains.skija.Paint.Cap.SQUARE)
}
- enum class Join {
- BEVEL,
- MITER,
- ROUND
+ enum class Join(val skija: org.jetbrains.skija.Paint.Join) {
+ BEVEL(org.jetbrains.skija.Paint.Join.BEVEL),
+ MITER(org.jetbrains.skija.Paint.Join.MITER),
+ ROUND((org.jetbrains.skija.Paint.Join.ROUND))
}
- constructor(flags: Int) {}
+ open class FontMetricsInt {
+ @JvmField
+ var top: Int = 0
+ @JvmField
+ var ascent: Int = 0
+ @JvmField
+ var descent: Int = 0
+ @JvmField
+ var bottom: Int = 0
+ @JvmField
+ var leading: Int = 0
+
+ override fun toString(): String {
+ return "FontMetricsInt: top=" + top + " ascent=" + ascent +
+ " descent=" + descent + " bottom=" + bottom +
+ " leading=" + leading
+ }
+ }
val skijaPaint = org.jetbrains.skija.Paint()
+ constructor(flags: Int) {
+ if (flags and 1 == 1) {
+ skijaPaint.setAntiAlias(true)
+ }
+ }
+
var color: Int
get() = skijaPaint.getColor().toInt()
set(value) {
skijaPaint.setColor(value.toLong())
}
- var strokeWidth: Float = 0f
- var style: Style = Style.STROKE
- var stokeCap: Cap = Cap.BUTT
+ var strokeWidth: Float
+ get() = skijaPaint.getStrokeWidth()
+ set(value) {
+ skijaPaint.setStrokeWidth(value)
+ }
+ var style: Style
+ get() = Style.values().first { it.skija == skijaPaint.getStyle() }
+ set(value) {
+ skijaPaint.setStyle(value.skija)
+ }
+ var strokeCap: Cap
+ get() = Cap.values().first { it.skija == skijaPaint.getStrokeCap() }
+ set(value) {
+ skijaPaint.setStrokeCap(value.skija)
+ }
+ var strokeMiter: Float
+ get() = skijaPaint.getStrokeMiter().toFloat()
+ set(value) {
+ skijaPaint.setStrokeMiter(value)
+ }
+ var strokeJoin: Join
+ get() = Join.values().first { it.skija == skijaPaint.getStrokeJoin() }
+ set(value) {
+ skijaPaint.setStrokeJoin(value.skija)
+ }
+ var antiAlias: Boolean
+ get() = skijaPaint.isAntiAlias()
+ set(value) {
+ skijaPaint.setAntiAlias(value)
+ }
+
+ var textSize: Float = 0f
+
+ private var typeface: Typeface? = null
+ fun getTypeface(): Typeface? = typeface
+ fun setTypeface(newTypeface: Typeface?): Typeface? {
+ val oldTypeface = typeface
+ typeface = newTypeface
+ return oldTypeface
+ }
+ var textLocale: java.util.Locale = java.util.Locale.getDefault()
+ var fontFeatureSettings: String? = null
+ var textScaleX: Float = 1f
+ var textSkewX: Float = 1f
+
+ fun setShadowLayer(radius: Float, dx: Float, dy: Float, shadowColor: Int) {
+ println("Paint.setShadowLayer")
+ }
+
+ fun setPathEffect(effect: PathEffect?): PathEffect? {
+ if (effect != null)
+ println("setPathEffect not implemented yet")
+ return effect
+ }
}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
index 0b6dba7..61cdafe 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
@@ -16,4 +16,6 @@
package android.graphics
-class Path
\ No newline at end of file
+class Path {
+ val skijaPath = org.jetbrains.skija.Path()
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/PathEffect.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/PathEffect.kt
new file mode 100644
index 0000000..0a668ef
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/PathEffect.kt
@@ -0,0 +1,19 @@
+/*
+ * 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 android.graphics
+
+open class PathEffect
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Rect.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Rect.kt
new file mode 100644
index 0000000..2ce6324
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Rect.kt
@@ -0,0 +1,33 @@
+/*
+ * 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 android.graphics
+
+class Rect(
+ var left: Int,
+ var top: Int,
+ var right: Int,
+ var bottom: Int
+) {
+ constructor() : this(0, 0, 0, 0)
+
+ fun set(left: Int, top: Int, right: Int, bottom: Int) {
+ this.left = left
+ this.top = top
+ this.right = right
+ this.bottom = bottom
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Region.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Region.kt
new file mode 100644
index 0000000..7426cbd
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Region.kt
@@ -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.
+ */
+
+class Region {
+ enum class Op(val skija: org.jetbrains.skija.Canvas.ClipOp) {
+ DIFFERENCE(org.jetbrains.skija.Canvas.ClipOp.DIFFERENCE),
+ INTERSECT(org.jetbrains.skija.Canvas.ClipOp.INTERSECT)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Typeface.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Typeface.kt
new file mode 100644
index 0000000..9b3aebe
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Typeface.kt
@@ -0,0 +1,63 @@
+/*
+ * 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 android.graphics
+
+private const val NORMAL_FONT_NAME = "NotoSans-Regular"
+private const val BOLD_FONT_NAME = "NotoSans-Bold"
+private const val ITALIC_FONT_NAME = "NotoSans-Italic"
+private const val BOLD_ITALIC_FONT_NAME = "NotoSans-BoldItalic"
+
+class Typeface(val skijaTypeface: org.jetbrains.skija.Typeface) {
+ companion object {
+ // TODO: Skija should make it possible to make fonts from non-file in-memory source
+ val NORMAL_TYPEFACE = Typeface(org.jetbrains.skija.Typeface.makeFromFile(
+ getFontPathAsString(NORMAL_FONT_NAME)))
+ val BOLD_TYPEFACE = Typeface(org.jetbrains.skija.Typeface.makeFromFile(
+ getFontPathAsString(BOLD_FONT_NAME)))
+ val ITALIC_TYPEFACE = Typeface(org.jetbrains.skija.Typeface.makeFromFile(
+ getFontPathAsString(ITALIC_FONT_NAME)))
+ val BOLD_ITALIC_TYPEFACE = Typeface(org.jetbrains.skija.Typeface.makeFromFile(
+ getFontPathAsString(BOLD_ITALIC_FONT_NAME)))
+
+ @JvmField
+ val DEFAULT = NORMAL_TYPEFACE
+
+ @JvmField
+ val NORMAL = 0x0
+
+ @JvmField
+ val BOLD = 0x1
+
+ @JvmField
+ val ITALIC = 0x2
+
+ @JvmField
+ val BOLD_ITALIC = 0x3
+
+ @JvmStatic
+ fun defaultFromStyle(style: Int): Typeface = when (style) {
+ BOLD -> BOLD_TYPEFACE
+ ITALIC -> ITALIC_TYPEFACE
+ BOLD_ITALIC -> BOLD_ITALIC_TYPEFACE
+ else -> DEFAULT
+ }
+ }
+}
+
+fun getFontPathAsString(font: String): String {
+ return Typeface::class.java.getClassLoader().getResource("$font.ttf").getFile()
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/Layout.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/Layout.kt
new file mode 100644
index 0000000..e88e804
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/Layout.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 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 android.text
+
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.Path
+import android.compat.annotation.UnsupportedAppUsage
+
+open class Layout(
+ var mText: CharSequence,
+ paint: TextPaint,
+ width: Int,
+ align: Alignment,
+ spacingmult: Float,
+ spacingadd: Float
+) {
+ enum class Alignment {
+ ALIGN_NORMAL,
+ ALIGN_OPPOSITE,
+ ALIGN_CENTER,
+ /** @hide */
+ @UnsupportedAppUsage
+ ALIGN_LEFT,
+ /** @hide */
+ @UnsupportedAppUsage
+ ALIGN_RIGHT,
+ }
+
+ class Directions(val mDirections: IntArray)
+
+ class TabStops(val increment: Float, val spans: Array<Any>)
+
+ companion object {
+ @JvmStatic
+ fun getDesiredWidth(source: CharSequence, start: Int, end: Int, paint: TextPaint): Float {
+ return minOf(end - start + 1, source.length) * 1f
+ }
+
+ @JvmField
+ val DIR_LEFT_TO_RIGHT = 1
+
+ @JvmField
+ val DIR_RIGHT_TO_LEFT = -1
+
+ @JvmField
+ val RUN_LENGTH_MASK = 0x03ffffff
+
+ @JvmField
+ val RUN_LEVEL_SHIFT = 26
+
+ @JvmField
+ val RUN_RTL_FLAG = 1 shl RUN_LEVEL_SHIFT
+
+ @JvmField
+ val DIRS_ALL_LEFT_TO_RIGHT = Directions(intArrayOf(0, RUN_LENGTH_MASK))
+
+ @JvmField
+ val DIRS_ALL_RIGHT_TO_LEFT = Directions(intArrayOf(0, RUN_LENGTH_MASK or RUN_RTL_FLAG))
+ }
+
+ fun replaceWith(
+ text: CharSequence,
+ paint: TextPaint,
+ width: Int,
+ align: Alignment,
+ spacingmult: Float,
+ spacingadd: Float
+ ) {
+ println("Layout.replaceWith")
+ mText = text
+ }
+
+ fun getText(): CharSequence = mText
+
+ open fun getHeight(): Int {
+ return 0
+ }
+
+ open fun getLineCount(): Int {
+ return 1
+ }
+
+ open fun getLineTop(line: Int): Int {
+ return 0
+ }
+
+ open fun getLineDescent(line: Int): Int {
+ return 0
+ }
+
+ open fun getLineStart(line: Int): Int {
+ return 0
+ }
+
+ open fun getParagraphDirection(line: Int): Int {
+ return DIR_LEFT_TO_RIGHT
+ }
+
+ open fun getLineContainsTab(line: Int): Boolean {
+ return false
+ }
+
+ open fun getLineMax(line: Int): Float {
+ return 0f
+ }
+
+ open fun getLineWidth(line: Int): Float {
+ return 0f
+ }
+
+ open fun getLineDirections(line: Int): Directions {
+ return Layout.DIRS_ALL_LEFT_TO_RIGHT
+ }
+
+ open fun getTopPadding(): Int {
+ return 0
+ }
+
+ open fun getBottomPadding(): Int {
+ return 0
+ }
+
+ open fun getEllipsisCount(line: Int): Int {
+ return 0
+ }
+
+ open fun getEllipsisStart(line: Int): Int {
+ return 0
+ }
+
+ open fun getEllipsizedWidth(): Int {
+ return 0
+ }
+
+ open fun draw(c: Canvas) {
+ println("Layout.draw1: $mText")
+ draw(c, null, null, 0)
+ }
+
+ open fun draw(canvas: Canvas, highlight: Path?, highlightpaint: Paint?, cursorOffset: Int) {
+ println("Layout.draw2")
+ drawText(canvas, 0, 1)
+ }
+
+ fun drawText(canvas: Canvas, firstLine: Int, lastLine: Int) {
+ println("Layout.drawText: $firstLine .. $lastLine")
+ canvas.drawText(mText, 0, mText.length, 0.5f, 0.5f, mWorkPaint)
+ }
+
+ fun getLineBaseline(line: Int): Int {
+ return getLineTop(line + 1) - getLineDescent(line)
+ }
+
+ val mWorkPaint = TextPaint(0)
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/StaticLayout.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/StaticLayout.kt
new file mode 100644
index 0000000..4e50e5f
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/StaticLayout.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 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 android.text
+
+class StaticLayout(
+ text: CharSequence,
+ paint: TextPaint,
+ width: Int,
+ align: Alignment,
+ spacingmult: Float,
+ spacingadd: Float
+) : Layout(text, paint, width, align, spacingmult, spacingadd)
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/TextLine.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/TextLine.kt
new file mode 100644
index 0000000..127a50c
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/TextLine.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 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 android.text
+
+import android.graphics.Paint.FontMetricsInt
+import android.text.Layout.Directions
+import android.text.Layout.TabStops
+
+class TextLine() {
+ var mText: CharSequence = ""
+ var mLen = 0
+
+ companion object {
+ @JvmStatic
+ fun obtain(): TextLine = TextLine()
+
+ @JvmStatic
+ fun recycle(line: TextLine) {
+ }
+ }
+
+ fun metrics(fmi: FontMetricsInt): Float {
+ println("TextLine.metrics")
+ return mLen * 1f
+ }
+
+ fun set(
+ paint: TextPaint,
+ text: CharSequence,
+ start: Int,
+ limit: Int,
+ dir: Int,
+ directions: Directions,
+ hasTabs: Boolean,
+ tabStops: TabStops?,
+ ellipsisStart: Int,
+ ellipsisEnd: Int
+ ) {
+ println("TextLine.set")
+ mText = text
+ mLen = limit - start
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/TextPaint.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/TextPaint.kt
new file mode 100644
index 0000000..aeff02b
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/text/TextPaint.kt
@@ -0,0 +1,21 @@
+/*
+ * 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 android.text
+
+import android.graphics.Paint
+
+class TextPaint(flags: Int) : Paint(flags)
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/util/Log.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/util/Log.kt
new file mode 100644
index 0000000..64411f9
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/util/Log.kt
@@ -0,0 +1,26 @@
+/*
+ * 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 android.util
+
+object Log {
+ fun v(scope: String, msg: String) {
+ println("$scope: msg")
+ }
+ fun e(scope: String, msg: String) {
+ println("$scope: $msg")
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
index d00265a..24d3a6d 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
@@ -18,8 +18,25 @@
import android.content.Context
import android.graphics.Canvas
+import android.graphics.Rect
+import android.util.LayoutDirection
open class View(val context: Context) {
+ companion object {
+ @JvmField
+ val LAYOUT_DIRECTION_LTR = LayoutDirection.LTR
+ @JvmField
+ val LAYOUT_DIRECTION_RTL = LayoutDirection.RTL
+
+ @JvmStatic
+ fun generateViewId(): Int {
+ // TODO: atomic in Android.
+ return sNextGeneratedId++
+ }
+
+ var sNextGeneratedId: Int = 1
+ }
+
open class AccessibilityDelegate()
interface OnApplyWindowInsetsListener {
@@ -43,7 +60,7 @@
fun requestLayout() {}
- fun invalidate() {}
+ open fun invalidate() {}
open fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {}
@@ -62,7 +79,7 @@
companion object {
@JvmStatic
fun getMode(measureSpec: Int): Int {
- return 1073741824 // EXACTLY
+ return -2147483648 // AT_MOST
}
@JvmStatic
@@ -71,4 +88,47 @@
}
}
}
+
+ var id: Int = 0
+
+ var alpha: Float = 1.0f
+ var scaleX: Float = 1.0f
+ var scaleY: Float = 1.0f
+ var translationX: Float = 0.0f
+ var translationY: Float = 0.0f
+ var elevation: Float = 0.0f
+ var rotation: Float = 0.0f
+ var rotationX: Float = 0.0f
+ var rotationY: Float = 0.0f
+ var pivotX: Float = 0.0f
+ var pivotY: Float = 0.0f
+
+ var left: Int = 0
+ var top: Int = 0
+ var right: Int = 0
+ var bottom: Int = 0
+ val width: Int get() = right - left
+ val height: Int get() = bottom - top
+
+ var clipToBounds: Boolean = false
+ var clipBounds: Rect? = null
+
+ var clipToOutline: Boolean = false
+
+ var outlineProvider: ViewOutlineProvider? = null
+
+ var drawingTime: Long = 0
+
+ var mRecreateDisplayList: Boolean = false
+
+ fun layout(left: Int, top: Int, right: Int, bottom: Int) {
+ this.left = left
+ this.top = top
+ this.right = right
+ this.bottom = bottom
+ }
+
+ fun updateDisplayListIfDirty() {
+ println("View.updateDisplayListIfDirty")
+ }
}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
index 2e2b1e4..b8b37bb 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
@@ -17,6 +17,10 @@
package android.view
import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Outline
+import android.graphics.Rect
+import org.jetbrains.skija.RoundedRect
abstract class ViewGroup(context: Context) : View(context) {
var clipChildren: Boolean = true
@@ -29,10 +33,69 @@
children.clear()
}
+ fun addView(child: android.view.View) {
+ children.add(child)
+ }
+
fun addView(child: android.view.View, params: ViewGroup.LayoutParams?) {
children.add(child)
}
+ fun drawChild(canvas: Canvas, view: View, drawingTime: Long): Boolean {
+ canvas.save()
+ canvas.translate(
+ view.left.toFloat() + view.translationX,
+ view.top.toFloat() + view.translationY
+ )
+ if (view.clipToBounds && view.clipBounds != null) {
+ canvas.clipRect(view.clipBounds!!)
+ }
+ if (view.clipToOutline) {
+ val outline = Outline()
+ view.outlineProvider?.getOutline(view, outline)
+ canvas.clipOutline(outline)
+ }
+ if (view.scaleX != 1f || view.scaleY != 1f) {
+ canvas.scale(view.scaleX, view.scaleY)
+ }
+
+ view.dispatchDraw(canvas)
+ canvas.restore()
+ return true
+ }
+
+ private fun Canvas.clipRect(rect: Rect) {
+ clipRect(
+ rect.left.toFloat(),
+ rect.top.toFloat(),
+ rect.right.toFloat(),
+ rect.bottom.toFloat(),
+ Region.Op.INTERSECT
+ )
+ }
+
+ private fun Canvas.clipOutline(outline: Outline) {
+ val rect = outline.rect
+ val radius = outline.radius
+ val path = outline.path
+ if (path != null) {
+ clipPath(path, Region.Op.INTERSECT)
+ } else if (radius != null && rect != null) {
+ skijaCanvas.clipRoundedRect(
+ RoundedRect.makeLTRB(
+ rect.left.toFloat(),
+ rect.top.toFloat(),
+ rect.right.toFloat(),
+ rect.bottom.toFloat(),
+ radius,
+ radius
+ )
+ )
+ } else if (rect != null) {
+ clipRect(rect)
+ }
+ }
+
class LayoutParams(width: Int, height: Int) {
companion object {
const val WRAP_CONTENT = 0
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewOutlineProvider.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewOutlineProvider.kt
new file mode 100644
index 0000000..4539838
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewOutlineProvider.kt
@@ -0,0 +1,21 @@
+/*
+ * 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 android.view
+
+abstract class ViewOutlineProvider {
+ abstract fun getOutline(view: View, outline: android.graphics.Outline)
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/accessibility/AccessibilityManager.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/accessibility/AccessibilityManager.kt
index e5229ba..4b85146 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/accessibility/AccessibilityManager.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/accessibility/AccessibilityManager.kt
@@ -16,4 +16,6 @@
package android.view.accessibility
-class AccessibilityManager()
+class AccessibilityManager() {
+ fun isEnabled(): Boolean = false
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/R.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/R.kt
new file mode 100644
index 0000000..dea489c
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/R.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.core
+
+class R {
+ class id {
+ companion object {
+ @JvmField
+ val wrapped_composition_tag = 0
+ @JvmField
+ val accessibility_custom_action_0 = 0
+ @JvmField
+ val accessibility_custom_action_1 = 1
+ @JvmField
+ val accessibility_custom_action_2 = 2
+ @JvmField
+ val accessibility_custom_action_3 = 3
+ @JvmField
+ val accessibility_custom_action_4 = 4
+ @JvmField
+ val accessibility_custom_action_5 = 5
+ @JvmField
+ val accessibility_custom_action_6 = 6
+ @JvmField
+ val accessibility_custom_action_7 = 7
+ @JvmField
+ val accessibility_custom_action_8 = 8
+ @JvmField
+ val accessibility_custom_action_9 = 9
+ @JvmField
+ val accessibility_custom_action_10 = 10
+ @JvmField
+ val accessibility_custom_action_11 = 11
+ @JvmField
+ val accessibility_custom_action_12 = 12
+ @JvmField
+ val accessibility_custom_action_13 = 13
+ @JvmField
+ val accessibility_custom_action_14 = 14
+ @JvmField
+ val accessibility_custom_action_15 = 15
+ @JvmField
+ val accessibility_custom_action_16 = 16
+ @JvmField
+ val accessibility_custom_action_17 = 17
+ @JvmField
+ val accessibility_custom_action_18 = 18
+ @JvmField
+ val accessibility_custom_action_19 = 19
+ @JvmField
+ val accessibility_custom_action_20 = 20
+ @JvmField
+ val accessibility_custom_action_21 = 21
+ @JvmField
+ val accessibility_custom_action_22 = 22
+ @JvmField
+ val accessibility_custom_action_23 = 23
+ @JvmField
+ val accessibility_custom_action_24 = 24
+ @JvmField
+ val accessibility_custom_action_25 = 25
+ @JvmField
+ val accessibility_custom_action_26 = 26
+ @JvmField
+ val accessibility_custom_action_27 = 27
+ @JvmField
+ val accessibility_custom_action_28 = 28
+ @JvmField
+ val accessibility_custom_action_29 = 29
+ @JvmField
+ val accessibility_custom_action_30 = 30
+ @JvmField
+ val accessibility_custom_action_31 = 31
+ }
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/ViewLayer.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/ViewLayer.kt
new file mode 100644
index 0000000..e71105e
--- /dev/null
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/androidx/ui/core/ViewLayer.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.core
+
+import android.content.Context
+import android.view.View
+
+class ViewLayer(context: Context) : View(context) {
+ init {
+ id = generateViewId()
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/build.gradle b/ui/ui-desktop/build.gradle
index e29bfe7..b482b0d 100644
--- a/ui/ui-desktop/build.gradle
+++ b/ui/ui-desktop/build.gradle
@@ -17,7 +17,9 @@
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
+import androidx.build.SupportConfigKt
import java.nio.file.Files
+import java.nio.file.FileSystems
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@@ -35,6 +37,7 @@
import java.io.FileOutputStream
import java.nio.file.Files
import java.nio.file.StandardCopyOption
+import java.util.regex.Pattern
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
@@ -52,8 +55,6 @@
mavenLocal()
}
-
-
configurations {
ui_components
compose_compiler_jar
@@ -103,6 +104,7 @@
}
jvmMain {
+ resources.srcDirs += new File(SupportConfigKt.getExternalProjectPath(project), "noto-fonts/other/")
}
jvmMain.dependencies {
@@ -139,13 +141,11 @@
"ui-animation-core",
"ui-core",
"ui-foundation",
- "ui-framework",
"ui-geometry",
"ui-graphics",
"ui-layout",
"ui-livedata",
"ui-material",
- "ui-platform",
"ui-saved-instance-state",
"ui-test",
"ui-text",
@@ -177,7 +177,7 @@
ZipInputStream stream = new ZipInputStream(bis)
ZipEntry entry = null
while ((entry = stream.getNextEntry()) != null) {
- if(!entry.name.equals("classes.jar")) continue;
+ if (!entry.name.equals("classes.jar")) continue;
FileOutputStream fos = new FileOutputStream(jar)
BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.size())
int len = 0
@@ -194,23 +194,45 @@
// Find in dependencies first (BFS) task's output ending with `name`.
-String findInDeps(Task root, String name) {
+String findInDeps(Task root, Closure<Boolean> matcher) {
// Do BFS by deps.
def queue = new java.util.ArrayDeque<Task>()
+ def seen = new java.util.HashSet<Task>()
queue.addLast(root)
while (queue.size() > 0) {
def task = queue.pop()
- def classes = task.outputs.files.files.find { it.name.endsWith(name) }
+ seen.add(task)
+ def classes = task.outputs.files.files.find { matcher(it.absolutePath) }
if (classes != null) {
return classes.absolutePath
}
task.taskDependencies.getDependencies(task).each {
- queue.addLast(it)
+ if (!seen.contains(it))
+ queue.addLast(it)
}
}
return null
}
+java.nio.file.FileSystem getFS(URI uri) {
+ try {
+ def result = FileSystems.getFileSystem(uri)
+ return result
+ } catch (java.nio.file.FileSystemNotFoundException e) {
+ def env = new HashMap<String, String>()
+ return FileSystems.newFileSystem(uri, env)
+ }
+}
+
+void addToJar(String jarName, String entryName, String entryContentPath) {
+ def jarPath = Paths.get(jarName)
+ def uri = URI.create("jar:" + jarPath.toUri());
+ def fs = getFS(uri)
+ def pathInZipFile = fs.getPath("/" + entryName)
+ Files.copy(Paths.get(entryContentPath), pathInZipFile, StandardCopyOption.REPLACE_EXISTING)
+ fs.close()
+}
+
task extractJars {
doLast {
// Find all JAR files matching components.
@@ -218,16 +240,30 @@
uiComponents.each { component ->
def depProject = project(":ui:" + component)
def task = depProject.tasks.named("assemble").get()
- def srcJar = findInDeps(task, "classes.jar")
+ def srcJar = findInDeps(task, { absolutePath ->
+ absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
+ })
if (srcJar == null) {
throw new Error("cannot find classes.jar in "+ task)
} else {
def destJar = composeClassDir + component + ".jar"
Files.copy(Paths.get(srcJar), Paths.get(destJar), StandardCopyOption.REPLACE_EXISTING)
+ // TODO: restore missing kotlin_module and remove this code.
+ def missingModuleDir = findInDeps(task, { absolutePath ->
+ absolutePath.indexOf("kotlin-classes/release") != -1
+ })
+ if (missingModuleDir == null)
+ throw new Error("cannot find build dir")
+ def shortName = "META-INF/" + component + "_release.kotlin_module"
+ def missingModule = missingModuleDir + "/" + shortName
+ addToJar(destJar, shortName, missingModule)
}
}
- def frameworkProject = project(":ui:ui-framework")
- def srcJar = findInDeps(frameworkProject.tasks.named("assemble").get(), "compose-compiler.jar")
+ def frameworkProject = project(":compose:compose-compiler")
+ def srcJar = findInDeps(frameworkProject.tasks.named("assemble").get(), {
+ absolutePath ->
+ Pattern.matches(".*/compose-compiler.*.jar", absolutePath)
+ })
if (srcJar == null)
throw new Error("cannot find compose-compiler.jar")
Files.copy(Paths.get(srcJar),
@@ -258,6 +294,7 @@
dependsOn("extractJars")
kotlinOptions {
useIR = true
+ jvmTarget = "1.8"
freeCompilerArgs += [
// TODO: hack, apply compose plugin better.
"-Xplugin=${project.rootDir.absolutePath}/ui-desktop/compose-libs/compose-compiler.jar",
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
index 6946fdc..72353f5 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
@@ -35,6 +35,8 @@
var renderTarget: BackendRenderTarget? = null
var surface: Surface? = null
var canvas: Canvas? = null
+ var textureId: Int = 0
+ val intBuf1 = IntBuffer.allocate(1)
fun clear() {
if (surface != null) {
@@ -43,6 +45,7 @@
if (renderTarget != null) {
renderTarget!!.close()
}
+ textureId = 0
}
}
@@ -73,6 +76,7 @@
val profile = GLProfile.get(GLProfile.GL3)
val capabilities = GLCapabilities(profile)
glCanvas = GLCanvas(capabilities)
+ capabilities.doubleBuffered = true
val skijaState = SkijaState()
glCanvas.autoSwapBufferMode = true
@@ -84,12 +88,12 @@
width: Int,
height: Int
) {
- initSkija(glCanvas, skijaState)
+ initSkija(glCanvas, skijaState, false)
renderer!!.onReshape(width, height)
}
override fun init(drawable: GLAutoDrawable?) {
- initSkija(glCanvas, skijaState)
+ initSkija(glCanvas, skijaState, true)
renderer!!.onInit()
}
@@ -99,11 +103,15 @@
override fun display(drawable: GLAutoDrawable?) {
skijaState.apply {
+ val gl = drawable!!.gl!!
+ gl.glBindTexture(GL.GL_TEXTURE_2D, textureId)
canvas!!.clear(0xFFFFFFFF)
renderer!!.onRender(
canvas!!, glCanvas.width, glCanvas.height
)
context!!.flush()
+ gl.glGetIntegerv(GL.GL_TEXTURE_BINDING_2D, intBuf1)
+ textureId = intBuf1[0]
}
}
})
@@ -128,7 +136,7 @@
}
}
- private fun initSkija(glCanvas: GLCanvas, skijaState: SkijaState) {
+ private fun initSkija(glCanvas: GLCanvas, skijaState: SkijaState, reinitTexture: Boolean) {
with(skijaState) {
val width = glCanvas.width
val height = glCanvas.height
@@ -154,6 +162,10 @@
)
canvas = surface!!.canvas
canvas!!.scale(dpi, dpi)
+ if (reinitTexture) {
+ glCanvas.gl.glGetIntegerv(GL.GL_TEXTURE_BINDING_2D, intBuf1)
+ skijaState.textureId = intBuf1[0]
+ }
}
}
}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
index 85e3647..e985ef9 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
@@ -23,11 +23,7 @@
import androidx.animation.ManualAnimationClock
import androidx.compose.Composable
import androidx.compose.Recomposer
-import androidx.ui.core.Modifier
-import androidx.ui.core.Owner
import androidx.ui.core.setContent
-import androidx.ui.layout.padding
-import androidx.ui.unit.dp
import javax.swing.SwingUtilities
@@ -35,23 +31,29 @@
fun SkiaWindow.setContent(content: @Composable () -> Unit) {
SwingUtilities.invokeLater {
- println("start composing!")
-
- rootAnimationClockFactory = { ManualAnimationClock(0L) }
+ val fps = 60
+ val clocks = mutableListOf<ManualAnimationClock>()
+ rootAnimationClockFactory = {
+ ManualAnimationClock(0L).also {
+ clocks.add(it)
+ }
+ }
val context = object : Context() {}
val viewGroup = object : ViewGroup(context) {}
viewGroup.setContent(Recomposer.current(), content)
val view = viewGroup.getChildAt(0)
- // we need this to override the root drawLayer() - RenderNode are not ported yet
- (view as Owner).root.modifier = Modifier.padding(0.dp)
view.onAttachedToWindow()
- this.renderer = Renderer(view)
- this.setFps(60)
+ this.renderer = Renderer(view, clocks, fps)
+ this.setFps(fps)
}
}
-private class Renderer(val view: View) : SkiaRenderer {
+private class Renderer(
+ val view: View,
+ val clocks: List<ManualAnimationClock>,
+ val fps: Int
+) : SkiaRenderer {
var androidCanvas: android.graphics.Canvas? = null
override fun onInit() {
@@ -65,6 +67,9 @@
}
override fun onRender(canvas: Canvas, width: Int, height: Int) {
+ clocks.forEach {
+ it.clockTimeMillis += 1000 / fps
+ }
if (androidCanvas == null) {
androidCanvas = android.graphics.Canvas(canvas)
}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/example/Main.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/example/Main.kt
index 2ff5111..894f704 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/example/Main.kt
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/example/Main.kt
@@ -16,14 +16,23 @@
package androidx.ui.desktop.example
import androidx.compose.Composable
+import androidx.ui.core.Alignment
+import androidx.ui.core.Modifier
import androidx.ui.graphics.Color
import androidx.ui.desktop.SkiaWindow
import androidx.ui.desktop.setContent
-import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
import androidx.ui.foundation.drawBackground
-import androidx.ui.core.Modifier
+import androidx.ui.layout.Arrangement
+import androidx.ui.layout.Column
import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.padding
+import androidx.ui.layout.wrapContentSize
+import androidx.ui.layout.preferredHeight
+import androidx.ui.material.Button
+import androidx.ui.material.CircularProgressIndicator
+import androidx.ui.material.ExtendedFloatingActionButton
+import androidx.ui.material.Scaffold
+import androidx.ui.material.TopAppBar
import androidx.ui.unit.dp
import javax.swing.WindowConstants
@@ -47,6 +56,36 @@
@Composable
fun App() {
- Box(Modifier.fillMaxSize(), backgroundColor = Color.Green)
- Box(Modifier.padding(40.dp) + Modifier.drawBackground(color = Color.Blue))
+ Scaffold(
+ topAppBar = {
+ TopAppBar(
+ title = { Text("Desktop Compose") }
+ )
+ },
+ floatingActionButton = {
+ ExtendedFloatingActionButton(
+ text = { Text("BUTTON") },
+ }
+ )
+ },
+ bodyContent = { modifier ->
+ Column(modifier.fillMaxSize(), Arrangement.SpaceEvenly) {
+ Text(
+ text = "Привет! ä½ å¥½! Desktop Compose!",
+ color = Color.Black,
+ modifier = Modifier
+ .drawBackground(Color.Blue)
+ .preferredHeight(56.dp)
+ .wrapContentSize(Alignment.Center)
+ )
+ var text = "Base"
+ Button(>
+ text = "Clicked"
+ }) {
+ Text(text)
+ }
+ CircularProgressIndicator()
+ }
+ }
+ )
}
diff --git a/ui/ui-foundation/OWNERS b/ui/ui-foundation/OWNERS
index dd5e772..22210830 100644
--- a/ui/ui-foundation/OWNERS
+++ b/ui/ui-foundation/OWNERS
@@ -4,6 +4,7 @@
malkov@google.com
lpf@google.com
tianliu@google.com
+soboleva@google.com
# Text
haoyuchang@google.com
diff --git a/ui/ui-foundation/api/0.1.0-dev12.txt b/ui/ui-foundation/api/0.1.0-dev12.txt
index 1b934f3..333d7fad 100644
--- a/ui/ui-foundation/api/0.1.0-dev12.txt
+++ b/ui/ui-foundation/api/0.1.0-dev12.txt
@@ -53,17 +53,10 @@
method public static void Dialog(kotlin.jvm.functions.Function0<kotlin.Unit> onCloseRequest, kotlin.jvm.functions.Function0<kotlin.Unit> children);
}
- public final class DrawBackground implements androidx.ui.core.DrawModifier {
- method public androidx.ui.foundation.DrawBackground copy(androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public void draw(androidx.ui.core.ContentDrawScope);
- }
-
public final class DrawBackgroundKt {
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground(androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground-qSsqlCY(long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground-IZZjS-Q(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
+ method @Deprecated public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
+ method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
+ method public static androidx.ui.core.Modifier drawBackground-s1Ed2t0(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
}
public final class DrawBorder implements androidx.ui.core.DrawModifier {
diff --git a/ui/ui-foundation/api/current.txt b/ui/ui-foundation/api/current.txt
index 1b934f3..333d7fad 100644
--- a/ui/ui-foundation/api/current.txt
+++ b/ui/ui-foundation/api/current.txt
@@ -53,17 +53,10 @@
method public static void Dialog(kotlin.jvm.functions.Function0<kotlin.Unit> onCloseRequest, kotlin.jvm.functions.Function0<kotlin.Unit> children);
}
- public final class DrawBackground implements androidx.ui.core.DrawModifier {
- method public androidx.ui.foundation.DrawBackground copy(androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public void draw(androidx.ui.core.ContentDrawScope);
- }
-
public final class DrawBackgroundKt {
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground(androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground-qSsqlCY(long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground-IZZjS-Q(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
+ method @Deprecated public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
+ method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
+ method public static androidx.ui.core.Modifier drawBackground-s1Ed2t0(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
}
public final class DrawBorder implements androidx.ui.core.DrawModifier {
diff --git a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev12.txt
index 1b934f3..333d7fad 100644
--- a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev12.txt
@@ -53,17 +53,10 @@
method public static void Dialog(kotlin.jvm.functions.Function0<kotlin.Unit> onCloseRequest, kotlin.jvm.functions.Function0<kotlin.Unit> children);
}
- public final class DrawBackground implements androidx.ui.core.DrawModifier {
- method public androidx.ui.foundation.DrawBackground copy(androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public void draw(androidx.ui.core.ContentDrawScope);
- }
-
public final class DrawBackgroundKt {
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground(androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground-qSsqlCY(long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground-IZZjS-Q(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
+ method @Deprecated public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
+ method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
+ method public static androidx.ui.core.Modifier drawBackground-s1Ed2t0(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
}
public final class DrawBorder implements androidx.ui.core.DrawModifier {
diff --git a/ui/ui-foundation/api/public_plus_experimental_current.txt b/ui/ui-foundation/api/public_plus_experimental_current.txt
index 1b934f3..333d7fad 100644
--- a/ui/ui-foundation/api/public_plus_experimental_current.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_current.txt
@@ -53,17 +53,10 @@
method public static void Dialog(kotlin.jvm.functions.Function0<kotlin.Unit> onCloseRequest, kotlin.jvm.functions.Function0<kotlin.Unit> children);
}
- public final class DrawBackground implements androidx.ui.core.DrawModifier {
- method public androidx.ui.foundation.DrawBackground copy(androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public void draw(androidx.ui.core.ContentDrawScope);
- }
-
public final class DrawBackgroundKt {
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground(androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground-qSsqlCY(long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground-IZZjS-Q(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
+ method @Deprecated public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
+ method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
+ method public static androidx.ui.core.Modifier drawBackground-s1Ed2t0(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
}
public final class DrawBorder implements androidx.ui.core.DrawModifier {
diff --git a/ui/ui-foundation/api/restricted_0.1.0-dev12.txt b/ui/ui-foundation/api/restricted_0.1.0-dev12.txt
index 1b934f3..333d7fad 100644
--- a/ui/ui-foundation/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-foundation/api/restricted_0.1.0-dev12.txt
@@ -53,17 +53,10 @@
method public static void Dialog(kotlin.jvm.functions.Function0<kotlin.Unit> onCloseRequest, kotlin.jvm.functions.Function0<kotlin.Unit> children);
}
- public final class DrawBackground implements androidx.ui.core.DrawModifier {
- method public androidx.ui.foundation.DrawBackground copy(androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public void draw(androidx.ui.core.ContentDrawScope);
- }
-
public final class DrawBackgroundKt {
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground(androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground-qSsqlCY(long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground-IZZjS-Q(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
+ method @Deprecated public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
+ method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
+ method public static androidx.ui.core.Modifier drawBackground-s1Ed2t0(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
}
public final class DrawBorder implements androidx.ui.core.DrawModifier {
diff --git a/ui/ui-foundation/api/restricted_current.txt b/ui/ui-foundation/api/restricted_current.txt
index 1b934f3..333d7fad 100644
--- a/ui/ui-foundation/api/restricted_current.txt
+++ b/ui/ui-foundation/api/restricted_current.txt
@@ -53,17 +53,10 @@
method public static void Dialog(kotlin.jvm.functions.Function0<kotlin.Unit> onCloseRequest, kotlin.jvm.functions.Function0<kotlin.Unit> children);
}
- public final class DrawBackground implements androidx.ui.core.DrawModifier {
- method public androidx.ui.foundation.DrawBackground copy(androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public void draw(androidx.ui.core.ContentDrawScope);
- }
-
public final class DrawBackgroundKt {
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground(androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method @Deprecated public static androidx.ui.foundation.DrawBackground DrawBackground-qSsqlCY(long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
- method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
- method public static androidx.ui.core.Modifier drawBackground-IZZjS-Q(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape);
+ method @Deprecated public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Paint paint, androidx.ui.graphics.Shape shape);
+ method public static androidx.ui.core.Modifier drawBackground(androidx.ui.core.Modifier, androidx.ui.graphics.Brush brush, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
+ method public static androidx.ui.core.Modifier drawBackground-s1Ed2t0(androidx.ui.core.Modifier, long color, androidx.ui.graphics.Shape shape = androidx.ui.graphics.RectangleShapeKt.RectangleShape, @FloatRange(from=0.0, to=1.0) float alpha = 1.0f, androidx.ui.graphics.painter.DrawStyle style = Fill, androidx.ui.graphics.ColorFilter? colorFilter = null, androidx.ui.graphics.BlendMode blendMode = CanvasScope.DefaultBlendMode);
}
public final class DrawBorder implements androidx.ui.core.DrawModifier {
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldFocusTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldFocusTest.kt
index 4e5d527..7aaa314 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldFocusTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldFocusTest.kt
@@ -22,7 +22,7 @@
import androidx.test.filters.LargeTest
import androidx.ui.core.Modifier
import androidx.ui.core.TestTag
-import androidx.ui.focus.FocusModifier
+import androidx.ui.core.focus.FocusModifier
import androidx.ui.input.EditorValue
import androidx.ui.layout.width
import androidx.ui.test.createComposeRule
diff --git a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldTest.kt b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldTest.kt
index 716f611..5a019b5 100644
--- a/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldTest.kt
+++ b/ui/ui-foundation/src/androidTest/java/androidx/ui/foundation/TextFieldTest.kt
@@ -27,9 +27,9 @@
import androidx.ui.core.TestTag
import androidx.ui.core.TextInputServiceAmbient
import androidx.ui.core.onPositioned
-import androidx.ui.focus.FocusModifier
-import androidx.ui.focus.FocusState
-import androidx.ui.focus.focusState
+import androidx.ui.core.focus.FocusModifier
+import androidx.ui.core.focus.FocusState
+import androidx.ui.core.focus.focusState
import androidx.ui.graphics.Color
import androidx.ui.graphics.RectangleShape
import androidx.ui.input.CommitTextEditOp
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBackground.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBackground.kt
index b2767ad..d7fbdae 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBackground.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBackground.kt
@@ -16,117 +16,129 @@
package androidx.ui.foundation
-import androidx.compose.Composable
-import androidx.compose.remember
+import androidx.annotation.FloatRange
import androidx.ui.core.ContentDrawScope
import androidx.ui.core.DrawModifier
import androidx.ui.core.Modifier
-import androidx.ui.core.composed
import androidx.ui.geometry.Size
-import androidx.ui.geometry.toRect
+import androidx.ui.graphics.BlendMode
import androidx.ui.graphics.Brush
import androidx.ui.graphics.Color
+import androidx.ui.graphics.ColorFilter
import androidx.ui.graphics.Outline
import androidx.ui.graphics.Paint
import androidx.ui.graphics.RectangleShape
import androidx.ui.graphics.Shape
-import androidx.ui.graphics.SolidColor
import androidx.ui.graphics.drawOutline
+import androidx.ui.graphics.painter.CanvasScope
+import androidx.ui.graphics.painter.DrawStyle
+import androidx.ui.graphics.painter.Fill
import androidx.ui.graphics.painter.drawCanvas
import androidx.ui.unit.Px
import androidx.ui.unit.PxSize
+import androidx.ui.unit.toRect
/**
- * Returns a [DrawModifier] that draws [shape] with a solid [color], with the size of the
- * layout's rectangle.
+ * Draws [shape] with [paint] behind the content.
+ */
+@Deprecated("Prefer usage of drawBackground(color, shape) or " +
+ "drawBackground(brush, shape)",
+ ReplaceWith("Modifier.drawBackground(color, shape)"))
+fun Modifier.drawBackground(
+ paint: Paint,
+ shape: Shape
+) = this + DrawBackground(
+ shape,
+ {
+ drawCanvas { canvas, size ->
+ canvas.drawRect(size.toRect(), paint)
+ }
+ },
+ { outline ->
+ drawCanvas { canvas, _ ->
+ canvas.drawOutline(outline, paint)
+ }
+ }
+ )
+
+/**
+ * Draws [shape] with a solid [color] behind the content.
*
* @sample androidx.ui.foundation.samples.DrawBackgroundColor
*
* @param color color to paint background with
* @param shape desired shape of the background
*/
-@Suppress("DEPRECATION")
-@Deprecated(
- "Use Modifier.drawBackground",
- replaceWith = ReplaceWith(
- "Modifier.drawBackground(color, shape)",
- "androidx.ui.core.Modifier",
- "androidx.ui.foundation.drawBackground",
- "androidx.ui.foundation.shape.RectangleShape"
- )
-)
-@Composable
-fun DrawBackground(color: Color, shape: Shape = RectangleShape): DrawBackground =
- DrawBackground(SolidColor(color), shape)
+fun Modifier.drawBackground(
+ color: Color,
+ shape: Shape = RectangleShape,
+ @FloatRange(from = 0.0, to = 1.0) alpha: Float = CanvasScope.DefaultAlpha,
+ style: DrawStyle = Fill,
+ colorFilter: ColorFilter? = null,
+ blendMode: BlendMode = CanvasScope.DefaultBlendMode
+) = this + DrawBackground(
+ shape,
+ {
+ drawRect(
+ color,
+ alpha = alpha,
+ style = style,
+ colorFilter = colorFilter,
+ blendMode = blendMode
+ )
+ },
+ { outline ->
+ drawOutline(
+ outline,
+ color,
+ alpha = alpha,
+ style = style,
+ colorFilter = colorFilter,
+ blendMode = blendMode
+ )
+ }
+ )
/**
- * Returns a [DrawModifier] that draws [shape] with [brush], with the size of the layout's
- * rectangle.
+ * Draws [shape] with [brush] behind the content.
*
* @sample androidx.ui.foundation.samples.DrawBackgroundShapedBrush
*
* @param brush brush to paint background with
* @param shape desired shape of the background
*/
-@Deprecated(
- "Use Modifier.drawBackground",
- replaceWith = ReplaceWith(
- "Modifier.drawBackground(brush, shape)",
- "androidx.ui.core.Modifier",
- "androidx.ui.foundation.drawBackground",
- "androidx.ui.foundation.shape.RectangleShape"
- )
-)
-@Composable
-fun DrawBackground(brush: Brush, shape: Shape = RectangleShape): DrawBackground {
- return remember(shape, brush) {
- val paint = Paint().also {
- brush.applyTo(it)
- }
- DrawBackground(paint, shape)
- }
-}
-
-/**
- * Draws [shape] with [paint] behind the content.
- */
-fun Modifier.drawBackground(
- paint: Paint,
- shape: Shape
-) = this + DrawBackground(paint, shape)
-
-/**
- * Draws [shape] with a solid [color] behind the content.
- *
- * @param color color to paint background with
- * @param shape desired shape of the background
- */
-fun Modifier.drawBackground(
- color: Color,
- shape: Shape = RectangleShape
-) = drawBackground(SolidColor(color), shape)
-
-/**
- * Draws [shape] with [brush] behind the content.
- *
- * @param brush brush to paint background with
- * @param shape desired shape of the background
- */
fun Modifier.drawBackground(
brush: Brush,
- shape: Shape = RectangleShape
-) = composed {
- drawBackground(
- remember(brush) {
- Paint().also { brush.applyTo(it) }
- },
- shape
- )
-}
+ shape: Shape = RectangleShape,
+ @FloatRange(from = 0.0, to = 1.0) alpha: Float = CanvasScope.DefaultAlpha,
+ style: DrawStyle = Fill,
+ colorFilter: ColorFilter? = null,
+ blendMode: BlendMode = CanvasScope.DefaultBlendMode
+) = this + DrawBackground(
+ shape,
+ { drawRect(
+ brush = brush,
+ alpha = alpha,
+ style = style,
+ colorFilter = colorFilter,
+ blendMode = blendMode
+ )
+ },
+ { outline ->
+ drawOutline(outline,
+ brush,
+ alpha = alpha,
+ style = style,
+ colorFilter = colorFilter,
+ blendMode = blendMode
+ )
+ }
+ )
-data class DrawBackground internal constructor(
- private val paint: Paint,
- private val shape: Shape
+private data class DrawBackground internal constructor(
+ private val shape: Shape,
+ private val drawRect: ContentDrawScope.() -> Unit,
+ private val drawOutline: ContentDrawScope.(outline: Outline) -> Unit
) : DrawModifier {
// naive cache outline calculation if size is the same
@@ -134,23 +146,21 @@
private var lastOutline: Outline? = null
override fun ContentDrawScope.draw() {
- drawCanvas { canvas, _ ->
- if (shape === RectangleShape) {
- // shortcut to avoid Outline calculation and allocation
- canvas.drawRect(size.toRect(), paint)
- } else {
- val localOutline =
- if (size == lastSize) {
- lastOutline!!
- } else {
- val pxSize = PxSize(Px(size.width), Px(size.height))
- shape.createOutline(pxSize, this)
- }
- canvas.drawOutline(localOutline, paint)
- lastOutline = localOutline
- lastSize = size
- }
- drawContent()
+ if (shape === RectangleShape) {
+ // shortcut to avoid Outline calculation and allocation
+ drawRect()
+ } else {
+ val localOutline =
+ if (size == lastSize) {
+ lastOutline!!
+ } else {
+ val pxSize = PxSize(Px(size.width), Px(size.height))
+ shape.createOutline(pxSize, this)
+ }
+ drawOutline(localOutline)
+ lastOutline = localOutline
+ lastSize = size
}
+ drawContent()
}
}
\ No newline at end of file
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt
index 77c5a40..9e6ca6f 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/DrawBorder.kt
@@ -20,25 +20,25 @@
import androidx.compose.remember
import androidx.ui.core.ContentDrawScope
import androidx.ui.core.DrawModifier
+import androidx.ui.core.DrawScope
import androidx.ui.core.Modifier
import androidx.ui.core.composed
import androidx.ui.geometry.Offset
import androidx.ui.geometry.Rect
+import androidx.ui.geometry.Size
import androidx.ui.geometry.isSimple
import androidx.ui.geometry.outerRect
import androidx.ui.graphics.Brush
-import androidx.ui.graphics.Canvas
import androidx.ui.graphics.Color
import androidx.ui.graphics.Outline
-import androidx.ui.graphics.Paint
-import androidx.ui.graphics.PaintingStyle
import androidx.ui.graphics.Path
import androidx.ui.graphics.PathOperation
import androidx.ui.graphics.RectangleShape
import androidx.ui.graphics.Shape
import androidx.ui.graphics.SolidColor
import androidx.ui.graphics.addOutline
-import androidx.ui.graphics.painter.drawCanvas
+import androidx.ui.graphics.painter.Fill
+import androidx.ui.graphics.painter.Stroke
import androidx.ui.unit.Density
import androidx.ui.unit.Dp
import androidx.ui.unit.Px
@@ -171,57 +171,47 @@
override fun ContentDrawScope.draw() {
val density = this
- drawCanvas { canvas, _ ->
- with(cache) {
- drawContent()
- modifierSize = PxSize(Px(size.width), Px(size.height))
- val outline = modifierSizeOutline(density)
- val borderSize =
- if (borderWidth == Dp.Hairline) 1f else borderWidth.value * density.density
- brush.applyTo(paint)
- paint.strokeWidth = borderSize
-
- if (borderSize <= 0 || size.minDimension <= 0.0f) {
- return
- } else if (outline is Outline.Rectangle) {
- drawRoundRectBorder(borderSize, outline.rect, 0f, canvas, paint)
- } else if (outline is Outline.Rounded && outline.rrect.isSimple) {
- val radius = outline.rrect.bottomLeftRadiusY
- drawRoundRectBorder(
- borderSize,
- outline.rrect.outerRect(),
- radius,
- canvas,
- paint
- )
- } else {
- val path = borderPath(density, borderSize)
- paint.style = PaintingStyle.fill
- canvas.drawPath(path, paint)
- }
+ with(cache) {
+ drawContent()
+ modifierSize = PxSize(Px(size.width), Px(size.height))
+ val outline = modifierSizeOutline(density)
+ val borderSize =
+ if (borderWidth == Dp.Hairline) 1f else borderWidth.value * density.density
+ if (borderSize <= 0 || size.minDimension <= 0.0f) {
+ return
+ } else if (outline is Outline.Rectangle) {
+ drawRoundRectBorder(borderSize, outline.rect, 0f, brush)
+ } else if (outline is Outline.Rounded && outline.rrect.isSimple) {
+ val radius = outline.rrect.bottomLeftRadiusY
+ drawRoundRectBorder(
+ borderSize,
+ outline.rrect.outerRect(),
+ radius,
+ brush
+ )
+ } else {
+ drawPath(borderPath(density, borderSize), brush)
}
}
}
- private fun drawRoundRectBorder(
+ private fun DrawScope.drawRoundRectBorder(
borderSize: Float,
rect: Rect,
radius: Float,
- canvas: Canvas,
- paint: Paint
+ brush: Brush
) {
val fillWithBorder = borderSize * 2 >= rect.minDimension
- paint.style = if (fillWithBorder) PaintingStyle.fill else PaintingStyle.stroke
+ val style = if (fillWithBorder) Fill else Stroke(borderSize)
val delta = if (fillWithBorder) 0f else borderSize / 2
- canvas.drawRoundRect(
- left = rect.left + delta,
- top = rect.top + delta,
- right = rect.right - delta,
- bottom = rect.bottom - delta,
+ drawRoundRect(
+ brush,
+ topLeft = Offset(rect.left + delta, rect.top + delta),
+ size = Size(rect.width - 2 * delta, rect.height - 2 * delta),
radiusX = radius,
radiusY = radius,
- paint = paint
+ style = style
)
}
@@ -255,8 +245,6 @@
private var dirtyOutline = true
private var outline: Outline? = null
- val paint = Paint().apply { isAntiAlias = true }
-
var lastShape: Shape? = null
set(value) {
if (value != field) {
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
index 7491312..6ca3992 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
@@ -24,7 +24,7 @@
import androidx.compose.state
import androidx.ui.core.Modifier
import androidx.ui.core.drawBehind
-import androidx.ui.focus.FocusModifier
+import androidx.ui.core.focus.FocusModifier
import androidx.ui.geometry.Offset
import androidx.ui.geometry.Rect
import androidx.ui.graphics.Color
diff --git a/ui/ui-geometry/api/api_lint.ignore b/ui/ui-geometry/api/api_lint.ignore
index db1ca8b..ea11d6f 100644
--- a/ui/ui-geometry/api/api_lint.ignore
+++ b/ui/ui-geometry/api/api_lint.ignore
@@ -1,13 +1,9 @@
// Baseline format: 1.0
+AcronymName: androidx.ui.geometry.Rect.Companion#fromCircle-hSKLB2U(long, float):
+ Acronyms should not be capitalized in method names: was `fromCircle-hSKLB2U`, should this be `fromCircle-hSklB2U`?
AcronymName: androidx.ui.geometry.Rect.Companion#fromLTRB(float, float, float, float):
Acronyms should not be capitalized in method names: was `fromLTRB`, should this be `fromLtrb`?
AcronymName: androidx.ui.geometry.Rect.Companion#fromLTWH(float, float, float, float):
Acronyms should not be capitalized in method names: was `fromLTWH`, should this be `fromLtwh`?
-
-
-KotlinOperator: androidx.ui.geometry.RRect#contains(androidx.ui.geometry.Offset):
- Note that adding the `operator` keyword would allow calling this method using operator syntax
-KotlinOperator: androidx.ui.geometry.Rect#contains(androidx.ui.geometry.Offset):
- Note that adding the `operator` keyword would allow calling this method using operator syntax
-KotlinOperator: androidx.ui.geometry.Size#contains(androidx.ui.geometry.Offset):
- Note that adding the `operator` keyword would allow calling this method using operator syntax
+AcronymName: androidx.ui.geometry.Size.Companion#lerp-T-c3OIQ(long, long, float):
+ Acronyms should not be capitalized in method names: was `lerp-T-c3OIQ`, should this be `lerp-T-c3Oiq`?
diff --git a/ui/ui-geometry/build.gradle b/ui/ui-geometry/build.gradle
index b6e818e..7a07948 100644
--- a/ui/ui-geometry/build.gradle
+++ b/ui/ui-geometry/build.gradle
@@ -25,26 +25,29 @@
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXUiPlugin")
- id("org.jetbrains.kotlin.android")
+ id("kotlin-multiplatform")
}
-dependencies {
- implementation(KOTLIN_STDLIB)
+kotlin {
+ android()
+ sourceSets {
+ commonMain.dependencies {
+ implementation(KOTLIN_STDLIB_COMMON)
- api "androidx.annotation:annotation:1.1.0"
- implementation project(":ui:ui-util")
+ implementation project(":ui:ui-util")
+ implementation project(":compose:compose-runtime")
+ }
+ jvmMain.dependencies {
+ implementation(KOTLIN_STDLIB)
+ }
+ androidMain.dependencies {
+ api "androidx.annotation:annotation:1.1.0"
+ }
- implementation project(":compose:compose-runtime")
-
- testImplementation(ANDROIDX_TEST_RULES)
- testImplementation(ANDROIDX_TEST_RUNNER)
- testImplementation(JUNIT)
- testImplementation(TRUTH)
-
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ESPRESSO_CORE)
- androidTestImplementation(JUNIT)
+ commonTest.dependencies {
+ implementation kotlin("test-junit")
+ }
+ }
}
androidx {
@@ -58,8 +61,7 @@
tasks.withType(KotlinCompile).configureEach {
kotlinOptions {
- freeCompilerArgs += ["-Xuse-experimental=kotlin.Experimental", "-XXLanguage:+InlineClasses"]
+ freeCompilerArgs += ["-XXLanguage:+InlineClasses"]
useIR = true
}
-}
-
+}
\ No newline at end of file
diff --git a/ui/ui-geometry/src/main/AndroidManifest.xml b/ui/ui-geometry/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from ui/ui-geometry/src/main/AndroidManifest.xml
rename to ui/ui-geometry/src/androidMain/AndroidManifest.xml
diff --git a/ui/ui-geometry/src/main/java/androidx/ui/geometry/Offset.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Offset.kt
similarity index 100%
rename from ui/ui-geometry/src/main/java/androidx/ui/geometry/Offset.kt
rename to ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Offset.kt
diff --git a/ui/ui-geometry/src/main/java/androidx/ui/geometry/OffsetBase.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/OffsetBase.kt
similarity index 100%
rename from ui/ui-geometry/src/main/java/androidx/ui/geometry/OffsetBase.kt
rename to ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/OffsetBase.kt
diff --git a/ui/ui-geometry/src/main/java/androidx/ui/geometry/RRect.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/RRect.kt
similarity index 94%
rename from ui/ui-geometry/src/main/java/androidx/ui/geometry/RRect.kt
rename to ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/RRect.kt
index 6ba68ed..e093dab 100644
--- a/ui/ui-geometry/src/main/java/androidx/ui/geometry/RRect.kt
+++ b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/RRect.kt
@@ -19,6 +19,8 @@
import androidx.ui.util.lerp
import androidx.ui.util.toStringAsFixed
import kotlin.math.absoluteValue
+import kotlin.math.max
+import kotlin.math.min
/**
* An immutable rounded rectangle with custom radii for all four corners.
@@ -101,7 +103,7 @@
private fun minRadius(min: Float, radius1: Float, radius2: Float, limit: Float): Float {
val sum = radius1 + radius2
return if (sum > limit && sum != 0.0f) {
- Math.min(min, limit / sum)
+ min(min, limit / sum)
} else {
min
}
@@ -216,7 +218,7 @@
companion object {
/** A rounded rectangle with all the values set to zero. */
- @JvmStatic
+ @kotlin.jvm.JvmStatic
val Zero = RRect(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)
}
}
@@ -416,12 +418,12 @@
* respective quadrant bisector.
*/
fun RRect.safeInnerRect(): Rect {
- val insetFactor = 0.29289321881f; // 1-cos(pi/4)
+ val insetFactor = 0.29289321881f // 1-cos(pi/4)
- val leftRadius = Math.max(bottomLeftRadiusX, topLeftRadiusX)
- val topRadius = Math.max(topLeftRadiusY, topRightRadiusY)
- val rightRadius = Math.max(topRightRadiusX, bottomRightRadiusX)
- val bottomRadius = Math.max(bottomRightRadiusY, bottomLeftRadiusY)
+ val leftRadius = max(bottomLeftRadiusX, topLeftRadiusX)
+ val topRadius = max(topLeftRadiusY, topRightRadiusY)
+ val rightRadius = max(topRightRadiusX, bottomRightRadiusX)
+ val bottomRadius = max(bottomRightRadiusY, bottomLeftRadiusY)
return Rect.fromLTRB(
left + leftRadius * insetFactor,
@@ -440,10 +442,10 @@
* or height.
*/
fun RRect.middleRect(): Rect {
- val leftRadius = Math.max(bottomLeftRadiusX, topLeftRadiusX)
- val topRadius = Math.max(topLeftRadiusY, topRightRadiusY)
- val rightRadius = Math.max(topRightRadiusX, bottomRightRadiusX)
- val bottomRadius = Math.max(bottomRightRadiusY, bottomLeftRadiusY)
+ val leftRadius = max(bottomLeftRadiusX, topLeftRadiusX)
+ val topRadius = max(topLeftRadiusY, topRightRadiusY)
+ val rightRadius = max(topRightRadiusX, bottomRightRadiusX)
+ val bottomRadius = max(bottomRightRadiusY, bottomLeftRadiusY)
return Rect.fromLTRB(
left + leftRadius,
top + topRadius,
@@ -459,8 +461,8 @@
* resulting [Rect] will have negative width or height.
*/
fun RRect.wideMiddleRect(): Rect {
- val topRadius = Math.max(topLeftRadiusY, topRightRadiusY)
- val bottomRadius = Math.max(bottomRightRadiusY, bottomLeftRadiusY)
+ val topRadius = max(topLeftRadiusY, topRightRadiusY)
+ val bottomRadius = max(bottomRightRadiusY, bottomLeftRadiusY)
return Rect.fromLTRB(
left,
top + topRadius,
@@ -476,8 +478,8 @@
* resulting [Rect] will have negative width or height.
*/
fun RRect.tallMiddleRect(): Rect {
- val leftRadius = Math.max(bottomLeftRadiusX, topLeftRadiusX)
- val rightRadius = Math.max(topRightRadiusX, bottomRightRadiusX)
+ val leftRadius = max(bottomLeftRadiusX, topLeftRadiusX)
+ val rightRadius = max(topRightRadiusX, bottomRightRadiusX)
return Rect.fromLTRB(
left + leftRadius,
top,
@@ -527,13 +529,13 @@
* The lesser of the magnitudes of the [RRect.width] and the [RRect.height] of this
* rounded rectangle.
*/
-val RRect.shortestSide get(): Float = Math.min(width.absoluteValue, height.absoluteValue)
+val RRect.shortestSide get(): Float = min(width.absoluteValue, height.absoluteValue)
/**
* The greater of the magnitudes of the [RRect.width] and the [RRect.height] of this
* rounded rectangle.
*/
-val RRect.longestSide get(): Float = Math.max(width.absoluteValue, height.absoluteValue)
+val RRect.longestSide get(): Float = max(width.absoluteValue, height.absoluteValue)
/**
* The offset to the point halfway between the left and right and the top and
diff --git a/ui/ui-geometry/src/main/java/androidx/ui/geometry/Radius.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Radius.kt
similarity index 100%
rename from ui/ui-geometry/src/main/java/androidx/ui/geometry/Radius.kt
rename to ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Radius.kt
diff --git a/ui/ui-geometry/src/main/java/androidx/ui/geometry/Rect.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Rect.kt
similarity index 92%
rename from ui/ui-geometry/src/main/java/androidx/ui/geometry/Rect.kt
rename to ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Rect.kt
index d24d2e5..dbf06c5 100644
--- a/ui/ui-geometry/src/main/java/androidx/ui/geometry/Rect.kt
+++ b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Rect.kt
@@ -69,10 +69,10 @@
*/
fun fromCircle(center: Offset, radius: Float): Rect {
return Rect(
- center.dx - radius,
- center.dy - radius,
- center.dx + radius,
- center.dy + radius
+ center.dx - radius,
+ center.dy - radius,
+ center.dx + radius,
+ center.dy + radius
)
}
@@ -82,10 +82,10 @@
*/
fun fromPoints(a: Offset, b: Offset): Rect {
return Rect(
- Math.min(a.dx, b.dx),
- Math.min(a.dy, b.dy),
- Math.max(a.dx, b.dx),
- Math.max(a.dy, b.dy)
+ min(a.dx, b.dx),
+ min(a.dy, b.dy),
+ max(a.dx, b.dx),
+ max(a.dy, b.dy)
)
}
@@ -171,10 +171,10 @@
*/
fun translate(translateX: Float, translateY: Float): Rect {
return fromLTRB(
- left + translateX,
- top + translateY,
- right + translateX,
- bottom + translateY
+ left + translateX,
+ top + translateY,
+ right + translateX,
+ bottom + translateY
)
}
@@ -194,10 +194,10 @@
*/
fun intersect(other: Rect): Rect {
return fromLTRB(
- Math.max(left, other.left),
- Math.max(top, other.top),
- Math.min(right, other.right),
- Math.min(bottom, other.bottom)
+ max(left, other.left),
+ max(top, other.top),
+ min(right, other.right),
+ min(bottom, other.bottom)
)
}
@@ -207,10 +207,10 @@
*/
fun expandToInclude(other: Rect): Rect {
return fromLTRB(
- Math.min(left, other.left),
- Math.min(top, other.top),
- Math.max(right, other.right),
- Math.max(bottom, other.bottom)
+ min(left, other.left),
+ min(top, other.top),
+ max(right, other.right),
+ max(bottom, other.bottom)
)
}
diff --git a/ui/ui-geometry/src/main/java/androidx/ui/geometry/Size.kt b/ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Size.kt
similarity index 100%
rename from ui/ui-geometry/src/main/java/androidx/ui/geometry/Size.kt
rename to ui/ui-geometry/src/commonMain/kotlin/androidx/ui/geometry/Size.kt
diff --git a/ui/ui-geometry/src/test/java/androidx/ui/geometry/RRectTest.kt b/ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RRectTest.kt
similarity index 100%
rename from ui/ui-geometry/src/test/java/androidx/ui/geometry/RRectTest.kt
rename to ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RRectTest.kt
diff --git a/ui/ui-geometry/src/test/java/androidx/ui/geometry/RectTest.kt b/ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RectTest.kt
similarity index 100%
rename from ui/ui-geometry/src/test/java/androidx/ui/geometry/RectTest.kt
rename to ui/ui-geometry/src/unitTest/kotlin/androidx/ui/geometry/RectTest.kt
diff --git a/ui/ui-graphics/api/api_lint.ignore b/ui/ui-graphics/api/api_lint.ignore
index 6bbb26a..8d69f10 100644
--- a/ui/ui-graphics/api/api_lint.ignore
+++ b/ui/ui-graphics/api/api_lint.ignore
@@ -1,4 +1,8 @@
// Baseline format: 1.0
+AcronymName: androidx.ui.graphics.Canvas#drawCircle-NfwrgZA(long, float, androidx.ui.graphics.Paint):
+ Acronyms should not be capitalized in method names: was `drawCircle-NfwrgZA`, should this be `drawCircle-NfwrgZa`?
+AcronymName: androidx.ui.graphics.Canvas#drawImage--AHD2Ng(androidx.ui.graphics.ImageAsset, long, androidx.ui.graphics.Paint):
+ Acronyms should not be capitalized in method names: was `drawImage--AHD2Ng`, should this be `drawImage--AhD2Ng`?
AcronymName: androidx.ui.graphics.ColorFilter.Companion#tint-QEYXlZo(long):
Acronyms should not be capitalized in method names: was `tint-QEYXlZo`, should this be `tint-QeyXlZo`?
AcronymName: androidx.ui.graphics.ColorKt#isSet-QEYXlZo(long):
@@ -15,8 +19,18 @@
Acronyms should not be capitalized in method names: was `setColor-QEYXlZo`, should this be `setColor-QeyXlZo`?
AcronymName: androidx.ui.graphics.SolidColor#copy-QEYXlZo(long):
Acronyms should not be capitalized in method names: was `copy-QEYXlZo`, should this be `copy-QeyXlZo`?
+AcronymName: androidx.ui.graphics.painter.CanvasScope#drawCircle-uHGJFV8(androidx.ui.graphics.Brush, float, long, float, androidx.ui.graphics.painter.DrawStyle, androidx.ui.graphics.ColorFilter, androidx.ui.graphics.BlendMode):
+ Acronyms should not be capitalized in method names: was `drawCircle-uHGJFV8`, should this be `drawCircle-uHgjfV8`?
+AcronymName: androidx.ui.graphics.painter.CanvasScope#drawLine-PWBr8KI(androidx.ui.graphics.Brush, long, long, androidx.ui.graphics.painter.Stroke, float, androidx.ui.graphics.ColorFilter, androidx.ui.graphics.BlendMode):
+ Acronyms should not be capitalized in method names: was `drawLine-PWBr8KI`, should this be `drawLine-PwBr8Ki`?
+AcronymName: androidx.ui.graphics.painter.CanvasScope#drawOval-EPCrxCw(long, long, long, float, androidx.ui.graphics.painter.DrawStyle, androidx.ui.graphics.ColorFilter, androidx.ui.graphics.BlendMode):
+ Acronyms should not be capitalized in method names: was `drawOval-EPCrxCw`, should this be `drawOval-EpCrxCw`?
+AcronymName: androidx.ui.graphics.painter.CanvasScope#drawRect-EPCrxCw(long, long, long, float, androidx.ui.graphics.painter.DrawStyle, androidx.ui.graphics.ColorFilter, androidx.ui.graphics.BlendMode):
+ Acronyms should not be capitalized in method names: was `drawRect-EPCrxCw`, should this be `drawRect-EpCrxCw`?
AcronymName: androidx.ui.graphics.painter.ColorPainter#copy-QEYXlZo(long):
Acronyms should not be capitalized in method names: was `copy-QEYXlZo`, should this be `copy-QeyXlZo`?
+AcronymName: androidx.ui.graphics.painter.ImagePainter#copy-gqgapXI(androidx.ui.graphics.ImageAsset, long, long):
+ Acronyms should not be capitalized in method names: was `copy-gqgapXI`, should this be `copy-gqgapXi`?
ArrayReturn: androidx.ui.graphics.BrushKt#HorizontalGradient-G0qqrXo(kotlin.Pair<java.lang.Float,androidx.ui.graphics.Color>[], float, float, androidx.ui.graphics.TileMode) parameter #0:
@@ -37,6 +51,46 @@
Must avoid boxed primitives (`java.lang.Float`)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#arcTo(float, float, float, boolean, boolean, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.arcTo(float,float,float,boolean,boolean,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#arcToRelative(float, float, float, boolean, boolean, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.arcToRelative(float,float,float,boolean,boolean,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#close():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.close()
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#curveTo(float, float, float, float, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.curveTo(float,float,float,float,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#curveToRelative(float, float, float, float, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.curveToRelative(float,float,float,float,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#horizontalLineTo(float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.horizontalLineTo(float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#horizontalLineToRelative(float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.horizontalLineToRelative(float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#lineTo(float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.lineTo(float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#lineToRelative(float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.lineToRelative(float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#moveTo(float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.moveTo(float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#moveToRelative(float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.moveToRelative(float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#quadTo(float, float, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.quadTo(float,float,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#quadToRelative(float, float, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.quadToRelative(float,float,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#reflectiveCurveTo(float, float, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.reflectiveCurveTo(float,float,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#reflectiveCurveToRelative(float, float, float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.reflectiveCurveToRelative(float,float,float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#reflectiveQuadTo(float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.reflectiveQuadTo(float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#reflectiveQuadToRelative(float, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.reflectiveQuadToRelative(float,float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#verticalLineTo(float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.verticalLineTo(float)
+BuilderSetStyle: androidx.ui.graphics.vector.PathBuilder#verticalLineToRelative(float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.graphics.vector.PathBuilder.verticalLineToRelative(float)
+
+
DocumentExceptions: androidx.ui.graphics.vectormath.Matrix3#get(androidx.ui.graphics.vectormath.MatrixColumn):
Method Matrix3.get appears to be throwing java.lang.IllegalArgumentException; this should be listed in the documentation; see https://android.github.io/kotlin-guides/interop.html#document-exceptions
DocumentExceptions: androidx.ui.graphics.vectormath.Matrix3#get(int):
diff --git a/ui/ui-layout/OWNERS b/ui/ui-layout/OWNERS
index 97f86be..0b1cdfa 100644
--- a/ui/ui-layout/OWNERS
+++ b/ui/ui-layout/OWNERS
@@ -1,2 +1,3 @@
mount@google.com
popam@google.com
+soboleva@google.com
diff --git a/ui/ui-layout/api/api_lint.ignore b/ui/ui-layout/api/api_lint.ignore
index cffda90..a86577a 100644
--- a/ui/ui-layout/api/api_lint.ignore
+++ b/ui/ui-layout/api/api_lint.ignore
@@ -25,6 +25,8 @@
Acronyms should not be capitalized in method names: was `offset-qJOR85M`, should this be `offset-qJoR85M`?
AcronymName: androidx.ui.layout.LayoutPaddingKt#padding-qJOR85M(androidx.ui.core.Modifier, float, float):
Acronyms should not be capitalized in method names: was `padding-qJOR85M`, should this be `padding-qJoR85M`?
+AcronymName: androidx.ui.layout.LayoutSizeKt#defaultMinSizeConstraints-qJOR85M(androidx.ui.core.Modifier, float, float):
+ Acronyms should not be capitalized in method names: was `defaultMinSizeConstraints-qJOR85M`, should this be `defaultMinSizeConstraints-qJoR85M`?
AcronymName: androidx.ui.layout.LayoutSizeKt#heightIn-qJOR85M(androidx.ui.core.Modifier, float, float):
Acronyms should not be capitalized in method names: was `heightIn-qJOR85M`, should this be `heightIn-qJoR85M`?
AcronymName: androidx.ui.layout.LayoutSizeKt#preferredHeightIn-qJOR85M(androidx.ui.core.Modifier, float, float):
diff --git a/ui/ui-material/OWNERS b/ui/ui-material/OWNERS
index 40a5c8b..844cef9 100644
--- a/ui/ui-material/OWNERS
+++ b/ui/ui-material/OWNERS
@@ -3,3 +3,4 @@
andreykulikov@google.com
malkov@google.com
lpf@google.com
+soboleva@google.com
\ No newline at end of file
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt b/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt
index 4f32ee2..2f23a18 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/ProgressIndicator.kt
@@ -26,6 +26,7 @@
import androidx.compose.Composable
import androidx.ui.animation.Transition
import androidx.ui.core.DensityAmbient
+import androidx.ui.core.DrawScope
import androidx.ui.core.Modifier
import androidx.ui.core.LayoutDirection
import androidx.ui.foundation.Canvas
@@ -126,12 +127,11 @@
}
}
-private fun CanvasScope.drawLinearIndicator(
+private fun DrawScope.drawLinearIndicator(
startFraction: Float,
endFraction: Float,
color: Color,
- stroke: Stroke,
- layoutDirection: LayoutDirection = LayoutDirection.Ltr
+ stroke: Stroke
) {
val width = size.width
val height = size.height
@@ -146,11 +146,10 @@
drawLine(color, Offset(barStart, yOffset), Offset(barEnd, yOffset), stroke)
}
-private fun CanvasScope.drawLinearIndicatorBackground(
+private fun DrawScope.drawLinearIndicatorBackground(
color: Color,
- stroke: Stroke,
- layoutDirection: LayoutDirection = LayoutDirection.Ltr
-) = drawLinearIndicator(0f, 1f, color, stroke, layoutDirection)
+ stroke: Stroke
+) = drawLinearIndicator(0f, 1f, color, stroke)
/**
* A determinate circular progress indicator that represents progress by drawing an arc ranging from
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt b/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
index 1b94655..375390a 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Tab.kt
@@ -67,6 +67,7 @@
import androidx.ui.unit.max
import androidx.ui.unit.sp
import androidx.ui.unit.toPx
+import androidx.ui.util.fastFirstOrNull
/**
* A TabRow contains a row of [Tab]s, and displays an indicator underneath the currently
@@ -285,13 +286,13 @@
// The divider is measured with its own height, and width equal to the total width
// of the tab row, and then placed on top of the tabs.
- measurables.firstOrNull { it.tag == dividerTag }
+ measurables.fastFirstOrNull { it.tag == dividerTag }
?.measure(constraints.copy(minWidth = layoutWidth, maxWidth = layoutWidth))
?.run { place(IntPx.Zero, layoutHeight - height) }
// The indicator container is measured to fill the entire space occupied by the tab
// row, and then placed on top of the divider.
- measurables.firstOrNull { it.tag == indicatorTag }
+ measurables.fastFirstOrNull { it.tag == indicatorTag }
?.measure(Constraints.fixed(layoutWidth, layoutHeight))
?.place(IntPx.Zero, IntPx.Zero)
}
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt b/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
index 5d9d446..49d1333 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
@@ -42,7 +42,7 @@
import androidx.ui.core.drawBehind
import androidx.ui.core.offset
import androidx.ui.core.tag
-import androidx.ui.focus.FocusModifier
+import androidx.ui.core.focus.FocusModifier
import androidx.ui.foundation.Box
import androidx.ui.foundation.Clickable
import androidx.ui.foundation.ContentColorAmbient
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt b/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
index 3b2f6c0..6758f33 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/internal/StateDraggable.kt
@@ -30,6 +30,7 @@
import androidx.ui.foundation.animation.fling
import androidx.ui.foundation.gestures.DragDirection
import androidx.ui.foundation.gestures.draggable
+import androidx.ui.util.fastFirstOrNull
/**
* Higher-level component that allows dragging around anchored positions binded to different states
@@ -74,7 +75,7 @@
val forceAnimationCheck = state { true }
val anchors = remember(anchorsToState) { anchorsToState.map { it.first } }
- val currentValue = anchorsToState.firstOrNull { it.second == state }!!.first
+ val currentValue = anchorsToState.fastFirstOrNull { it.second == state }!!.first
val flingConfig =
AnchorsFlingConfig(anchors, animationBuilder, reason, finalValue, _ ->
if (reason != AnimationEndReason.Interrupted) {
diff --git a/ui/ui-test/api/api_lint.ignore b/ui/ui-test/api/api_lint.ignore
index f23a46e..3138bb5 100644
--- a/ui/ui-test/api/api_lint.ignore
+++ b/ui/ui-test/api/api_lint.ignore
@@ -1,6 +1,8 @@
// Baseline format: 1.0
AcronymName: androidx.ui.test.BitmapHelpersKt#assertPixelColor-9bBi3KA(android.graphics.Bitmap, long, int, int, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.Color,java.lang.String>):
Acronyms should not be capitalized in method names: was `assertPixelColor-9bBi3KA`, should this be `assertPixelColor-9bBi3Ka`?
+AcronymName: androidx.ui.test.BitmapHelpersKt#assertShape-2l1GYV8(android.graphics.Bitmap, androidx.ui.unit.Density, float, float, long, long, androidx.ui.graphics.Shape, float):
+ Acronyms should not be capitalized in method names: was `assertShape-2l1GYV8`, should this be `assertShape-2l1GyV8`?
AcronymName: androidx.ui.test.BitmapHelpersKt#assertShape-nbwoFSQ(android.graphics.Bitmap, androidx.ui.unit.Density, androidx.ui.graphics.Shape, long, long, androidx.ui.graphics.Shape, float, float, float, float, float, float, float):
Acronyms should not be capitalized in method names: was `assertShape-nbwoFSQ`, should this be `assertShape-nbwoFsq`?
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/IsDisplayedTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/IsDisplayedTest.kt
new file mode 100644
index 0000000..728707c
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/IsDisplayedTest.kt
@@ -0,0 +1,165 @@
+/*
+ * 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.ui.test
+
+import androidx.compose.Composable
+import androidx.compose.getValue
+import androidx.compose.mutableStateOf
+import androidx.compose.setValue
+import androidx.test.filters.MediumTest
+import androidx.ui.core.Layout
+import androidx.ui.core.Modifier
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.VerticalScroller
+import androidx.ui.graphics.Color
+import androidx.ui.layout.Column
+import androidx.ui.layout.Row
+import androidx.ui.layout.Stack
+import androidx.ui.layout.fillMaxHeight
+import androidx.ui.layout.fillMaxWidth
+import androidx.ui.layout.height
+import androidx.ui.layout.size
+import androidx.ui.layout.width
+import androidx.ui.test.util.BoundaryNode
+import androidx.ui.unit.Dp
+import androidx.ui.unit.dp
+import androidx.ui.unit.ipx
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@MediumTest
+@RunWith(JUnit4::class)
+class IsDisplayedTest {
+
+ @get:Rule
+ val composeTestRule = createComposeRule(disableTransitions = true)
+
+ private val colors = listOf(Color.Red, Color.Green, Color.Blue)
+
+ @Composable
+ private fun Item(i: Int, width: Dp? = null, height: Dp? = null) {
+ BoundaryNode("item$i") {
+ Box(
+ modifier = with(Modifier) { width?.let { width(it) } ?: fillMaxWidth() } +
+ with(Modifier) { height?.let { height(it) } ?: fillMaxHeight() },
+ backgroundColor = colors[i % colors.size]
+ )
+ }
+ }
+
+ @Composable
+ fun PlaceConditionally(place: Boolean, child: @Composable () -> Unit) {
+ Layout(children = child) { measurables, constraints, _ ->
+ if (place) {
+ val placeable = measurables[0].measure(constraints)
+ layout(placeable.width, placeable.height) {
+ placeable.place(0.ipx, 0.ipx)
+ }
+ } else {
+ layout(0.ipx, 0.ipx) {}
+ }
+ }
+ }
+
+ @Test
+ fun componentInScrollable_isDisplayed() {
+ composeTestRule.setContent {
+ VerticalScroller(modifier = Modifier.size(100.dp)) {
+ Column {
+ repeat(10) { Item(it, height = 30.dp) }
+ }
+ }
+ }
+
+ findByTag("item0")
+ .assertIsDisplayed()
+ }
+
+ @Test
+ fun componentInScrollable_isNotDisplayed() {
+ composeTestRule.setContent {
+ VerticalScroller(modifier = Modifier.size(100.dp)) {
+ Column {
+ repeat(10) { Item(it, height = 30.dp) }
+ }
+ }
+ }
+
+ findByTag("item4")
+ .assertIsNotDisplayed()
+ }
+
+ @Test
+ fun togglePlacement() {
+ var place by mutableStateOf(true)
+
+ composeTestRule.setContent {
+ PlaceConditionally(place) {
+ // Item instead of BoundaryNode because we need non-zero size
+ Item(0)
+ }
+ }
+
+ findByTag("item0")
+ .assertIsDisplayed()
+
+ runOnIdleCompose {
+ place = false
+ }
+
+ findByTag("item0")
+ .assertIsNotDisplayed()
+ }
+
+ @Test
+ fun toggleParentPlacement() {
+ var place by mutableStateOf(true)
+
+ composeTestRule.setContent {
+ PlaceConditionally(place) {
+ Stack {
+ // Item instead of BoundaryNode because we need non-zero size
+ Item(0)
+ }
+ }
+ }
+
+ findByTag("item0")
+ .assertIsDisplayed()
+
+ runOnIdleCompose {
+ place = false
+ }
+
+ findByTag("item0")
+ .assertIsNotDisplayed()
+ }
+
+ @Test
+ fun rowTooSmall() {
+ composeTestRule.setContent {
+ Row(modifier = Modifier.size(100.dp)) {
+ repeat(10) { Item(it, width = 30.dp) }
+ }
+ }
+
+ findByTag("item9")
+ .assertIsNotDisplayed()
+ }
+}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/IsDisplayedTests.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/IsDisplayedTests.kt
deleted file mode 100644
index fca460a..0000000
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/IsDisplayedTests.kt
+++ /dev/null
@@ -1,284 +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.ui.test
-
-import androidx.compose.Composable
-import androidx.compose.Model
-import androidx.test.filters.MediumTest
-import androidx.ui.core.Alignment
-import androidx.ui.core.Layout
-import androidx.ui.core.Modifier
-import androidx.ui.core.TestTag
-import androidx.ui.foundation.Box
-import androidx.ui.foundation.Canvas
-import androidx.ui.foundation.Text
-import androidx.ui.foundation.VerticalScroller
-import androidx.ui.graphics.Color
-import androidx.ui.layout.Column
-import androidx.ui.layout.Row
-import androidx.ui.layout.Stack
-import androidx.ui.layout.padding
-import androidx.ui.layout.preferredSize
-import androidx.ui.semantics.ScrollTo
-import androidx.ui.semantics.Semantics
-import androidx.ui.text.TextStyle
-import androidx.ui.unit.IntPx
-import androidx.ui.unit.Px
-import androidx.ui.unit.dp
-import androidx.ui.unit.ipx
-import androidx.ui.unit.px
-import androidx.ui.unit.sp
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@MediumTest
-@RunWith(JUnit4::class)
-class IsDisplayedTests {
-
- @get:Rule
- val composeTestRule = createComposeRule(disableTransitions = true)
-
- @Test
- fun componentInScrollable_isDisplayed() {
- createScrollableContent()
-
- findByText("2")
- .assertIsDisplayed()
- }
-
- @Test
- fun componentInScrollable_isNotDisplayed() {
- createScrollableContent()
-
- findByText("50")
- .assertIsNotDisplayed()
- }
-
- private fun createScrollableContent() {
- composeTestRule.setContent {
- val style = TextStyle(fontSize = 30.sp)
- VerticalScroller(modifier = Modifier.padding(10.dp)) {
- Column {
- for (i in 1..100) {
- Semantics(container = true) {
- Text(text = i.toString(), style = style)
- }
- }
- }
- }
- }
- }
-
- @Test
- fun toggleParentVisibility() {
- /*
- - topNode
- -- secondNode
- --- thirdNode
- ---- Text
- */
-
- val model = AssertsUiTestsModel(true)
-
- composeTestRule.setContent {
- val lastNode = @Composable {
- Stack {
- Semantics(container = true) {
- Text("Foo")
- }
- }
- }
-
- val thirdNode = @Composable {
- Stack {
- lastNode()
- }
- }
-
- val secondNode = @Composable {
- Layout({
- thirdNode()
- }) { measurables, constraints, _ ->
- if (model.value) {
- val placeable = measurables[0].measure(constraints)
- layout(placeable.width, placeable.height) {
- placeable.place(0.ipx, 0.ipx)
- }
- } else {
- layout(0.ipx, 0.ipx) {}
- }
- }
- }
-
- val topNode = @Composable {
- Layout({
- secondNode()
- }) { measurables, constraints, _ ->
- if (model.value) {
- val placeable = measurables[0].measure(constraints)
- layout(placeable.width, placeable.height) {
- placeable.place(0.ipx, 0.ipx)
- }
- } else {
- layout(0.ipx, 0.ipx) {
- }
- }
- }
- }
-
- topNode()
- }
-
- findByText("Foo")
- .assertIsDisplayed()
-
- runOnUiThread {
- model.value = false
- }
-
- findByText("Foo")
- .assertIsNotDisplayed()
- }
-
- @Test
- fun rowTooSmall() {
- composeTestRule.setContent {
- val style = TextStyle(fontSize = 30.sp)
- Stack {
- // TODO(popam): remove this when a modifier can be used instead
- Layout(
- children = {
- Row {
- for (i in 1..100) {
- Semantics(container = true) {
- Text(text = i.toString(), style = style)
- }
- }
- }
- },
- modifier = Modifier.gravity(Alignment.Center)
- ) { measurables, constraints, _ ->
- val placeable =
- measurables[0].measure(constraints.copy(maxWidth = IntPx.Infinity))
- layout(placeable.width, placeable.height) {
- placeable.place(0.ipx, 0.ipx)
- }
- }
- }
- }
-
- findByText("90")
- .assertIsNotDisplayed()
- }
-
- @Test
- fun checkSemanticsAction_scrollTo_isCalled() {
- var wasScrollToCalled = false
- val tag = "myTag"
-
- composeTestRule.setContent {
- Semantics(container = true, properties = {
- ScrollTo(action = { _, _ ->
- wasScrollToCalled = true
- return@ScrollTo true
- })
- }) {
- Box {
- TestTag(tag) {
- Semantics(container = true) {
- Box()
- }
- }
- }
- }
- }
-
- runOnIdleCompose {
- Assert.assertTrue(!wasScrollToCalled)
- }
-
- findByTag(tag)
- .doScrollTo()
-
- runOnIdleCompose {
- Assert.assertTrue(wasScrollToCalled)
- }
- }
-
- @Test
- fun checkSemanticsAction_scrollTo_coordAreCorrect() {
- var currentScrollPositionY = 0.px
- var currentScrollPositionX = 0.px
- var elementHeight = 0.px
- val tag = "myTag"
-
- val drawRect = @Composable { color: Color ->
- Semantics(container = true) {
- Canvas(Modifier.preferredSize(100.dp)) {
- drawRect(color)
-
- elementHeight = Px(size.height)
- }
- }
- }
-
- composeTestRule.setContent {
- // Need to make the "scrolling" container the semantics boundary so that it
- // doesn't try to include the padding
- Semantics(container = true, properties = {
- ScrollTo(action = { x, y ->
- currentScrollPositionY = y
- currentScrollPositionX = x
- return@ScrollTo true
- })
- }) {
- val red = Color(alpha = 0xFF, red = 0xFF, green = 0, blue = 0)
- val blue = Color(alpha = 0xFF, red = 0, green = 0, blue = 0xFF)
- val green = Color(alpha = 0xFF, red = 0, green = 0xFF, blue = 0)
-
- Column {
- drawRect(red)
- drawRect(blue)
- TestTag(tag) {
- drawRect(green)
- }
- }
- }
- }
-
- runOnIdleCompose {
- assertThat(currentScrollPositionY).isEqualTo(0.px)
- assertThat(currentScrollPositionX).isEqualTo(0.px)
- }
-
- findByTag(tag)
- .doScrollTo() // scroll to third element
-
- runOnIdleCompose {
- val expected = elementHeight * 2
- assertThat(currentScrollPositionY).isEqualTo(expected)
- assertThat(currentScrollPositionX).isEqualTo(0.px)
- }
- }
-}
-
-@Model
-class AssertsUiTestsModel(var value: Boolean)
\ No newline at end of file
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt
new file mode 100644
index 0000000..c8f1e9f
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt
@@ -0,0 +1,130 @@
+/*
+ * 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.test
+
+import androidx.compose.Composable
+import androidx.ui.core.Modifier
+import androidx.ui.core.TestTag
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Canvas
+import androidx.ui.graphics.Color
+import androidx.ui.layout.Column
+import androidx.ui.layout.preferredSize
+import androidx.ui.semantics.ScrollTo
+import androidx.ui.semantics.Semantics
+import androidx.ui.unit.Px
+import androidx.ui.unit.dp
+import androidx.ui.unit.px
+import com.google.common.truth.Truth
+import org.junit.Assert
+import org.junit.Rule
+import org.junit.Test
+
+class ScrollToTest {
+ @get:Rule
+ val composeTestRule = createComposeRule(disableTransitions = true)
+
+ @Test
+ fun checkSemanticsAction_scrollTo_isCalled() {
+ var wasScrollToCalled = false
+ val tag = "myTag"
+
+ composeTestRule.setContent {
+ Semantics(container = true, properties = {
+ ScrollTo(action = { _, _ ->
+ wasScrollToCalled = true
+ return@ScrollTo true
+ })
+ }) {
+ Box {
+ TestTag(tag) {
+ Semantics(container = true) {
+ Box()
+ }
+ }
+ }
+ }
+ }
+
+ runOnIdleCompose {
+ Assert.assertTrue(!wasScrollToCalled)
+ }
+
+ findByTag(tag)
+ .doScrollTo()
+
+ runOnIdleCompose {
+ Assert.assertTrue(wasScrollToCalled)
+ }
+ }
+
+ @Test
+ fun checkSemanticsAction_scrollTo_coordAreCorrect() {
+ var currentScrollPositionY = 0.px
+ var currentScrollPositionX = 0.px
+ var elementHeight = 0.px
+ val tag = "myTag"
+
+ val drawRect = @Composable { color: Color ->
+ Semantics(container = true) {
+ Canvas(Modifier.preferredSize(100.dp)) {
+ drawRect(color)
+
+ elementHeight = Px(size.height)
+ }
+ }
+ }
+
+ composeTestRule.setContent {
+ // Need to make the "scrolling" container the semantics boundary so that it
+ // doesn't try to include the padding
+ Semantics(container = true, properties = {
+ ScrollTo(action = { x, y ->
+ currentScrollPositionY = y
+ currentScrollPositionX = x
+ return@ScrollTo true
+ })
+ }) {
+ val red = Color(alpha = 0xFF, red = 0xFF, green = 0, blue = 0)
+ val blue = Color(alpha = 0xFF, red = 0, green = 0, blue = 0xFF)
+ val green = Color(alpha = 0xFF, red = 0, green = 0xFF, blue = 0)
+
+ Column {
+ drawRect(red)
+ drawRect(blue)
+ TestTag(tag) {
+ drawRect(green)
+ }
+ }
+ }
+ }
+
+ runOnIdleCompose {
+ Truth.assertThat(currentScrollPositionY).isEqualTo(0.px)
+ Truth.assertThat(currentScrollPositionX).isEqualTo(0.px)
+ }
+
+ findByTag(tag)
+ .doScrollTo() // scroll to third element
+
+ runOnIdleCompose {
+ val expected = elementHeight * 2
+ Truth.assertThat(currentScrollPositionY).isEqualTo(expected)
+ Truth.assertThat(currentScrollPositionX).isEqualTo(0.px)
+ }
+ }
+}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
index a2c7d34..aa24a07f 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
@@ -17,6 +17,7 @@
package androidx.ui.test
import androidx.test.filters.MediumTest
+import androidx.ui.test.android.AndroidOwnerRegistry
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -35,7 +36,6 @@
@Test
fun runOnUiThread_void() {
var called = false
-
runOnUiThread { called = true }
assertThat(called).isTrue()
}
@@ -48,21 +48,35 @@
@Test
fun runOnIdleCompose() {
- val result = runOnIdleCompose { "Hello" }
- assertThat(result).isEqualTo("Hello")
+ withAndroidOwnerRegistry {
+ val result = runOnIdleCompose { "Hello" }
+ assertThat(result).isEqualTo("Hello")
+ }
}
@Test
fun runOnIdleCompose_void() {
- var called = false
-
- runOnIdleCompose { called = true }
- assertThat(called).isTrue()
+ withAndroidOwnerRegistry {
+ var called = false
+ runOnIdleCompose { called = true }
+ assertThat(called).isTrue()
+ }
}
@Test
fun runOnIdleCompose_nullable() {
- val result: String? = runOnIdleCompose { null }
- assertThat(result).isEqualTo(null)
+ withAndroidOwnerRegistry {
+ val result: String? = runOnIdleCompose { null }
+ assertThat(result).isEqualTo(null)
+ }
+ }
+
+ private fun withAndroidOwnerRegistry(block: () -> Unit) {
+ AndroidOwnerRegistry.setupRegistry()
+ try {
+ block()
+ } finally {
+ AndroidOwnerRegistry.tearDownRegistry()
+ }
}
}
\ No newline at end of file
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt b/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
index 077b462..00dc01c 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Assertions.kt
@@ -16,6 +16,8 @@
package androidx.ui.test
+import androidx.ui.core.AndroidOwner
+import androidx.ui.core.ComponentNode
import androidx.ui.core.LayoutNode
import androidx.ui.core.findClosestParentNode
import androidx.ui.core.semantics.SemanticsNode
@@ -23,9 +25,9 @@
import androidx.ui.geometry.Rect
import androidx.ui.semantics.AccessibilityRangeInfo
import androidx.ui.semantics.SemanticsProperties
-import androidx.ui.test.android.SynchronizedTreeCollector
import androidx.ui.unit.PxBounds
import androidx.ui.unit.PxPosition
+import androidx.ui.unit.PxSize
import androidx.ui.unit.height
import androidx.ui.unit.px
import androidx.ui.unit.toPx
@@ -288,38 +290,41 @@
// hierarchy check - check layout nodes are visible
val errorMessageOnFail = "Failed to perform isDisplayed check."
val node = fetchSemanticsNode(errorMessageOnFail)
- if (node.componentNode.findClosestParentNode {
- it is LayoutNode && !it.isPlaced
- } != null) {
+
+ fun isNotPlaced(node: ComponentNode): Boolean {
+ return node is LayoutNode && !node.isPlaced
+ }
+
+ val componentNode = node.componentNode
+ if (isNotPlaced(componentNode) || componentNode.findClosestParentNode(::isNotPlaced) != null) {
return false
}
// check node doesn't clip unintentionally (e.g. row too small for content)
val globalRect = node.globalBounds
- if (!isInScreenBounds(globalRect)) {
+ if (!node.isInScreenBounds()) {
return false
}
return (globalRect.width > 0.px && globalRect.height > 0.px)
}
-internal fun isInScreenBounds(rectangle: PxBounds): Boolean {
- if (rectangle.width == 0.px && rectangle.height == 0.px) {
+private fun SemanticsNode.isInScreenBounds(): Boolean {
+ val nodeBounds = globalBounds
+ if (nodeBounds.width == 0.px && nodeBounds.height == 0.px) {
return false
}
- val displayMetrics = SynchronizedTreeCollector.collectOwners()
- .findActivity()
- .resources
- .displayMetrics
- val bottomRight = PxPosition(
- displayMetrics.widthPixels.px,
- displayMetrics.heightPixels.px
+ val displayMetrics = (componentNode.owner as AndroidOwner).view.resources.displayMetrics
+ val screenBounds = PxBounds(
+ PxPosition.Origin,
+ PxSize(displayMetrics.widthPixels.px, displayMetrics.heightPixels.px)
)
- return rectangle.top >= 0.px &&
- rectangle.left >= 0.px &&
- rectangle.right <= bottomRight.x &&
- rectangle.bottom <= bottomRight.y
+
+ return nodeBounds.top >= screenBounds.top &&
+ nodeBounds.left >= screenBounds.left &&
+ nodeBounds.right <= screenBounds.right &&
+ nodeBounds.bottom <= screenBounds.bottom
}
/**
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt b/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
index b65642e..0173dce 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/BitmapHelpers.kt
@@ -21,11 +21,8 @@
import android.content.ContextWrapper
import android.graphics.Bitmap
import android.os.Build
-import android.os.Handler
-import android.os.Looper
import android.view.View
import androidx.annotation.RequiresApi
-import androidx.ui.core.semantics.SemanticsNode
import androidx.ui.geometry.Offset
import androidx.ui.geometry.Rect
import androidx.ui.graphics.Canvas
@@ -35,7 +32,6 @@
import androidx.ui.graphics.Shape
import androidx.ui.graphics.addOutline
import androidx.ui.graphics.asAndroidPath
-import androidx.ui.test.android.SynchronizedTreeCollector
import androidx.ui.test.android.captureRegionToBitmap
import androidx.ui.unit.Density
import androidx.ui.unit.Dp
@@ -50,29 +46,6 @@
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
-@RequiresApi(Build.VERSION_CODES.O)
-internal fun captureNodeToBitmap(node: SemanticsNode): Bitmap {
- val collectedInfo = SynchronizedTreeCollector.collectOwners()
-
- val exists = getAllSemanticsNodes().any { it.id == node.id }
- if (!exists) {
- throw AssertionError("The required node is no longer in the tree!")
- }
-
- val window = collectedInfo.findActivity().window
-
- // TODO(pavlis): Consider doing assertIsDisplayed here. Will need to move things around.
-
- // TODO(pavlis): Make sure that the Activity actually hosts the view. As in case of popup
- // it wouldn't. This will require us rewriting the structure how we collect the nodes.
-
- // TODO(pavlis): Add support for popups. So if we find composable hosted in popup we can
- // grab its reference to its window (need to add a hook to popup).
-
- val handler = Handler(Looper.getMainLooper())
- return captureRegionToBitmap(node.globalBounds.toRect(), handler, window)
-}
-
/**
* Captures the underlying component's surface into bitmap.
*
@@ -82,8 +55,9 @@
*/
@RequiresApi(Build.VERSION_CODES.O)
fun SemanticsNodeInteraction.captureToBitmap(): Bitmap {
- val errorMessageOnFail = "Failed to capture a node to bitmap."
- return captureNodeToBitmap(fetchSemanticsNode(errorMessageOnFail))
+ val node = fetchSemanticsNode("Failed to capture a node to bitmap.")
+ // TODO(pavlis): Consider doing assertIsDisplayed here. Will need to move things around.
+ return captureRegionToBitmap(node.globalBounds.toRect(), node.componentNode.owner!!)
}
/**
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
index 1dcf1c8..66e4164 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
@@ -91,5 +91,5 @@
}
internal fun getAllSemanticsNodes(): List<SemanticsNode> {
- return SynchronizedTreeCollector.collectOwners().getAllSemanticNodes()
+ return SynchronizedTreeCollector.collectAllSemanticsNodes()
}
\ No newline at end of file
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
index bb03972..bf03018 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidInputDispatcher.kt
@@ -239,7 +239,7 @@
}
/**
- * Sends the [event] to the [CollectedOwners] and [recycles][MotionEvent.recycle] it
+ * Sends the [event] to the MotionEvent dispatcher and [recycles][MotionEvent.recycle] it
* regardless of the result. This method blocks until the event is sent.
*/
private fun sendAndRecycleEvent(event: MotionEvent) {
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidOwnerRegistry.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidOwnerRegistry.kt
index d62da1b..44f9aa2 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidOwnerRegistry.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidOwnerRegistry.kt
@@ -37,7 +37,7 @@
/**
* Returns if the registry is setup to receive registrations from [AndroidOwner]s
*/
- val isSetup: Boolean
+ val isSetUp: Boolean
get() = AndroidOwner. ::onAndroidOwnerCreated
/**
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
index eecbc3b..5e95c72 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
@@ -16,9 +16,6 @@
package androidx.ui.test.android
-import android.app.Activity
-import android.content.Context
-import android.content.ContextWrapper
import android.view.Choreographer
import androidx.compose.onCommit
import androidx.test.espresso.Espresso
@@ -31,31 +28,32 @@
import java.util.concurrent.TimeUnit
/**
- * Collects all [AndroidOwner]s that are part of the currently visible window.
+ * Collects all [SemanticsNode]s that are part of all compose hierarchies hosted by resumed
+ * activities.
*
* This operation is performed only after compose is idle via Espresso.
*/
internal object SynchronizedTreeCollector {
/**
- * Collects all [AndroidOwner]s that are part of the currently visible window. Can only be
- * used when using [ComposeTestRule][androidx.ui.test.ComposeTestRule]
+ * Collects all [SemanticsNode]s from all compose hierarchies. Can only be used when using
+ * [ComposeTestRule][androidx.ui.test.ComposeTestRule].
*
* This is a blocking call. Returns only after compose is idle.
*
* Can crash in case Espresso hits time out. This is not supposed to be handled as it
* surfaces only in incorrect tests.
*/
- internal fun collectOwners(): CollectedOwners {
- check(AndroidOwnerRegistry.isSetup) {
- "Test not setup properly. Use a ComposeTestRule in your test to be able to interact " +
- "with composables"
- }
+ internal fun collectAllSemanticsNodes(): List<SemanticsNode> {
+ ensureAndroidOwnerRegistryIsSetUp()
+
+ // TODO(pavlis): Instead of returning a flatMap, let all consumers handle a tree
+ // structure. In case of multiple AndroidOwners, add a fake root
waitForIdle()
- return CollectedOwners(AndroidOwnerRegistry.getOwners().also {
+ return AndroidOwnerRegistry.getOwners().also {
// TODO(b/153632210): This check should be done by callers of collectOwners
check(it.isNotEmpty()) { "No AndroidOwners found. Is your Activity resumed?" }
- })
+ }.flatMap { it.semanticsOwner.getAllSemanticsNodes() }
}
/**
@@ -85,6 +83,13 @@
waitForOnCommitCallbacks()
}
+ private fun ensureAndroidOwnerRegistryIsSetUp() {
+ check(AndroidOwnerRegistry.isSetUp) {
+ "Test not setup properly. Use a ComposeTestRule in your test to be able to interact " +
+ "with composables"
+ }
+ }
+
/**
* Waits for all scheduled [onCommit] callbacks to be executed.
*/
@@ -98,6 +103,8 @@
}
private fun waitForAndroidOwners() {
+ ensureAndroidOwnerRegistryIsSetUp()
+
fun hasAndroidOwners(): Boolean = AndroidOwnerRegistry.getOwners().isNotEmpty()
if (!hasAndroidOwners()) {
@@ -120,36 +127,3 @@
}
}
}
-
-/**
- * There can be multiple Compose views in the Android hierarchy and we want to interact with all
- * of them. This class merges all the [AndroidOwner]s into one, hiding the fact that the API
- * might be interacting with several Compose roots.
- */
-internal data class CollectedOwners(val owners: Set<AndroidOwner>) {
- // Recursively search for the Activity context through (possible) ContextWrappers
- private fun Context.getActivity(): Activity? {
- return when (this) {
- is Activity -> this
- is ContextWrapper -> this.baseContext.getActivity()
- else -> null
- }
- }
-
- fun findActivity(): Activity {
- owners.forEach {
- val activity = it.view.context.getActivity()
- if (activity != null) {
- return activity
- }
- }
- throw AssertionError(
- "Out of ${owners.size} Owners, none were attached to an Activity"
- )
- }
-
- fun getAllSemanticNodes(): List<SemanticsNode> {
- // TODO(pavlis): Once we have a tree support we will just add a fake root parent here
- return owners.flatMap { it.semanticsOwner.getAllSemanticsNodes() }
- }
-}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/WindowCapture.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/WindowCapture.kt
index 7f5e5b9..caf7ee8 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/WindowCapture.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/WindowCapture.kt
@@ -16,12 +16,18 @@
package androidx.ui.test.android
+import android.app.Activity
+import android.content.Context
+import android.content.ContextWrapper
import android.graphics.Bitmap
import android.os.Build
import android.os.Handler
+import android.os.Looper
import android.view.PixelCopy
import android.view.Window
import androidx.annotation.RequiresApi
+import androidx.ui.core.AndroidOwner
+import androidx.ui.core.Owner
import androidx.ui.geometry.Rect
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@@ -29,21 +35,48 @@
@RequiresApi(Build.VERSION_CODES.O)
internal fun captureRegionToBitmap(
- globalRect: Rect,
+ captureRect: Rect,
+ owner: Owner
+): Bitmap {
+
+ fun Context.getActivity(): Activity? {
+ return when (this) {
+ is Activity -> this
+ is ContextWrapper -> this.baseContext.getActivity()
+ else -> null
+ }
+ }
+
+ // TODO(pavlis): Make sure that the Activity actually hosts the view. As in case of popup
+ // it wouldn't. This will require us rewriting the structure how we collect the nodes.
+
+ // TODO(pavlis): Add support for popups. So if we find composable hosted in popup we can
+ // grab its reference to its window (need to add a hook to popup).
+
+ val window = (owner as AndroidOwner).view.context.getActivity()!!.window
+ val handler = Handler(Looper.getMainLooper())
+ return captureRegionToBitmap(captureRect, handler, window)
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+internal fun captureRegionToBitmap(
+ captureRect: Rect,
handler: Handler,
window: Window
): Bitmap {
val destBitmap = Bitmap.createBitmap(
- globalRect.width.roundToInt(),
- globalRect.height.roundToInt(),
- Bitmap.Config.ARGB_8888)
+ captureRect.width.roundToInt(),
+ captureRect.height.roundToInt(),
+ Bitmap.Config.ARGB_8888
+ )
// TODO: This could go to some Android specific extensions.
val srcRect = android.graphics.Rect(
- globalRect.left.roundToInt(),
- globalRect.top.roundToInt(),
- globalRect.right.roundToInt(),
- globalRect.bottom.roundToInt())
+ captureRect.left.roundToInt(),
+ captureRect.top.roundToInt(),
+ captureRect.right.roundToInt(),
+ captureRect.bottom.roundToInt()
+ )
val latch = CountDownLatch(1)
var copyResult = 0
diff --git a/ui/ui-text-android/api/0.1.0-dev12.txt b/ui/ui-text-android/api/0.1.0-dev12.txt
index 756ead2..182bb12 100644
--- a/ui/ui-text-android/api/0.1.0-dev12.txt
+++ b/ui/ui-text-android/api/0.1.0-dev12.txt
@@ -11,6 +11,9 @@
package androidx.ui.text.platform.style {
+ public final class FontWeightStyleSpanKt {
+ }
+
public final class PlaceholderSpanKt {
}
diff --git a/ui/ui-text-android/api/current.txt b/ui/ui-text-android/api/current.txt
index 756ead2..182bb12 100644
--- a/ui/ui-text-android/api/current.txt
+++ b/ui/ui-text-android/api/current.txt
@@ -11,6 +11,9 @@
package androidx.ui.text.platform.style {
+ public final class FontWeightStyleSpanKt {
+ }
+
public final class PlaceholderSpanKt {
}
diff --git a/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev12.txt
index 756ead2..182bb12 100644
--- a/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev12.txt
@@ -11,6 +11,9 @@
package androidx.ui.text.platform.style {
+ public final class FontWeightStyleSpanKt {
+ }
+
public final class PlaceholderSpanKt {
}
diff --git a/ui/ui-text-android/api/public_plus_experimental_current.txt b/ui/ui-text-android/api/public_plus_experimental_current.txt
index 756ead2..182bb12 100644
--- a/ui/ui-text-android/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-android/api/public_plus_experimental_current.txt
@@ -11,6 +11,9 @@
package androidx.ui.text.platform.style {
+ public final class FontWeightStyleSpanKt {
+ }
+
public final class PlaceholderSpanKt {
}
diff --git a/ui/ui-text-android/api/restricted_0.1.0-dev12.txt b/ui/ui-text-android/api/restricted_0.1.0-dev12.txt
index 4d862c7..01d0e25 100644
--- a/ui/ui-text-android/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-text-android/api/restricted_0.1.0-dev12.txt
@@ -85,6 +85,31 @@
method public void updateMeasureState(android.text.TextPaint textPaint);
}
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class FontSpan extends android.text.style.MetricAffectingSpan {
+ ctor public FontSpan(kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Boolean,? extends android.graphics.Typeface> getTypeface);
+ method public kotlin.jvm.functions.Function2<java.lang.Integer,java.lang.Boolean,android.graphics.Typeface> getGetTypeface();
+ method public void updateDrawState(android.text.TextPaint textPaint);
+ method public void updateMeasureState(android.text.TextPaint textPaint);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class FontWeightStyleSpan extends android.text.style.MetricAffectingSpan {
+ ctor public FontWeightStyleSpan(@IntRange(from=null, to=null) int weight, int style);
+ method public int getStyle();
+ method public int getWeight();
+ method public void updateDrawState(android.text.TextPaint textPaint);
+ method public void updateMeasureState(android.text.TextPaint textPaint);
+ field public static final androidx.ui.text.platform.style.FontWeightStyleSpan.Companion! Companion;
+ field public static final int STYLE_ITALIC = 2; // 0x2
+ field public static final int STYLE_NONE = -1; // 0xffffffff
+ field public static final int STYLE_NORMAL = 0; // 0x0
+ }
+
+ public static final class FontWeightStyleSpan.Companion {
+ }
+
+ public final class FontWeightStyleSpanKt {
+ }
+
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class LetterSpacingSpanEm extends android.text.style.MetricAffectingSpan {
ctor public LetterSpacingSpanEm(float letterSpacing);
method public float getLetterSpacing();
diff --git a/ui/ui-text-android/api/restricted_current.txt b/ui/ui-text-android/api/restricted_current.txt
index 4d862c7..01d0e25 100644
--- a/ui/ui-text-android/api/restricted_current.txt
+++ b/ui/ui-text-android/api/restricted_current.txt
@@ -85,6 +85,31 @@
method public void updateMeasureState(android.text.TextPaint textPaint);
}
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class FontSpan extends android.text.style.MetricAffectingSpan {
+ ctor public FontSpan(kotlin.jvm.functions.Function2<? super java.lang.Integer,? super java.lang.Boolean,? extends android.graphics.Typeface> getTypeface);
+ method public kotlin.jvm.functions.Function2<java.lang.Integer,java.lang.Boolean,android.graphics.Typeface> getGetTypeface();
+ method public void updateDrawState(android.text.TextPaint textPaint);
+ method public void updateMeasureState(android.text.TextPaint textPaint);
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class FontWeightStyleSpan extends android.text.style.MetricAffectingSpan {
+ ctor public FontWeightStyleSpan(@IntRange(from=null, to=null) int weight, int style);
+ method public int getStyle();
+ method public int getWeight();
+ method public void updateDrawState(android.text.TextPaint textPaint);
+ method public void updateMeasureState(android.text.TextPaint textPaint);
+ field public static final androidx.ui.text.platform.style.FontWeightStyleSpan.Companion! Companion;
+ field public static final int STYLE_ITALIC = 2; // 0x2
+ field public static final int STYLE_NONE = -1; // 0xffffffff
+ field public static final int STYLE_NORMAL = 0; // 0x0
+ }
+
+ public static final class FontWeightStyleSpan.Companion {
+ }
+
+ public final class FontWeightStyleSpanKt {
+ }
+
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class LetterSpacingSpanEm extends android.text.style.MetricAffectingSpan {
ctor public LetterSpacingSpanEm(float letterSpacing);
method public float getLetterSpacing();
diff --git a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/FontSpanTest.kt b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/FontSpanTest.kt
new file mode 100644
index 0000000..6cfdf55
--- /dev/null
+++ b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/FontSpanTest.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.text.platform.style
+
+import android.graphics.Typeface
+import android.text.TextPaint
+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 FontSpanTest {
+ @Test
+ fun updatePaint() {
+ val textPaint = TextPaint()
+ val typeface = Typeface.defaultFromStyle(Typeface.BOLD_ITALIC)
+ val span = FontSpan { _, _ -> typeface }
+
+ assertThat(textPaint.typeface).isNotSameInstanceAs(typeface)
+ span.updatePaint(textPaint)
+ assertThat(textPaint.typeface).isSameInstanceAs(typeface)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/FontWeightStyleSpanTest.kt b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/FontWeightStyleSpanTest.kt
new file mode 100644
index 0000000..03deb5e
--- /dev/null
+++ b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/FontWeightStyleSpanTest.kt
@@ -0,0 +1,206 @@
+/*
+ * 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.text.platform.style
+
+import android.graphics.Typeface
+import android.graphics.fonts.FontStyle
+import android.text.TextPaint
+import androidx.test.filters.SdkSuppress
+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 FontWeightStyleSpanTest {
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_withFontWeightBold() {
+ val textPaint = TextPaint()
+ val weight = FontStyle.FONT_WEIGHT_BOLD
+ val span = FontWeightStyleSpan(weight, FontWeightStyleSpan.STYLE_NONE)
+ span.updatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isNotNull()
+ assertThat(textPaint.typeface.weight).isEqualTo(weight)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_withFontWeightLight() {
+ val textPaint = TextPaint()
+ val weight = FontStyle.FONT_WEIGHT_LIGHT
+ val span = FontWeightStyleSpan(weight, FontWeightStyleSpan.STYLE_NONE)
+ span.updatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isNotNull()
+ assertThat(textPaint.typeface.weight).isEqualTo(weight)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_withFontWeightBoldToNormal() {
+ val textPaint = TextPaint().apply {
+ typeface = Typeface.create(null, FontStyle.FONT_WEIGHT_BOLD, false)
+ }
+ val weight = FontStyle.FONT_WEIGHT_NORMAL
+ val span = FontWeightStyleSpan(weight, FontWeightStyleSpan.STYLE_NONE)
+ span.updatePaint(textPaint)
+
+ assertThat(textPaint.typeface.isBold).isFalse()
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_withFontWeightNull() {
+ val textPaint = TextPaint().apply {
+ typeface = Typeface.create(null, FontStyle.FONT_WEIGHT_BOLD, true)
+ }
+ val span = FontWeightStyleSpan(0, FontWeightStyleSpan.STYLE_NORMAL)
+ span.updatePaint(textPaint)
+
+ assertThat(textPaint.typeface.weight).isEqualTo(FontStyle.FONT_WEIGHT_BOLD)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_withItalic() {
+ val textPaint = TextPaint()
+ val span = FontWeightStyleSpan(0, FontWeightStyleSpan.STYLE_ITALIC)
+ span.updatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isNotNull()
+ assertThat(textPaint.typeface.isItalic).isTrue()
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_withItalicNull() {
+ val textPaint = TextPaint().apply {
+ typeface = Typeface.create(null, FontStyle.FONT_WEIGHT_BOLD, true)
+ }
+ val span = FontWeightStyleSpan(
+ weight = FontStyle.FONT_WEIGHT_NORMAL,
+ style = FontWeightStyleSpan.STYLE_NONE)
+ span.updatePaint(textPaint)
+
+ assertThat(textPaint.typeface.isItalic).isTrue()
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 28)
+ fun updatePaint_noChange() {
+ val typeface = Typeface.create(null, FontStyle.FONT_WEIGHT_BOLD, true)
+ val textPaint = TextPaint().apply { this.typeface = typeface }
+ val span = FontWeightStyleSpan(FontStyle.FONT_WEIGHT_BOLD, FontWeightStyleSpan.STYLE_ITALIC)
+ span.updatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isSameInstanceAs(typeface)
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun legacyUpdatePaint_withFontWeightBold() {
+ val textPaint = TextPaint()
+ val weight = FontStyle.FONT_WEIGHT_BOLD
+ val span = FontWeightStyleSpan(weight, FontWeightStyleSpan.STYLE_NONE)
+ span.legacyUpdatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isNotNull()
+ assertThat(textPaint.typeface.isBold).isTrue()
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun legacyUpdatePaint_withFontWeightLight() {
+ val textPaint = TextPaint()
+ val weight = FontStyle.FONT_WEIGHT_LIGHT
+ val span = FontWeightStyleSpan(weight, FontWeightStyleSpan.STYLE_NONE)
+ span.legacyUpdatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isNotNull()
+ assertThat(textPaint.typeface.isBold).isFalse()
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun legacyUpdatePaint_withFontWeightBoldToNormal() {
+ val textPaint = TextPaint().apply {
+ typeface = Typeface.defaultFromStyle(Typeface.BOLD)
+ }
+ val weight = FontStyle.FONT_WEIGHT_NORMAL
+ val span = FontWeightStyleSpan(weight, FontWeightStyleSpan.STYLE_NONE)
+ span.legacyUpdatePaint(textPaint)
+
+ assertThat(textPaint.typeface.isBold).isFalse()
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun legacyUpdatePaint_withFontWeightNull() {
+ val textPaint = TextPaint().apply {
+ typeface = Typeface.defaultFromStyle(Typeface.BOLD_ITALIC)
+ }
+ val span = FontWeightStyleSpan(0, FontWeightStyleSpan.STYLE_NORMAL)
+ span.legacyUpdatePaint(textPaint)
+
+ assertThat(textPaint.typeface.isBold).isTrue()
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun legacyUpdatePaint_withItalic() {
+ val textPaint = TextPaint().apply {
+ typeface = Typeface.defaultFromStyle(Typeface.BOLD)
+ }
+ val weight = FontStyle.FONT_WEIGHT_NORMAL
+ val span = FontWeightStyleSpan(weight, FontWeightStyleSpan.STYLE_NONE)
+ span.legacyUpdatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isNotNull()
+ assertThat(textPaint.typeface.isBold).isFalse()
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun legacyUpdatePaint_withItalicNull() {
+ val textPaint = TextPaint().apply {
+ typeface = Typeface.defaultFromStyle(Typeface.BOLD_ITALIC)
+ }
+ val span = FontWeightStyleSpan(0, FontWeightStyleSpan.STYLE_NORMAL)
+ span.legacyUpdatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isNotNull()
+ assertThat(textPaint.typeface.isItalic).isFalse()
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 27)
+ fun legacyUpdatePaint_noChange() {
+ val typeface = Typeface.defaultFromStyle(Typeface.BOLD_ITALIC)
+ val textPaint = TextPaint().apply { this.typeface = typeface }
+ val span = FontWeightStyleSpan(
+ weight = FontStyle.FONT_WEIGHT_BOLD,
+ style = FontWeightStyleSpan.STYLE_ITALIC
+ )
+ span.legacyUpdatePaint(textPaint)
+
+ assertThat(textPaint.typeface).isSameInstanceAs(typeface)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-text-android/src/main/java/androidx/ui/text/platform/style/FontSpan.kt b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/style/FontSpan.kt
new file mode 100644
index 0000000..d68e518
--- /dev/null
+++ b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/style/FontSpan.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.text.platform.style
+
+import android.graphics.Typeface
+import android.graphics.fonts.FontStyle
+import android.os.Build
+import android.text.TextPaint
+import android.text.style.MetricAffectingSpan
+import androidx.annotation.RestrictTo
+import androidx.annotation.VisibleForTesting
+
+/**
+ * Span that changes the typeface of the text.
+ *
+ * @param getTypeface a lambda function that returns the typeface used to render the affected text.
+ * @suppress
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+class FontSpan(
+ val getTypeface: (weight: Int, isItalic: Boolean) -> Typeface
+) : MetricAffectingSpan() {
+
+ @VisibleForTesting
+ internal fun updatePaint(textPaint: TextPaint) {
+ val oldTypeface: Typeface? = textPaint.typeface
+ if (oldTypeface == null) {
+ textPaint.typeface = getTypeface(FontStyle.FONT_WEIGHT_NORMAL, false)
+ return
+ }
+ val weight = if (Build.VERSION.SDK_INT <= 28) {
+ if (oldTypeface.isBold) {
+ FontStyle.FONT_WEIGHT_BOLD
+ } else {
+ FontStyle.FONT_WEIGHT_NORMAL
+ }
+ } else {
+ oldTypeface.weight
+ }
+ textPaint.typeface = getTypeface(weight, oldTypeface.isItalic)
+ }
+
+ override fun updateDrawState(textPaint: TextPaint) {
+ updatePaint(textPaint)
+ }
+
+ override fun updateMeasureState(textPaint: TextPaint) {
+ updatePaint(textPaint)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-text-android/src/main/java/androidx/ui/text/platform/style/FontWeightStyleSpan.kt b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/style/FontWeightStyleSpan.kt
new file mode 100644
index 0000000..4842c22
--- /dev/null
+++ b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/style/FontWeightStyleSpan.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.ui.text.platform.style
+
+import android.graphics.Typeface
+import android.graphics.fonts.FontStyle
+import android.os.Build
+import android.text.TextPaint
+import android.text.style.MetricAffectingSpan
+import androidx.annotation.IntDef
+import androidx.annotation.IntRange
+import androidx.annotation.RequiresApi
+import androidx.annotation.RestrictTo
+import androidx.annotation.VisibleForTesting
+
+private const val AndroidBoldWeight = 600
+
+/**
+ * The span which changes the font weight and the font style of the affected text.
+ *
+ * @param weight the target font weight. If it's 0, this span won't modify the font weight.
+ * @param style the font style specified by this span. It can be STYLE_NONE, STYLE_NORMAL and
+ * STYLE_ITALIC. If STYLE_NONE is given, this span won't modify the font style.
+ *
+ * @suppress
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+class FontWeightStyleSpan(
+ @IntRange(from = 0, to = 1000)
+ val weight: Int,
+ @FontStyleMode
+ val style: Int
+) : MetricAffectingSpan() {
+ companion object {
+ const val STYLE_NONE = -1
+ const val STYLE_NORMAL = 0
+ const val STYLE_ITALIC = 2
+
+ @Retention(AnnotationRetention.SOURCE)
+ @IntDef(
+ STYLE_NONE,
+ STYLE_NORMAL,
+ STYLE_ITALIC
+ )
+ internal annotation class FontStyleMode
+ }
+
+ @VisibleForTesting
+ @RequiresApi(value = 28)
+ internal fun updatePaint(textPaint: TextPaint) {
+ val oldTypeface: Typeface? = textPaint.typeface
+ val weightChanged =
+ (weight != 0 && weight != oldTypeface?.weight)
+ val styleChanged =
+ (style != STYLE_NONE && (style == STYLE_ITALIC) != oldTypeface?.isItalic)
+ val needsUpdate = weightChanged || styleChanged
+ // Nothing to change. Early return.
+ if (!needsUpdate) {
+ return
+ }
+
+ val newWeight = if (weight != 0) {
+ weight
+ } else {
+ oldTypeface?.weight ?: FontStyle.FONT_WEIGHT_NORMAL
+ }
+
+ val newItalic = when (style) {
+ STYLE_NORMAL -> false
+ STYLE_ITALIC -> true
+ else -> oldTypeface?.isItalic ?: false
+ }
+
+ textPaint.typeface = Typeface.create(oldTypeface, newWeight, newItalic)
+ }
+
+ @VisibleForTesting
+ internal fun legacyUpdatePaint(textPaint: TextPaint) {
+ val oldTypeface: Typeface? = textPaint.typeface
+ val boldChanged =
+ (weight != 0 || isBold(weight) != oldTypeface?.isBold)
+ val styleChanged =
+ (style != STYLE_NONE && (style == STYLE_ITALIC) != oldTypeface?.isItalic)
+ val needsUpdate = boldChanged || styleChanged
+ // Nothing to change. Early return.
+ if (!needsUpdate) {
+ return
+ }
+ val newBold = if (weight != 0) {
+ isBold(weight)
+ } else {
+ oldTypeface?.isBold ?: false
+ }
+
+ val newItalic = when (style) {
+ STYLE_NORMAL -> false
+ STYLE_ITALIC -> true
+ else -> oldTypeface?.isItalic ?: false
+ }
+
+ textPaint.typeface = Typeface.create(oldTypeface, getTypefaceStyle(newBold, newItalic))
+ }
+
+ override fun updateDrawState(textPaint: TextPaint) {
+ if (Build.VERSION.SDK_INT >= 28) {
+ updatePaint(textPaint)
+ } else {
+ legacyUpdatePaint(textPaint)
+ }
+ }
+
+ override fun updateMeasureState(textPaint: TextPaint) {
+ if (Build.VERSION.SDK_INT >= 28) {
+ updatePaint(textPaint)
+ } else {
+ legacyUpdatePaint(textPaint)
+ }
+ }
+}
+
+// Helper function that checks if the given weight is bold or not.
+// It assumes weight is within [1, 1000].
+private fun isBold(weight: Int): Boolean {
+ return weight >= AndroidBoldWeight
+}
+
+internal fun getTypefaceStyle(isBold: Boolean, isItalic: Boolean): Int {
+ return if (isBold && isItalic) {
+ Typeface.BOLD_ITALIC
+ } else if (isBold) {
+ Typeface.BOLD
+ } else if (isItalic) {
+ Typeface.ITALIC
+ } else {
+ Typeface.NORMAL
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-text-core/api/0.1.0-dev12.txt b/ui/ui-text-core/api/0.1.0-dev12.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/0.1.0-dev12.txt
+++ b/ui/ui-text-core/api/0.1.0-dev12.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/api_lint.ignore b/ui/ui-text-core/api/api_lint.ignore
index f6d6d03..0b3a507 100644
--- a/ui/ui-text-core/api/api_lint.ignore
+++ b/ui/ui-text-core/api/api_lint.ignore
@@ -3,6 +3,28 @@
Acronyms should not be capitalized in method names: was `copy-4Bo2vQE`, should this be `copy-4Bo2vQe`?
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#append(String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.append(String)
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#append(androidx.ui.text.AnnotatedString):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.append(androidx.ui.text.AnnotatedString)
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#append(char):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.append(char)
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#pop():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.pop()
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#pop(int):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.pop(int)
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#pushStringAnnotation(String, String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.pushStringAnnotation(String,String)
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#pushStyle(androidx.ui.text.ParagraphStyle):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.pushStyle(androidx.ui.text.ParagraphStyle)
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#pushStyle(androidx.ui.text.SpanStyle):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.pushStyle(androidx.ui.text.SpanStyle)
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#toAnnotatedString():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.toAnnotatedString()
+BuilderSetStyle: androidx.ui.text.AnnotatedString.Builder#toString():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.ui.text.AnnotatedString.Builder.toString()
+
+
KotlinOperator: androidx.ui.text.font.FontListFontFamily#contains(androidx.ui.text.font.Font):
Note that adding the `operator` keyword would allow calling this method using operator syntax
KotlinOperator: androidx.ui.text.style.TextDecoration#contains(androidx.ui.text.style.TextDecoration):
@@ -15,3 +37,11 @@
MissingNullability: androidx.ui.text.style.BaselineShift#toString-impl(float):
Missing nullability on method `toString-impl` return
+
+
+SetterReturnsThis: androidx.ui.text.AnnotatedString.Builder#addAnnotationString(String, String, int, int):
+ Methods must return the builder object (return type androidx.ui.text.AnnotatedString.Builder instead of void): method androidx.ui.text.AnnotatedString.Builder.addAnnotationString(String,String,int,int)
+SetterReturnsThis: androidx.ui.text.AnnotatedString.Builder#addStyle(androidx.ui.text.ParagraphStyle, int, int):
+ Methods must return the builder object (return type androidx.ui.text.AnnotatedString.Builder instead of void): method androidx.ui.text.AnnotatedString.Builder.addStyle(androidx.ui.text.ParagraphStyle,int,int)
+SetterReturnsThis: androidx.ui.text.AnnotatedString.Builder#addStyle(androidx.ui.text.SpanStyle, int, int):
+ Methods must return the builder object (return type androidx.ui.text.AnnotatedString.Builder instead of void): method androidx.ui.text.AnnotatedString.Builder.addStyle(androidx.ui.text.SpanStyle,int,int)
diff --git a/ui/ui-text-core/api/current.txt b/ui/ui-text-core/api/current.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/current.txt
+++ b/ui/ui-text-core/api/current.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev12.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/public_plus_experimental_current.txt b/ui/ui-text-core/api/public_plus_experimental_current.txt
index 946c57b..d08cf00 100644
--- a/ui/ui-text-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_current.txt
@@ -413,7 +413,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/restricted_0.1.0-dev12.txt b/ui/ui-text-core/api/restricted_0.1.0-dev12.txt
index 07f2f76..6f7ebdd 100644
--- a/ui/ui-text-core/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-text-core/api/restricted_0.1.0-dev12.txt
@@ -418,7 +418,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/api/restricted_current.txt b/ui/ui-text-core/api/restricted_current.txt
index 07f2f76..6f7ebdd 100644
--- a/ui/ui-text-core/api/restricted_current.txt
+++ b/ui/ui-text-core/api/restricted_current.txt
@@ -418,7 +418,7 @@
}
public final class ParagraphIntrinsicsKt {
- method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = listOf(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = listOf(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
+ method public static androidx.ui.text.ParagraphIntrinsics ParagraphIntrinsics(String text, androidx.ui.text.TextStyle style, java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.SpanStyle>> spanStyles = emptyList(), java.util.List<androidx.ui.text.AnnotatedString.Item<androidx.ui.text.Placeholder>> placeholders = emptyList(), androidx.ui.unit.Density density, androidx.ui.text.font.Font.ResourceLoader resourceLoader);
}
public final class ParagraphKt {
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphHelperTest.kt b/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphHelperTest.kt
new file mode 100644
index 0000000..865af7f
--- /dev/null
+++ b/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphHelperTest.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.text.platform
+
+import android.text.SpannableString
+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 AndroidParagraphHelperTest {
+ @Test
+ fun setSpanWithPriority_withSamePriority_returnSameSetOrder() {
+ val spanned = SpannableString("Hello World")
+ val span0 = Any()
+ val span1 = Any()
+ val span2 = Any()
+ val priority = 0
+ spanned.setSpanWithPriority(span0, 0, 1, priority)
+ spanned.setSpanWithPriority(span1, 0, 1, priority)
+ spanned.setSpanWithPriority(span2, 0, 1, priority)
+
+ val spans = spanned.getSpans(0, 1, Any::class.java)
+ assertThat(spans[0]).isSameInstanceAs(span0)
+ assertThat(spans[1]).isSameInstanceAs(span1)
+ assertThat(spans[2]).isSameInstanceAs(span2)
+ }
+
+ @Test
+ fun setSpanWithPriority_withIncreasingPriority_returnPriorityOrder() {
+ val spanned = SpannableString("Hello World")
+ val span0 = Any()
+ val span1 = Any()
+ val span2 = Any()
+ spanned.setSpanWithPriority(span0, 0, 1, 0)
+ spanned.setSpanWithPriority(span1, 0, 1, 1)
+ spanned.setSpanWithPriority(span2, 0, 1, 2)
+
+ val spans = spanned.getSpans(0, 1, Any::class.java)
+ assertThat(spans[0]).isSameInstanceAs(span2)
+ assertThat(spans[1]).isSameInstanceAs(span1)
+ assertThat(spans[2]).isSameInstanceAs(span0)
+ }
+
+ @Test
+ fun setSpanWithPriority_withDescendingPriority_returnPriorityOrder() {
+ val spanned = SpannableString("Hello World")
+ val span0 = Any()
+ val span1 = Any()
+ val span2 = Any()
+ spanned.setSpanWithPriority(span0, 0, 1, 2)
+ spanned.setSpanWithPriority(span1, 0, 1, 1)
+ spanned.setSpanWithPriority(span2, 0, 1, 0)
+
+ val spans = spanned.getSpans(0, 1, Any::class.java)
+ assertThat(spans[0]).isSameInstanceAs(span0)
+ assertThat(spans[1]).isSameInstanceAs(span1)
+ assertThat(spans[2]).isSameInstanceAs(span2)
+ }
+
+ @Test
+ fun setSpanWithPriority_withWigglingPriority_returnPriorityOrder() {
+ val spanned = SpannableString("Hello World")
+ val span0 = Any()
+ val span1 = Any()
+ val span2 = Any()
+ val span3 = Any()
+ spanned.setSpanWithPriority(span0, 0, 1, 0)
+ spanned.setSpanWithPriority(span1, 0, 1, 1)
+ spanned.setSpanWithPriority(span2, 0, 1, 0)
+ spanned.setSpanWithPriority(span3, 0, 1, 1)
+
+ val spans = spanned.getSpans(0, 1, Any::class.java)
+ assertThat(spans[0]).isSameInstanceAs(span1)
+ assertThat(spans[1]).isSameInstanceAs(span3)
+ assertThat(spans[2]).isSameInstanceAs(span0)
+ assertThat(spans[3]).isSameInstanceAs(span2)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt b/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
index 96cde3d..b784a96 100644
--- a/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
+++ b/ui/ui-text-core/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
@@ -19,7 +19,6 @@
import androidx.ui.text.platform.style.LetterSpacingSpanPx
import androidx.ui.text.platform.style.ShadowSpan
import androidx.ui.text.platform.style.SkewXSpan
-import androidx.ui.text.platform.style.TypefaceSpan
import androidx.ui.geometry.Offset
import androidx.ui.graphics.Color
import androidx.ui.graphics.Shadow
@@ -37,6 +36,7 @@
import androidx.ui.text.font.FontWeight
import androidx.ui.text.font.asFontFamily
import androidx.ui.text.matchers.assertThat
+import androidx.ui.text.platform.style.FontSpan
import androidx.ui.text.style.BaselineShift
import androidx.ui.text.style.TextAlign
import androidx.ui.text.style.TextDecoration
@@ -49,6 +49,7 @@
import androidx.ui.unit.sp
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.atLeastOnce
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
@@ -714,8 +715,8 @@
assertThat(paragraph.charSequence.toString()).isEqualTo(text)
assertThat(paragraph.charSequence)
- .hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
- span.typeface == expectedTypeface
+ .hasSpan(FontSpan::class, expectedStart, expectedEnd) { span ->
+ span.getTypeface(FontWeight.Bold.weight, true) == expectedTypeface
}
}
@@ -751,8 +752,8 @@
assertThat(paragraph.charSequence.toString()).isEqualTo(text)
assertThat(paragraph.charSequence)
- .hasSpan(TypefaceSpan::class, expectedStart, expectedEnd) { span ->
- span.typeface == expectedTypeface
+ .hasSpan(FontSpan::class, expectedStart, expectedEnd) { span ->
+ span.getTypeface(FontWeight.Bold.weight, true) == expectedTypeface
}
}
@@ -883,7 +884,7 @@
constraints = ParagraphConstraints(width = Float.MAX_VALUE)
)
- verify(typefaceAdapter, times(1)).create(
+ verify(typefaceAdapter, atLeastOnce()).create(
fontFamily = eq(basicFontFamily),
fontWeight = eq(FontWeight.Normal),
fontStyle = eq(FontStyle.Normal),
@@ -895,6 +896,23 @@
}
@Test
+ fun testFontFamily_appliedAsSpan() {
+ val text = "abc"
+ val typefaceAdapter = spy(TypefaceAdapter())
+ val paragraph = simpleParagraph(
+ text = text,
+ style = TextStyle(
+ fontFamily = basicFontFamily
+ ),
+ typefaceAdapter = typefaceAdapter,
+ constraints = ParagraphConstraints(width = Float.MAX_VALUE)
+ )
+
+ val charSequence = paragraph.charSequence
+ assertThat(charSequence).hasSpan(FontSpan::class, 0, text.length)
+ }
+
+ @Test
fun testEllipsis_withMaxLineEqualsNull_doesNotEllipsis() {
with(defaultDensity) {
val text = "abc"
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt b/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
index 6e4abe5..fe529f3 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
+++ b/ui/ui-text-core/src/main/java/androidx/ui/text/ParagraphIntrinsics.kt
@@ -45,8 +45,8 @@
/* actual */ fun ParagraphIntrinsics(
text: String,
style: TextStyle,
- spanStyles: List<AnnotatedString.Item<SpanStyle>> = listOf(),
- placeholders: List<AnnotatedString.Item<Placeholder>> = listOf(),
+ spanStyles: List<AnnotatedString.Item<SpanStyle>> = emptyList(),
+ placeholders: List<AnnotatedString.Item<Placeholder>> = emptyList(),
density: Density,
resourceLoader: Font.ResourceLoader
): ParagraphIntrinsics {
diff --git a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt b/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
index 202db23..2af715f 100644
--- a/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
+++ b/ui/ui-text-core/src/main/java/androidx/ui/text/platform/AndroidParagraphHelper.kt
@@ -18,6 +18,7 @@
import android.graphics.Typeface
import android.os.Build
+import android.text.Spannable
import android.text.SpannableString
import android.text.Spanned
import android.text.TextPaint
@@ -31,6 +32,7 @@
import android.text.style.StrikethroughSpan
import android.text.style.UnderlineSpan
import androidx.annotation.RequiresApi
+import androidx.annotation.VisibleForTesting
import androidx.ui.text.platform.style.BaselineShiftSpan
import androidx.ui.text.platform.style.FontFeatureSpan
import androidx.ui.text.platform.style.LetterSpacingSpanEm
@@ -39,7 +41,6 @@
import androidx.ui.text.platform.style.PlaceholderSpan
import androidx.ui.text.platform.style.ShadowSpan
import androidx.ui.text.platform.style.SkewXSpan
-import androidx.ui.text.platform.style.TypefaceSpan
import androidx.ui.graphics.Color
import androidx.ui.graphics.isSet
import androidx.ui.unit.Density
@@ -53,18 +54,36 @@
import androidx.ui.text.Placeholder
import androidx.ui.text.PlaceholderVerticalAlign
import androidx.ui.text.SpanStyle
+import androidx.ui.text.font.FontFamily
+import androidx.ui.text.font.FontListFontFamily
import androidx.ui.text.font.FontStyle
import androidx.ui.text.font.FontSynthesis
import androidx.ui.text.font.FontWeight
+import androidx.ui.text.platform.style.FontSpan
+import androidx.ui.text.platform.style.FontWeightStyleSpan
import androidx.ui.text.style.BaselineShift
import androidx.ui.text.style.TextDecoration
import androidx.ui.text.style.TextDirectionAlgorithm
import androidx.ui.text.style.TextIndent
+import androidx.ui.util.fastForEach
import kotlin.math.ceil
import kotlin.math.roundToInt
import android.os.LocaleList as AndroidLocaleList
import java.util.Locale as JavaLocale
+// Maximum span priority supported by android framework.
+private const val SPAN_PRIORITY_MAX = 255
+// Minimum span priority supported by android framework.
+private const val SPAN_PRIORITY_MIN = 0
+// Span priority is in the range of [0, 255]. Here we used 127 as default priority(instead of 0)
+// in case some spans need lower priority.
+private const val SPAN_PRIORITY_NORMAL = 127
+// FontSpan must be applied after FontWeightStyleSpan, but before LetterSpacingSpan.
+private const val SPAN_PRIORITY_FONTSPAN = 1
+// LetterSpacingSpanPx or LetterSpacingSpanEm must be applied after all other spans
+// that change fontSize and scaleX.
+private const val SPAN_PRIORITY_LETTERSPACING = 0
+
internal fun TextPaint.applySpanStyle(
style: SpanStyle,
typefaceAdapter: TypefaceAdapter,
@@ -134,10 +153,18 @@
}
}
+ // When FontFamily is a custom font(FontListFontFamily), it needs to be applied on Paint to
+ // compute empty paragraph height. Meanwhile, we also need a FontSpan for
+ // FontStyle/FontWeight span to work correctly.
// letterSpacing with unit Sp needs to be handled by span.
// baselineShift and bgColor is reset in the Android Layout constructor,
// therefore we cannot apply them on paint, have to use spans.
return SpanStyle(
+ fontFamily = if (style.fontFamily != null && style.fontFamily is FontListFontFamily) {
+ style.fontFamily
+ } else {
+ null
+ },
letterSpacing = if (style.letterSpacing.type == TextUnitType.Sp &&
style.letterSpacing.value != 0f) {
style.letterSpacing
@@ -169,26 +196,22 @@
): CharSequence {
if (spanStyles.isEmpty() && textIndent == null) return text
val spannableString = SpannableString(text)
- // Spans collected and applied at last. LetterSpacingSpanPx must be applied all other spans
- // that changes fontSize and scaleX. Notice, we can also utilize priority on span flags for
- // the purpose. If priority gets complicated, use flags instead.
- val deferredSpans = mutableListOf<Triple<Any, Int, Int>>()
when (lineHeight.type) {
TextUnitType.Sp -> with(density) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
LineHeightSpan(ceil(lineHeight.toPx().value).toInt()),
0,
text.length,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
TextUnitType.Em -> {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
LineHeightSpan(ceil(lineHeight.value * contextFontSize).toInt()),
0,
text.length,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
TextUnitType.Inherit -> {} // Do nothing
@@ -208,14 +231,14 @@
TextUnitType.Em -> indent.restLine.value * contextFontSize
TextUnitType.Inherit -> { 0f } // do nothing
}
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
LeadingMarginSpan.Standard(
ceil(firstLine).toInt(),
ceil(restLine).toInt()
),
0,
text.length,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
}
@@ -230,118 +253,151 @@
// Be aware that SuperscriptSpan needs to be applied before all other spans which
// affect FontMetrics
style.baselineShift?.let {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
BaselineShiftSpan(it.multiplier),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
if (style.color.isSet) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
ForegroundColorSpan(style.color.toArgb()),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
style.textDecoration?.let {
if (it.contains(TextDecoration.Underline)) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
UnderlineSpan(),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
if (it.contains(TextDecoration.LineThrough)) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
StrikethroughSpan(),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
}
when (style.fontSize.type) {
TextUnitType.Sp -> with(density) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
AbsoluteSizeSpan(style.fontSize.toPx().value.roundToInt(), true),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
TextUnitType.Em -> {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
RelativeSizeSpan(style.fontSize.value),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
TextUnitType.Inherit -> {} // Do nothing
}
style.fontFeatureSettings?.let {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
FontFeatureSpan(it),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
- if (style.hasFontAttributes()) {
- spannableString.setSpan(
- TypefaceSpan(createTypeface(style, typefaceAdapter)),
+ style.fontFamily?.let {
+ spannableString.setSpanWithPriority(
+ FontSpan { weight, isItalic ->
+ createTypeface(
+ fontFamily = it,
+ weight = weight,
+ isItalic = isItalic,
+ fontSynthesis = style.fontSynthesis,
+ typefaceAdapter = typefaceAdapter
+ )
+ },
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ if (it is FontListFontFamily) {
+ SPAN_PRIORITY_FONTSPAN
+ } else {
+ SPAN_PRIORITY_NORMAL
+ }
+ )
+ }
+
+ if (style.fontStyle != null || style.fontWeight != null) {
+ val weight = style.fontWeight?.weight ?: 0
+ val fontStyle = when (style.fontStyle) {
+ FontStyle.Normal -> FontWeightStyleSpan.STYLE_NORMAL
+ FontStyle.Italic -> FontWeightStyleSpan.STYLE_ITALIC
+ else -> FontWeightStyleSpan.STYLE_NONE
+ }
+ spannableString.setSpanWithPriority(
+ FontWeightStyleSpan(weight, fontStyle),
+ start,
+ end,
+ SPAN_PRIORITY_NORMAL
)
}
style.textGeometricTransform?.let {
if (it.scaleX != 1.0f) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
ScaleXSpan(it.scaleX),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
}
style.textGeometricTransform?.let {
if (it.skewX != 0f) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
SkewXSpan(it.skewX),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
}
when (style.letterSpacing.type) {
TextUnitType.Sp -> with(density) {
- deferredSpans.add(
- Triple(LetterSpacingSpanPx(style.letterSpacing.toPx().value), start, end)
+ spannableString.setSpanWithPriority(
+ LetterSpacingSpanPx(style.letterSpacing.toPx().value),
+ start,
+ end,
+ SPAN_PRIORITY_LETTERSPACING
)
}
TextUnitType.Em -> {
- deferredSpans.add(
- Triple(LetterSpacingSpanEm(style.letterSpacing.value), start, end)
+ spannableString.setSpanWithPriority(
+ LetterSpacingSpanEm(style.letterSpacing.value),
+ start,
+ end,
+ SPAN_PRIORITY_LETTERSPACING
)
}
TextUnitType.Inherit -> {}
}
style.localeList?.let {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
if (Build.VERSION.SDK_INT >= 24) {
LocaleSpan(it.toAndroidLocaleList())
} else {
@@ -350,32 +406,31 @@
},
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
if (style.background.isSet) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
BackgroundColorSpan(style.background.toArgb()),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
style.shadow?.let {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
ShadowSpan(it.color.toArgb(), it.offset.dx, it.offset.dy, it.blurRadius.value),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
}
- for ((span, start, end) in deferredSpans) {
- spannableString.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
- }
- for ((placeholder, start, end) in placeholders) {
+
+ placeholders.fastForEach {
+ val (placeholder, start, end) = it
with(placeholder) {
- spannableString.setSpan(
+ spannableString.setSpanWithPriority(
PlaceholderSpan(
width = width.value,
widthUnit = width.spanUnit,
@@ -386,13 +441,22 @@
),
start,
end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ SPAN_PRIORITY_NORMAL
)
}
}
return spannableString
}
+@VisibleForTesting
+internal fun Spannable.setSpanWithPriority(span: Any, start: Int, end: Int, priority: Int) {
+ require(priority >= SPAN_PRIORITY_MIN && priority <= SPAN_PRIORITY_MAX) {
+ "Invalid span priority: $priority must be in the range of [0, 255]."
+ }
+ val flag = (priority shl Spanned.SPAN_PRIORITY_SHIFT) or Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ setSpan(span, start, end, flag)
+}
+
/**
* Returns true if this [SpanStyle] contains any font style attributes set.
*/
@@ -409,6 +473,24 @@
)
}
+private fun createTypeface(
+ fontFamily: FontFamily?,
+ weight: Int,
+ isItalic: Boolean,
+ fontSynthesis: FontSynthesis?,
+ typefaceAdapter: TypefaceAdapter
+): Typeface {
+ val fontWeight = FontWeight(weight)
+ val fontStyle = if (isItalic) FontStyle.Italic else FontStyle.Normal
+
+ return typefaceAdapter.create(
+ fontFamily = fontFamily,
+ fontWeight = fontWeight,
+ fontStyle = fontStyle,
+ fontSynthesis = fontSynthesis ?: FontSynthesis.All
+ )
+}
+
/**
* For a given [TextDirectionAlgorithm] return [TextLayout] constants for text direction
* heuristics.
@@ -451,4 +533,4 @@
PlaceholderVerticalAlign.TextTop -> PlaceholderSpan.ALIGN_TEXT_TOP
PlaceholderVerticalAlign.TextBottom -> PlaceholderSpan.ALIGN_TEXT_BOTTOM
PlaceholderVerticalAlign.TextCenter -> PlaceholderSpan.ALIGN_TEXT_CENTER
- }
\ No newline at end of file
+ }
diff --git a/ui/ui-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/ui/text/demos/ComposeInputFieldFocusTransition.kt b/ui/ui-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/ui/text/demos/ComposeInputFieldFocusTransition.kt
index 27426fb..8eaec74 100644
--- a/ui/ui-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/ui/text/demos/ComposeInputFieldFocusTransition.kt
+++ b/ui/ui-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/ui/text/demos/ComposeInputFieldFocusTransition.kt
@@ -18,7 +18,7 @@
import androidx.compose.Composable
import androidx.compose.state
-import androidx.ui.focus.FocusModifier
+import androidx.ui.core.focus.FocusModifier
import androidx.ui.foundation.TextField
import androidx.ui.foundation.TextFieldValue
import androidx.ui.foundation.VerticalScroller
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt b/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
index 7792233..c6f613c 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
@@ -35,9 +35,9 @@
import androidx.ui.core.gesture.dragGestureFilter
import androidx.ui.core.gesture.pressIndicatorGestureFilter
import androidx.ui.core.onPositioned
-import androidx.ui.focus.FocusModifier
-import androidx.ui.focus.FocusState
-import androidx.ui.focus.focusState
+import androidx.ui.core.focus.FocusModifier
+import androidx.ui.core.focus.FocusState
+import androidx.ui.core.focus.focusState
import androidx.ui.graphics.painter.drawCanvas
import androidx.ui.input.EditProcessor
import androidx.ui.input.EditorValue
@@ -274,12 +274,14 @@
) {
val prevState = state { FocusState.NotFocused }
if (focusModifier.focusState == FocusState.Focused &&
- prevState.value == FocusState.NotFocused) {
+ prevState.value == FocusState.NotFocused
+ ) {
onFocus()
}
if (focusModifier.focusState == FocusState.NotFocused &&
- prevState.value == FocusState.Focused) {
+ prevState.value == FocusState.Focused
+ ) {
onBlur(false) // TODO: Need to know if there is next focus element
}
diff --git a/ui/ui-tooling/api/api_lint.ignore b/ui/ui-tooling/api/api_lint.ignore
deleted file mode 100644
index 9f69676..0000000
--- a/ui/ui-tooling/api/api_lint.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-MissingNullability: androidx.ui.tooling.InspectableKt#getTables():
- Missing nullability on method `getTables` return
diff --git a/ui/ui-unit/api/0.1.0-dev12.txt b/ui/ui-unit/api/0.1.0-dev12.txt
index 30a4329..95ef9ab 100644
--- a/ui/ui-unit/api/0.1.0-dev12.txt
+++ b/ui/ui-unit/api/0.1.0-dev12.txt
@@ -76,6 +76,10 @@
package androidx.ui.unit {
+ public final class AndroidDensityKt {
+ method public static androidx.ui.unit.Density Density(android.content.Context context);
+ }
+
public final class Bounds {
method public float component1();
method public float component2();
@@ -112,7 +116,6 @@
}
public final class DensityKt {
- method public static androidx.ui.unit.Density Density(android.content.Context context);
method public static androidx.ui.unit.Density Density(float density, float fontScale = 1f);
}
diff --git a/ui/ui-unit/api/current.txt b/ui/ui-unit/api/current.txt
index 30a4329..95ef9ab 100644
--- a/ui/ui-unit/api/current.txt
+++ b/ui/ui-unit/api/current.txt
@@ -76,6 +76,10 @@
package androidx.ui.unit {
+ public final class AndroidDensityKt {
+ method public static androidx.ui.unit.Density Density(android.content.Context context);
+ }
+
public final class Bounds {
method public float component1();
method public float component2();
@@ -112,7 +116,6 @@
}
public final class DensityKt {
- method public static androidx.ui.unit.Density Density(android.content.Context context);
method public static androidx.ui.unit.Density Density(float density, float fontScale = 1f);
}
diff --git a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt
index 30a4329..95ef9ab 100644
--- a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt
@@ -76,6 +76,10 @@
package androidx.ui.unit {
+ public final class AndroidDensityKt {
+ method public static androidx.ui.unit.Density Density(android.content.Context context);
+ }
+
public final class Bounds {
method public float component1();
method public float component2();
@@ -112,7 +116,6 @@
}
public final class DensityKt {
- method public static androidx.ui.unit.Density Density(android.content.Context context);
method public static androidx.ui.unit.Density Density(float density, float fontScale = 1f);
}
diff --git a/ui/ui-unit/api/public_plus_experimental_current.txt b/ui/ui-unit/api/public_plus_experimental_current.txt
index 30a4329..95ef9ab 100644
--- a/ui/ui-unit/api/public_plus_experimental_current.txt
+++ b/ui/ui-unit/api/public_plus_experimental_current.txt
@@ -76,6 +76,10 @@
package androidx.ui.unit {
+ public final class AndroidDensityKt {
+ method public static androidx.ui.unit.Density Density(android.content.Context context);
+ }
+
public final class Bounds {
method public float component1();
method public float component2();
@@ -112,7 +116,6 @@
}
public final class DensityKt {
- method public static androidx.ui.unit.Density Density(android.content.Context context);
method public static androidx.ui.unit.Density Density(float density, float fontScale = 1f);
}
diff --git a/ui/ui-unit/api/restricted_0.1.0-dev12.txt b/ui/ui-unit/api/restricted_0.1.0-dev12.txt
index 30a4329..95ef9ab 100644
--- a/ui/ui-unit/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-unit/api/restricted_0.1.0-dev12.txt
@@ -76,6 +76,10 @@
package androidx.ui.unit {
+ public final class AndroidDensityKt {
+ method public static androidx.ui.unit.Density Density(android.content.Context context);
+ }
+
public final class Bounds {
method public float component1();
method public float component2();
@@ -112,7 +116,6 @@
}
public final class DensityKt {
- method public static androidx.ui.unit.Density Density(android.content.Context context);
method public static androidx.ui.unit.Density Density(float density, float fontScale = 1f);
}
diff --git a/ui/ui-unit/api/restricted_current.txt b/ui/ui-unit/api/restricted_current.txt
index 30a4329..95ef9ab 100644
--- a/ui/ui-unit/api/restricted_current.txt
+++ b/ui/ui-unit/api/restricted_current.txt
@@ -76,6 +76,10 @@
package androidx.ui.unit {
+ public final class AndroidDensityKt {
+ method public static androidx.ui.unit.Density Density(android.content.Context context);
+ }
+
public final class Bounds {
method public float component1();
method public float component2();
@@ -112,7 +116,6 @@
}
public final class DensityKt {
- method public static androidx.ui.unit.Density Density(android.content.Context context);
method public static androidx.ui.unit.Density Density(float density, float fontScale = 1f);
}
diff --git a/ui/ui-unit/build.gradle b/ui/ui-unit/build.gradle
index cd5d933..ba8fe17 100644
--- a/ui/ui-unit/build.gradle
+++ b/ui/ui-unit/build.gradle
@@ -25,27 +25,39 @@
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXUiPlugin")
- id("org.jetbrains.kotlin.android")
+ id("kotlin-multiplatform")
}
-dependencies {
- implementation(KOTLIN_STDLIB)
+kotlin {
+ android()
+ sourceSets {
+ commonMain.dependencies {
+ implementation(KOTLIN_STDLIB_COMMON)
+ api project(":ui:ui-geometry")
- api "androidx.annotation:annotation:1.1.0"
- implementation project(":ui:ui-util")
- api project(":ui:ui-geometry")
+ implementation project(":ui:ui-util")
+ implementation project(":compose:compose-runtime")
+ }
+ jvmMain.dependencies {
+ implementation(KOTLIN_STDLIB)
+ }
+ androidMain.dependencies {
+ api "androidx.annotation:annotation:1.1.0"
+ }
- implementation project(":compose:compose-runtime")
-
- testImplementation(ANDROIDX_TEST_RULES)
- testImplementation(ANDROIDX_TEST_RUNNER)
- testImplementation(JUNIT)
- testImplementation(TRUTH)
-
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ESPRESSO_CORE)
- androidTestImplementation(JUNIT)
+ commonTest.dependencies {
+ implementation kotlin("test-junit")
+ }
+ // TODO: should be unitTest, figure out why that doesn't work
+ androidTest.dependencies {
+ implementation(TRUTH)
+ }
+ androidAndroidTest.dependencies {
+ implementation(ANDROIDX_TEST_RULES)
+ implementation(ANDROIDX_TEST_RUNNER)
+ implementation(ESPRESSO_CORE)
+ }
+ }
}
androidx {
@@ -59,7 +71,7 @@
tasks.withType(KotlinCompile).configureEach {
kotlinOptions {
- freeCompilerArgs += ["-Xuse-experimental=kotlin.Experimental", "-XXLanguage:+InlineClasses"]
+ freeCompilerArgs += ["-XXLanguage:+InlineClasses"]
useIR = true
}
}
diff --git a/ui/ui-unit/src/androidTest/AndroidManifest.xml b/ui/ui-unit/src/androidAndroidTest/AndroidManifest.xml
similarity index 100%
rename from ui/ui-unit/src/androidTest/AndroidManifest.xml
rename to ui/ui-unit/src/androidAndroidTest/AndroidManifest.xml
diff --git a/ui/ui-unit/src/androidTest/java/androidx/ui/unit/DpDeviceTest.kt b/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/DpDeviceTest.kt
similarity index 100%
rename from ui/ui-unit/src/androidTest/java/androidx/ui/unit/DpDeviceTest.kt
rename to ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/DpDeviceTest.kt
diff --git a/ui/ui-unit/src/androidTest/java/androidx/ui/unit/SpDeviceTest.kt b/ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/SpDeviceTest.kt
similarity index 100%
rename from ui/ui-unit/src/androidTest/java/androidx/ui/unit/SpDeviceTest.kt
rename to ui/ui-unit/src/androidAndroidTest/kotlin/androidx/ui/unit/SpDeviceTest.kt
diff --git a/ui/ui-unit/src/main/AndroidManifest.xml b/ui/ui-unit/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from ui/ui-unit/src/main/AndroidManifest.xml
rename to ui/ui-unit/src/androidMain/AndroidManifest.xml
diff --git a/ui/ui-unit/src/androidMain/kotlin/androidx/ui/unit/AndroidDensity.kt b/ui/ui-unit/src/androidMain/kotlin/androidx/ui/unit/AndroidDensity.kt
new file mode 100644
index 0000000..0d2c60f
--- /dev/null
+++ b/ui/ui-unit/src/androidMain/kotlin/androidx/ui/unit/AndroidDensity.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.unit
+
+import android.content.Context
+
+/**
+ * Creates a [Density] for this [Context].
+ *
+ * @param context density values will be extracted from this [Context]
+ */
+fun Density(context: Context): Density =
+ Density(
+ context.resources.displayMetrics.density,
+ context.resources.configuration.fontScale
+ )
diff --git a/ui/ui-unit/src/main/java/androidx/ui/core/Constraints.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/core/Constraints.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/core/Constraints.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/core/Constraints.kt
diff --git a/ui/ui-unit/src/main/java/androidx/ui/core/Constraints2.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/core/Constraints2.kt
similarity index 99%
rename from ui/ui-unit/src/main/java/androidx/ui/core/Constraints2.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/core/Constraints2.kt
index 4e22058..5363d74 100644
--- a/ui/ui-unit/src/main/java/androidx/ui/core/Constraints2.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/core/Constraints2.kt
@@ -17,9 +17,9 @@
package androidx.ui.core
-import androidx.annotation.IntRange
import androidx.compose.Immutable
import androidx.ui.unit.IntSize
+import androidx.ui.util.annotation.IntRange
import kotlin.math.max
/**
@@ -173,7 +173,7 @@
* be considered infinite. [hasBoundedHeight] or [hasBoundedWidth] will be
* `true` when [maxHeight] or [maxWidth] is [Infinity], respectively.
*/
- const val Infinity = Integer.MIN_VALUE / 2
+ const val Infinity = Int.MIN_VALUE / 2
/**
* The bit distribution when the focus of the bits should be on the width, but only
diff --git a/ui/ui-unit/src/main/java/androidx/ui/core/LayoutDirection.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/core/LayoutDirection.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/core/LayoutDirection.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/core/LayoutDirection.kt
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/Density.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Density.kt
similarity index 92%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/Density.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Density.kt
index 839168d..915db4d 100644
--- a/ui/ui-unit/src/main/java/androidx/ui/unit/Density.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Density.kt
@@ -16,21 +16,9 @@
package androidx.ui.unit
-import android.content.Context
import androidx.ui.geometry.Rect
/**
- * Creates a [Density] for this [Context].
- *
- * @param context density values will be extracted from this [Context]
- */
-fun Density(context: Context): Density =
- Density(
- context.resources.displayMetrics.density,
- context.resources.configuration.fontScale
- )
-
-/**
* A density of the screen. Used for convert [Dp] to pixels.
*
* @param density The logical density of the display. This is a scaling factor for the [Dp] unit.
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/Dp.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Dp.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/Dp.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Dp.kt
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/Duration.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Duration.kt
similarity index 99%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/Duration.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Duration.kt
index 6a4e82c..5db5baa 100644
--- a/ui/ui-unit/src/main/java/androidx/ui/unit/Duration.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Duration.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-@file:JvmName("Durations")
+@file:kotlin.jvm.JvmName("Durations")
@file:Suppress("NOTHING_TO_INLINE")
package androidx.ui.unit
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/IntPx.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/IntPx.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/IntSize.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntSize.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/IntSize.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntSize.kt
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/Px.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Px.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/Px.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Px.kt
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/TextUnit.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/TextUnit.kt
similarity index 97%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/TextUnit.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/TextUnit.kt
index 009e06f..d90d823 100644
--- a/ui/ui-unit/src/main/java/androidx/ui/unit/TextUnit.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/TextUnit.kt
@@ -172,6 +172,8 @@
}
companion object {
+ internal val TextUnitTypes = arrayOf(TextUnitType.Inherit, TextUnitType.Sp, TextUnitType.Em)
+
/**
* Creates a SP unit [TextUnit].
*/
@@ -221,12 +223,7 @@
*
* @throws RuntimeException if unknown unknown unit type is appeared.
*/
- val type: TextUnitType get() = when (rawType) {
- UNIT_TYPE_INHERIT -> TextUnitType.Inherit
- UNIT_TYPE_SP -> TextUnitType.Sp
- UNIT_TYPE_EM -> TextUnitType.Em
- else -> throw RuntimeException("packed TextUnit has unknown unit type.")
- }
+ val type: TextUnitType get() = TextUnitTypes[(rawType ushr 32).toInt()]
/**
* True if this is [TextUnit.Inherit], otherwise false.
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/Uptime.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Uptime.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/Uptime.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Uptime.kt
diff --git a/ui/ui-unit/src/main/java/androidx/ui/unit/Velocity.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Velocity.kt
similarity index 100%
rename from ui/ui-unit/src/main/java/androidx/ui/unit/Velocity.kt
rename to ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/Velocity.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/DpTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/DpTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/DpTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/DpTest.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/DurationTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/DurationTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/DurationTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/DurationTest.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/IntPxTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntPxTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/IntPxTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntPxTest.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/IntSizeTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntSizeTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/IntSizeTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/IntSizeTest.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/PxTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/PxTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/PxTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/PxTest.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/TextUnitTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/TextUnitTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/TextUnitTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/TextUnitTest.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/UptimeTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/UptimeTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/UptimeTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/UptimeTest.kt
diff --git a/ui/ui-unit/src/test/java/androidx/ui/unit/VelocityTest.kt b/ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/VelocityTest.kt
similarity index 100%
rename from ui/ui-unit/src/test/java/androidx/ui/unit/VelocityTest.kt
rename to ui/ui-unit/src/unitTest/kotlin/androidx/ui/unit/VelocityTest.kt
diff --git a/ui/ui-util/api/0.1.0-dev12.txt b/ui/ui-util/api/0.1.0-dev12.txt
index e8faee5..9286e03 100644
--- a/ui/ui-util/api/0.1.0-dev12.txt
+++ b/ui/ui-util/api/0.1.0-dev12.txt
@@ -1,6 +1,10 @@
// Signature format: 3.0
package androidx.ui.util {
+ public final class AndroidTraceKt {
+ method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class InlineClassHelperKt {
method public static inline long packFloats(float val1, float val2);
method public static inline long packInts(int val1, int val2);
@@ -10,8 +14,23 @@
method public static inline int unpackInt2(long value);
}
+ public final class JvmMathHelpersKt {
+ method public static String toStringAsFixed(float, int digits);
+ }
+
+ public final class JvmMiscHelpersKt {
+ method public static StringBuilder deleteAt(StringBuilder, int index);
+ method public static String format(String, java.lang.Object?... args);
+ method public static int identityHashCode(Object?);
+ }
+
+ public final class JvmSynchronizationHelperKt {
+ method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
@@ -20,15 +39,13 @@
method public static int lerp(int start, int stop, float fraction);
method public static long lerp(long start, long stop, float fraction);
method public static String toHexString(int);
- method public static String toStringAsFixed(float, int digits);
}
- public final class SynchronizationHelperKt {
- method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
- }
+}
- public final class TraceKt {
- method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+package androidx.ui.util.annotation {
+
+ public final class AndroidAnnotationKt {
}
}
diff --git a/ui/ui-util/api/current.txt b/ui/ui-util/api/current.txt
index e8faee5..9286e03 100644
--- a/ui/ui-util/api/current.txt
+++ b/ui/ui-util/api/current.txt
@@ -1,6 +1,10 @@
// Signature format: 3.0
package androidx.ui.util {
+ public final class AndroidTraceKt {
+ method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class InlineClassHelperKt {
method public static inline long packFloats(float val1, float val2);
method public static inline long packInts(int val1, int val2);
@@ -10,8 +14,23 @@
method public static inline int unpackInt2(long value);
}
+ public final class JvmMathHelpersKt {
+ method public static String toStringAsFixed(float, int digits);
+ }
+
+ public final class JvmMiscHelpersKt {
+ method public static StringBuilder deleteAt(StringBuilder, int index);
+ method public static String format(String, java.lang.Object?... args);
+ method public static int identityHashCode(Object?);
+ }
+
+ public final class JvmSynchronizationHelperKt {
+ method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
@@ -20,15 +39,13 @@
method public static int lerp(int start, int stop, float fraction);
method public static long lerp(long start, long stop, float fraction);
method public static String toHexString(int);
- method public static String toStringAsFixed(float, int digits);
}
- public final class SynchronizationHelperKt {
- method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
- }
+}
- public final class TraceKt {
- method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+package androidx.ui.util.annotation {
+
+ public final class AndroidAnnotationKt {
}
}
diff --git a/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt
index e8faee5..9286e03 100644
--- a/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-util/api/public_plus_experimental_0.1.0-dev12.txt
@@ -1,6 +1,10 @@
// Signature format: 3.0
package androidx.ui.util {
+ public final class AndroidTraceKt {
+ method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class InlineClassHelperKt {
method public static inline long packFloats(float val1, float val2);
method public static inline long packInts(int val1, int val2);
@@ -10,8 +14,23 @@
method public static inline int unpackInt2(long value);
}
+ public final class JvmMathHelpersKt {
+ method public static String toStringAsFixed(float, int digits);
+ }
+
+ public final class JvmMiscHelpersKt {
+ method public static StringBuilder deleteAt(StringBuilder, int index);
+ method public static String format(String, java.lang.Object?... args);
+ method public static int identityHashCode(Object?);
+ }
+
+ public final class JvmSynchronizationHelperKt {
+ method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
@@ -20,15 +39,13 @@
method public static int lerp(int start, int stop, float fraction);
method public static long lerp(long start, long stop, float fraction);
method public static String toHexString(int);
- method public static String toStringAsFixed(float, int digits);
}
- public final class SynchronizationHelperKt {
- method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
- }
+}
- public final class TraceKt {
- method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+package androidx.ui.util.annotation {
+
+ public final class AndroidAnnotationKt {
}
}
diff --git a/ui/ui-util/api/public_plus_experimental_current.txt b/ui/ui-util/api/public_plus_experimental_current.txt
index e8faee5..9286e03 100644
--- a/ui/ui-util/api/public_plus_experimental_current.txt
+++ b/ui/ui-util/api/public_plus_experimental_current.txt
@@ -1,6 +1,10 @@
// Signature format: 3.0
package androidx.ui.util {
+ public final class AndroidTraceKt {
+ method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class InlineClassHelperKt {
method public static inline long packFloats(float val1, float val2);
method public static inline long packInts(int val1, int val2);
@@ -10,8 +14,23 @@
method public static inline int unpackInt2(long value);
}
+ public final class JvmMathHelpersKt {
+ method public static String toStringAsFixed(float, int digits);
+ }
+
+ public final class JvmMiscHelpersKt {
+ method public static StringBuilder deleteAt(StringBuilder, int index);
+ method public static String format(String, java.lang.Object?... args);
+ method public static int identityHashCode(Object?);
+ }
+
+ public final class JvmSynchronizationHelperKt {
+ method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
@@ -20,15 +39,13 @@
method public static int lerp(int start, int stop, float fraction);
method public static long lerp(long start, long stop, float fraction);
method public static String toHexString(int);
- method public static String toStringAsFixed(float, int digits);
}
- public final class SynchronizationHelperKt {
- method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
- }
+}
- public final class TraceKt {
- method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+package androidx.ui.util.annotation {
+
+ public final class AndroidAnnotationKt {
}
}
diff --git a/ui/ui-util/api/restricted_0.1.0-dev12.txt b/ui/ui-util/api/restricted_0.1.0-dev12.txt
index e8faee5..9286e03 100644
--- a/ui/ui-util/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-util/api/restricted_0.1.0-dev12.txt
@@ -1,6 +1,10 @@
// Signature format: 3.0
package androidx.ui.util {
+ public final class AndroidTraceKt {
+ method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class InlineClassHelperKt {
method public static inline long packFloats(float val1, float val2);
method public static inline long packInts(int val1, int val2);
@@ -10,8 +14,23 @@
method public static inline int unpackInt2(long value);
}
+ public final class JvmMathHelpersKt {
+ method public static String toStringAsFixed(float, int digits);
+ }
+
+ public final class JvmMiscHelpersKt {
+ method public static StringBuilder deleteAt(StringBuilder, int index);
+ method public static String format(String, java.lang.Object?... args);
+ method public static int identityHashCode(Object?);
+ }
+
+ public final class JvmSynchronizationHelperKt {
+ method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
@@ -20,15 +39,13 @@
method public static int lerp(int start, int stop, float fraction);
method public static long lerp(long start, long stop, float fraction);
method public static String toHexString(int);
- method public static String toStringAsFixed(float, int digits);
}
- public final class SynchronizationHelperKt {
- method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
- }
+}
- public final class TraceKt {
- method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+package androidx.ui.util.annotation {
+
+ public final class AndroidAnnotationKt {
}
}
diff --git a/ui/ui-util/api/restricted_current.txt b/ui/ui-util/api/restricted_current.txt
index e8faee5..9286e03 100644
--- a/ui/ui-util/api/restricted_current.txt
+++ b/ui/ui-util/api/restricted_current.txt
@@ -1,6 +1,10 @@
// Signature format: 3.0
package androidx.ui.util {
+ public final class AndroidTraceKt {
+ method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class InlineClassHelperKt {
method public static inline long packFloats(float val1, float val2);
method public static inline long packInts(int val1, int val2);
@@ -10,8 +14,23 @@
method public static inline int unpackInt2(long value);
}
+ public final class JvmMathHelpersKt {
+ method public static String toStringAsFixed(float, int digits);
+ }
+
+ public final class JvmMiscHelpersKt {
+ method public static StringBuilder deleteAt(StringBuilder, int index);
+ method public static String format(String, java.lang.Object?... args);
+ method public static int identityHashCode(Object?);
+ }
+
+ public final class JvmSynchronizationHelperKt {
+ method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
public final class ListUtilsKt {
method public static inline <T> boolean fastAny(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method public static inline <T> T? fastFirstOrNull(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
method public static inline <T> void fastForEach(java.util.List<? extends T>, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> action);
}
@@ -20,15 +39,13 @@
method public static int lerp(int start, int stop, float fraction);
method public static long lerp(long start, long stop, float fraction);
method public static String toHexString(int);
- method public static String toStringAsFixed(float, int digits);
}
- public final class SynchronizationHelperKt {
- method public static <T> T! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends T> block);
- }
+}
- public final class TraceKt {
- method public static inline <T> T! trace(String sectionName, kotlin.jvm.functions.Function0<? extends T> block);
+package androidx.ui.util.annotation {
+
+ public final class AndroidAnnotationKt {
}
}
diff --git a/ui/ui-util/build.gradle b/ui/ui-util/build.gradle
index f149962..5f8d4e6 100644
--- a/ui/ui-util/build.gradle
+++ b/ui/ui-util/build.gradle
@@ -25,25 +25,32 @@
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXUiPlugin")
- id("org.jetbrains.kotlin.android")
+ id("kotlin-multiplatform")
}
-dependencies {
- implementation(KOTLIN_STDLIB)
+kotlin {
+ android()
+ sourceSets {
+ commonMain.dependencies {
+ implementation(KOTLIN_STDLIB_COMMON)
- api "androidx.annotation:annotation:1.1.0"
+ implementation project(":compose:compose-runtime")
+ }
+ jvmMain.dependencies {
+ implementation(KOTLIN_STDLIB)
+ }
+ androidMain.dependencies {
+ api "androidx.annotation:annotation:1.1.0"
+ }
- implementation project(":compose:compose-runtime")
-
- testImplementation(ANDROIDX_TEST_RULES)
- testImplementation(ANDROIDX_TEST_RUNNER)
- testImplementation(JUNIT)
- testImplementation(TRUTH)
-
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ESPRESSO_CORE)
- androidTestImplementation(JUNIT)
+ commonTest.dependencies {
+ implementation kotlin("test-junit")
+ }
+ // TODO: should be unitTest, figure out why that doesn't work
+ androidTest.dependencies {
+ implementation(TRUTH)
+ }
+ }
}
androidx {
@@ -57,7 +64,7 @@
tasks.withType(KotlinCompile).configureEach {
kotlinOptions {
- freeCompilerArgs += ["-Xuse-experimental=kotlin.Experimental", "-XXLanguage:+InlineClasses"]
-// useIR = true
+ freeCompilerArgs += ["-XXLanguage:+InlineClasses"]
+ useIR = true
}
}
diff --git a/ui/ui-util/src/main/AndroidManifest.xml b/ui/ui-util/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from ui/ui-util/src/main/AndroidManifest.xml
rename to ui/ui-util/src/androidMain/AndroidManifest.xml
diff --git a/ui/ui-util/src/main/java/androidx/ui/util/Trace.kt b/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/AndroidTrace.kt
similarity index 100%
rename from ui/ui-util/src/main/java/androidx/ui/util/Trace.kt
rename to ui/ui-util/src/androidMain/kotlin/androidx/ui/util/AndroidTrace.kt
diff --git a/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/annotation/AndroidAnnotation.kt b/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/annotation/AndroidAnnotation.kt
new file mode 100644
index 0000000..b407c4a
--- /dev/null
+++ b/ui/ui-util/src/androidMain/kotlin/androidx/ui/util/annotation/AndroidAnnotation.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.util.annotation
+
+actual typealias ColorInt = androidx.annotation.ColorInt
+actual typealias FloatRange = androidx.annotation.FloatRange
+actual typealias IntRange = androidx.annotation.IntRange
+actual typealias Size = androidx.annotation.Size
+actual typealias GuardedBy = androidx.annotation.GuardedBy
+actual typealias VisibleForTesting = androidx.annotation.VisibleForTesting
\ No newline at end of file
diff --git a/ui/ui-util/src/main/java/androidx/ui/util/InlineClassHelper.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/InlineClassHelper.kt
similarity index 100%
rename from ui/ui-util/src/main/java/androidx/ui/util/InlineClassHelper.kt
rename to ui/ui-util/src/commonMain/kotlin/androidx/ui/util/InlineClassHelper.kt
diff --git a/ui/ui-util/src/main/java/androidx/ui/util/ListUtils.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
similarity index 82%
rename from ui/ui-util/src/main/java/androidx/ui/util/ListUtils.kt
rename to ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
index f032a4f..cc900d5 100644
--- a/ui/ui-util/src/main/java/androidx/ui/util/ListUtils.kt
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/ListUtils.kt
@@ -34,3 +34,11 @@
fastForEach { if (predicate(it)) return true }
return false
}
+
+/**
+ * Returns the first value that [predicate] returns `true` for or `null` if nothing matches.
+ */
+inline fun <T> List<T>.fastFirstOrNull(predicate: (T) -> Boolean): T? {
+ fastForEach { if (predicate(it)) return it }
+ return null
+}
\ No newline at end of file
diff --git a/ui/ui-util/src/main/java/androidx/ui/util/MathHelpers.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MathHelpers.kt
similarity index 94%
rename from ui/ui-util/src/main/java/androidx/ui/util/MathHelpers.kt
rename to ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MathHelpers.kt
index 45bc4d9..8965a5c 100644
--- a/ui/ui-util/src/main/java/androidx/ui/util/MathHelpers.kt
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MathHelpers.kt
@@ -39,7 +39,7 @@
return start + ((stop - start) * fraction.toDouble()).roundToLong()
}
-fun Float.toStringAsFixed(digits: Int) = String.format("%.${digits}f", this)
+expect fun Float.toStringAsFixed(digits: Int): String
@OptIn(kotlin.ExperimentalUnsignedTypes::class)
fun Int.toHexString() = "0x${toUInt().toString(16).padStart(8, '0')}"
\ No newline at end of file
diff --git a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MiscHelpers.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MiscHelpers.kt
new file mode 100644
index 0000000..802ad61
--- /dev/null
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/MiscHelpers.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.util
+
+expect fun Any?.identityHashCode(): Int
+
+expect fun String.format(vararg args: Any?): String
+
+expect fun StringBuilder.deleteAt(index: Int): StringBuilder
\ No newline at end of file
diff --git a/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/annotation/Annotation.kt b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/annotation/Annotation.kt
new file mode 100644
index 0000000..3bee49a
--- /dev/null
+++ b/ui/ui-util/src/commonMain/kotlin/androidx/ui/util/annotation/Annotation.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.util.annotation
+
+@OptionalExpectation
+@ExperimentalMultiplatform
+expect annotation class ColorInt()
+
+@OptionalExpectation
+@ExperimentalMultiplatform
+expect annotation class FloatRange(
+ val from: Double,
+ val to: Double,
+ val fromInclusive: Boolean = true,
+ val toInclusive: Boolean = true
+)
+
+@OptionalExpectation
+@ExperimentalMultiplatform
+expect annotation class IntRange(val from: Long = Long.MIN_VALUE, val to: Long = Long.MAX_VALUE)
+
+@OptionalExpectation
+@ExperimentalMultiplatform
+expect annotation class Size(
+ val value: Long = -1,
+ val min: Long = Long.MIN_VALUE,
+ val max: Long = Long.MAX_VALUE,
+ val multiple: Long = 1
+)
+
+@OptionalExpectation
+@ExperimentalMultiplatform
+expect annotation class GuardedBy(
+ val value: String
+)
+
+@OptionalExpectation
+@ExperimentalMultiplatform
+expect annotation class VisibleForTesting(
+ val otherwise: Int = 2
+)
diff --git a/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmMathHelpers.kt b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmMathHelpers.kt
new file mode 100644
index 0000000..2a17e08
--- /dev/null
+++ b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmMathHelpers.kt
@@ -0,0 +1,19 @@
+/*
+ * 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.util
+
+actual fun Float.toStringAsFixed(digits: Int): String = String.format("%.${digits}f", this)
diff --git a/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmMiscHelpers.kt b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmMiscHelpers.kt
new file mode 100644
index 0000000..b93d83f
--- /dev/null
+++ b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmMiscHelpers.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.util
+
+actual fun Any?.identityHashCode(): Int = if (this == null) 0 else System.identityHashCode(this)
+
+actual fun String.format(vararg args: Any?): String = java.lang.String.format(this, *args)
+
+actual fun StringBuilder.deleteAt(index: Int): StringBuilder {
+ this.deleteCharAt(index)
+ return this
+}
\ No newline at end of file
diff --git a/ui/ui-util/src/main/java/androidx/ui/util/SynchronizationHelper.kt b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmSynchronizationHelper.kt
similarity index 98%
rename from ui/ui-util/src/main/java/androidx/ui/util/SynchronizationHelper.kt
rename to ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmSynchronizationHelper.kt
index c940781..9ef5426 100644
--- a/ui/ui-util/src/main/java/androidx/ui/util/SynchronizationHelper.kt
+++ b/ui/ui-util/src/jvmMain/kotlin/androidx/ui/util/JvmSynchronizationHelper.kt
@@ -23,7 +23,7 @@
/**
* [kotlin.synchronized][synchronized] is deprecated, and the build fails if we use
* [kotlin.synchronized][synchronized] along with the IR compiler. As a workaround, we have this
- * function here, which is in a module that doesn't use the IR COmpiler.
+ * function here, which is in a module that doesn't use the IR Compiler.
*/
@OptIn(ExperimentalContracts::class)
fun <T> synchronized(lock: Any, block: () -> T): T {
diff --git a/ui/ui-util/src/test/java/androidx/ui/util/InlineClassHelperTest.kt b/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/InlineClassHelperTest.kt
similarity index 100%
rename from ui/ui-util/src/test/java/androidx/ui/util/InlineClassHelperTest.kt
rename to ui/ui-util/src/unitTest/kotlin/androidx/ui/util/InlineClassHelperTest.kt
diff --git a/ui/ui-util/src/test/java/androidx/ui/util/ListUtilsTest.kt b/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/ListUtilsTest.kt
similarity index 85%
rename from ui/ui-util/src/test/java/androidx/ui/util/ListUtilsTest.kt
rename to ui/ui-util/src/unitTest/kotlin/androidx/ui/util/ListUtilsTest.kt
index 8d1ae60..46ae408 100644
--- a/ui/ui-util/src/test/java/androidx/ui/util/ListUtilsTest.kt
+++ b/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/ListUtilsTest.kt
@@ -18,6 +18,7 @@
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
@@ -69,4 +70,15 @@
val list = listOf(0, -1, -500, 1)
assertTrue(list.fastAny { it > 0 })
}
+
+ @Test
+ fun firstOrNullNotFound() {
+ val list = listOf(0, -1, -500)
+ assertNull(list.fastFirstOrNull { it > 0 })
+ }
+ @Test
+ fun firstOrNullFound() {
+ val list = listOf(0, -1, -500, 1)
+ assertEquals(1, list.fastFirstOrNull { it > 0 })
+ }
}
\ No newline at end of file
diff --git a/ui/ui-util/src/test/java/androidx/ui/util/MathHelpersTest.kt b/ui/ui-util/src/unitTest/kotlin/androidx/ui/util/MathHelpersTest.kt
similarity index 100%
rename from ui/ui-util/src/test/java/androidx/ui/util/MathHelpersTest.kt
rename to ui/ui-util/src/unitTest/kotlin/androidx/ui/util/MathHelpersTest.kt
diff --git a/wear/wear/api/api_lint.ignore b/wear/wear/api/api_lint.ignore
index 194e0f2..1cbce750 100644
--- a/wear/wear/api/api_lint.ignore
+++ b/wear/wear/api/api_lint.ignore
@@ -13,10 +13,6 @@
Inconsistent extra value; expected `androidx.wear.ambient.extra.LOWBIT_AMBIENT`, was `com.google.android.wearable.compat.extra.LOWBIT_AMBIENT`
-CallbackMethodName: androidx.wear.widget.CurvingLayoutCallback:
- Callback method names must follow the on<Something> style: adjustAnchorOffsetXY
-
-
ForbiddenSuperClass: androidx.wear.activity.ConfirmationActivity:
ConfirmationActivity should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead.
diff --git a/webkit/webkit/api/api_lint.ignore b/webkit/webkit/api/api_lint.ignore
index 2eb478a..0ec5493 100644
--- a/webkit/webkit/api/api_lint.ignore
+++ b/webkit/webkit/api/api_lint.ignore
@@ -7,6 +7,12 @@
Method should return Collection<WebMessagePortCompat> (or subclass) instead of raw array; was `androidx.webkit.WebMessagePortCompat[]`
+BuilderSetStyle: androidx.webkit.ProxyConfig.Builder#bypassSimpleHostnames():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.webkit.ProxyConfig.Builder.bypassSimpleHostnames()
+BuilderSetStyle: androidx.webkit.ProxyConfig.Builder#removeImplicitRules():
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.webkit.ProxyConfig.Builder.removeImplicitRules()
+
+
IntentName: androidx.webkit.WebViewFeature#DISABLED_ACTION_MODE_MENU_ITEMS:
Intent action constant name must be ACTION_FOO: DISABLED_ACTION_MODE_MENU_ITEMS
diff --git a/work/workmanager-testing/api/api_lint.ignore b/work/workmanager-testing/api/api_lint.ignore
index 583b20b..a23d747 100644
--- a/work/workmanager-testing/api/api_lint.ignore
+++ b/work/workmanager-testing/api/api_lint.ignore
@@ -1,4 +1,10 @@
// Baseline format: 1.0
+BuilderSetStyle: androidx.work.testing.TestListenableWorkerBuilder#from(android.content.Context, Class<W>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.testing.TestListenableWorkerBuilder.from(android.content.Context,Class<W>)
+BuilderSetStyle: androidx.work.testing.TestListenableWorkerBuilder#from(android.content.Context, androidx.work.WorkRequest):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.testing.TestListenableWorkerBuilder.from(android.content.Context,androidx.work.WorkRequest)
+
+
MissingNullability: androidx.work.testing.TestListenableWorkerBuilderKt#TestListenableWorkerBuilder(android.content.Context, androidx.work.Data, java.util.List<? extends java.lang.String>, int, java.util.List<? extends android.net.Uri>, java.util.List<? extends java.lang.String>):
Missing nullability on method `TestListenableWorkerBuilder` return
MissingNullability: androidx.work.testing.TestWorkerBuilderKt#TestWorkerBuilder(android.content.Context, java.util.concurrent.Executor, androidx.work.Data, java.util.List<? extends java.lang.String>, int, java.util.List<? extends android.net.Uri>, java.util.List<? extends java.lang.String>):
diff --git a/work/workmanager/api/api_lint.ignore b/work/workmanager/api/api_lint.ignore
index 6185dcc..444e9d1 100644
--- a/work/workmanager/api/api_lint.ignore
+++ b/work/workmanager/api/api_lint.ignore
@@ -7,6 +7,44 @@
Acronyms should not be capitalized in class names: was `SUCCESS`, should this be `Success`?
+BuilderSetStyle: androidx.work.Data.Builder#putAll(androidx.work.Data):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putAll(androidx.work.Data)
+BuilderSetStyle: androidx.work.Data.Builder#putAll(java.util.Map<java.lang.String,java.lang.Object>):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putAll(java.util.Map<java.lang.String,java.lang.Object>)
+BuilderSetStyle: androidx.work.Data.Builder#putBoolean(String, boolean):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putBoolean(String,boolean)
+BuilderSetStyle: androidx.work.Data.Builder#putBooleanArray(String, boolean[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putBooleanArray(String,boolean[])
+BuilderSetStyle: androidx.work.Data.Builder#putByte(String, byte):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putByte(String,byte)
+BuilderSetStyle: androidx.work.Data.Builder#putByteArray(String, byte[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putByteArray(String,byte[])
+BuilderSetStyle: androidx.work.Data.Builder#putDouble(String, double):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putDouble(String,double)
+BuilderSetStyle: androidx.work.Data.Builder#putDoubleArray(String, double[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putDoubleArray(String,double[])
+BuilderSetStyle: androidx.work.Data.Builder#putFloat(String, float):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putFloat(String,float)
+BuilderSetStyle: androidx.work.Data.Builder#putFloatArray(String, float[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putFloatArray(String,float[])
+BuilderSetStyle: androidx.work.Data.Builder#putInt(String, int):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putInt(String,int)
+BuilderSetStyle: androidx.work.Data.Builder#putIntArray(String, int[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putIntArray(String,int[])
+BuilderSetStyle: androidx.work.Data.Builder#putLong(String, long):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putLong(String,long)
+BuilderSetStyle: androidx.work.Data.Builder#putLongArray(String, long[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putLongArray(String,long[])
+BuilderSetStyle: androidx.work.Data.Builder#putString(String, String):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putString(String,String)
+BuilderSetStyle: androidx.work.Data.Builder#putStringArray(String, String[]):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.Data.Builder.putStringArray(String,String[])
+BuilderSetStyle: androidx.work.WorkRequest.Builder#keepResultsForAtLeast(java.time.Duration):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.WorkRequest.Builder.keepResultsForAtLeast(java.time.Duration)
+BuilderSetStyle: androidx.work.WorkRequest.Builder#keepResultsForAtLeast(long, java.util.concurrent.TimeUnit):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.WorkRequest.Builder.keepResultsForAtLeast(long,java.util.concurrent.TimeUnit)
+
+
MissingNullability: androidx.work.Constraints#NONE:
Missing nullability on field `NONE` in class `class androidx.work.Constraints`
MissingNullability: androidx.work.Constraints.Builder#setTriggerContentMaxDelay(java.time.Duration) parameter #0:
@@ -25,6 +63,8 @@
Should avoid odd sized primitives; use `int` instead of `byte` in parameter value in androidx.work.Data.Builder.putByte(String key, byte value)
+SetterReturnsThis: androidx.work.WorkRequest.Builder#addTag(String):
+ Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.addTag(String)
SetterReturnsThis: androidx.work.WorkRequest.Builder#setBackoffCriteria(androidx.work.BackoffPolicy, java.time.Duration):
Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setBackoffCriteria(androidx.work.BackoffPolicy,java.time.Duration)
SetterReturnsThis: androidx.work.WorkRequest.Builder#setBackoffCriteria(androidx.work.BackoffPolicy, long, java.util.concurrent.TimeUnit):