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

Commit ad33fb2b authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Implement LaunchableView for footer actions Views.

Bug: 243636422
Test: Manual
Change-Id: I0264b119d60cc70c1d9a23d056343c764242a955
parent 4327ce40
Loading
Loading
Loading
Loading
+27 −8
Original line number Diff line number Diff line
@@ -113,6 +113,19 @@ constructor(
            }
        val animateFrom = animatedParent?.dialogContentWithBackground ?: view

        if (animatedParent == null && animateFrom !is LaunchableView) {
            // Make sure the View we launch from implements LaunchableView to avoid visibility
            // issues. Given that we don't own dialog decorViews so we can't enforce it for launches
            // from a dialog.
            // TODO(b/243636422): Throw instead of logging to enforce this.
            Log.w(
                TAG,
                "A dialog was launched from a View that does not implement LaunchableView. This " +
                    "can lead to subtle bugs where the visibility of the View we are " +
                    "launching from is not what we expected."
            )
        }

        // Make sure we don't run the launch animation from the same view twice at the same time.
        if (animateFrom.getTag(TAG_LAUNCH_ANIMATION_RUNNING) != null) {
            Log.e(TAG, "Not running dialog launch animation as there is already one running")
@@ -156,9 +169,14 @@ constructor(
            openedDialogs.firstOrNull { it.dialog == animateFrom }?.dialogContentWithBackground
                ?: throw IllegalStateException(
                    "The animateFrom dialog was not animated using " +
                        "DialogLaunchAnimator.showFrom(View|Dialog)")
                        "DialogLaunchAnimator.showFrom(View|Dialog)"
                )
        showFromView(
            dialog, view, animateBackgroundBoundsChange = animateBackgroundBoundsChange, cuj = cuj)
            dialog,
            view,
            animateBackgroundBoundsChange = animateBackgroundBoundsChange,
            cuj = cuj
        )
    }

    /**
@@ -556,7 +574,8 @@ private class AnimatedDialog(
        window.setDecorFitsSystemWindows(false)
        val viewWithInsets = (dialogContentWithBackground.parent as ViewGroup)
        viewWithInsets.setOnApplyWindowInsetsListener { view, windowInsets ->
            val type = if (wasFittingNavigationBars) {
            val type =
                if (wasFittingNavigationBars) {
                    WindowInsets.Type.displayCutout() or WindowInsets.Type.navigationBars()
                } else {
                    WindowInsets.Type.displayCutout()
+66 −2
Original line number Diff line number Diff line
@@ -16,15 +16,79 @@

package com.android.systemui.animation

import android.view.View

/** A view that can expand/launch into an app or a dialog. */
interface LaunchableView {
    /**
     * Set whether this view should block/prevent all visibility changes. This ensures that this
     * view remains invisible during the launch animation given that it is ghosted and already drawn
     * Set whether this view should block/postpone all visibility changes. This ensures that this
     * view:
     * - remains invisible during the launch animation given that it is ghosted and already drawn
     * somewhere else.
     * - remains invisible as long as a dialog expanded from it is shown.
     * - restores its expected visibility once the dialog expanded from it is dismissed.
     *
     * Note that when this is set to true, both the [normal][android.view.View.setVisibility] and
     * [transition][android.view.View.setTransitionVisibility] visibility changes must be blocked.
     *
     * @param block whether we should block/postpone all calls to `setVisibility` and
     * `setTransitionVisibility`.
     */
    fun setShouldBlockVisibilityChanges(block: Boolean)
}

/** A delegate that can be used by views to make the implementation of [LaunchableView] easier. */
class LaunchableViewDelegate(
    private val view: View,

    /**
     * The lambda that should set the actual visibility of [view], usually by calling
     * super.setVisibility(visibility).
     */
    private val superSetVisibility: (Int) -> Unit,

    /**
     * The lambda that should set the actual transition visibility of [view], usually by calling
     * super.setTransitionVisibility(visibility).
     */
    private val superSetTransitionVisibility: (Int) -> Unit,
) {
    private var blockVisibilityChanges = false
    private var lastVisibility = view.visibility

    /** Call this when [LaunchableView.setShouldBlockVisibilityChanges] is called. */
    fun setShouldBlockVisibilityChanges(block: Boolean) {
        if (block == blockVisibilityChanges) {
            return
        }

        blockVisibilityChanges = block
        if (block) {
            lastVisibility = view.visibility
        } else {
            superSetVisibility(lastVisibility)
        }
    }

    /** Call this when [View.setVisibility] is called. */
    fun setVisibility(visibility: Int) {
        if (blockVisibilityChanges) {
            lastVisibility = visibility
            return
        }

        superSetVisibility(visibility)
    }

    /** Call this when [View.setTransitionVisibility] is called. */
    fun setTransitionVisibility(visibility: Int) {
        if (blockVisibilityChanges) {
            // View.setTransitionVisibility just sets the visibility flag, so we don't have to save
            // the transition visibility separately from the normal visibility.
            lastVisibility = visibility
            return
        }

        superSetTransitionVisibility(visibility)
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<FrameLayout
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/qs_footer_action_button_size"
    android:layout_height="@dimen/qs_footer_action_button_size"
@@ -36,4 +36,4 @@
        android:layout_gravity="bottom|end"
        android:src="@drawable/fgs_dot"
        android:contentDescription="@string/fgs_dot_content_description" />
</FrameLayout>
 No newline at end of file
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
 No newline at end of file
+2 −2
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<LinearLayout
<com.android.systemui.common.ui.view.LaunchableLinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="0dp"
    android:layout_height="@dimen/qs_security_footer_single_line_height"
@@ -63,4 +63,4 @@
        android:src="@*android:drawable/ic_chevron_end"
        android:autoMirrored="true"
        android:tint="?android:attr/textColorSecondary" />
</LinearLayout>
 No newline at end of file
</com.android.systemui.common.ui.view.LaunchableLinearLayout>
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

package com.android.systemui.common.ui
package com.android.systemui.common.ui.binder

import android.view.View
import com.android.systemui.common.shared.model.ContentDescription
Loading