Как определить, какой макет выбран Android в моем приложении?

Предположим, что у меня есть активность с тремя разными макетами в разных папках ресурсов. Например:

layout-land/my_act.xml
layout-xlarge/my_act.xml
layout-xlarge-land/my_act.xml

В разных устройствах и разных позициях один из них выбирается Android.
Как узнать, какой из них выбран программно ?

Есть ли у Android API, который возвращает эти макеты в программу?


Редактировать : Решение Graham Borland имеет проблемы в некоторых ситуациях, о которых я упоминал в комментариях.

Solutions Collecting From Web of "Как определить, какой макет выбран Android в моем приложении?"

Вы можете создать каталог values-<config> для каждой из поддерживаемых конфигураций. Внутри каждого из этих каталогов создайте strings.xml с одной строкой selected_configuration которая описывает текущую конфигурацию. Во время выполнения извлеките строку, используя стандартный метод getString , который будет выполнять разрешение конфигурации для вас и вернет правильную строку для конфигурации. Это не проверено.

Вы можете установить другой атрибут android:tag в представлениях в каждом файле ресурсов и прочитать тег во время выполнения с помощью View.getTag() .

Пример:

Макет-XLarge-земля / my_act.xml

 <View android:id="@+id/mainview" android:tag="xlarge-landscape" /> 

Макет-XLarge / my_act.xml

 <View android:id="@+id/mainview" android:tag="xlarge-portrait" /> 

MyActivity.java

 String tag = view.getTag(); if (tag.equals("xlarge-landscape") { ... } 

Вы можете попробовать повторить этот алгоритм «Как Android называет наилучший ресурс» – это довольно просто, особенно если у вас разные макеты только для разных экранов.

Мой ответ выполнен с @Graham Borland

  @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); switch(metrics.densityDpi){ case DisplayMetrics.DENSITY_LOW: if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); String tag = view.getTag(); if (tag.equals("small-landscape") { ..... } } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); String tag = view.getTag(); if (tag.equals("small-potrait") { ..... } } break; case DisplayMetrics.DENSITY_MEDIUM: if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); String tag = view.getTag(); if (tag.equals("medium-landscape") { ..... } } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); String tag = view.getTag(); if (tag.equals("medium-potrait") { ..... } } break; case DisplayMetrics.DENSITY_HIGH: if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); String tag = view.getTag(); if (tag.equals("large-landscape") { ..... } } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); String tag = view.getTag(); if (tag.equals("large-potrait") { ..... } } break; } 

Это будет работать в API lavel 4 или выше.

Я предполагаю, что вы используете setContentView(int resID) для настройки содержимого ваших действий.


МЕТОД 1 (Это мой ответ)

Теперь во всех ваших макетах убедитесь, что в корневом представлении всегда есть правильный тег:

пример:

layout-xlarge/main.xml :

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:tag="xlarge-landscape" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 

layout-small/main.xml :

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:tag="small" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 

Теперь пусть ваша деятельность расширяет эту деятельность:

 package shush.android.screendetection; import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class SkeletonActivity extends Activity { protected String resourceType; @Override public void setContentView(int layoutResID) { LayoutInflater inflater = getLayoutInflater(); View view = inflater.inflate(layoutResID, null); resourceType = (String)view.getTag(); super.setContentView(view); } } 

В этом случае вы можете использовать resourceType чтобы узнать, что используется идентификатор ресурса.


МЕТОД 2 (Это был мой ответ, но до публикации я подумал о лучшем)

Теперь во всех ваших макетах убедитесь, что в корневом представлении всегда есть правильный тег:

пример:

layout-xlarge/main.xml :

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:tag="xlarge-landscape" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 

layout-small/main.xml :

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:tag="small" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 

Теперь пусть ваша деятельность расширяет эту деятельность:

 package shush.android.screendetection; import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class SkeletonActivity extends Activity { @Override public void setContentView(int layoutResID) { LayoutInflater inflater = getLayoutInflater(); View view = inflater.inflate(layoutResID, null); fix(view, view.getTag()); super.setContentView(view); } private void fix(View child, Object tag) { if (child == null) return; if (child instanceof ViewGroup) { fix((ViewGroup) child, tag); } else if (child != null) { child.setTag(tag); } } private void fix(ViewGroup parent, Object tag) { for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); if (child instanceof ViewGroup) { fix((ViewGroup) child, tag); } else { fix(child, tag); } } } } 

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

Я не знаю, как именно найти его. Но мы можем найти его по-разному.

Добавьте одно текстовое изображение во все макеты (видимость скрыта). Присвоить значения, например, xlarge, land, xlarge-land соответственно.

В программе получите значение из textview. Каким-то образом мы можем узнать вот так.

Вы можете получить информацию об ориентации и размере экрана с объекта Resources . Оттуда вы можете понять, какой макет используется.

getResources().getConfiguration().orientation; – возвращает либо Configuration.ORIENTATION_PORTRAIT либо Configuration.ORIENTATION_LANDSCAPE .

int size = getResources().getConfiguration().screenLayout; – возвращает маску размера экрана. Вы можете протестировать малые, нормальные, большие, большие размеры. Например:

 if ((size & Configuration.SCREENLAYOUT_SIZE_XLARGE)==Configuration.SCREENLAYOUT_SIZE_XLARGE) 

Ваш вопрос такой же, как и этот. Как получить путь к файлу xml?
Вы можете добавить скрытый текстовый вид с соответствующими именами папок в xml. Получить строку в текстовом представлении.

 TextView path = (TextView)findViewbyid(R.id.hiddentextview); String s = path.gettext().tostring(); 

Убедитесь, что все идентификаторы текстового вида одинаковы.

пример

 if your xml is in `normal-mdpi` in hidden textview hard code `normal-mdpi` if your xml is in `large-mdpi` in hidden textview hard code `large-mdpi`