summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/animation/res/values/ids.xml1
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt66
-rw-r--r--packages/SystemUI/res/layout/media_ttt_chip.xml126
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt159
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt16
7 files changed, 323 insertions, 66 deletions
diff --git a/packages/SystemUI/animation/res/values/ids.xml b/packages/SystemUI/animation/res/values/ids.xml
index 03ca462beb76..f7150ab548dd 100644
--- a/packages/SystemUI/animation/res/values/ids.xml
+++ b/packages/SystemUI/animation/res/values/ids.xml
@@ -21,6 +21,7 @@
<!-- ViewBoundsAnimator -->
<item type="id" name="tag_animator"/>
+ <item type="id" name="tag_alpha_animator"/>
<item type="id" name="tag_layout_listener"/>
<item type="id" name="tag_override_bottom"/>
<item type="id" name="tag_override_left"/>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
index 093589f8c636..4c3cd3c2b441 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
@@ -39,6 +39,7 @@ class ViewHierarchyAnimator {
private val DEFAULT_INTERPOLATOR = Interpolators.STANDARD
private val DEFAULT_ADDITION_INTERPOLATOR = Interpolators.STANDARD_DECELERATE
private val DEFAULT_REMOVAL_INTERPOLATOR = Interpolators.STANDARD_ACCELERATE
+ private val DEFAULT_FADE_IN_INTERPOLATOR = Interpolators.ALPHA_IN
/** The properties used to animate the view bounds. */
private val PROPERTIES = mapOf(
@@ -162,6 +163,10 @@ class ViewHierarchyAnimator {
* animate an already visible view, see [animate] and [animateNextUpdate].
*
* Then animator unregisters itself once the first addition animation is complete.
+ *
+ * @param includeFadeIn true if the animator should also fade in the view and child views.
+ * @param fadeInInterpolator the interpolator to use when fading in the view. Unused if
+ * [includeFadeIn] is false.
*/
@JvmOverloads
fun animateAddition(
@@ -169,7 +174,9 @@ class ViewHierarchyAnimator {
origin: Hotspot = Hotspot.CENTER,
interpolator: Interpolator = DEFAULT_ADDITION_INTERPOLATOR,
duration: Long = DEFAULT_DURATION,
- includeMargins: Boolean = false
+ includeMargins: Boolean = false,
+ includeFadeIn: Boolean = false,
+ fadeInInterpolator: Interpolator = DEFAULT_FADE_IN_INTERPOLATOR
): Boolean {
if (isVisible(
rootView.visibility,
@@ -186,6 +193,42 @@ class ViewHierarchyAnimator {
origin, interpolator, duration, ignorePreviousValues = !includeMargins
)
addListener(rootView, listener, recursive = true)
+
+ if (!includeFadeIn) {
+ return true
+ }
+
+ if (rootView is ViewGroup) {
+ // First, fade in the container view
+ val containerDuration = duration / 6
+ createAndStartFadeInAnimator(
+ rootView, containerDuration, startDelay = 0, interpolator = fadeInInterpolator
+ )
+
+ // Then, fade in the child views
+ val childDuration = duration / 3
+ for (i in 0 until rootView.childCount) {
+ val view = rootView.getChildAt(i)
+ createAndStartFadeInAnimator(
+ view,
+ childDuration,
+ // Wait until the container fades in before fading in the children
+ startDelay = containerDuration,
+ interpolator = fadeInInterpolator
+ )
+ }
+ // For now, we don't recursively fade in additional sub views (e.g. grandchild
+ // views) since it hasn't been necessary, but we could add that functionality.
+ } else {
+ // Fade in the view during the first half of the addition
+ createAndStartFadeInAnimator(
+ rootView,
+ duration / 2,
+ startDelay = 0,
+ interpolator = fadeInInterpolator
+ )
+ }
+
return true
}
@@ -834,6 +877,27 @@ class ViewHierarchyAnimator {
view.setTag(R.id.tag_animator, animator)
animator.start()
}
+
+ private fun createAndStartFadeInAnimator(
+ view: View,
+ duration: Long,
+ startDelay: Long,
+ interpolator: Interpolator
+ ) {
+ val animator = ObjectAnimator.ofFloat(view, "alpha", 1f)
+ animator.startDelay = startDelay
+ animator.duration = duration
+ animator.interpolator = interpolator
+ animator.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ view.setTag(R.id.tag_alpha_animator, null /* tag */)
+ }
+ })
+
+ (view.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.cancel()
+ view.setTag(R.id.tag_alpha_animator, animator)
+ animator.start()
+ }
}
/** An enum used to determine the origin of addition animations. */
diff --git a/packages/SystemUI/res/layout/media_ttt_chip.xml b/packages/SystemUI/res/layout/media_ttt_chip.xml
index a502d33a0be1..4d24140abbf4 100644
--- a/packages/SystemUI/res/layout/media_ttt_chip.xml
+++ b/packages/SystemUI/res/layout/media_ttt_chip.xml
@@ -13,71 +13,85 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<LinearLayout
+<!-- Wrap in a frame layout so that we can update the margins on the inner layout. (Since this view
+ is the root view of a window, we cannot change the root view's margins.) -->
+<!-- Alphas start as 0 because the view will be animated in. -->
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/media_ttt_sender_chip"
- android:orientation="horizontal"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="@dimen/media_ttt_chip_outer_padding"
- android:background="@drawable/media_ttt_chip_background"
- android:layout_marginTop="50dp"
- android:clipToPadding="false"
- android:gravity="center_vertical"
- >
+ android:layout_height="wrap_content">
- <com.android.internal.widget.CachingIconView
- android:id="@+id/app_icon"
- android:layout_width="@dimen/media_ttt_app_icon_size"
- android:layout_height="@dimen/media_ttt_app_icon_size"
- android:layout_marginEnd="12dp"
- />
-
- <TextView
- android:id="@+id/text"
+ <LinearLayout
+ android:id="@+id/media_ttt_sender_chip_inner"
+ android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textSize="@dimen/media_ttt_text_size"
- android:textColor="?android:attr/textColorPrimary"
- />
+ android:padding="@dimen/media_ttt_chip_outer_padding"
+ android:background="@drawable/media_ttt_chip_background"
+ android:layout_marginTop="20dp"
+ android:clipToPadding="false"
+ android:gravity="center_vertical"
+ android:alpha="0.0"
+ >
- <!-- At most one of [loading, failure_icon, undo] will be visible at a time. -->
+ <com.android.internal.widget.CachingIconView
+ android:id="@+id/app_icon"
+ android:layout_width="@dimen/media_ttt_app_icon_size"
+ android:layout_height="@dimen/media_ttt_app_icon_size"
+ android:layout_marginEnd="12dp"
+ android:alpha="0.0"
+ />
- <ProgressBar
- android:id="@+id/loading"
- android:indeterminate="true"
- android:layout_width="@dimen/media_ttt_status_icon_size"
- android:layout_height="@dimen/media_ttt_status_icon_size"
- android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
- android:indeterminateTint="?androidprv:attr/colorAccentPrimaryVariant"
- style="?android:attr/progressBarStyleSmall"
- />
+ <TextView
+ android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/media_ttt_text_size"
+ android:textColor="?android:attr/textColorPrimary"
+ android:alpha="0.0"
+ />
- <ImageView
- android:id="@+id/failure_icon"
- android:layout_width="@dimen/media_ttt_status_icon_size"
- android:layout_height="@dimen/media_ttt_status_icon_size"
- android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
- android:src="@drawable/ic_warning"
- android:tint="@color/GM2_red_500"
- />
+ <!-- At most one of [loading, failure_icon, undo] will be visible at a time. -->
+ <ProgressBar
+ android:id="@+id/loading"
+ android:indeterminate="true"
+ android:layout_width="@dimen/media_ttt_status_icon_size"
+ android:layout_height="@dimen/media_ttt_status_icon_size"
+ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+ android:indeterminateTint="?androidprv:attr/colorAccentPrimaryVariant"
+ style="?android:attr/progressBarStyleSmall"
+ android:alpha="0.0"
+ />
- <TextView
- android:id="@+id/undo"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/media_transfer_undo"
- android:textColor="?androidprv:attr/textColorOnAccent"
- android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
- android:textSize="@dimen/media_ttt_text_size"
- android:paddingStart="@dimen/media_ttt_chip_outer_padding"
- android:paddingEnd="@dimen/media_ttt_chip_outer_padding"
- android:paddingTop="@dimen/media_ttt_undo_button_vertical_padding"
- android:paddingBottom="@dimen/media_ttt_undo_button_vertical_padding"
- android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin"
- android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin"
- android:background="@drawable/media_ttt_undo_background"
- />
+ <ImageView
+ android:id="@+id/failure_icon"
+ android:layout_width="@dimen/media_ttt_status_icon_size"
+ android:layout_height="@dimen/media_ttt_status_icon_size"
+ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+ android:src="@drawable/ic_warning"
+ android:tint="@color/GM2_red_500"
+ android:alpha="0.0"
+ />
+
+ <TextView
+ android:id="@+id/undo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/media_transfer_undo"
+ android:textColor="?androidprv:attr/textColorOnAccent"
+ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+ android:textSize="@dimen/media_ttt_text_size"
+ android:paddingStart="@dimen/media_ttt_chip_outer_padding"
+ android:paddingEnd="@dimen/media_ttt_chip_outer_padding"
+ android:paddingTop="@dimen/media_ttt_undo_button_vertical_padding"
+ android:paddingBottom="@dimen/media_ttt_undo_button_vertical_padding"
+ android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin"
+ android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin"
+ android:background="@drawable/media_ttt_undo_background"
+ android:alpha="0.0"
+ />
-</LinearLayout>
+ </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
index 54b0c1345601..7cc52e428218 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
@@ -106,6 +106,7 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>(
PowerManager.WAKE_REASON_APPLICATION,
"com.android.systemui:media_tap_to_transfer_activated"
)
+ animateChipIn(currentChipView)
}
// Cancel and re-set the chip timeout each time we get a new state.
@@ -138,6 +139,12 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>(
abstract fun updateChipView(chipInfo: T, currentChipView: ViewGroup)
/**
+ * A method that can be implemented by subclcasses to do custom animations for when the chip
+ * appears.
+ */
+ open fun animateChipIn(chipView: ViewGroup) {}
+
+ /**
* Returns the size that the icon should be, or null if no size override is needed.
*/
open fun getIconSize(isAppIcon: Boolean): Int? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
index 9f5ec7e1a330..54b4380e2443 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
@@ -27,6 +27,8 @@ import android.view.WindowManager
import android.widget.TextView
import com.android.internal.statusbar.IUndoMediaTransferCallback
import com.android.systemui.R
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.animation.ViewHierarchyAnimator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.common.ChipInfoCommon
@@ -124,7 +126,6 @@ class MediaTttChipControllerSender @Inject constructor(
currentChipView.requireViewById<View>(R.id.loading).visibility =
chipState.isMidTransfer.visibleIfTrue()
-
// Undo
val undoView = currentChipView.requireViewById<View>(R.id.undo)
val undoClickListener = chipState.undoClickListener(
@@ -138,6 +139,17 @@ class MediaTttChipControllerSender @Inject constructor(
chipState.isTransferFailure.visibleIfTrue()
}
+ override fun animateChipIn(chipView: ViewGroup) {
+ ViewHierarchyAnimator.animateAddition(
+ chipView.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner),
+ ViewHierarchyAnimator.Hotspot.TOP,
+ Interpolators.EMPHASIZED_DECELERATE,
+ duration = 500L,
+ includeMargins = true,
+ includeFadeIn = true,
+ )
+ }
+
override fun removeChip(removalReason: String) {
// Don't remove the chip if we're mid-transfer since the user should still be able to
// see the status of the transfer. (But do remove it if it's finally timed out.)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
index 6a9bb3e343be..b61fbbe1ea75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
@@ -520,6 +520,145 @@ ViewHierarchyAnimatorTest : SysuiTestCase() {
endAnimation(rootView)
}
+ @Test
+ fun animatesAppearingViewsFadeIn_alphaStartsAtZero_endsAtOne() {
+ rootView.alpha = 0f
+ ViewHierarchyAnimator.animateAddition(rootView, includeFadeIn = true)
+ rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */)
+
+ advanceFadeInAnimation(rootView, fraction = 1f)
+ endFadeInAnimation(rootView)
+
+ assertNull(rootView.getTag(R.id.tag_alpha_animator))
+ assertEquals(1f, rootView.alpha)
+ }
+
+ @Test
+ fun animatesAppearingViewsFadeIn_alphaStartsAboveZero_endsAtOne() {
+ rootView.alpha = 0.2f
+ ViewHierarchyAnimator.animateAddition(rootView, includeFadeIn = true)
+ rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */)
+
+ advanceFadeInAnimation(rootView, fraction = 1f)
+ endFadeInAnimation(rootView)
+
+ assertNull(rootView.getTag(R.id.tag_alpha_animator))
+ assertEquals(1f, rootView.alpha)
+ }
+
+ @Test
+ fun animatesAppearingViewsFadeIn_alphaStartsAsZero_alphaUpdatedMidAnimation() {
+ rootView.alpha = 0f
+ ViewHierarchyAnimator.animateAddition(
+ rootView,
+ includeFadeIn = true,
+ fadeInInterpolator = Interpolators.LINEAR
+ )
+ rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */)
+
+ advanceFadeInAnimation(rootView, fraction = 0.42f)
+
+ assertEquals(0.42f, rootView.alpha)
+ }
+
+ @Test
+ fun animatesAppearingViewsFadeIn_alphaStartsAboveZero_alphaUpdatedMidAnimation() {
+ rootView.alpha = 0.6f
+ ViewHierarchyAnimator.animateAddition(
+ rootView,
+ includeFadeIn = true,
+ fadeInInterpolator = Interpolators.LINEAR
+ )
+ rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */)
+
+ advanceFadeInAnimation(rootView, fraction = 0.5f)
+
+ assertEquals(0.8f, rootView.alpha)
+ }
+
+ @Test
+ fun animatesAppearingViewsFadeIn_childViewAlphasAlsoAnimated() {
+ rootView.alpha = 0f
+ val firstChild = View(context)
+ firstChild.alpha = 0f
+ val secondChild = View(context)
+ secondChild.alpha = 0f
+ rootView.addView(firstChild)
+ rootView.addView(secondChild)
+
+ ViewHierarchyAnimator.animateAddition(
+ rootView,
+ includeFadeIn = true,
+ fadeInInterpolator = Interpolators.LINEAR
+ )
+ rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */)
+
+ advanceFadeInAnimation(rootView, fraction = 0.5f)
+
+ assertEquals(0.5f, rootView.alpha)
+ assertEquals(0.5f, firstChild.alpha)
+ assertEquals(0.5f, secondChild.alpha)
+ }
+
+ @Test
+ fun animatesAppearingViewsFadeIn_animatesFromPreviousAnimationProgress() {
+ rootView.alpha = 0f
+ ViewHierarchyAnimator.animateAddition(
+ rootView,
+ includeFadeIn = true,
+ fadeInInterpolator = Interpolators.LINEAR
+ )
+ rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */)
+
+ advanceFadeInAnimation(rootView, fraction = 0.5f)
+ assertEquals(0.5f, rootView.alpha)
+ assertNotNull(rootView.getTag(R.id.tag_alpha_animator))
+
+ // IF we request animation again
+ ViewHierarchyAnimator.animateAddition(
+ rootView,
+ includeFadeIn = true,
+ fadeInInterpolator = Interpolators.LINEAR
+ )
+
+ // THEN the alpha remains at its current value (it doesn't get reset to 0)
+ assertNotNull(rootView.getTag(R.id.tag_alpha_animator))
+ assertEquals(0.5f, rootView.alpha)
+
+ // IF we advance the new animation to the end
+ advanceFadeInAnimation(rootView, fraction = 1f)
+ endFadeInAnimation(rootView)
+
+ // THEN we still end at the correct value
+ assertNull(rootView.getTag(R.id.tag_alpha_animator))
+ assertEquals(1f, rootView.alpha)
+ }
+
+ @Test
+ fun animatesAppearingViews_fadeInFalse_alphasNotUpdated() {
+ rootView.alpha = 0.3f
+ val firstChild = View(context)
+ firstChild.alpha = 0.4f
+ val secondChild = View(context)
+ secondChild.alpha = 0.5f
+ rootView.addView(firstChild)
+ rootView.addView(secondChild)
+
+ ViewHierarchyAnimator.animateAddition(
+ rootView,
+ includeFadeIn = false,
+ fadeInInterpolator = Interpolators.LINEAR
+ )
+ rootView.layout(50 /* l */, 50 /* t */, 100 /* r */, 100 /* b */)
+
+ advanceFadeInAnimation(rootView, fraction = 1f)
+
+ assertEquals(0.3f, rootView.alpha)
+ assertEquals(0.4f, firstChild.alpha)
+ assertEquals(0.5f, secondChild.alpha)
+ }
+
+ @Test
fun animatesViewRemovalFromStartToEnd() {
setUpRootWithChildren()
@@ -1003,6 +1142,16 @@ ViewHierarchyAnimatorTest : SysuiTestCase() {
}
}
+ private fun advanceFadeInAnimation(rootView: View, fraction: Float) {
+ (rootView.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.setCurrentFraction(fraction)
+
+ if (rootView is ViewGroup) {
+ for (i in 0 until rootView.childCount) {
+ advanceFadeInAnimation(rootView.getChildAt(i), fraction)
+ }
+ }
+ }
+
private fun endAnimation(rootView: View) {
(rootView.getTag(R.id.tag_animator) as? ObjectAnimator)?.end()
@@ -1012,4 +1161,14 @@ ViewHierarchyAnimatorTest : SysuiTestCase() {
}
}
}
+
+ private fun endFadeInAnimation(rootView: View) {
+ (rootView.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.end()
+
+ if (rootView is ViewGroup) {
+ for (i in 0 until rootView.childCount) {
+ endFadeInAnimation(rootView.getChildAt(i))
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
index 9a01464fc869..a8c72ddfd5d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
@@ -25,9 +25,9 @@ import android.os.PowerManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
+import android.view.ViewGroup
import android.view.WindowManager
import android.widget.ImageView
-import android.widget.LinearLayout
import android.widget.TextView
import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
@@ -620,22 +620,22 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
verify(windowManager).removeView(any())
}
- private fun LinearLayout.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
+ private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
- private fun LinearLayout.getChipText(): String =
+ private fun ViewGroup.getChipText(): String =
(this.requireViewById<TextView>(R.id.text)).text as String
- private fun LinearLayout.getLoadingIconVisibility(): Int =
+ private fun ViewGroup.getLoadingIconVisibility(): Int =
this.requireViewById<View>(R.id.loading).visibility
- private fun LinearLayout.getUndoButton(): View = this.requireViewById(R.id.undo)
+ private fun ViewGroup.getUndoButton(): View = this.requireViewById(R.id.undo)
- private fun LinearLayout.getFailureIcon(): View = this.requireViewById(R.id.failure_icon)
+ private fun ViewGroup.getFailureIcon(): View = this.requireViewById(R.id.failure_icon)
- private fun getChipView(): LinearLayout {
+ private fun getChipView(): ViewGroup {
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
verify(windowManager).addView(viewCaptor.capture(), any())
- return viewCaptor.value as LinearLayout
+ return viewCaptor.value as ViewGroup
}
/** Helper method providing default parameters to not clutter up the tests. */