Как определить, какой макет выбран 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") {
    ...
}

Ответ 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`