跳转至

Android处理DialogFragment横屏首次显示被缩小的问题

更新日期: 2026-08-27
  • 2026-08-27 新建文档

问题描述

在横屏 Activity 中弹出自定义 DialogFragment 时,出现首次显示尺寸偏小(被压缩),但在关闭后第二次显示恢复正常的诡异现象。

加入 adjustFontScale() 后意外解决了该问题

在 onCreate() 中调用 adjustFontScale() 时,执行了以下核心代码:

Resources resources = getResources();
// ... 修改 configuration ...
resources.updateConfiguration(configuration, metrics);
强制触发配置重算(Re-layout):resources.updateConfiguration() 相当于向系统发送了一个配置变更信号,强行刷新了当前资源上下文和 DisplayMetrics。

提前厘清度量指标:这使得在后续执行到 onCreateView() 和 onStart() 时,系统已经完成了横屏状态下的真实像素矩阵更新,从而成功避免了首次获取宽度错乱的问题。

代码实现

通过在 onCreate 中预先校准配置,并在 onCreateView 与 onStart 中通过百分比动态计算并应用宽度,最终的代码实现如下:

import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.os.LocaleList;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;

import java.util.Locale;

/**
 * 横屏专用
 */
public class RustHorAngleEditDialog extends DialogFragment {

    private static final double WIDTH_PERCENT = 0.45;

    private Locale mTargetLocale = Locale.SIMPLIFIED_CHINESE;

    public static RustHorAngleEditDialog newInstance() {
        RustHorAngleEditDialog dialog = new RustHorAngleEditDialog();
        Bundle args = new Bundle();
        // 业务代码...
        dialog.setArguments(args);
        return dialog;
    }

    // IMPORTANT: Make sure the empty constructor remains for the FragmentManager
    public RustHorAngleEditDialog() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        adjustFontScale();
        setStyle(DialogFragment.STYLE_NORMAL, R.style.RustFullScreenDialogOnLandscape);
        Bundle args = getArguments();
        if (args != null) {
            // 业务代码...
        }
    }

    private void adjustFontScale() {
        Resources resources = getResources();
        Configuration configuration = resources.getConfiguration();
        // 1. 获取app设置的locale或者系统的locale 具体看app用了哪个
        mTargetLocale = MultiLanguageUtils.RustGetSavedSettingLocale();
        // 2. 修改字体缩放
        configuration.fontScale = 1.0f;
        // 3. 关键步骤:必须同时显式设置 Locale,否则会被系统重置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            configuration.setLocale(mTargetLocale);
            configuration.setLocales(new LocaleList(mTargetLocale));
        } else {
            configuration.locale = mTargetLocale;
        }
        DisplayMetrics metrics = resources.getDisplayMetrics();
        metrics.scaledDensity = configuration.fontScale * metrics.density;
        // 注意:updateConfiguration 会影响 Activity 级别的资源
        resources.updateConfiguration(configuration, metrics);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(requireActivity()).inflate(R.layout.Rust_dialog_angle_edit, container, false);

        // ui设置...

        Window window = getDialog() != null ? getDialog().getWindow() : null;
        if (window != null) {
            DisplayMetrics metrics = new DisplayMetrics();
            requireActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
            window.setLayout((int) (metrics.widthPixels * WIDTH_PERCENT), ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        // ui交互设置...
        return view;
    }

    @Override
    public void onStart() {
        super.onStart();
        Window window = getDialog() != null ? getDialog().getWindow() : null;
        if (window == null) {
            return;
        }

        // 兜底:确保窗口尺寸为期望值(正常路径在 onCreateView 已设置)
        DisplayMetrics metrics = new DisplayMetrics();
        requireActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
        window.setLayout((int) (metrics.widthPixels * WIDTH_PERCENT), ViewGroup.LayoutParams.WRAP_CONTENT);

        // 软键盘:adjustResize,横屏屏矮时输入框不会被键盘遮挡(不自动弹出)
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    }
}

style如下

    <style name="RustFullScreenDialogOnLandscape" parent="Theme.AppCompat.Light.Dialog">
        <item name="windowFixedWidthMajor">@null</item>
        <item name="windowFixedWidthMinor">@null</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:backgroundDimAmount">0</item>
    </style>

注意

注意 API 兼容:resources.updateConfiguration() 在高版本 Android 中已被标记过时(Deprecated),若后续升级项目架构,建议优先考虑通过重写 attachBaseContext 使用 createConfigurationContext 来管理局部语言和字体,避免对全局资源造成潜在影响。

本站说明

一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~

🖥️云雨服务器 🙋反馈问题 🔥最近更新 🍪投喂作者