Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I programmatically choose the Android layout folder?

I'm building an Android app that resizes based on the screen size using different layout folders (i.e. large, xlarge, etc.).

The only problem is that I want to provide a way for users to switch between the small and large screen layouts, in case they have a pre-honeycomb tablet that doesn't recognize the xlarge tag, or the device is closer to phone size but still big enough that the user wants to use the tablet layouts.

Is there a way that I can create a button to switch layout folders? I still want to use the automatic folder selection based on screen size, I just ALSO want to be able to force the app to use one folder or the other.

Is that possible?

like image 577
M Dapp Avatar asked Jan 20 '12 15:01

M Dapp


3 Answers

The android team encourage you to use the resource qualifiers for any kind of multiple devices support-ion. For example

layout-small for devices with small screens layout-ldpi for devices with low density layout-en for locales...

read this it will help you a lot

But generally NO, there is no programmatic way to do this, maybe there are some workarounds but I do not encourage to do that.

Also maybe you need to see the fragments design to understand the development of gui for different devices like tablets and phones...

like image 155
Lukap Avatar answered Sep 24 '22 08:09

Lukap


Yes, you can. It's simple! I do this because legacy (pre API Level 13) systems do not support the newer layout folder filters. Specifically, I need to distinguish QVGA (small) from WQVGA (normal) and other normal resolutions.

Just add a variety of layout files to your layout and layout-land folders, e.g.

layout
    my_layout_default.xml
    my_layout_qvga.xml
layout-land
    my_layout_default.xml
    my_layout_qvga.xml

Then, select the appropriate layout at run time:

protected void onCreate(Bundle savedInstanceState)
{
    // Some code that uses DisplayMetrics to determine the screen type
    ScreenType st = Util.getScreenType(this);
    super.onCreate(savedInstanceState);
    setContentView(st == ScreenType.ST_QVGA ? R.layout.my_layout_qvga : R.layout.my_layout_default);
    // ...

You can add a tag to each layout to discover which one was actually loaded, if you like, e.g.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/my_root_view"
    android:tag="st_port_QVGA"

FrameLayout flRoot = (FrameLayout)findViewById(R.id.my_root_view);
Object objTag = flRoot.getTag();
if (objTag instanceof String)
{
    String strTag = (String)objTag;
    System.out.println("Tag = " + strTag);
}

BTW, there's no reason why you cannot combine this technique with the usual resource qualifiers, e.g. add files like my_layout_default.xml to other folders.

like image 40
Jeff Lawson Avatar answered Sep 25 '22 08:09

Jeff Lawson


I faced a pretty similar situation. My detail fragment usually appears fullscreen, but on tablets, it can sometimes take up only 70% of the screen width (in a master-detail flow). When the detail fragment is fullscreen on tablets, it should use a large layout. When the detail fragment is only 70% of the width, it should use the smaller phone layout. Here's how I handle it.

I have a fragment_detail.xml like so

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/fragment_detail_force_phone" />

</LinearLayout>

with fragment_detail_force_phone.xml containing the actual layout for a small screen (or when it's being shown on a tablet with only 70% width). This avoids code duplication.

The large layout is in sw600dp/fragment_detail.xml. When I'm inflating the detail fragment, I check getActivity() to see if this fragment is being loaded in a narrow space, which means I want to force the phone layout. If that's the case, I inflate R.layout.fragment_detail_force_phone. Since there's not a tablet version of that layout, it always loads the phone code if I specify so. Otherwise, I inflate R.layout.fragment_detail and Android will appropriately choose as usual.

like image 23
Patrick Avatar answered Sep 26 '22 08:09

Patrick