如何在我的应用程序中检测Android选择的布局?

时间:2022-11-15 20:49:29

Assume I have an activity with three different layouts in different resource folders. For example:

假设我在不同的资源文件夹中有三种不同布局的活动。例如:

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

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

In different devices and different positions one of them is selected by Android.
How can I find out which one is selected programmatically?

在不同的设备和不同的位置,其中一个由Android选择。如何找出以编程方式选择的?

Does Android have any API that returns these layouts to the program?

Android是否有任何API将这些布局返回给程序?


Edit: Graham Borland's solution has a problem in some situations that I mentioned in the comments.

编辑:Graham Borland的解决方案在我在评论中提到的某些情况下存在问题。

8 个解决方案

#1


38  

You could create a values-<config> directory for each of your supported configurations. Inside of each of those directories, create a strings.xml with a single selected_configuration string which describes the current configuration. At runtime, fetch the string using the standard getString method, which will do the configuration resolution for you and return the correct string for the configuration. This is untested.

您可以为每个支持的配置创建values- 目录。在每个目录中,创建一个strings.xml,其中包含一个selected_configuration字符串,用于描述当前配置。在运行时,使用标准getString方法获取字符串,该方法将为您执行配置解析并返回配置的正确字符串。这是未经测试的。

#2


67  

You can set a different android:tag attribute on the views in each different resource file, and read the tag back at runtime with View.getTag().

您可以在每个不同资源文件的视图上设置不同的android:tag属性,并使用View.getTag()在运行时读取标记。

Example:

例:

layout-xlarge-land/my_act.xml

布局XLARGE土地/ my_act.xml

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

layout-xlarge/my_act.xml

布局XLARGE / my_act.xml

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

MyActivity.java

MyActivity.java

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

#3


8  

You can try to repeat this algorithm "How Android Finds the Best-matching Resource" - it's quite simple, especially if you have different layouts only for different screens.

你可以尝试重复这个算法“Android如何找到最匹配的资源” - 这很简单,特别是如果你有不同的布局只针对不同的屏幕。

#4


5  

My answer is implemented from @Graham Borland

我的回答是从@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;
        }

This will work in API lavel 4 or higher.

这将适用于API lavel 4或更高版本。

#5


3  

I am assuming you are using setContentView(int resID) to set the content of your activities.

我假设您正在使用setContentView(int resID)来设置活动的内容。


METHOD 1 (This is my answer)

方法1(这是我的答案)

Now in all your layouts make sure that the root view always has the right tag:

现在,在所有布局中,确保根视图始终具有正确的标记:

example:

例:

layout-xlarge/main.xml:

布局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:

布局小/ 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>

Now let your activities extend this activity:

现在让您的活动扩展此活动:

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);
    }
}

In this case, you can use the resourceType to know what is the resource identifier used.

在这种情况下,您可以使用resourceType来了解所使用的资源标识符。


METHOD 2 (This was my answer but before posting I thought of the better one)

方法2(这是我的答案,但在发布之前,我想到了更好的一个)

Now in all your layouts make sure that the root view always has the right tag:

现在,在所有布局中,确保根视图始终具有正确的标记:

example:

例:

layout-xlarge/main.xml:

布局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:

布局小/ 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>

Now let your activities extend this activity:

现在让您的活动扩展此活动:

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);
            }
        }
    }
}

In this case all your views in your hierarchy will have the same tag.

在这种情况下,层次结构中的所有视图都将具有相同的标记。

#6


2  

I dont know the exact way to find it. But we can find it in different way.

我不知道找到它的确切方法。但我们可以用不同的方式找到它。

Add one textview in all the layouts.(visibility hidden). Assign values like xlarge, land, xlarge-land accordingly.

在所有布局中添加一个textview。(隐藏可见性)。相应地分配像xlarge,land,xlarge-land这样的值。

In program, get the value from textview. Somehow we can get to know like this.

在程序中,从textview获取值。不知何故,我们可以这样了解。

#7


2  

You can get info about screen orientation and size from Resources object. From there you can understand which layout is used.

您可以从Resources对象获取有关屏幕方向和大小的信息。从那里你可以了解使用哪种布局。

getResources().getConfiguration().orientation; - returns either Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE.

。getResources()getConfiguration()取向。 - 返回Configuration.ORIENTATION_PORTRAIT或Configuration.ORIENTATION_LANDSCAPE。

int size = getResources().getConfiguration().screenLayout; - returns mask of screen size. You can test against Small, Normal, Large, xLarge sizes. For example:

int size = getResources()。getConfiguration()。screenLayout; - 返回屏幕大小的掩码。您可以针对Small,Normal,Large,xLarge大小进行测试。例如:

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

#8


1  

