Rastio
Rastio

Reputation: 1516

How to define layout that will work on 720p as well as 1080p screens?

I know I'm supposed to define different layouts for different screens, please read on.

I'm working on the app that will be run an "Android on the stick" plugged to either 720p or 1080p TV and left alone to show some "slide show".

I need something like android:layout_width="n%". I know I can do it with LinearLayout, but the screen is rather complex and such deep nesting is discouraged. I would like to stick to RelativeLayout.

I have designed the layout specifying the metrics in pixels, designing for 1080p and put the layout to layout-tvdpi or layout-xhdpi hoping Android would scale it properly down to 720p. It does not. All artefacts are overblown and overlap.

Is there a way to achieve what I want? Thanks.

Upvotes: 1

Views: 1275

Answers (2)

Rastio
Rastio

Reputation: 1516

As I mentioned in the question, the app I'm working on will be displayed on either 720p or 1080p TV. This allows me to commit the following blasphemy: All view sizes/paddings/margins and text sizes are defined in PX, not DP, not SP. This way I can control the exact screen layout. Now, contrary to what the documentation made me to believe, Android will not resize any layout element that has size defined in PX. It will only do it for drawables or DP/SP.

Thus I had to resize on my own.

I define the layouts for 1080p. in Activity.onCreate() get the root layout and pass it to:

private static final float RATIO_720_1080 = 720f/1080f;

/**
 * If the screen is 720p, the resources will resize
 * to fit the screen.
 * @param root Root view where the resources are found.
 */
public void resizeViews(ViewGroup root) {
    DisplayMetrics metrics = getResources().getDisplayMetrics();
    // only resize if 720p
    if (metrics.widthPixels != 1280) return;

    int childCount = root.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View v = root.getChildAt(i);

        // digg deep
        if (v instanceof ViewGroup) {
            resizeViews((ViewGroup)v);
        }

        // do the size
        ViewGroup.LayoutParams params = v.getLayoutParams();
        // keep the match_parent constants intact
        if (params.height > 0) {
            params.height = Math.round(params.height * RATIO_720_1080);
        }
        if (params.width > 0) {
            params.width = Math.round(params.width * RATIO_720_1080);
        }
        if (params instanceof ViewGroup.MarginLayoutParams) {
            ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) params;
            marginParams.setMargins(Math.round(marginParams.leftMargin * RATIO_720_1080),
                    Math.round(marginParams.topMargin * RATIO_720_1080),
                    Math.round(marginParams.rightMargin * RATIO_720_1080),
                    Math.round(marginParams.bottomMargin * RATIO_720_1080));
        }
        v.setLayoutParams(params);

        v.setPadding(Math.round(v.getPaddingLeft() * RATIO_720_1080),
                Math.round(v.getPaddingTop() * RATIO_720_1080),
                Math.round(v.getPaddingRight() * RATIO_720_1080),
                Math.round(v.getPaddingBottom() * RATIO_720_1080));

        // text size
        if (v instanceof TextView) {
            float size = ((TextView)v).getTextSize();
            size *= RATIO_720_1080;
            ((TextView)v).setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
        }
    }
}

Upvotes: 1

Yuichi Araki
Yuichi Araki

Reputation: 3458

You can use a layout file like below. Notice the layout_sum attribute in the parent layout, and the layout_weight attribute in each child. The first child will occupy 70% of the parent, and the second child 30%.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="100">
    <Button
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="70"
        android:text="A"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="30"
        android:text="B"/>
</LinearLayout>

Upvotes: 0

Related Questions