简体   繁体   English

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

[英]Android staticlayout height is not consistent which causes weird rendering bug

I have recently created a custom view to test the StaticLayout.getHeight() method and I found out that it is really inconsistent. 我最近创建了一个自定义视图来测试StaticLayout.getHeight()方法,但发现它确实不一致。 Let me write down the code first before I explain what is wrong: 在解释错误之前,让我先写下代码:

This is my MainActivity.java 这是我的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);
    }

}

This is my custom layout: 这是我的自定义布局:

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

This is my activity_main.xml: 这是我的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>

This is my activity_test3.xml that I inflated: 这是我夸大的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>

Now my problem is that in my custom Layout, I tell its child which is a relativeLayout to measure itself. 现在我的问题是,在我的自定义布局中,我告诉它的子项是要测量自身的relativeLayout。 The relativeLayout is basically the relativeLayout from the activity_test3.xml which contains the custom view I created called titleTextView. relativeLayout基本上是来自activity_test3.xml的relativeLayout,其中包含我创建的名为titleTextView的自定义视图。 In this view I override the onMeasure() method and use a staticLayout to obtain a height to set. 在此视图中,我重写onMeasure()方法,并使用staticLayout获得要设置的高度。 Then my relativeLayout which is the parent of titleTextView basically measure itself and has the constraint from its child which is the titleTextView(See the Code Above to Clarify any confusion cause it is really hard to explain). 然后,我的relativeLayout是titleTextView的父级,基本上可以自行测量,并且受到其子项(titleTextView)的约束(请参见上面的代码来澄清任何难以解释的混淆原因)。

My problem is this that the relativeLayout height comes out to be smaller than than what is needed and hence it clip the child. 我的问题是,relativeLayout的高度比所需的高度要小,因此会夹住孩子。 Here are some image: 这是一些图片:

在此处输入图片说明

在此处输入图片说明

Furthermore, you can see, the height is really inconsistent for both the different devices and I thought that staticLayout.getHeight() suppose to return a consistent pixel size. 此外,您可以看到,两个设备的高度都确实不一致,并且我认为staticLayout.getHeight()应该返回一致的像素大小。 I am not so sure how to fix it and would like help. 我不确定如何解决它,并希望获得帮助。

Note: I have tried multiplying the pixel size return by staticLayout.getHeight by the density and it becomes too large to perfectly fit the text inside it. 注意:我尝试将返回的像素大小乘以staticLayout.getHeight乘以密度,但它变得太大而无法完全适合其中的文本。

Add the top (rect.top = 20 in your case) offset to the rect.bottom in your custom layout onLayout method: 在自定义布局onLayout方法中,将top偏移量(在您的情况下为rect.top = 20)添加到onLayout

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

The inconsistency in the height is due to the different pixel density of the devices. 高度不一致是由于设备的像素密度不同所致。 Some relative information can be found at What is the difference between getWidth/Height() and getMeasuredWidth/Height() in Android SDK? 可以在以下位置找到一些相关信息: Android SDK中的getWidth / Height()和getMeasuredWidth / Height()有什么区别?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM