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

Commit 2dbdc269 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/23814274'] into udc-release.

Change-Id: I7f42fe8e8be5ea97515d428ad3fcba902c0652a5
parents 2220ab49 7d095878
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -19,4 +19,8 @@
    <item type="id" name="option_tile" />
    <item type="id" name="option_tile" />
    <!-- ID for the label of an option tile -->
    <!-- ID for the label of an option tile -->
    <item type="id" name="option_label" />
    <item type="id" name="option_label" />

    <!-- ID for the a11y actions on carousel -->
    <item type="id" name="action_scroll_forward" />
    <item type="id" name="action_scroll_backward" />
</resources>
</resources>
 No newline at end of file
+18 −0
Original line number Original line Diff line number Diff line
@@ -507,4 +507,22 @@
    [CHAR LIMIT=NONE].
    [CHAR LIMIT=NONE].
    -->
    -->
    <string name="content_description_color_option">Color option <xliff:g name="color_number" example="1">%1$d</xliff:g></string>
    <string name="content_description_color_option">Color option <xliff:g name="color_number" example="1">%1$d</xliff:g></string>

    <!--
    Accessibility label for forward scrolling in the carousel of clock faces.
    [CHAR LIMIT=128].
    -->
    <string name="scroll_forward_and_select">Swipe left to choose a different clock face</string>

    <!--
    Accessibility label for backward scrolling in the carousel of clock faces.
    [CHAR LIMIT=128].
    -->
    <string name="scroll_backward_and_select">Swipe right to choose a different clock face</string>

    <!--
    Accessibility label for the carousel of clock faces.
    [CHAR LIMIT=128].
    -->
    <string name="custom_clocks_label">Custom Clocks</string>
</resources>
</resources>
+71 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.android.customization.picker.clock.ui.binder

import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.accessibility.AccessibilityNodeInfo
import com.android.wallpaper.R

class CarouselAccessibilityDelegate(
    private val context: Context,
    private val scrollForwardCallback: () -> Unit,
    private val scrollBackwardCallback: () -> Unit
) : View.AccessibilityDelegate() {

    var contentDescriptionOfSelectedClock = ""

    private val ACTION_SCROLL_BACKWARD = R.id.action_scroll_backward
    private val ACTION_SCROLL_FORWARD = R.id.action_scroll_forward

    override fun onInitializeAccessibilityNodeInfo(host: View?, info: AccessibilityNodeInfo?) {
        super.onInitializeAccessibilityNodeInfo(host, info)
        info?.isScrollable = true
        info?.addAction(
            AccessibilityNodeInfo.AccessibilityAction(
                ACTION_SCROLL_FORWARD,
                context.getString(R.string.scroll_forward_and_select)
            )
        )
        info?.addAction(
            AccessibilityNodeInfo.AccessibilityAction(
                ACTION_SCROLL_BACKWARD,
                context.getString(R.string.scroll_backward_and_select)
            )
        )
        info?.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS)
        // We need to specifically set the content description since for some reason the talkback
        // service does not go to children of the clock carousel in the view hierarchy
        info?.contentDescription = contentDescriptionOfSelectedClock
    }

    override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean {
        when (action) {
            ACTION_SCROLL_BACKWARD -> {
                scrollBackwardCallback.invoke()
                return true
            }
            ACTION_SCROLL_FORWARD -> {
                scrollForwardCallback.invoke()
                return true
            }
        }
        return super.performAccessibilityAction(host, action, args)
    }
}
+20 −0
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
 */
 */
package com.android.customization.picker.clock.ui.binder
package com.android.customization.picker.clock.ui.binder


import android.content.Context
import android.view.ViewGroup
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.FrameLayout
import androidx.core.view.isVisible
import androidx.core.view.isVisible
@@ -27,6 +28,7 @@ import com.android.customization.picker.clock.ui.view.ClockCarouselView
import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.wallpaper.R
import com.android.wallpaper.R
import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewClickView
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import kotlinx.coroutines.launch


