androidlayoutandroid-screen-support

How to allow an app to adapt to different screen widths automatically


I did a bit of digging into this article, but was not able to get any solution to work.

My problem: I have a header layout that is included in all my screens. And depending on the width of the screen, I want to show one of three different header layouts. Sidenote; my app only supports portrait mode.

My layouts are:

And they should be chosen automatically by the app depending on the screen width. I want to get around doing this programatically because I would need to do this pretty much in every activity, so would be nice if this could be done correct so that the system can handle it.

I tried (but didn't work):

Thanks a lot for your answers in advance!

Edit: The layout looks actually a bit more complicated that described here. The actual layout is the following:

<LinearLayout>
   <RelativeLayout>
     <ImageView />
     <LinearLayout>
        <LinearLayout>
           <ImageView />
           <TextView />
        </LinearLayout>
        <LinearLayout>
           <ImageView />
           <TextView />
        </LinearLayout>
     </LinearLayout>
   </RelativeLayout>
 </LinearLayout>

Also the image inside the first ImageView is loaded from the internet and I don't know its size before it has been loaded.


Solution

  • I create this layout for you. You only need to create one XML file and place the items in this container. Set the importance of the elements. Items with low importance will be remowed (GONE) if there is not enough space. Please tell me if you need something to supplement or change. On my device it works.

    Example

    <com.sup.dev.android.views.widgets.layouts.LayoutImportance
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/red_700"
            android:text="text_1"
            app:LayoutImportance_Layout_importance="5"/>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/blue_700"
            app:LayoutImportance_Layout_importance="1"
            android:text="teeeeeeeeext_2"/>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/green_700"
            app:LayoutImportance_Layout_importance="2"
            android:text="teeeeeeeeext_3_teeeeext"/>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/amber_700"
            app:LayoutImportance_Layout_importance="3"
            android:text="teeeeeeeeext_4_teeeeeeeeeeeeeeeeeeext"/>
    
    </com.sup.dev.android.views.widgets.layouts.LayoutImportance>
    

    LayoutImportance.java

    public class LayoutImportance extends LinearLayout {
    
    private int lock;
    
    public LayoutImportance(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
        if (lock == 0) for (int i = 0; i < getChildCount(); i++) getChildAt(i).setVisibility(VISIBLE);
    
        int w = MeasureSpec.getSize(widthMeasureSpec);
    
        super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.UNSPECIFIED), heightMeasureSpec);
    
        if (getMeasuredWidth() > w) {
    
            ArrayList<View> children = new ArrayList<>();
            for (int i = 0; i < getChildCount(); i++) if (getChildAt(i).getVisibility() == VISIBLE) children.add(getChildAt(i));
            if(children.isEmpty())return;
    
            Collections.sort(children, (o1, o2) -> ((LayoutParams) o1.getLayoutParams()).importance - ((LayoutParams) o2.getLayoutParams()).importance);
            children.get(0).setVisibility(GONE);
    
            lock++;
            onMeasure(widthMeasureSpec, heightMeasureSpec);
            lock--;
        }
    
    }
    
    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }
    
    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(getContext(), null);
    }
    
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }
    
    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        return new LayoutParams(p.width, p.height);
    }
    
    
    public static class LayoutParams extends LinearLayout.LayoutParams {
    
        public int importance;
    
        public LayoutParams(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LayoutImportance_Layout);
            importance = a.getInt(R.styleable.LayoutImportance_Layout_LayoutImportance_Layout_importance, 0);
            a.recycle();
        }
    
        public LayoutParams(int w, int h) {
            super(w, h);
        }
    
    }
    

    }

    attrs.xml

    <declare-styleable name="LayoutImportance_Layout">
        <attr name="LayoutImportance_Layout_importance" format="integer"/>
    </declare-styleable>