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

Commit 7f8afc0f authored by Ivan Chiang's avatar Ivan Chiang
Browse files

[PM] Support material AlertDialog (1/N)

- Use MaterialAlertDialog in InstallConfirmation dialog
- Create UiUtil
- Update the font style to the original one
- Create the temporary themes and styles, after we replaces all
  dialogs, will remove them

Flag: android.content.pm.use_pia_v2
Test: manual
Bug: 274120822
Change-Id: I117cc7136ffb08a92347b750edc194c93acee434
parent db3e0319
Loading
Loading
Loading
Loading
+35 −11
Original line number Diff line number Diff line
@@ -16,18 +16,13 @@
  -->
<resources>

    <style name="Widget.PackageInstaller.Button" parent="android:Widget.DeviceDefault.Button">
        <item name="android:textColor">?android:attr/colorAccent</item>
        <item name="android:background">@null</item>
        <item name="android:minHeight">@dimen/button_min_height</item>
        <item name="android:layout_marginStart">8dp</item>
    </style>

    <!-- TODO (b/274120822): Remove these styles when we replace all dialogs to MaterialAlertDialog -->
    <style name="Widget.PackageInstaller.Button.Colored" parent="android:Widget.DeviceDefault.Button.Colored">
        <item name="android:background">@drawable/background_colored_button</item>
        <item name="android:minHeight">@dimen/button_min_height</item>
        <item name="android:paddingHorizontal">24dp</item>
        <item name="android:layout_marginStart">8dp</item>
        <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
    </style>

    <style name="Widget.PackageInstaller.Button.Outlined" parent="android:Widget.DeviceDefault.Button.Colored">
@@ -35,12 +30,14 @@
        <item name="android:textColor">?android:attr/colorAccent</item>
        <item name="android:minHeight">@dimen/button_min_height</item>
        <item name="android:layout_marginStart">8dp</item>
        <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
    </style>

    <style name="Widget.PackageInstaller.ButtonBar" parent="">
        <item name="android:paddingBottom">20dp</item>
        <item name="android:paddingTop">4dp</item>
        <item name="android:paddingHorizontal">12dp</item>
        <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
    </style>

    <style name="Widget.PackageInstaller.WindowTitle" parent="">
@@ -49,21 +46,48 @@
        <item name="android:autoSizeTextType">uniform</item>
    </style>

    <style name="Widget.PackageInstaller.Material.WindowTitle" parent="@style/MaterialAlertDialog.Material3.Title.Text">
        <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Headline</item>
        <item name="android:layout_marginTop">4dp</item>
        <item name="android:autoSizeTextType">uniform</item>
    </style>

    <style name="Widget.PackageInstaller.Material.Button" parent="@style/Widget.Material3.Button.TextButton">
        <item name="android:textColor">?android:attr/colorAccent</item>
        <item name="android:minHeight">@dimen/button_min_height</item>
        <item name="android:layout_marginStart">8dp</item>
        <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
    </style>

    <style name="Widget.PackageInstaller.Material.Button.Colored" parent="@style/Widget.Material3.Button">
        <item name="android:minHeight">@dimen/button_min_height</item>
        <item name="android:paddingHorizontal">24dp</item>
        <item name="android:layout_marginStart">8dp</item>
        <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
    </style>

    <style name="Widget.PackageInstaller.Material.Button.Outlined" parent="@style/Widget.Material3.Button.OutlinedButton">
        <item name="android:textColor">?android:attr/colorAccent</item>
        <item name="android:minHeight">@dimen/button_min_height</item>
        <item name="android:layout_marginStart">8dp</item>
        <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
    </style>

    <style name="Widget.PackageInstaller.TextView.AppLabel" parent="@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle">
        <item name="android:textFontWeight">600</item>
        <item name="android:color">?android:attr/textColorPrimary</item>
    </style>

    <style name="Widget.PackageInstaller.TextView.CustomMessage" parent="@android:style/TextAppearance.DeviceDefault.Small">
    <style name="Widget.PackageInstaller.TextView.CustomMessage" parent="@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle">
        <item name="android:textColor">?android:attr/textColorSecondary</item>
    </style>

    <style name="Widget.PackageInstaller.TextView.KeepData.Heading" parent="@android:style/TextAppearance.DeviceDefault.Small">
    <style name="Widget.PackageInstaller.TextView.KeepData.Heading" parent="@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle">
        <item name="android:textColor">?android:attr/textColorSecondary</item>
        <item name="android:textFontWeight">600</item>
    </style>

    <style name="Widget.PackageInstaller.TextView.KeepData.SubHeading" parent="@android:style/TextAppearance.DeviceDefault.Small">
    <style name="Widget.PackageInstaller.TextView.KeepData.SubHeading" parent="@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle">
        <item name="android:textColor">?android:attr/textColorSecondary</item>
    </style>
