Как предотвратить изменение размера дисплея устройства Android в моем приложении? - PullRequest
1 голос
/ 26 июня 2019

Я разрабатываю приложение с React Native для iOS и Android и пытаюсь предотвратить масштабирование дисплея в приложении для конкретного устройства.

Для масштабирования размера текста / шрифта размещение следующего кода в файле App.js корневого уровня решает проблему как для iOS, так и для Android:

if (Text.defaultProps == null) {
    Text.defaultProps = {};
}
Text.defaultProps.allowFontScaling = false;

Однако устройства Android имеют следующую настройку размера экрана, которая все еще применяется:

Android Device Display size setting

Я пытался (безуспешно) собрать воедино различные «решения» этой проблемы, которые я нашел в ответах на следующие вопросы:

Изменение размера системного дисплея программно 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 лет назад. Я потратил несколько мучительных часов, пытаясь понять это, и любая помощь будет очень оценена.

пс. Мне хорошо известно, что настройки доступности существуют по уважительной причине, поэтому, пожалуйста, избавьте меня от диатрибы, которую я видел во многих «ответах» о том, почему мне нужно исправить свой пользовательский интерфейс, чтобы работать с настройками доступности, а не отключать их.

1 Ответ

1 голос
/ 26 июня 2019

Вы можете попробовать следующий код (переопределение 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

Итак, используя этот код, я могу получить одно и то же измерение в пикселях независимо от уровня масштабирования.

Редактировать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...