Your question is as same as this How to get layout xml file path?
You can add a Hidden Text View with corresponding Folder names in the xml Get the String in the text view by

您的问题与此如何获取布局xml文件路径相同?您可以在xml中添加带有相应文件夹名称的隐藏文本视图。在文本视图中获取字符串

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

Make sure that all the id's of the text view are same.

确保文本视图的所有ID都相同。

Example

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`

#1


38  

You could create a values-<config> directory for each of your supported configurations. Inside of each of those directories, create a strings.xml with a single selected_configuration string which describes the current configuration. At runtime, fetch the string using the standard getString method, which will do the configuration resolution for you and return the correct string for the configuration. This is untested.

您可以为每个支持的配置创建values- 目录。在每个目录中,创建一个strings.xml,其中包含一个selected_configuration字符串,用于描述当前配置。在运行时,使用标准getString方法获取字符串,该方法将为您执行配置解析并返回配置的正确字符串。这是未经测试的。

#2


67  

You can set a different android:tag attribute on the views in each different resource file, and read the tag back at runtime with View.getTag().

您可以在每个不同资源文件的视图上设置不同的android:tag属性,并使用View.getTag()在运行时读取标记。

Example:

例:

layout-xlarge-land/my_act.xml

布局XLARGE土地/ my_act.xml

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

layout-xlarge/my_act.xml

布局XLARGE / my_act.xml

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

MyActivity.java

MyActivity.java

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

#3


8  

You can try to repeat this algorithm "How Android Finds the Best-matching Resource" - it's quite simple, especially if you have different layouts only for different screens.

你可以尝试重复这个算法“Android如何找到最匹配的资源” - 这很简单,特别是如果你有不同的布局只针对不同的屏幕。

#4


5  

My answer is implemented from @Graham Borland

我的回答是从@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;
        }

This will work in API lavel 4 or higher.

这将适用于API lavel 4或更高版本。

#5


3  

I am assuming you are using setContentView(int resID) to set the content of your activities.

我假设您正在使用setContentView(int resID)来设置活动的内容。


METHOD 1 (This is my answer)

方法1(这是我的答案)

Now in all your layouts make sure that the root view always has the right tag:

现在,在所有布局中,确保根视图始终具有正确的标记:

example:

例:

layout-xlarge/main.xml:

布局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:

布局小/ 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>

Now let your activities extend this activity:

现在让您的活动扩展此活动:

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);
    }
}

In this case, you can use the resourceType to know what is the resource identifier used.

在这种情况下,您可以使用resourceType来了解所使用的资源标识符。


METHOD 2 (This was my answer but before posting I thought of the better one)

方法2(这是我的答案,但在发布之前,我想到了更好的一个)

Now in all your layouts make sure that the root view always has the right tag:

现在,在所有布局中,确保根视图始终具有正确的标记:

example:

例:

layout-xlarge/main.xml:

布局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:

布局小/ 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>

Now let your activities extend this activity:

现在让您的活动扩展此活动:

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);
            }
        }
    }
}

In this case all your views in your hierarchy will have the same tag.

在这种情况下,层次结构中的所有视图都将具有相同的标记。

#6


2  

I dont know the exact way to find it. But we can find it in different way.

我不知道找到它的确切方法。但我们可以用不同的方式找到它。

Add one textview in all the layouts.(visibility hidden). Assign values like xlarge, land, xlarge-land accordingly.

在所有布局中添加一个textview。(隐藏可见性)。相应地分配像xlarge,land,xlarge-land这样的值。

In program, get the value from textview. Somehow we can get to know like this.

在程序中,从textview获取值。不知何故,我们可以这样了解。

#7


2  

You can get info about screen orientation and size from Resources object. From there you can understand which layout is used.

您可以从Resources对象获取有关屏幕方向和大小的信息。从那里你可以了解使用哪种布局。

getResources().getConfiguration().orientation; - returns either Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE.

。getResources()getConfiguration()取向。 - 返回Configuration.ORIENTATION_PORTRAIT或Configuration.ORIENTATION_LANDSCAPE。

int size = getResources().getConfiguration().screenLayout; - returns mask of screen size. You can test against Small, Normal, Large, xLarge sizes. For example:

int size = getResources()。getConfiguration()。screenLayout; - 返回屏幕大小的掩码。您可以针对Small,Normal,Large,xLarge大小进行测试。例如:

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

#8


1  

Your question is as same as this How to get layout xml file path?
You can add a Hidden Text View with corresponding Folder names in the xml Get the String in the text view by

您的问题与此如何获取布局xml文件路径相同?您可以在xml中添加带有相应文件夹名称的隐藏文本视图。在文本视图中获取字符串

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

Make sure that all the id's of the text view are same.

确保文本视图的所有ID都相同。

Example

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`