Android staticlayout高度不一致导致奇怪的渲染错误

时间:2016-04-05 07:15:09

标签: java android

我最近创建了一个自定义视图来测试StaticLayout.getHeight()方法,我发现它确实不一致。在我解释错误之前,让我先写下代码:

这是我的MainActivity.java

   package com.ayto.android.test;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.RelativeLayout;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RelativeLayout mainParent = (RelativeLayout) findViewById(R.id.mainActivity);
        RelativeLayout childRelativeLayout = (RelativeLayout) getLayoutInflater().inflate(R.layout.activity_test3,null);
        noteLayout testNoteLayout = new noteLayout(this);
        testNoteLayout.addView(childRelativeLayout);
        mainParent.addView(testNoteLayout);
    }

}

这是我的自定义布局:

package com.ayto.android.test;
import android.content.Context;
import android.graphics.RectF;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
public class noteLayout extends ViewGroup {
    public noteLayout(Context activityContext)
    {
        super(activityContext);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        RelativeLayout mainParent = (RelativeLayout) getParent();
        for (int i = 0; i < getChildCount(); i++) {
            RelativeLayout child = (RelativeLayout) getChildAt(i);
            child.measure(MeasureSpec.makeMeasureSpec((mainParent.getWidth() / 2), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (child.getChildAt(0).getMeasuredHeight()), MeasureSpec.EXACTLY));
        }
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int numberOfChild = getChildCount();
        for (int i = 0;i<numberOfChild;i++){
            View childView = getChildAt(i);
            float childHeight = (float) childView.getMeasuredHeight();
            float childWidth = (float) childView.getMeasuredWidth();
            RectF rect = new RectF();
            rect.bottom = childHeight;
            rect.top = 20;
            rect.left = 20;
            rect.right = childWidth+20;
            childView.layout((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom);
        }
    }
}

这是我的activity_main.xml:

    <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" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
    android:id="@+id/mainActivity">

    />
</RelativeLayout>

这是我膨胀的activity_test3.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#EF5350">

    <com.ayto.android.test.titleTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/titleTextView"
        android:textSize="18sp"
        android:text="sadasdas das dasd asd as dasdasdasdsad sad asd asd asdasdasdsa sa zvczz xczxczxczx sadasasdsadsadsaasd "

        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

</RelativeLayout>

现在我的问题是在我的自定义布局中,我告诉它的孩子哪个是relativeLayout来衡量自己。 relativeLayout基本上是来自activity_test3.xml的relativeLayout,它包含我创建的名为titleTextView的自定义视图。在此视图中,我覆盖onMeasure()方法并使用staticLayout获取要设置的高度。然后我的relativeLayout(它是titleTextView的父亲)基本上测量自己并且具有来自其子节点的约束,即titleTextView(请参阅上面的代码以澄清任何混淆,因为它很难解释)。

我的问题是,relativeLayout高度小于所需的高度,因此会剪切孩子。这是一些图片:

enter image description here

enter image description here

此外,您可以看到,不同设备的高度确实不一致,我认为staticLayout.getHeight()假设返回一致的像素大小。我不太确定如何解决它并希望得到帮助。

注意:我已经尝试将staticLayout.getHeight返回的像素大小乘以密度,它变得太大而不能完全适合其中的文本。

1 个答案:

答案 0 :(得分:0)

在自定义布局onLayout方法中将top(rect.top = 20,在您的情况下)偏移添加到rect.bottom:

protected void onLayout(boolean changed, int l, int t, int r, int b) {
        .
        .
        .
        rect.bottom = childHeight + 20;

高度的不一致是由于设备的像素密度不同。可以在What is the difference between getWidth/Height() and getMeasuredWidth/Height() in Android SDK?

找到一些相关信息