Как предотвратить изменение размера дисплея устройства Android в моем приложении?
Я разрабатываю приложение с React Native как для iOS, так и для Android, и пытаюсь предотвратить масштабирование дисплея в приложении для конкретного устройства.
Для масштабирования размера текста / шрифта размещение следующего кода в файле App.js корневого уровня решает проблему как для iOS, так и для Android:
if (Text.defaultProps == null) {
Text.defaultProps = {};
}
Text.defaultProps.allowFontScaling = false;
Тем не менее, устройства Android имеют следующую настройку размера экрана, которая все еще применяется:
Я пытался (безуспешно) собрать воедино различные "решения" этой проблемы, которые я нашел в ответах на следующие вопросы:
Изменение размера дисплея системы программно Android N
Как предотвратить эффекты изменения размера шрифта системы для приложений Android?
Я часто встречал ссылки на BaseActivity
класс, который расширяет Activity
класс. Насколько я понимаю, это внутри того класса, где я буду писать метод (давайте назовем его adjustDisplayScale
) внести изменения в Configuration
из Context
что я получаю от Resources
и что тогда я буду звонить adjustDisplayScale
в пределах onCreate()
метод после super.onCreate()
в MainApplication.java
файл.
На данный момент в этом каталоге у меня есть только два файла - MainApplication.java
а также MainActivity.java
,
Я попытался создать новый модуль и связанный файл пакета для реализации adjustDisplayScale
следуя этим инструкциям, и это не сработало: https://facebook.github.io/react-native/docs/text.html
Я попытался разместить реализацию функциональности adjustDisplayScale
в пределах onCreate()
вот так и не получилось
@Override
public void onCreate() {
super.onCreate();
Context context = getApplicationContext();
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
configuration.fontScale = 1f;
DisplayMetrics metrics = res.getDisplayMetrics();
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metrics);
metrics.scaledDensity = 1f;
configuration.densityDpi = (int) res.getDisplayMetrics().xdpi;
context = context.createConfigurationContext(configuration);
SoLoader.init(this, /* native exopackage */ false);
}
Потенциально многообещающий ответ включал следующее:
protected override void AttachBaseContext(Context @base) {
var configuration = new Configuration(@base.Resources.Configuration);
configuration.FontScale = 1f;
var config = Application.Context.CreateConfigurationContext(configuration);
base.AttachBaseContext(config);
}
Но когда я попытался использовать это, я получил ошибки из-за того, что не распознал символ @base.
Немного предыстории... Я выполнил 99% своей работы над этим проектом в JavaScript / React Native, и у меня почти нет понимания таких вещей, как Resources
, Context
, Configuration
, а также DisplayMetrics
связан с разработкой Android И последний раз, когда я писал код на Java, было 10 лет назад. Я провел несколько мучительных часов, пытаясь понять это, и любая помощь будет принята с благодарностью.
пс. Я хорошо знаю, что настройки доступности существуют по уважительной причине, поэтому, пожалуйста, избавьте меня от диатрибы, которую я видел во многих "ответах" о том, почему мне нужно исправить свой пользовательский интерфейс, чтобы работать с настройками доступности, а не отключать их.
3 ответа
Вы можете попробовать следующий код (переопределение attachBaseContext
). Это "отключит" масштабирование экрана в вашем приложении. Это способ масштабировать весь экран сразу.
@Override
protected void attachBaseContext(final Context baseContext) {
Context newContext;
if(Build.VERSION.SDK_INT >= VERSION_CODES.N) {
DisplayMetrics displayMetrics = baseContext.getResources().getDisplayMetrics();
Configuration configuration = baseContext.getResources().getConfiguration();
if (displayMetrics.densityDpi != DisplayMetrics.DENSITY_DEVICE_STABLE) {
// Current density is different from Default Density. Override it
displayMetrics.densityDpi = DisplayMetrics.DENSITY_DEVICE_STABLE;
configuration.densityDpi = DisplayMetrics.DENSITY_DEVICE_STABLE;
newContext = baseContext;//baseContext.createConfigurationContext(configuration);
} else {
// Same density. Just use same context
newContext = baseContext;
}
} else {
// Old API. Screen zoom not supported
newContext = baseContext;
}
super.attachBaseContext(newContext);
}
В этом коде я проверяю, отличается ли плотность тока от плотности устройства по умолчанию. Если они отличаются, я создаю новый контекст, используя плотность по умолчанию (а не текущий). Затем я присоединяю этот измененный контекст.
Вы должны сделать это на каждом Activity
, Итак, вы можете создать BaseActivity
и добавьте этот код там. Затем вам просто нужно обновить свою деятельность, чтобы расширить BaseActivity
public class BaseActivity extends AppCompatActivity {
@Override
protected void attachBaseContext(final Context baseContext) {
....
}
}
Тогда в вашей деятельности:
public class MainActivity extends BaseActivity {
// Since I'm extending BaseActivity, I don't need to add the code
// on attachBaseContext again
// If you don't want to create a base activity, you must copy/paste that
// attachBaseContext code into all activities
}
Я проверил этот код с:
Log.v("Test", "Dimension: " + getResources().getDimension(R.dimen.test_dimension));
Другой масштаб экрана (с использованием этого кода):
2019-06-26 16:38:17.193 16312-16312/com.test.testapplication V/Test: Dimension: 105.0
2019-06-26 16:38:35.545 16312-16312/com.test.testapplication V/Test: Dimension: 105.0
2019-06-26 16:38:43.021 16579-16579/com.test.testapplication V/Test: Dimension: 105.0
Другой масштаб экрана (без этого кода):
2019-06-26 16:42:53.807 17090-17090/com.test.testapplication V/Test: Dimension: 135.0
2019-06-26 16:43:19.381 17090-17090/com.test.testapplication V/Test: Dimension: 120.0
2019-06-26 16:44:00.125 17090-17090/com.test.testapplication V/Test: Dimension: 105.0
Таким образом, используя этот код, я могу получить одно и то же измерение в пикселях независимо от уровня масштабирования.
редактировать
Упрощенная версия метода @guipivoto в сочетании с масштабированием шрифта.
@Override
protected void attachBaseContext(Context newBase) {
final Configuration configuration = newBase.getResources().getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
final DisplayMetrics displayMetrics = newBase.getResources().getDisplayMetrics();
if (displayMetrics.densityDpi != DisplayMetrics.DENSITY_DEVICE_STABLE)
{
// Current density is different from Default Density. Override it
configuration.densityDpi = DisplayMetrics.DENSITY_DEVICE_STABLE;
}
}
configuration.fontScale = 1.0f;
Context newContext = newBase.createConfigurationContext(configuration);
super.attachBaseContext(newContext);
}
мы можем использовать код раздела
Configuration configuration = getResources().getConfiguration();
configuration.fontScale = (float) 1; //0.85 small size, 1 normal size, 1,15 big etc
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
configuration.densityDpi = (int) getResources().getDisplayMetrics().xdpi;
getBaseContext().getResources().updateConfiguration(configuration, metrics);
если вы нашли это полезным, вы можете проголосовать за THIS_ANSWER.