首页 文章

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

提问于
浏览
14

Android Material Design规范说"Type aligns to a 4 dp baseline grid."(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行文字显示

Headers 线一个尺寸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 回答

  • 3

    Update

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

    它不是简单地确保4dp对齐,而是允许分别设置所有线和第一行的前导,以及最后一行下降:

    enter image description here


    之前的回复,留给历史目的(删除大屏幕截图)

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

    该方法将在基线网格上着陆现有视图,因为其上限已经在基线网格上 . 输入参数是网格的步长(4dp,以像素为单位,可能是从资源中读取)和所需的行前导(例如,以像素为单位的20dp) .

    Note 这确定了大小确定性(即 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);
    }
    
  • 0

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

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

    您可以在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>
    
  • 0

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

相关问题