Android材质将字体基线对齐到4dp网格

时间:2014-10-21 13:09:43

标签: android fonts grid alignment

Android材料设计规范说"类型与4 dp基线网格对齐。"(http://www.google.com/design/spec/layout/metrics-and-keylines.html#

它还在示例图形中说明列表中的行应该是72dp高。

它还表示不同的字体样式以及字体应该是多大以及它的前导应该是什么(http://www.google.com/design/spec/style/typography.html#typography-standard-styles)。

我正在尝试将所有这些规则应用到我的应用程序中以调整列表中行的布局,但是我不知道如何将行中的文本框分开。

我的每一行

都有3行文字显示

标题线一号14sp    细节线两个 - 大小12sp    细节第三行 - 大小12sp

如何确保每个文本框中文本的基线与网格对齐?我无法对齐文本框的底部,因为这不是基线,文本框的底部是基线+下降不是吗?

我需要尽可能均匀地分隔3行文本,但要确保它们的基线与网格对齐。

我不相信我可以简单地使用填充/边距,因为这不会确保每行文本的基线与网格对齐。

另外,当我进行所有这些计算时,我需要确保行高为72dp(对于指定了正常字体大小的mdpi设备)。

最后我将如何指定领先?据我所知,这是从上面一行文本的基线到底行最高文本顶部的空间。再次,我不能使用填充/边距,因为这不是基线。

enter image description here

编辑:列表的材料规范有更多信息,说明当您有3行文本时,列表中的图块应如何显示。 http://www.google.co.uk/design/spec/components/lists.html#lists-keylines

但它仍然没有说明3行文本是如何实际垂直放置的,以便它们的基线在4dp网格上对齐。 enter image description here

4 个答案:

答案 0 :(得分:5)

<强>更新

根据我的回答,我做了a small library。它比现在的答案更适合现实世界使用,所以请随时查看。

不是简单地确保4dp对齐,而是允许分别在所有行和第一行上设置前导,并且最后一行下降:

enter image description here

上一个回复,左侧是出于历史目的(已移除大型屏幕截图)

好的,这已经很晚了,但我想出了如何以最不可能的hackish 的方式做到这一点。

此方法将在基准网格上放置现有视图,前提是其上限已在基线网格上。输入参数是网格的一个步骤(4dp,以像素为单位,可能是从资源中读取)和所需的行前导(例如20dp,以像素为单位)。

注意,这不会为您提供所需的确切高度,但它会使TextView的大小具有确定性(即step的高度倍数与基线在网格上),使用整数边距使您更容易布局。

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);
}

答案 1 :(得分:3)

您可以使用特定高度的辅助视图将文本视图基准到此高度。

<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>

使用此助手视图

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();
   }
}

答案 2 :(得分:0)

您可以在XML文件中使用android:lineSpacingExtra和android:lineSpacingMultiplier来获取行间距。要对ListView的单行进行适当的布局,它可能有所帮助: -

<?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="88dp"
    android:background="#fff"
    android:orientation="horizontal"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:paddingLeft="16dp" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="45dp"
        android:layout_height="match_parent"
        android:background="#000"
        android:padding="16dp" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:paddingRight="72dp"
        android:paddingLeft="16dp"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"            
            android:text="TextView"
            android:textColor="#000"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/textView2"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:text="asdjkfah asdfakj sdfjshd sdgf dfg " />
    </LinearLayout>

</LinearLayout>

答案 3 :(得分:0)

您应该引用此类,以便将TextView中的文本与4dp基线网格对齐:
https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/ui/widget/BaselineGridTextView.java