</resources>
+15 −6
Original line number Diff line number Diff line
@@ -24,20 +24,29 @@
        <item name="android:windowAnimationStyle">@null</item>
    </style>

    <style name="Theme.AlertDialogActivity.Material" >
        <item name="android:alertDialogTheme">@style/Theme.MaterialAlertDialog</item>
    <style name="Theme.AlertDialogActivity.Material" parent="Theme.Material3.DynamicColors.DayNight">
        <!-- TODO (b/274120822): Remove this attribute when we replace all dialogs to MaterialAlertDialog -->
        <item name="android:alertDialogTheme">@style/Theme.MaterialAlertDialog.System</item>
        <item name="materialAlertDialogTheme">@style/Theme.MaterialAlertDialog</item>
    </style>

    <style name="Theme.MaterialAlertDialog" parent="@style/Theme.AlertDialogActivity">
    <!-- TODO (b/274120822): Remove this theme when we replace all dialogs to MaterialAlertDialog -->
    <style name="Theme.MaterialAlertDialog.System" parent="@style/Theme.AlertDialogActivity">
        <item name="android:buttonBarPositiveButtonStyle">@style/Widget.PackageInstaller.Button.Colored</item>
        <item name="android:buttonBarNegativeButtonStyle">@style/Widget.PackageInstaller.Button.Outlined</item>
        <item name="android:buttonBarStyle">@style/Widget.PackageInstaller.ButtonBar</item>
        <item name="android:windowTitleStyle">@style/Widget.PackageInstaller.WindowTitle</item>
    </style>

    <style name="Theme.MaterialAlertDialog.Variant">
        <item name="android:buttonBarPositiveButtonStyle">@style/Widget.PackageInstaller.Button</item>
        <item name="android:buttonBarNegativeButtonStyle">@style/Widget.PackageInstaller.Button</item>
    <style name="Theme.MaterialAlertDialog" parent="@style/ThemeOverlay.Material3.MaterialAlertDialog">
        <item name="buttonBarPositiveButtonStyle">@style/Widget.PackageInstaller.Material.Button.Colored</item>
        <item name="buttonBarNegativeButtonStyle">@style/Widget.PackageInstaller.Material.Button.Outlined</item>
        <item name="materialAlertDialogTitleTextStyle">@style/Widget.PackageInstaller.Material.WindowTitle</item>
    </style>

    <style name="Theme.MaterialAlertDialog.Variant" parent="@style/Theme.MaterialAlertDialog.System">
        <item name="android:buttonBarPositiveButtonStyle">@style/Widget.PackageInstaller.Material.Button</item>
        <item name="android:buttonBarNegativeButtonStyle">@style/Widget.PackageInstaller.Material.Button</item>
    </style>

    <style name="Theme.UninstallerActivity"
