The Android Material Design Specification says "Type aligns to a 4 dp baseline grid."(http://www.google.com/design/spec/layout/metrics-and-keylines.html#)
It also says in the example graphics that a row in a list should be 72dp high.
It also indicates different font styles and what size the font should be and what its leading should be (http://www.google.com/design/spec/style/typography.html#typography-standard-styles).
I am trying to apply all of these rules to my application to adjust the layout of a row in my listing however I do not know how to space out the text boxes in my row.
I have 3 lines of text to display in each of my row
Heading line one - size 14sp Details line two - size 12sp Details line three - size 12sp
How do I ensure that the baseline of the text in each of these text boxes align with the grid? I can not align the bottom of the text box as this is not the base line, the bottom of the text box is the baseline + descent isn't it?
I need to space out the 3 lines of text as evenly as possible but ensure their baselines align to the grid.
I don't believe I can simply use padding/margins as this will not ensure the baselines of each of the lines of text align with the grid.
Futhermore when I do all this calculations I need to ensure that the row height is 72dp (for an mdpi device with normal font size specified).
Finally how would i specify the leading? As from what I understand this is the space from the baseline of the text of the row above to the top of the highest text in the bottom row. Again i cant use padding/margin as this is not from the baseline.
Edit: The Material Specification for lists have a little more information on how the Tiles in the list should appear when you have 3 lines of text. http://www.google.co.uk/design/spec/components/lists.html#lists-keylines
But it still does not indicate how the 3 lines of text are actually placed vertically so that their baselines align on the 4dp grid.
Update
Based on my answer I made a small library. It is better tailored for real world use than this answer, so please feel free to check it out.
Instead of simply ensuring 4dp alignment, it allows to set leading on all lines and the first line separately, and the last line descent:
Previous reply, left for historical purposes (large screenshot removed)
OK, this is pretty late, but I figured out how to do it in the least possible hackish way.
This method will land an existing view on a baseline grid, given that its upper bound is already on the baseline grid. Input parameters are the step of the grid (4dp in pixels, probably read from resources) and desired leading of the line (e.g. 20dp in pixels).
Note that this won't get you the exact heights that you need, but it will make TextView's size deterministic (i.e. height multiple of step
with baseline being on the grid), making it much easier to layout as you need with the use of integer margins.
private static void setLeading(TextView view, int step, int leading) {
// This is to make the behavior more deterministic: remove extra top/bottom padding
view.setIncludeFontPadding(false);
// Get font metrics and calculate required inter-line extra
Paint.FontMetricsInt metrics = view.getPaint().getFontMetricsInt();
final int extra = leading - metrics.descent + metrics.ascent;
view.setLineSpacing(extra, 1);
// Determine minimum required top extra so that the view lands on the grid
final int alignTopExtra = (step + metrics.ascent % step) % step;
// Determine minimum required bottom extra so that view bounds are aligned with the grid
final int alignBottomExtra = (step - metrics.descent % step) % step;
view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + alignTopExtra, view.getPaddingRight(), view.getPaddingBottom() + alignBottomExtra);
}
You can use a helper view of a specific height to baseline the textviews to this height.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.baselinetest.BaseLineHelperView
android:id="@+id/v_baselinehelper"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="#FF0000" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/v_baselinehelper"
android:text="@string/hello_world" />
</RelativeLayout>
Use this helper view
public class BaseLineHelperView extends View {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public BaseLineHelperView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public BaseLineHelperView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BaseLineHelperView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BaseLineHelperView(Context context) {
super(context);
}
@Override
@ExportedProperty(category = "layout")
public int getBaseline() {
return getHeight();
}
}
You should refer to this class in order to align text in the TextView to 4dp baseline grid:
https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/ui/widget/BaselineGridTextView.java
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With