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

Commit 06020c29 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Focus on the right pane when choosing an app on left" into main

parents 1812030b a34a264a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.launcher3.widget.picker;

import static android.animation.ValueAnimator.areAnimatorsEnabled;

import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_LIST;

import androidx.recyclerview.widget.DefaultItemAnimator;
@@ -26,6 +28,14 @@ public class WidgetsListItemAnimator extends DefaultItemAnimator {
    public static final int MOVE_DURATION_MS = 90;
    public static final int ADD_DURATION_MS = 120;

    // DefaultItemAnimator runs change and move animations before running add animations (i.e.
    // before expanded list item's content start animating to become visible on screen).
    public static final int WIDGET_LIST_ITEM_APPEARANCE_START_DELAY =
            areAnimatorsEnabled() ? (CHANGE_DURATION_MS + MOVE_DURATION_MS) : 0;
    // Delay after which all item animations are ran and list item's content is visible.
    public static final int WIDGET_LIST_ITEM_APPEARANCE_DELAY =
            WIDGET_LIST_ITEM_APPEARANCE_START_DELAY + ADD_DURATION_MS;

    public WidgetsListItemAnimator() {
        super();

+2 −6
Original line number Diff line number Diff line
@@ -15,10 +15,7 @@
 */
package com.android.launcher3.widget.picker;

import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.CHANGE_DURATION_MS;
import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.MOVE_DURATION_MS;

import static android.animation.ValueAnimator.areAnimatorsEnabled;
import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.WIDGET_LIST_ITEM_APPEARANCE_START_DELAY;

import android.content.Context;
import android.graphics.Bitmap;
@@ -157,8 +154,7 @@ public final class WidgetsListTableViewHolderBinder
            // Pass resize delay to let the "move" and "change" animations run before resizing the
            // row.
            tableRow.setupRow(widgetItems.size(),
                    /*resizeDelayMs=*/
                    areAnimatorsEnabled() ? (CHANGE_DURATION_MS + MOVE_DURATION_MS) : 0);
                    /*resizeDelayMs=*/ WIDGET_LIST_ITEM_APPEARANCE_START_DELAY);
            if (tableRow.getChildCount() > widgetItems.size()) {
                for (int j = widgetItems.size(); j < tableRow.getChildCount(); j++) {
                    tableRow.getChildAt(j).setVisibility(View.GONE);
+43 −12
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.launcher3.UtilitiesKt.CLIP_CHILDREN_FALSE_MODIFIER;
import static com.android.launcher3.UtilitiesKt.CLIP_TO_PADDING_FALSE_MODIFIER;
import static com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree;
import static com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree;
import static com.android.launcher3.widget.picker.WidgetsListItemAnimator.WIDGET_LIST_ITEM_APPEARANCE_DELAY;

import android.content.Context;
import android.graphics.Rect;
@@ -31,6 +32,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;
@@ -281,10 +283,19 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
            mRightPane.removeAllViews();
            mRightPane.addView(mWidgetRecommendationsContainer);
            mRightPaneScrollView.setScrollY(0);
            mRightPane.setAccessibilityPaneTitle(suggestionsRightPaneTitle);
            mSuggestedWidgetsPackageUserKey = PackageUserKey.fromPackageItemInfo(packageItemInfo);
            final boolean isChangingHeaders = mSelectedHeader == null
                    || !mSelectedHeader.equals(mSuggestedWidgetsPackageUserKey);
            // If the initial focus view is still focused, it is likely a programmatic header
            // click.
            if (mSelectedHeader != null
                    && !getAccessibilityInitialFocusView().isAccessibilityFocused()) {
                post(() -> {
                    mRightPaneScrollView.setAccessibilityPaneTitle(suggestionsRightPaneTitle);
                    mRightPaneScrollView.performAccessibilityAction(
                            AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
                });
            }
            if (isChangingHeaders)  {
                // If switching from another header, unselect any WidgetCells. This is necessary
                // because we do not clear/recycle the WidgetCells in the recommendations container
@@ -296,7 +307,6 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
            mSelectedHeader = mSuggestedWidgetsPackageUserKey;
        });
        mSuggestedWidgetsContainer.addView(mSuggestedWidgetsHeader);
        mRightPane.setAccessibilityPaneTitle(suggestionsRightPaneTitle);
    }

    @Override
@@ -323,12 +333,14 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {

        mActivePage = currentActivePage;

        if (mSuggestedWidgetsHeader == null) {
        // When using talkback, swiping left while on right pane, should navigate to the widgets
        // list on left.
        mAdapters.get(mActivePage).mWidgetsRecyclerView.setAccessibilityTraversalBefore(
                mRightPaneScrollView.getId());

        // On page change, select the first item in the list to show in the right pane.
        mAdapters.get(currentActivePage).mWidgetsListAdapter.selectFirstHeaderEntry();
        mAdapters.get(currentActivePage).mWidgetsRecyclerView.scrollToTop();
        } else if (currentActivePage == PERSONAL_TAB || currentActivePage == WORK_TAB) {
            mSuggestedWidgetsHeader.callOnClick();
        }
    }

    @Override
@@ -383,6 +395,10 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
            public void onHeaderChanged(@NonNull PackageUserKey selectedHeader) {
                final boolean isSameHeader = mSelectedHeader != null
                        && mSelectedHeader.equals(selectedHeader);
                // If the initial focus view is still focused, it is likely a programmatic header
                // click.
                final boolean isUserClick = mSelectedHeader != null
                        && !getAccessibilityInitialFocusView().isAccessibilityFocused();
                mSelectedHeader = selectedHeader;
                WidgetsListContentEntry contentEntry = mActivityContext.getPopupDataProvider()
                        .getSelectedAppWidgets(selectedHeader);
@@ -427,11 +443,14 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
                };
                mRightPane.removeAllViews();
                mRightPane.addView(widgetsRowViewHolder.itemView);
                mRightPaneScrollView.setScrollY(0);
                mRightPane.setAccessibilityPaneTitle(
                        getContext().getString(
                if (isUserClick) {
                    mRightPaneScrollView.setAccessibilityPaneTitle(getContext().getString(
                            R.string.widget_picker_right_pane_accessibility_title,
                            contentEntry.mPkgItem.title));
                    postDelayed(() -> focusOnFirstWidgetCell(widgetsRowViewHolder.tableContainer),
                            WIDGET_LIST_ITEM_APPEARANCE_DELAY);
                }
                mRightPaneScrollView.setScrollY(0);
            }
        };
    }
@@ -445,6 +464,18 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet {
        }
    }

    /**
     * Requests focus on the first widget cell in the given widget section.
     */
    private static void focusOnFirstWidgetCell(ViewGroup parent) {
        if (parent == null) return;
        WidgetCell cell = Utilities.findViewByPredicate(parent, v -> v instanceof WidgetCell);
        if (cell != null) {
            cell.performAccessibilityAction(
                    AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
        }
    }

    private static void unselectWidgetCell(ViewGroup parent, WidgetItem item) {
        if (parent == null || item == null) return;
        WidgetCell cell = Utilities.findViewByPredicate(parent, v -> v instanceof WidgetCell wc