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

Commit 55fded37 authored by Shamali P's avatar Shamali P Committed by Shamali Patwa
Browse files

Remove the "expand/collapse" actions on the apps list in 2 pane picker.

In a single pane picker, apps list is expandable / collapsable, but,
its not applicable for 2-pane variant. in 2-pane one, it should just
say "double tap to activate".

Also opened b/324073588 to make it clear from a11y perspective that it
is two pane and on click, right pane change should be announced.
(just like it does in settings with talkback).

see screencast/cast/NTQ1Mjk0MjIzOTg1ODY4OHw4OTc5ZjAzNS0wOQ

Bug: 319195592
Flag: None
Test: WidgetsListHeaderAccessibilityTest & manual.
Change-Id: I9ae3fbacc29364bd7459f6e6d85e0a1e919de3f8
parent 6474a3b4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
    android:importantForAccessibility="yes"
    android:focusable="true"
    launcher:appIconSize="48dp"
    launcher:collapsable="false"
    android:descendantFocusability="afterDescendants"
    android:background="@drawable/bg_widgets_header_two_pane" >

+1 −0
Original line number Diff line number Diff line
@@ -582,6 +582,7 @@

    <declare-styleable name="WidgetsListRowHeader">
        <attr name="appIconSize" format="dimension" />
        <attr name="collapsable" format="boolean" />
    </declare-styleable>

    <attr name="materialColorOnSecondaryFixedVariant" format="color" />
+33 −24
Original line number Diff line number Diff line
@@ -52,7 +52,11 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
    private static final int[] EXPANDED_DRAWABLE_STATE = new int[] {android.R.attr.state_expanded};

    private final int mIconSize;

    /**
     * Indicates if the header is collapsable. For example, when displayed in a two pane layout,
     * widget apps aren't collapsable.
    */
    private final boolean mIsCollapsable;
    @Nullable private HandlerRunnable mIconLoadRequest;
    @Nullable private Drawable mIconDrawable;
    @Nullable private WidgetsListDrawableState mListDrawableState;
@@ -79,6 +83,7 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
                R.styleable.WidgetsListRowHeader, defStyleAttr, /* defStyleRes= */ 0);
        mIconSize = a.getDimensionPixelSize(R.styleable.WidgetsListRowHeader_appIconSize,
                grid.iconSizePx);
        mIsCollapsable = a.getBoolean(R.styleable.WidgetsListRowHeader_collapsable, true);
    }

    @Override
@@ -87,10 +92,13 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
        mAppIcon = findViewById(R.id.app_icon);
        mTitle = findViewById(R.id.app_title);
        mSubtitle = findViewById(R.id.app_subtitle);
        // Lists that cannot collapse, don't need EXPAND or COLLAPSE accessibility actions.
        if (mIsCollapsable) {
            setAccessibilityDelegate(new AccessibilityDelegate() {

                @Override
            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
                public void onInitializeAccessibilityNodeInfo(View host,
                        AccessibilityNodeInfo info) {
                    if (mIsExpanded) {
                        info.removeAction(AccessibilityNodeInfo.ACTION_EXPAND);
                        info.addAction(AccessibilityNodeInfo.ACTION_COLLAPSE);
@@ -114,6 +122,7 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
                }
            });
        }
    }

    /** Sets the expand toggle to expand / collapse. */
    @UiThread
+87 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.launcher3.widget.picker;

import static androidx.test.core.app.ApplicationProvider.getApplicationContext;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.launcher3.R;
import com.android.launcher3.util.ActivityContextWrapper;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class WidgetsListHeaderAccessibilityTest {
    private Context mContext;
    private LayoutInflater mLayoutInflater;
    @Mock
    private View.OnClickListener mOnClickListener;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        mContext = new ActivityContextWrapper(getApplicationContext());
        mLayoutInflater = LayoutInflater.from(
                new ContextThemeWrapper(mContext, R.style.WidgetContainerTheme));
    }

    @Test
    public void singlePaneCollapsable_hasCustomAccessibilityActions() {
        WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
                R.layout.widgets_list_row_header,
                new FrameLayout(mContext), false);

        assertThat(header.getAccessibilityDelegate()).isNotNull();

        header.setOnClickListener(mOnClickListener);
        header.getAccessibilityDelegate().performAccessibilityAction(header,
                AccessibilityNodeInfo.ACTION_EXPAND, null);
        header.getAccessibilityDelegate().performAccessibilityAction(header,
                AccessibilityNodeInfo.ACTION_COLLAPSE, null);

        verify(mOnClickListener, times(2)).onClick(header);
    }

    @Test
    public void twoPaneNonCollapsable_noCustomAccessibilityDelegate() {
        WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
                R.layout.widgets_list_row_header_two_pane,
                new FrameLayout(mContext), false);

        assertThat(header.getAccessibilityDelegate()).isNull();
    }
}