Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f455f723 authored by Mykola Podolian's avatar Mykola Podolian Committed by Android (Google) Code Review
Browse files

Merge "Added method to perform actions on all drop targets removed." into main

parents 2c3b168c ed5b55a4
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ class DropTargetManager(
    private var morphRect: RectF = RectF(0f, 0f, 0f, 0f)
    private val isLayoutRtl = container.isLayoutRtl
    private val viewAnimatorsMap = mutableMapOf<View, ValueAnimator>()
    private var onDropTargetsRemovedAction: Runnable? = null

    private companion object {
        const val MORPH_ANIM_DURATION = 250L
@@ -111,15 +112,29 @@ class DropTargetManager(
    /** Called when the drag ended. */
    fun onDragEnded() {
        val dropState = state ?: return
        startFadeAnimation(dropTargetView, to = 0f) { container.removeView(dropTargetView) }
        startFadeAnimation(dropTargetView, to = 0f) {
            container.removeView(dropTargetView)
            onDropTargetRemoved()
        }
        startFadeAnimation(secondDropTargetView, to = 0f) {
            container.removeView(secondDropTargetView)
            secondDropTargetView = null
            onDropTargetRemoved()
        }
        dragZoneChangedListener.onDragEnded(dropState.currentDragZone)
        state = null
    }

    /**
     * Runs the provided action once all drop target views are removed from the container.
     * If there are no drop target views currently present or being animated, the action will be
     * executed immediately.
     */
    fun onDropTargetRemoved(action: Runnable) {
        onDropTargetsRemovedAction = action
        onDropTargetRemoved()
    }

    private fun updateDropTarget() {
        val dropState = state ?: return
        val currentDragZone = dropState.currentDragZone
@@ -191,6 +206,15 @@ class DropTargetManager(
        animator.start()
    }

    private fun onDropTargetRemoved() {
        val action = onDropTargetsRemovedAction ?: return
        if ((0 until container.childCount).any { container.getChildAt(it) is DropTargetView }) {
            return
        }
        onDropTargetsRemovedAction = null
        action.run()
    }

    /** Stores the current drag state. */
    private inner class DragState(
        private val dragZones: List<DragZone>,
+46 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.shared.bubbles

import android.content.Context
import android.graphics.Rect
import android.view.View
import android.widget.FrameLayout
import androidx.core.animation.AnimatorTestRule
import androidx.test.core.app.ApplicationProvider.getApplicationContext
@@ -469,6 +470,51 @@ class DropTargetManagerTest {
        )
    }

    @Test
    fun runOnDropTargetsRemoved_dropTargetViewsAdded_notExecutedUntilAllViewsRemoved() {
        var runnableExecuted = false
        val action = Runnable { runnableExecuted = true }
        dropTargetManager.onDragStarted(
            DraggedObject.LauncherIcon(bubbleBarHasBubbles = false) {},
            listOf(bubbleLeftDragZoneWithSecondDropTarget, bubbleRightDragZoneWithSecondDropTarget)
        )
        assertThat(container.childCount).isEqualTo(DROP_VIEWS_COUNT_FOR_LAUNCHER_ICON)
        dropTargetManager.onDropTargetRemoved(action)
        assertThat(runnableExecuted).isFalse()

        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            dropTargetManager.onDragEnded()
        }
        assertThat(container.childCount).isEqualTo(DROP_VIEWS_COUNT_FOR_LAUNCHER_ICON)
        assertThat(runnableExecuted).isFalse()

        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            animatorTestRule.advanceTimeBy(200)
        }

        assertThat(container.childCount).isEqualTo(0)
        assertThat(runnableExecuted).isTrue()
    }

    @Test
    fun onDropTargetsRemoved_dropTargetViewsAbsent_actionExecuted() {
        var runnableExecuted = false
        val action = Runnable { runnableExecuted = true }
        assertThat(container.childCount).isEqualTo(0)
        dropTargetManager.onDropTargetRemoved(action)
        assertThat(runnableExecuted).isTrue()
    }

    @Test
    fun onDropTargetsRemoved_NonDropTargetViewPresent_actionExecuted() {
        var runnableExecuted = false
        val action = Runnable { runnableExecuted = true }
        container.addView(View(context))
        assertThat(container.childCount).isEqualTo(1)
        dropTargetManager.onDropTargetRemoved(action)
        assertThat(runnableExecuted).isTrue()
    }

    private fun verifyDropTargetPosition(rect: Rect) {
        verifyDropTargetPosition(dropTargetView, rect)
    }