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

Commit 116b39c4 authored by Anton Potapov's avatar Anton Potapov Committed by Android (Google) Code Review
Browse files

Merge "Rework ANC button click" into main

parents 47529a16 dacc5097
Loading
Loading
Loading
Loading
+34 −25
Original line number Diff line number Diff line
@@ -19,10 +19,13 @@ package com.android.systemui.volume.panel.component.anc.ui.composable
import android.view.Gravity
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -32,15 +35,15 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.LiveRegionMode
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.liveRegion
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -66,13 +69,6 @@ constructor(
            with(LocalDensity.current) { LocalConfiguration.current.screenWidthDp.dp.toPx() }
        var gravity by remember { mutableIntStateOf(Gravity.CENTER_HORIZONTAL) }
        val isClickable = viewModel.isClickable(slice)
        val onClick =
            if (isClickable) {
                { with(ancPopup) { show(null, gravity) } }
            } else {
                null
            }

        Column(
            modifier =
                modifier.onGloballyPositioned {
@@ -80,21 +76,34 @@ constructor(
                },
            verticalArrangement = Arrangement.spacedBy(12.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            Box(
                modifier = Modifier.height(64.dp),
            ) {
                SliceAndroidView(
                modifier =
                    Modifier.height(64.dp)
                        .fillMaxWidth()
                        .semantics {
                            role = Role.Button
                            contentDescription = label
                        }
                        .clip(RoundedCornerShape(28.dp)),
                    modifier = modifier.fillMaxSize(),
                    slice = slice,
                isEnabled = onClick != null,
                    onWidthChanged = viewModel::onButtonSliceWidthChanged,
                onClick = onClick,
                    enableAccessibility = false,
                )
                Button(
                    modifier =
                        modifier.fillMaxSize().padding(8.dp).semantics {
                            liveRegion = LiveRegionMode.Polite
                            contentDescription = label
                        },
                    enabled = isClickable,
                    onClick = { with(ancPopup) { show(null, gravity) } },
                    colors =
                        ButtonColors(
                            contentColor = Color.Transparent,
                            containerColor = Color.Transparent,
                            disabledContentColor = Color.Transparent,
                            disabledContainerColor = Color.Transparent,
                        )
                ) {}
            }

            Text(
                modifier = Modifier.clearAndSetSemantics {}.basicMarquee(),
                text = label,
+41 −27
Original line number Diff line number Diff line
@@ -16,11 +16,12 @@

package com.android.systemui.volume.panel.component.anc.ui.composable

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.ContextThemeWrapper
import android.view.MotionEvent
import android.view.View
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
@@ -32,14 +33,13 @@ import com.android.systemui.res.R
fun SliceAndroidView(
    slice: Slice?,
    modifier: Modifier = Modifier,
    isEnabled: Boolean = true,
    onWidthChanged: ((Int) -> Unit)? = null,
    onClick: (() -> Unit)? = null,
    enableAccessibility: Boolean = true,
) {
    AndroidView(
        modifier = modifier,
        factory = { context: Context ->
            ClickableSliceView(
            ComposeSliceView(
                    ContextThemeWrapper(context, R.style.Widget_SliceView_VolumePanel),
                )
                .apply {
@@ -47,17 +47,18 @@ fun SliceAndroidView(
                    isScrollable = false
                    importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
                    setShowTitleItems(true)
                    if (onWidthChanged != null) {
                        addOnLayoutChangeListener(OnWidthChangedLayoutListener(onWidthChanged))
                    }
                }
        },
        update = { sliceView: ClickableSliceView ->
        update = { sliceView: ComposeSliceView ->
            sliceView.slice = slice
            sliceView.onClick = onClick
            sliceView.isEnabled = isEnabled
            sliceView.isClickable = isEnabled
        }
            sliceView.layoutListener = onWidthChanged?.let(::OnWidthChangedLayoutListener)
            sliceView.enableAccessibility = enableAccessibility
        },
        onRelease = { sliceView: ComposeSliceView ->
            sliceView.layoutListener = null
            sliceView.slice = null
            sliceView.enableAccessibility = true
        },
    )
}

@@ -83,26 +84,39 @@ class OnWidthChangedLayoutListener(private val widthChanged: (Int) -> Unit) :
    }
}

/**
 * [SliceView] that prioritises [onClick] when its clicked instead of passing the event to the slice
 * first.
 */
@SuppressLint("ViewConstructor") // only used in this class
private class ClickableSliceView(context: Context) : SliceView(context) {
private class ComposeSliceView(context: Context) : SliceView(context) {

    var onClick: (() -> Unit)? = null
    var enableAccessibility: Boolean = true
    var layoutListener: OnLayoutChangeListener? = null
        set(value) {
            field?.let { removeOnLayoutChangeListener(it) }
            field = value
            field?.let { addOnLayoutChangeListener(it) }
        }

    init {
        if (onClick != null) {
            setOnClickListener {}
    override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo?) {
        if (enableAccessibility) {
            super.onInitializeAccessibilityNodeInfo(info)
        }
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return (isSliceViewClickable && onClick != null) || super.onInterceptTouchEvent(ev)
    override fun onInitializeAccessibilityEvent(event: AccessibilityEvent?) {
        if (enableAccessibility) {
            super.onInitializeAccessibilityEvent(event)
        }
    }

    override fun onClick(v: View?) {
        onClick?.takeIf { isSliceViewClickable }?.let { it() } ?: super.onClick(v)
    override fun performAccessibilityAction(action: Int, arguments: Bundle?): Boolean {
        return if (enableAccessibility) {
            super.performAccessibilityAction(action, arguments)
        } else {
            false
        }
    }

    override fun addChildrenForAccessibility(outChildren: ArrayList<View>?) {
        if (enableAccessibility) {
            super.addChildrenForAccessibility(outChildren)
        }
    }
}