+1 −5
Original line number Diff line number Diff line
@@ -89,11 +89,7 @@ class InstallLaunch : FragmentActivity(), InstallActionListener {
        // theme to support the material design.
        if (PackageUtil.isMaterialDesignEnabled(this)) {
            Log.d(LOG_TAG, "Apply material design")
            theme.applyStyle(R.style.Theme_AlertDialogActivity_Material, /* force= */ true)
            // Apply the material theme for the material components
            theme.applyStyle(
                com.google.android.material.R.style.Theme_Material3_DynamicColors_DayNight,
                /* force= */ false)
            theme.applyStyle(R.style.Theme_AlertDialogActivity_Material, /* force= */ false)
        }

        fragmentManager = supportFragmentManager
+103 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

package com.android.packageinstaller.v2.ui;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.PackageUtil;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;

/**
 * The utility of UI components.
 */
public class UiUtil {

    public static final String LOG_TAG = UiUtil.class.getSimpleName();
    /**
     * If material design is enabled, return the material layout resource id. Otherwise, return the
     * default layout resource id.
     */
    public static int getInstallationLayoutResId(@NonNull Context context) {
        if (PackageUtil.isMaterialDesignEnabled(context)) {
            return R.layout.install_fragment_material_layout;
        } else {
            return R.layout.install_fragment_layout;
        }
    }

    /**
     * Gets the positive button in the {@code dialog}. Returns null if the specified
     * button does not exist or the dialog has not yet been fully created.
     */
    public static Button getAlertDialogPositiveButton(@NonNull Dialog dialog) {
        return getAlertiDialogButton(dialog, DialogInterface.BUTTON_POSITIVE);
    }

    /**
     * Gets one of the buttons used in the {@code dialog}. Returns null if the specified
     * button does not exist or the dialog has not yet been fully created.
     *
     * @param whichButton The identifier of the button that should be returned.
     *            For example, this can be {@link DialogInterface#BUTTON_POSITIVE}.
     * @return The button from the dialog, or null if a button does not exist.
     */
    @Nullable
    private static Button getAlertiDialogButton(@NonNull Dialog dialog, int whichButton) {
        if (dialog instanceof android.app.AlertDialog alertDialog) {
            return alertDialog.getButton(whichButton);
        } else if (dialog instanceof androidx.appcompat.app.AlertDialog alertDialog) {
            return alertDialog.getButton(whichButton);
        } else {
            return null;
        }
    }

    /**
     * If material design is enabled, return the MaterialAlertDialog. Otherwise, return the
     * system AlertDialog.
     */
    public static Dialog getAlertDialog(@NonNull Context context, @NonNull String title,
            @NonNull View contentView, int positiveBtnTextResId, int negativeBtnTextResId,
            @Nullable DialogInterface.OnClickListener positiveBtnListener,
            @Nullable DialogInterface.OnClickListener negativeBtnListener) {
        if (PackageUtil.isMaterialDesignEnabled(context)) {
            return new MaterialAlertDialogBuilder(context)
                    .setTitle(title)
                    .setView(contentView)
                    .setPositiveButton(positiveBtnTextResId, positiveBtnListener)
                    .setNegativeButton(negativeBtnTextResId, negativeBtnListener)
                    .create();
        } else {
            return new AlertDialog.Builder(context)
                    .setTitle(title)
                    .setView(contentView)
                    .setPositiveButton(positiveBtnTextResId, positiveBtnListener)
                    .setNegativeButton(negativeBtnTextResId, negativeBtnListener)
                    .create();
        }
    }
}
+21 −14
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_EXISTING_OW
import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_UPDATING;
import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_NEW_OWNER;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -31,6 +30,7 @@ import android.text.Html;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

@@ -42,6 +42,7 @@ import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallUserActionRequired;
import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
import com.android.packageinstaller.v2.ui.UiUtil;

/**
 * Dialog to show when the requesting user confirmation for installing an app.
@@ -53,7 +54,7 @@ public class InstallConfirmationFragment extends DialogFragment {
    @NonNull
    private InstallActionListener mInstallActionListener;
    @NonNull
    private AlertDialog mDialog;
    private Dialog mDialog;

    public InstallConfirmationFragment() {
        // Required for DialogFragment
@@ -93,7 +94,8 @@ public class InstallConfirmationFragment extends DialogFragment {

        Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);

        View dialogView = getLayoutInflater().inflate(R.layout.install_fragment_layout, null);
        View dialogView = getLayoutInflater().inflate(
                UiUtil.getInstallationLayoutResId(requireContext()), null);
        dialogView.requireViewById(R.id.app_snippet).setVisibility(View.VISIBLE);
        ((ImageView) dialogView.requireViewById(R.id.app_icon))
            .setImageDrawable(mDialogData.getAppIcon());
@@ -123,16 +125,12 @@ public class InstallConfirmationFragment extends DialogFragment {
            positiveBtnTextRes = R.string.button_install;
        }

        mDialog = new AlertDialog.Builder(requireContext())
            .setTitle(title)
            .setView(dialogView)
            .setPositiveButton(positiveBtnTextRes,
        mDialog = UiUtil.getAlertDialog(requireContext(), title, dialogView,
                positiveBtnTextRes, R.string.button_cancel,
                (dialogInt, which) -> mInstallActionListener.onPositiveResponse(
                    InstallUserActionRequired.USER_ACTION_REASON_INSTALL_CONFIRMATION))
            .setNegativeButton(R.string.button_cancel,
                        InstallUserActionRequired.USER_ACTION_REASON_INSTALL_CONFIRMATION),
                (dialogInt, which) -> mInstallActionListener.onNegativeResponse(
                    mDialogData.getStageCode()))
            .create();
                                mDialogData.getStageCode()));

        return mDialog;
    }
@@ -146,7 +144,10 @@ public class InstallConfirmationFragment extends DialogFragment {
    @Override
    public void onStart() {
        super.onStart();
        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
        Button button = UiUtil.getAlertDialogPositiveButton(mDialog);
        if (button != null) {
            button.setFilterTouchesWhenObscured(true);
        }
    }

    @Override
@@ -154,13 +155,19 @@ public class InstallConfirmationFragment extends DialogFragment {
        super.onPause();
        // This prevents tapjacking since an overlay activity started in front of Pia will
        // cause Pia to be paused.
        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
        Button button = UiUtil.getAlertDialogPositiveButton(mDialog);
        if (button != null) {
            button.setEnabled(false);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
        Button button = UiUtil.getAlertDialogPositiveButton(mDialog);
        if (button != null) {
            button.setEnabled(true);
        }
    }

    private void setDialogData(Bundle args) {
Loading