How can I detect which layout is selected by Android in my application?

AndroidAndroid LayoutResources

Android Problem Overview


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

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

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


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

Android Solutions


Solution 1 - Android

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().

Example:

layout-xlarge-land/my_act.xml

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

layout-xlarge/my_act.xml

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

MyActivity.java

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

Solution 2 - Android

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.

Solution 3 - Android

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.

Solution 4 - Android

My answer is implemented from @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.

Solution 5 - Android

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


METHOD 1 (This is my answer)

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

example:

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>

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.


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

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

example:

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>

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.

Solution 6 - Android

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

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

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

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

Solution 7 - Android

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.

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

Solution 8 - Android

Your question is as same as this https://stackoverflow.com/q/11315111/1008278
You can add a Hidden Text View with corresponding Folder names in the xml Get the String in the text view by

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.

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`

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBobsView Question on Stackoverflow
Solution 1 - AndroidGraham BorlandView Answer on Stackoverflow
Solution 2 - AndroidEdward DaleView Answer on Stackoverflow
Solution 3 - AndroidJin35View Answer on Stackoverflow
Solution 4 - AndroidDineshView Answer on Stackoverflow
Solution 5 - AndroidSherif elKhatibView Answer on Stackoverflow
Solution 6 - AndroidsshturmaView Answer on Stackoverflow
Solution 7 - AndroidRaghu NagarajuView Answer on Stackoverflow
Solution 8 - AndroidVenomVendorView Answer on Stackoverflow