From 85f2f0c7d0e94b51a5e2fc9a142668723cddf899 Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Wed, 13 Oct 2021 17:14:06 +0700 Subject: [PATCH] Support using getInsetsIgnoringVisibility (#121) --- library/api/library.api | 4 +- .../java/dev/chrisbanes/insetter/Insetter.kt | 71 ++++++++++++++----- .../dev/chrisbanes/insetter/InsetterDsl.kt | 9 +++ 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/library/api/library.api b/library/api/library.api index 33e37bd..ab121f6 100644 --- a/library/api/library.api +++ b/library/api/library.api @@ -3,7 +3,7 @@ public final class dev/chrisbanes/insetter/Insetter { public static final field CONSUME_AUTO I public static final field CONSUME_NONE I public static final field Companion Ldev/chrisbanes/insetter/Insetter$Companion; - public synthetic fun (Ldev/chrisbanes/insetter/SideApply;Ldev/chrisbanes/insetter/SideApply;Ldev/chrisbanes/insetter/OnApplyInsetsListener;IILjava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ldev/chrisbanes/insetter/SideApply;Ldev/chrisbanes/insetter/SideApply;Ldev/chrisbanes/insetter/OnApplyInsetsListener;IILjava/util/List;ZLkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun applyInsetsToView (Landroid/view/View;Landroidx/core/view/WindowInsetsCompat;Ldev/chrisbanes/insetter/ViewState;)V public final fun applyToView (Landroid/view/View;)V public static final fun builder ()Ldev/chrisbanes/insetter/Insetter$Builder; @@ -13,6 +13,7 @@ public final class dev/chrisbanes/insetter/Insetter$Builder { public final fun applyToView (Landroid/view/View;)Ldev/chrisbanes/insetter/Insetter; public final fun build ()Ldev/chrisbanes/insetter/Insetter; public final fun consume (I)Ldev/chrisbanes/insetter/Insetter$Builder; + public final fun ignoreVisibility (Z)Ldev/chrisbanes/insetter/Insetter$Builder; public final fun margin (I)Ldev/chrisbanes/insetter/Insetter$Builder; public final fun margin (II)Ldev/chrisbanes/insetter/Insetter$Builder; public final fun margin (IIZ)Ldev/chrisbanes/insetter/Insetter$Builder; @@ -62,6 +63,7 @@ public final class dev/chrisbanes/insetter/InsetterApplyTypeDsl { public final class dev/chrisbanes/insetter/InsetterDsl { public final fun consume (I)V public final fun consume (Z)V + public final fun ignoreVisibility (Z)V public final fun syncTranslationTo ([Landroid/view/View;)V public final fun type (ILkotlin/jvm/functions/Function1;)V public final fun type (ZZZZZZZZLkotlin/jvm/functions/Function1;)V diff --git a/library/src/main/java/dev/chrisbanes/insetter/Insetter.kt b/library/src/main/java/dev/chrisbanes/insetter/Insetter.kt index 6b43749..a17ab1d 100644 --- a/library/src/main/java/dev/chrisbanes/insetter/Insetter.kt +++ b/library/src/main/java/dev/chrisbanes/insetter/Insetter.kt @@ -65,6 +65,7 @@ class Insetter private constructor( @ConsumeOptions private val consume: Int, private val animatingTypes: Int, private val animateSyncViews: List, + private val ignoreVisibility: Boolean, ) { @IntDef(value = [CONSUME_NONE, CONSUME_ALL, CONSUME_AUTO]) @Retention(AnnotationRetention.SOURCE) @@ -92,6 +93,8 @@ class Insetter private constructor( private var consume = CONSUME_NONE + private var ignoreVisibility = false + private var animatingTypes = 0 private var animateSyncViews = ArrayList() @@ -318,6 +321,15 @@ class Insetter private constructor( return this } + /** + * @param ignoreVisibility true to return the insets regardless of whether the given type is + * currently visible or not. + */ + fun ignoreVisibility(ignoreVisibility: Boolean): Builder { + this.ignoreVisibility = ignoreVisibility + return this + } + /** * Builds the [Insetter] instance and sets it as an * [OnApplyWindowInsetsListener][androidx.core.view.OnApplyWindowInsetsListener] on @@ -341,6 +353,7 @@ class Insetter private constructor( animatingTypes = animatingTypes, animateSyncViews = animateSyncViews, consume = consume, + ignoreVisibility = ignoreVisibility, ) } @@ -382,11 +395,11 @@ class Insetter private constructor( CONSUME_ALL -> WindowInsetsCompat.CONSUMED CONSUME_AUTO -> { WindowInsetsCompat.Builder(insets) - .consumeType(Type.statusBars(), insets, persistentTypes) - .consumeType(Type.navigationBars(), insets, persistentTypes) - .consumeType(Type.ime(), insets, persistentTypes) - .consumeType(Type.systemGestures(), insets, persistentTypes) - .consumeType(Type.displayCutout(), insets, persistentTypes) + .consumeType(Type.statusBars(), insets, persistentTypes, ignoreVisibility) + .consumeType(Type.navigationBars(), insets, persistentTypes, ignoreVisibility) + .consumeType(Type.ime(), insets, persistentTypes, ignoreVisibility) + .consumeType(Type.systemGestures(), insets, persistentTypes, ignoreVisibility) + .consumeType(Type.displayCutout(), insets, persistentTypes, ignoreVisibility) .build() } else -> insets @@ -505,12 +518,14 @@ class Insetter private constructor( view.applyPadding( insets = insets, typesToApply = paddingTypes - currentlyDeferredTypes, - initialPaddings = initialState.paddings + initialPaddings = initialState.paddings, + ignoreVisibility = ignoreVisibility ) view.applyMargins( insets = insets, typesToApply = marginTypes - currentlyDeferredTypes, - initialMargins = initialState.margins + initialMargins = initialState.margins, + ignoreVisibility = ignoreVisibility ) } @@ -620,25 +635,26 @@ private fun View.applyPadding( insets: WindowInsetsCompat, typesToApply: SideApply, initialPaddings: ViewDimensions, + ignoreVisibility: Boolean, ) { // If there's no types to apply, nothing to do... if (typesToApply.isEmpty) return val paddingLeft = when (typesToApply.left) { Side.NONE -> paddingLeft - else -> initialPaddings.left + insets.getInsets(typesToApply.left).left + else -> initialPaddings.left + insets.getInsets(typesToApply.left, ignoreVisibility).left } val paddingTop = when (typesToApply.top) { Side.NONE -> paddingTop - else -> initialPaddings.top + insets.getInsets(typesToApply.top).top + else -> initialPaddings.top + insets.getInsets(typesToApply.top, ignoreVisibility).top } val paddingRight = when (typesToApply.right) { Side.NONE -> paddingRight - else -> initialPaddings.right + insets.getInsets(typesToApply.right).right + else -> initialPaddings.right + insets.getInsets(typesToApply.right, ignoreVisibility).right } val paddingBottom = when (typesToApply.bottom) { Side.NONE -> paddingBottom - else -> initialPaddings.bottom + insets.getInsets(typesToApply.bottom).bottom + else -> initialPaddings.bottom + insets.getInsets(typesToApply.bottom, ignoreVisibility).bottom } // setPadding() does it's own value change check, so no need to do our own to avoid layout @@ -655,6 +671,7 @@ private fun View.applyMargins( insets: WindowInsetsCompat, typesToApply: SideApply, initialMargins: ViewDimensions, + ignoreVisibility: Boolean, ) { // If there's no types to apply, nothing to do... if (typesToApply.isEmpty) return @@ -667,19 +684,19 @@ private fun View.applyMargins( val marginLeft = when (typesToApply.left) { Side.NONE -> lp.leftMargin - else -> initialMargins.left + insets.getInsets(typesToApply.left).left + else -> initialMargins.left + insets.getInsets(typesToApply.left, ignoreVisibility).left } val marginTop = when (typesToApply.top) { Side.NONE -> lp.topMargin - else -> initialMargins.top + insets.getInsets(typesToApply.top).top + else -> initialMargins.top + insets.getInsets(typesToApply.top, ignoreVisibility).top } val marginRight = when (typesToApply.right) { Side.NONE -> lp.rightMargin - else -> initialMargins.right + insets.getInsets(typesToApply.right).right + else -> initialMargins.right + insets.getInsets(typesToApply.right, ignoreVisibility).right } val marginBottom = when (typesToApply.bottom) { Side.NONE -> lp.bottomMargin - else -> initialMargins.bottom + insets.getInsets(typesToApply.bottom).bottom + else -> initialMargins.bottom + insets.getInsets(typesToApply.bottom, ignoreVisibility).bottom } // Update the layoutParams margins. Will return true if any value has changed @@ -724,12 +741,13 @@ private fun WindowInsetsCompat.Builder.consumeType( type: Int, windowInsets: WindowInsetsCompat, applied: SideApply, + ignoreVisibility: Boolean, ): WindowInsetsCompat.Builder { // Fast path. If this type wasn't applied at all, no need to do anything if (applied.all and type != type) return this // First we get the original insets for the type - val insets = windowInsets.getInsets(type) + val insets = windowInsets.getInsets(type, ignoreVisibility) // If the insets are empty, nothing to do if (insets == Insets.NONE) return this @@ -746,3 +764,24 @@ private fun WindowInsetsCompat.Builder.consumeType( ) return this } + +/** + * Returns the insets of a specific set of windows causing insets, denoted by the + * [typeMask] bit mask of [Type]s. + * + * @param typeMask Bit mask of [Type]s to query the insets for. + * @param ignoreVisibility True to return the insets regardless of whether that type is currently + * visible or not. + * @see WindowInsetsCompat.getInsets + * @see WindowInsetsCompat.getInsetsIgnoringVisibility + */ +private fun WindowInsetsCompat.getInsets( + @Type.InsetsType typeMask: Int, + ignoreVisibility: Boolean +): Insets { + return if (ignoreVisibility) { + getInsetsIgnoringVisibility(typeMask) + } else { + getInsets(typeMask) + } +} diff --git a/library/src/main/java/dev/chrisbanes/insetter/InsetterDsl.kt b/library/src/main/java/dev/chrisbanes/insetter/InsetterDsl.kt index 1310fb8..1b6fa14 100644 --- a/library/src/main/java/dev/chrisbanes/insetter/InsetterDsl.kt +++ b/library/src/main/java/dev/chrisbanes/insetter/InsetterDsl.kt @@ -181,6 +181,15 @@ class InsetterDsl internal constructor() { builder = builder.consume(consume) } + /** + * @param ignoreVisibility true to return the insets regardless of whether the given type is + * currently visible or not. + * @see Insetter.Builder.ignoreVisibility + */ + fun ignoreVisibility(ignoreVisibility: Boolean) { + builder = builder.ignoreVisibility(ignoreVisibility) + } + /** * When reacting to window insets animations it is often useful to apply the same * animated translation X and Y to other views. The views provided to this function