Как определить, какой макет выбран Android в моем приложении?
Предположим, что у меня есть активность с тремя разными макетами в разных папках ресурсов. Например:
layout-land/my_act.xml
layout-xlarge/my_act.xml
layout-xlarge-land/my_act.xml
В разных устройствах и разных позициях один из них выбирается Android.
Как узнать, какой из программ выбран программно?
Есть ли у Android какой-либо API, который возвращает эти макеты в программу?
Изменить: Решение Graham Borland имеет проблемы в некоторых ситуациях, о которых я упоминал в комментариях.
Ответы
Ответ 1
Вы можете создать каталог values-<config>
для каждой из поддерживаемых конфигураций. Внутри каждого из этих каталогов создайте strings.xml
с единственной строкой selected_configuration
, которая описывает текущую конфигурацию. Во время выполнения выберите строку, используя стандартный метод getString
, который будет выполнять разрешение конфигурации для вас и вернет правильную строку для конфигурации. Это не проверено.
Ответ 2
Вы можете установить другой атрибут 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") {
...
}
Ответ 3
Вы можете попробовать повторить этот алгоритм "Как Android называет наилучший сопоставимый ресурс" - это довольно просто, особенно если у вас разные макеты только для разных экранов.
Ответ 4
Мой ответ выполнен с @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 или выше.
Ответ 5
Я предполагаю, что вы используете 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);
}
}
}
}
В этом случае все ваши представления в вашей иерархии будут иметь один и тот же тег.
Ответ 6
Я не знаю, как именно найти его. Но мы можем найти его по-разному.
Добавьте одно текстовое изображение во все макеты (видимость скрыта). Присвоить значения, например, xlarge, land, xlarge-land соответственно.
В программе получите значение из textview. Как-то мы можем так поступить.
Ответ 7
Вы можете получить информацию об ориентации и размере экрана с объекта 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)
Ответ 8
Ваш вопрос такой же, как этот Как получить путь к файлу 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`