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

Commit ccb970ba authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android (Google) Code Review
Browse files

Merge changes from topic "notif_redesign_action_spacing" into main

* changes:
  [Notif redesign] Update spacing of smart replies & actions
  Rename "big" to "contentView"
parents c6761560 6cf6be36
Loading
Loading
Loading
Loading
+109 −64
Original line number Diff line number Diff line
@@ -6453,45 +6453,47 @@ public class Notification implements Parcelable
            return mN.showsTime() || mN.showsChronometer();
        }
        private void resetStandardTemplateWithActions(RemoteViews big) {
        private void resetStandardTemplateWithActions(RemoteViews contentView) {
            // actions_container is only reset when there are no actions to avoid focus issues with
            // remote inputs.
            big.setViewVisibility(R.id.actions, View.GONE);
            big.removeAllViews(R.id.actions);
            big.setViewVisibility(R.id.notification_material_reply_container, View.GONE);
            big.setTextViewText(R.id.notification_material_reply_text_1, null);
            big.setViewVisibility(R.id.notification_material_reply_text_1_container, View.GONE);
            big.setViewVisibility(R.id.notification_material_reply_progress, View.GONE);
            big.setViewVisibility(R.id.notification_material_reply_text_2, View.GONE);
            big.setTextViewText(R.id.notification_material_reply_text_2, null);
            big.setViewVisibility(R.id.notification_material_reply_text_3, View.GONE);
            big.setTextViewText(R.id.notification_material_reply_text_3, null);
            // This may get erased by bindSnoozeAction
            big.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
            contentView.setViewVisibility(R.id.actions, View.GONE);
            contentView.removeAllViews(R.id.actions);
            contentView.setViewVisibility(R.id.notification_material_reply_container, View.GONE);
            contentView.setTextViewText(R.id.notification_material_reply_text_1, null);
            contentView.setViewVisibility(R.id.notification_material_reply_text_1_container,
                    View.GONE);
            contentView.setViewVisibility(R.id.notification_material_reply_progress, View.GONE);
            contentView.setViewVisibility(R.id.notification_material_reply_text_2, View.GONE);
            contentView.setTextViewText(R.id.notification_material_reply_text_2, null);
            contentView.setViewVisibility(R.id.notification_material_reply_text_3, View.GONE);
            contentView.setTextViewText(R.id.notification_material_reply_text_3, null);
            // This may get erased by bindSnoozeAction, or if we're showing the bubble icon
            contentView.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
                    RemoteViews.MARGIN_BOTTOM, R.dimen.notification_content_margin);
        }
        private void bindSnoozeAction(RemoteViews big, StandardTemplateParams p) {
        private boolean bindSnoozeAction(RemoteViews contentView, StandardTemplateParams p) {
            boolean hideSnoozeButton = mN.isFgsOrUij()
                    || mN.fullScreenIntent != null
                    || isBackgroundColorized(p)
                    || p.mViewType != StandardTemplateParams.VIEW_TYPE_EXPANDED;
            big.setBoolean(R.id.snooze_button, "setEnabled", !hideSnoozeButton);
            contentView.setBoolean(R.id.snooze_button, "setEnabled", !hideSnoozeButton);
            if (hideSnoozeButton) {
                // Only hide; NotificationContentView will show it when it adds the click listener
                big.setViewVisibility(R.id.snooze_button, View.GONE);
                contentView.setViewVisibility(R.id.snooze_button, View.GONE);
            }
            final boolean snoozeEnabled = !hideSnoozeButton
                    && mContext.getContentResolver() != null
                    && isSnoozeSettingEnabled();
            if (snoozeEnabled) {
                big.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
                contentView.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
                        RemoteViews.MARGIN_BOTTOM, 0);
            }
            return snoozeEnabled;
        }
        private boolean isSnoozeSettingEnabled() {
@@ -6526,16 +6528,14 @@ public class Notification implements Parcelable
        private RemoteViews applyStandardTemplateWithActions(int layoutId,
                StandardTemplateParams p, TemplateBindResult result) {
            RemoteViews big = applyStandardTemplate(layoutId, p, result);
            RemoteViews contentView = applyStandardTemplate(layoutId, p, result);
            resetStandardTemplateWithActions(big);
            bindSnoozeAction(big, p);
            resetStandardTemplateWithActions(contentView);
            boolean snoozeEnabled = bindSnoozeAction(contentView, p);
            // color the snooze and bubble actions with the theme color
            ColorStateList actionColor = ColorStateList.valueOf(getStandardActionColor(p));
            big.setColorStateList(R.id.snooze_button, "setImageTintList", actionColor);
            big.setColorStateList(R.id.bubble_button, "setImageTintList", actionColor);
            boolean validRemoteInput = false;
            contentView.setColorStateList(R.id.snooze_button, "setImageTintList", actionColor);
            contentView.setColorStateList(R.id.bubble_button, "setImageTintList", actionColor);
            // In the UI, contextual actions appear separately from the standard actions, so we
            // filter them out here.
@@ -6549,47 +6549,64 @@ public class Notification implements Parcelable
            if (p.mCallStyleActions) {
                // Clear view padding to allow buttons to start on the left edge.
                // This must be done before 'setEmphasizedMode' which sets top/bottom margins.
                big.setViewPadding(R.id.actions, 0, 0, 0, 0);
                contentView.setViewPadding(R.id.actions, 0, 0, 0, 0);
                if (!Flags.notificationsRedesignTemplates()) {
                    // Add an optional indent that will make buttons start at the correct column
                    // when there is enough space to do so (and fall back to the left edge if not).
                    // This is handled directly in NotificationActionListLayout in the new design.
                    big.setInt(R.id.actions, "setCollapsibleIndentDimen",
                    contentView.setInt(R.id.actions, "setCollapsibleIndentDimen",
                            R.dimen.call_notification_collapsible_indent);
                }
                if (evenlyDividedCallStyleActionLayout()) {
                    if (CallStyle.DEBUG_NEW_ACTION_LAYOUT) {
                        Log.d(TAG, "setting evenly divided mode on action list");
                    }
                    big.setBoolean(R.id.actions, "setEvenlyDividedMode", true);
                    contentView.setBoolean(R.id.actions, "setEvenlyDividedMode", true);
                }
            }
            if (!notificationsRedesignTemplates()) {
                contentView.setBoolean(R.id.actions, "setEmphasizedMode", emphasizedMode);
            }
            big.setBoolean(R.id.actions, "setEmphasizedMode", emphasizedMode);
            boolean validRemoteInput = false;
            if (numActions > 0 && !p.mHideActions) {
                big.setViewVisibility(R.id.actions_container, View.VISIBLE);
                big.setViewVisibility(R.id.actions, View.VISIBLE);
                big.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
                contentView.setViewVisibility(R.id.actions_container, View.VISIBLE);
                contentView.setViewVisibility(R.id.actions, View.VISIBLE);
                contentView.setViewLayoutMarginDimen(R.id.notification_action_list_margin_target,
                        RemoteViews.MARGIN_BOTTOM, 0);
                for (int i = 0; i < numActions; i++) {
                    Action action = nonContextualActions.get(i);
                    boolean actionHasValidInput = hasValidRemoteInput(action);
                    validRemoteInput |= actionHasValidInput;
                    final RemoteViews button = generateActionButton(action, emphasizedMode, p);
                    if (actionHasValidInput && !emphasizedMode) {
                        // Clear the drawable
                        button.setInt(R.id.action0, "setBackgroundResource", 0);
                    }
                    if (emphasizedMode && i > 0) {
                        // Clear start margin from non-first buttons to reduce the gap between them.
                        //  (8dp remaining gap is from all buttons' standard 4dp inset).
                        button.setViewLayoutMarginDimen(R.id.action0, RemoteViews.MARGIN_START, 0);
                if (notificationsRedesignTemplates()) {
                    // No need for additional space under smart replies/smart actions.
                    contentView.setViewLayoutMarginDimen(R.id.smart_reply_container,
                            RemoteViews.MARGIN_BOTTOM, 0);
                    if (emphasizedMode) {
                        // Emphasized actions look similar to smart replies, so let's use the same
                        // margins.
                        contentView.setViewLayoutMarginDimen(R.id.actions_container,
                                RemoteViews.MARGIN_TOP,
                                R.dimen.notification_2025_smart_reply_container_margin);
                        contentView.setViewLayoutMarginDimen(R.id.actions_container,
                                RemoteViews.MARGIN_BOTTOM,
                                R.dimen.notification_2025_smart_reply_container_margin);
                    } else {
                        contentView.setViewLayoutMarginDimen(R.id.actions_container,
                                RemoteViews.MARGIN_TOP, 0);
                        contentView.setViewLayoutMarginDimen(R.id.actions_container,
                                RemoteViews.MARGIN_BOTTOM,
                                R.dimen.notification_2025_action_list_margin_bottom);
                    }
                    big.addView(R.id.actions, button);
                }
                validRemoteInput = populateActionsContainer(contentView, p, nonContextualActions,
                        numActions, emphasizedMode);
            } else {
                big.setViewVisibility(R.id.actions_container, View.GONE);
                contentView.setViewVisibility(R.id.actions_container, View.GONE);
                if (notificationsRedesignTemplates() && !snoozeEnabled) {
                    // Make sure smart replies & smart actions have enough space at the bottom
                    // (if present) when there are no actions. This should be set to 0 if we're
                    // showing the snooze or bubble buttons.
                    contentView.setViewLayoutMarginDimen(R.id.smart_reply_container,
                            RemoteViews.MARGIN_BOTTOM,
                            R.dimen.notification_2025_smart_reply_container_margin);
                }
            }
            RemoteInputHistoryItem[] replyText = getParcelableArrayFromBundle(
@@ -6598,37 +6615,65 @@ public class Notification implements Parcelable
                    && !TextUtils.isEmpty(replyText[0].getText())
                    && p.maxRemoteInputHistory > 0) {
                boolean showSpinner = mN.extras.getBoolean(EXTRA_SHOW_REMOTE_INPUT_SPINNER);
                big.setViewVisibility(R.id.notification_material_reply_container, View.VISIBLE);
                big.setViewVisibility(R.id.notification_material_reply_text_1_container,
                contentView.setViewVisibility(R.id.notification_material_reply_container,
                        View.VISIBLE);
                contentView.setViewVisibility(R.id.notification_material_reply_text_1_container,
                        View.VISIBLE);
                big.setTextViewText(R.id.notification_material_reply_text_1,
                contentView.setTextViewText(R.id.notification_material_reply_text_1,
                        ensureColorSpanContrastOrStripStyling(replyText[0].getText(), p));
                setTextViewColorSecondary(big, R.id.notification_material_reply_text_1, p);
                big.setViewVisibility(R.id.notification_material_reply_progress,
                setTextViewColorSecondary(contentView, R.id.notification_material_reply_text_1, p);
                contentView.setViewVisibility(R.id.notification_material_reply_progress,
                        showSpinner ? View.VISIBLE : View.GONE);
                big.setProgressIndeterminateTintList(
                contentView.setProgressIndeterminateTintList(
                        R.id.notification_material_reply_progress,
                        ColorStateList.valueOf(getPrimaryAccentColor(p)));
                if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1].getText())
                        && p.maxRemoteInputHistory > 1) {
                    big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE);
                    big.setTextViewText(R.id.notification_material_reply_text_2,
                    contentView.setViewVisibility(R.id.notification_material_reply_text_2,
                            View.VISIBLE);
                    contentView.setTextViewText(R.id.notification_material_reply_text_2,
                            ensureColorSpanContrastOrStripStyling(replyText[1].getText(), p));
                    setTextViewColorSecondary(big, R.id.notification_material_reply_text_2, p);
                    setTextViewColorSecondary(contentView, R.id.notification_material_reply_text_2,
                            p);
                    if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2].getText())
                            && p.maxRemoteInputHistory > 2) {
                        big.setViewVisibility(
                        contentView.setViewVisibility(
                                R.id.notification_material_reply_text_3, View.VISIBLE);
                        big.setTextViewText(R.id.notification_material_reply_text_3,
                        contentView.setTextViewText(R.id.notification_material_reply_text_3,
                                ensureColorSpanContrastOrStripStyling(replyText[2].getText(), p));
                        setTextViewColorSecondary(big, R.id.notification_material_reply_text_3, p);
                        setTextViewColorSecondary(contentView,
                                R.id.notification_material_reply_text_3, p);
                    }
                }
            }
            return big;
            return contentView;
        }
        private boolean populateActionsContainer(RemoteViews contentView, StandardTemplateParams p,
                List<Action> nonContextualActions, int numActions, boolean emphasizedMode) {
            boolean validRemoteInput = false;
            for (int i = 0; i < numActions; i++) {
                Action action = nonContextualActions.get(i);
                boolean actionHasValidInput = hasValidRemoteInput(action);
                validRemoteInput |= actionHasValidInput;
                final RemoteViews button = generateActionButton(action, emphasizedMode, p);
                if (actionHasValidInput && !emphasizedMode) {
                    // Clear the drawable
                    button.setInt(R.id.action0, "setBackgroundResource", 0);
                }
                if (emphasizedMode && i > 0) {
                    // Clear start margin from non-first buttons to reduce the gap between them.
                    //  (8dp remaining gap is from all buttons' standard 4dp inset).
                    button.setViewLayoutMarginDimen(R.id.action0, RemoteViews.MARGIN_START, 0);
                }
                contentView.addView(R.id.actions, button);
            }
            return validRemoteInput;
        }
        /**
+15 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.widget;

import static android.app.Flags.notificationsRedesignTemplates;
import static android.app.Notification.CallStyle.DEBUG_NEW_ACTION_LAYOUT;
import static android.app.Flags.evenlyDividedCallStyleActionLayout;

@@ -368,12 +369,17 @@ public class NotificationActionListLayout extends LinearLayout {
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (!notificationsRedesignTemplates()) {
            mDefaultPaddingBottom = getPaddingBottom();
            mDefaultPaddingTop = getPaddingTop();
            updateHeights();
        }
    }

    private void updateHeights() {
        if (notificationsRedesignTemplates()) {
            return;
        }
        int inset = getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.button_inset_vertical_material);
        mEmphasizedPaddingTop = getResources().getDimensionPixelSize(
@@ -440,6 +446,9 @@ public class NotificationActionListLayout extends LinearLayout {
     */
    @RemotableViewMethod
    public void setEmphasizedMode(boolean emphasizedMode) {
        if (notificationsRedesignTemplates()) {
            return;
        }
        mEmphasizedMode = emphasizedMode;
        int height;
        if (emphasizedMode) {
@@ -462,7 +471,9 @@ public class NotificationActionListLayout extends LinearLayout {
    }

    public int getExtraMeasureHeight() {
        if (mEmphasizedMode) {
        // Note: the emphasized height is no longer different from the regular height when the
        // notificationsRedesignTemplates flag is on.
        if (!notificationsRedesignTemplates() && mEmphasizedMode) {
            return mEmphasizedHeight - mRegularHeight;
        }
        return 0;
+84 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2025 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
  -->

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/actions_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:layout_marginBottom="@dimen/notification_2025_action_list_margin_bottom"
    >

    <LinearLayout
        android:id="@+id/actions_container_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:layout_gravity="bottom"
        android:orientation="horizontal"
        android:background="@color/notification_action_list_background_color"
        >

        <com.android.internal.widget.NotificationActionListLayout
            android:id="@+id/actions"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:minHeight="@dimen/notification_2025_action_list_height"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:visibility="gone"
            >
            <!-- actions will be added here -->
        </com.android.internal.widget.NotificationActionListLayout>

        <!--
        This nested linear layout exists to ensure that if the neither of the contained
        actions is visible we have some minimum padding at the end of the actions is present,
        then there will be 12dp of padding at the end of the actions list.

        The end padding exists to match the bottom margin of the actions, for symmetry when the icon
        is shown in the corner of the notification.
        -->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            android:paddingEnd="@dimen/notification_2025_action_list_margin_bottom"
            android:minWidth="@dimen/snooze_and_bubble_gone_padding_end"
            >
            <ImageView
                android:id="@+id/snooze_button"
                android:layout_width="@dimen/notification_2025_actions_icon_size"
                android:layout_height="@dimen/notification_2025_actions_icon_size"
                android:layout_gravity="center_vertical|end"
                android:visibility="gone"
                android:scaleType="centerInside"
                />

            <ImageView
                android:id="@+id/bubble_button"
                android:layout_width="@dimen/notification_2025_actions_icon_size"
                android:layout_height="@dimen/notification_2025_actions_icon_size"
                android:layout_gravity="center_vertical|end"
                android:visibility="gone"
                android:scaleType="centerInside"
                />
        </LinearLayout>
    </LinearLayout>
</FrameLayout>
+2 −2
Original line number Diff line number Diff line
@@ -182,10 +182,10 @@
            <include layout="@layout/notification_template_smart_reply_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/notification_content_margin"
                android:layout_marginTop="@dimen/notification_2025_smart_reply_container_margin"
                android:layout_marginStart="@dimen/notification_2025_content_margin_start"
                android:layout_marginEnd="@dimen/notification_content_margin_end" />
            <include layout="@layout/notification_material_action_list" />
            <include layout="@layout/notification_2025_action_list" />
        </LinearLayout>
    </LinearLayout>

+2 −2
Original line number Diff line number Diff line
@@ -206,10 +206,10 @@
        <include layout="@layout/notification_template_smart_reply_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/notification_content_margin"
                android:layout_marginTop="@dimen/notification_2025_smart_reply_container_margin"
                android:layout_marginStart="@dimen/notification_2025_content_margin_start"
                android:layout_marginEnd="@dimen/notification_content_margin_end" />
        <include layout="@layout/notification_material_action_list" />
        <include layout="@layout/notification_2025_action_list" />
    </LinearLayout>
</LinearLayout>
</com.android.internal.widget.ConversationLayout>
Loading