Android处理DialogFragment横屏首次显示被缩小的问题¶
更新日期: 2026-08-27
- 2026-08-27 新建文档
问题描述¶
在横屏 Activity 中弹出自定义 DialogFragment 时,出现首次显示尺寸偏小(被压缩),但在关闭后第二次显示恢复正常的诡异现象。
加入 adjustFontScale() 后意外解决了该问题¶
在 onCreate() 中调用 adjustFontScale() 时,执行了以下核心代码:
Resources resources = getResources();
// ... 修改 configuration ...
resources.updateConfiguration(configuration, metrics);
提前厘清度量指标:这使得在后续执行到 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 来管理局部语言和字体,避免对全局资源造成潜在影响。