In my app I'm trying to adjust this layout so it's readable when the user scales the system wide font size in Android System settings -> Display -> Font size (or in accessibility settings on some devices). Doing some digging I found out this adjusts the device configuration font scale (getResources().getConfiguration.fontScale
) from 1.0
to 1.15
.
I'm getting some weird behavior in a LinearLayout
where one of the TextView
s width gets crushed, when it's set to wrap_content
, and also doesn't reflect a set minWidth
.
What it looks like normally
What it looks like when font is scaled
Here is the LinearLayout
in question (comments added for context in screenshot)
<LinearLayout
android:id="@+id/sectionPaintStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- () 6 Paint Items -->
<LinearLayout
android:id="@+id/sectionPaintItemToggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="5dp">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabExpandPaintItems"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:rotation="180"
android:src="@drawable/ic_collapse"
app:elevation="2dp"
app:fabSize="mini"/>
<TextView
android:id="@+id/tvPaintItemCount"
style="@style/Label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="0 Paint Items"
android:textSize="16sp"/>
<ImageView
android:id="@+id/imgPaintAreaWarning"
android:layout_width="20dp"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
android:scaleType="centerInside"
android:src="@drawable/ic_edit_warning2"
android:visibility="invisible"/>
</LinearLayout>
<!-- Inner layout to consume middle width and right align the rest -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/layoutPaintItemCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="vertical"
android:visibility="invisible">
<TextView
android:id="@+id/tvPaintItemCountStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Paint Items"
android:textSize="16sp"/>
</LinearLayout>
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="30dp"
android:scaleType="centerInside"
android:src="@drawable/ic_time"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="vertical">
<TextView
android:id="@+id/tvPaintTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2.5h"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Time"
android:textSize="16sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:minWidth="70dp"
android:gravity="end"
android:orientation="vertical">
<TextView
android:id="@+id/tvPaintTotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="$123.22"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total"
android:textSize="16sp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Why is that last LinearLayout
containing 2 TextView
s not properly wrapping content? I tried removing the minWidth
incase that was causing any issues and got the same result. I don't understand why all the other layouts wrap their content properly but the last one doesn't.
And is it possible to add a resource folder for scaled system wide font?
Edit It appears removing margins allow the TextView
to wrap the proper width but obviously I need the margins.
Can anyone explain this strange behavior?
Edit Solved It turns out I completely forgot about an invisible element in the layout between the "Paint Items" label and the time icon. It was causing me to run out of horizontal space.
You appear to have used layout_width="match_parent"
and gravity="end"
to align your elements.
I assume on small devices (or with large text) you'd like the "0 Paint Items" to ellipsize when not enough space, and have the 'Time' and 'Total' fields to show at full width.
To do this, we make the following changes:
First, make the sectionPaintItemToggle
have 0dp
width and layout_weight="1"
- this tells Android "this should fill as much space is available".
<LinearLayout
android:id="@+id/sectionPaintItemToggle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
... >
I removed all the gravity="end"
settings.
I changed the "inner layout" (as per the comment) to be have wrap_content
width.
I deleted the entire layoutPaintItemCount
layout - I feel like you were trying a different way to do the "N paint items" layout.
In the end, we have something like this (I swapped in an ImageView for the FAB and just used resources I already had - I think I changed some margins too):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/sectionPaintStatus"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
>
<!-- () 6 Paint Items -->
<LinearLayout
android:id="@+id/sectionPaintItemToggle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clipToPadding="false"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="5dp">
<ImageView
android:id="@+id/fabExpandPaintItems"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="5dp"
android:rotation="180"
android:src="@drawable/ic_edit_black_24dp"/>
<TextView
android:id="@+id/tvPaintItemCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="0 Paint Items"
android:textSize="16sp"/>
<ImageView
android:id="@+id/imgPaintAreaWarning"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
android:scaleType="centerInside"
android:src="@drawable/ic_edit_black_24dp"
android:visibility="invisible"/>
</LinearLayout>
<!-- Inner layout to consume middle width and right align the rest -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="centerInside"
android:src="@drawable/ic_edit_black_24dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tvPaintTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2.5h"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Time"
android:textSize="16sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="30dp"
android:layout_marginStart="30dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvPaintTotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="$123.22"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total"
android:textSize="16sp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
The key part was to convince Android that the "N Paint Items" view was the one you wanted to shrink.