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

Commit 2a482374 authored by Fabian Kozynski's avatar Fabian Kozynski Committed by Android (Google) Code Review
Browse files

Merge "Add scrolling to QS" into main

parents b3066dc7 436a2714
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -133,7 +133,14 @@ fun SceneScope.QuickSettingsLayout(
    Column(
        verticalArrangement = Arrangement.spacedBy(QuickSettingsShade.Dimensions.Padding),
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = modifier.fillMaxWidth().padding(QuickSettingsShade.Dimensions.Padding),
        modifier =
            modifier
                .fillMaxWidth()
                .padding(
                    start = QuickSettingsShade.Dimensions.Padding,
                    end = QuickSettingsShade.Dimensions.Padding,
                    top = QuickSettingsShade.Dimensions.Padding,
                ),
    ) {
        BrightnessSliderContainer(
            viewModel = viewModel.brightnessSliderViewModel,
+60 −18
Original line number Diff line number Diff line
@@ -23,7 +23,9 @@ import android.graphics.Rect
import android.os.Bundle
import android.util.IndentingPrintWriter
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.activity.OnBackPressedDispatcher
@@ -35,6 +37,7 @@ import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -43,6 +46,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -83,6 +87,7 @@ import com.android.systemui.Dumpable
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dump.DumpManager
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.setSnapshotBinding
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.dagger.MediaModule.QS_PANEL
@@ -145,6 +150,7 @@ constructor(
    private val qqsVisible = MutableStateFlow(false)
    private val qqsPositionOnRoot = Rect()
    private val composeViewPositionOnScreen = Rect()
    private val scrollState = ScrollState(0)

    // Inside object for namespacing
    private val notificationScrimClippingParams =
@@ -210,6 +216,9 @@ constructor(
                context,
                { notificationScrimClippingParams.isEnabled },
                { notificationScrimClippingParams.params.top },
                // Only allow scrolling when we are fully expanded. That way, we don't intercept
                // swipes in lockscreen (when somehow QS is receiving touches).
                { scrollState.canScrollForward && viewModel.expansionState.value.progress >= 1f },
            )
        frame.addView(
            composeView,
@@ -488,12 +497,8 @@ constructor(
    private fun setListenerCollections() {
        lifecycleScope.launch {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    //                    TODO
                    //                    setListenerJob(
                    //                            scrollListener,
                    //
                    //                    )
                this@QSFragmentCompose.view?.setSnapshotBinding {
                    scrollListener.value?.onQsPanelScrollChanged(scrollState.value)
                }
                launch {
                    setListenerJob(
@@ -528,6 +533,7 @@ constructor(
            viewModel.containerViewModel.quickQuickSettingsViewModel.squishinessViewModel
                .squishiness
                .collectAsStateWithLifecycle()

        Column(modifier = Modifier.sysuiResTag("quick_qs_panel")) {
            Box(
                modifier =
@@ -591,7 +597,12 @@ constructor(
                    modifier =
                        Modifier.element(ElementKeys.QuickSettingsContent).fillMaxSize().weight(1f)
                ) {
                    Column {
                    DisposableEffect(Unit) {
                        lifecycleScope.launch { scrollState.scrollTo(0) }
                        onDispose { lifecycleScope.launch { scrollState.scrollTo(0) } }
                    }

                    Column(modifier = Modifier.verticalScroll(scrollState)) {
                        Spacer(
                            modifier = Modifier.height { qqsPadding + qsExtraPadding.roundToPx() }
                        )
@@ -601,18 +612,17 @@ constructor(
                        )
                    }
                }
            }
            QuickSettingsTheme {
                FooterActions(
                    viewModel = viewModel.footerActionsViewModel,
                    qsVisibilityLifecycleOwner = this@QSFragmentCompose,
                    modifier =
                            Modifier.sysuiResTag("qs_footer_actions")
                                .element(ElementKeys.FooterActions),
                        Modifier.sysuiResTag("qs_footer_actions").element(ElementKeys.FooterActions),
                )
            }
        }
    }
    }

    private fun Modifier.collapseExpandSemanticAction(label: String): Modifier {
        return viewModel.collapseExpandAccessibilityAction?.let {
@@ -791,13 +801,17 @@ private class ExpansionTransition(currentProgress: Float) :
private const val EDIT_MODE_TIME_MILLIS = 500

/**
 * Ignore touches below the value returned by [clippingTopProvider], when clipping is enabled, as
 * Performs different touch handling based on the state of the ComposeView:
 * * Ignore touches below the value returned by [clippingTopProvider], when clipping is enabled, as
 *   per [clippingEnabledProvider].
 * * Intercept touches that would overscroll QS forward and instead allow them to be used to close
 *   the shade.
 */
private class FrameLayoutTouchPassthrough(
    context: Context,
    private val clippingEnabledProvider: () -> Boolean,
    private val clippingTopProvider: () -> Int,
    private val canScrollForwardQs: () -> Boolean,
) : FrameLayout(context) {
    override fun isTransformedTouchPointInView(
        x: Float,
@@ -811,4 +825,32 @@ private class FrameLayoutTouchPassthrough(
            super.isTransformedTouchPointInView(x, y, child, outLocalPoint)
        }
    }

    val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
    var downY = 0f

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        // If there's a touch on this view and we can scroll down, we don't want to be intercepted
        val action = ev.actionMasked

        when (action) {
            MotionEvent.ACTION_DOWN -> {
                // If we can scroll down, make sure none of our parents intercepts us.
                if (canScrollForwardQs()) {
                    parent?.requestDisallowInterceptTouchEvent(true)
                }
                downY = ev.y
            }

            MotionEvent.ACTION_MOVE -> {
                val y = ev.y.toInt()
                val yDiff: Float = y - downY
                if (yDiff < -touchSlop && !canScrollForwardQs()) {
                    // Intercept touches that are overscrolling.
                    return true
                }
            }
        }
        return super.onInterceptTouchEvent(ev)
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.systemui.qs.panels.ui.compose
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
@@ -97,7 +97,9 @@ constructor(
                    TileGrid(tiles = page, modifier = Modifier, editModeStart = {})
                }
            }
            Box(modifier = Modifier.height(FooterHeight).fillMaxWidth()) {
            // Use requiredHeight so it won't be squished if the view doesn't quite fit. As this is
            // expected to be inside a scrollable container, this should not be an issue.
            Box(modifier = Modifier.requiredHeight(FooterHeight).fillMaxWidth()) {
                PagerDots(
                    pagerState = pagerState,
                    activeColor = MaterialTheme.colorScheme.primary,
+1 −2
Original line number Diff line number Diff line
@@ -41,8 +41,7 @@ fun SceneScope.QuickQuickSettings(
    viewModel: QuickQuickSettingsViewModel,
    modifier: Modifier = Modifier,
) {
    val sizedTiles by
        viewModel.tileViewModels.collectAsStateWithLifecycle(initialValue = emptyList())
    val sizedTiles by viewModel.tileViewModels.collectAsStateWithLifecycle()
    val tiles = sizedTiles.fastMap { it.tile }
    val bounceables = remember(sizedTiles) { List(sizedTiles.size) { BounceableTileViewModel() } }
    val squishiness by viewModel.squishinessViewModel.squishiness.collectAsStateWithLifecycle()