@@ -34,8 +36,10 @@ object ClockCarouselViewBinder {


    @JvmStatic
    @JvmStatic
    fun bind(
    fun bind(
        context: Context,
        carouselView: ClockCarouselView,
        carouselView: ClockCarouselView,
        singleClockView: ViewGroup,
        singleClockView: ViewGroup,
        screenPreviewClickView: ScreenPreviewClickView,
        viewModel: ClockCarouselViewModel,
        viewModel: ClockCarouselViewModel,
        clockViewFactory: ClockViewFactory,
        clockViewFactory: ClockViewFactory,
        lifecycleOwner: LifecycleOwner,
        lifecycleOwner: LifecycleOwner,
@@ -43,6 +47,20 @@ object ClockCarouselViewBinder {
    ) {
    ) {
        carouselView.setClockViewFactory(clockViewFactory)
        carouselView.setClockViewFactory(clockViewFactory)
        clockViewFactory.updateRegionDarkness()
        clockViewFactory.updateRegionDarkness()
        val carouselAccessibilityDelegate =
            CarouselAccessibilityDelegate(
                context,
                scrollForwardCallback = {
                    // Callback code for scrolling forward
                    carouselView.transitionToNext()
                },
                scrollBackwardCallback = {
                    // Callback code for scrolling backward
                    carouselView.transitionToPrevious()
                }
            )
        screenPreviewClickView.accessibilityDelegate = carouselAccessibilityDelegate

        val singleClockHostView =
        val singleClockHostView =
            singleClockView.requireViewById<FrameLayout>(R.id.single_clock_host_view)
            singleClockView.requireViewById<FrameLayout>(R.id.single_clock_host_view)
        lifecycleOwner.lifecycleScope.launch {
        lifecycleOwner.lifecycleScope.launch {
@@ -71,6 +89,8 @@ object ClockCarouselViewBinder {


                launch {
                launch {
                    viewModel.selectedIndex.collect { selectedIndex ->
                    viewModel.selectedIndex.collect { selectedIndex ->
                        carouselAccessibilityDelegate.contentDescriptionOfSelectedClock =
                            carouselView.getContentDescription(selectedIndex)
                        carouselView.setSelectedClockIndex(selectedIndex)
                        carouselView.setSelectedClockIndex(selectedIndex)
                    }
                    }
                }
                }
+25 −1
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.customization.picker.clock.ui.view
package com.android.customization.picker.clock.ui.view


import android.content.Context
import android.content.Context
import android.content.res.Resources
import android.util.AttributeSet
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.LayoutInflater
import android.view.View
import android.view.View
@@ -60,6 +61,7 @@ class ClockCarouselView(
        val clockCarousel = LayoutInflater.from(context).inflate(R.layout.clock_carousel, this)
        val clockCarousel = LayoutInflater.from(context).inflate(R.layout.clock_carousel, this)
        carousel = clockCarousel.requireViewById(R.id.carousel)
        carousel = clockCarousel.requireViewById(R.id.carousel)
        motionLayout = clockCarousel.requireViewById(R.id.motion_container)
        motionLayout = clockCarousel.requireViewById(R.id.motion_container)
        motionLayout.contentDescription = context.getString(R.string.custom_clocks_label)
    }
    }


    /**
    /**
@@ -69,6 +71,24 @@ class ClockCarouselView(
        clockViewFactory = factory
        clockViewFactory = factory
    }
    }


    fun transitionToNext() {
        val index = (carousel.currentIndex + 1) % carousel.count
        if (index < carousel.count && index > 0) {
            carousel.transitionToIndex(index, 0)
        }
    }

    fun transitionToPrevious() {
        val index = (carousel.currentIndex - 1) % carousel.count
        if (index < carousel.count && index > 0) {
            carousel.transitionToIndex(index, 0)
        }
    }

    fun getContentDescription(index: Int): String {
        return adapter.getContentDescription(index, resources)
    }

    fun setUpClockCarouselView(
    fun setUpClockCarouselView(
        clockSize: ClockSize,
        clockSize: ClockSize,
        clocks: List<ClockCarouselItemViewModel>,
        clocks: List<ClockCarouselItemViewModel>,
@@ -304,6 +324,10 @@ class ClockCarouselView(
        private val onClockSelected: (clock: ClockCarouselItemViewModel) -> Unit
        private val onClockSelected: (clock: ClockCarouselItemViewModel) -> Unit
    ) : Carousel.Adapter {
    ) : Carousel.Adapter {


        fun getContentDescription(index: Int, resources: Resources): String {
            return clocks[index].getContentDescription(resources)
        }

        override fun count(): Int {
        override fun count(): Int {
            return clocks.size
            return clocks.size
        }
        }
@@ -336,7 +360,7 @@ class ClockCarouselView(
            val isMiddleView = isMiddleView(viewRoot.id)
            val isMiddleView = isMiddleView(viewRoot.id)


            // Accessibility
            // Accessibility
            viewRoot.contentDescription = clocks[index].getContentDescription(view.resources)
            viewRoot.contentDescription = getContentDescription(index, view.resources)
            viewRoot.isSelected = isMiddleView
            viewRoot.isSelected = isMiddleView


            when (clockSize) {
            when (clockSize) {
Loading