2

I have recently created a custom view to test the StaticLayout.getHeight() method and I found out that it is really inconsistent. Let me write down the code first before I explain what is wrong:

This is my 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:

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

<?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. The relativeLayout is basically the relativeLayout from the activity_test3.xml which contains the custom view I created called titleTextView. In this view I override the onMeasure() method and use a staticLayout to obtain a height to set. 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).

My problem is this that the relativeLayout height comes out to be smaller than than what is needed and hence it clip the child. Here are some image:

enter image description here

enter image description here

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

Wowzer
  • 1,103
  • 2
  • 12
  • 26

1 Answers1

0

Add the top (rect.top = 20 in your case) offset to the rect.bottom in your custom layout onLayout method:

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?

Community
  • 1
  • 1
  • Hey thanks for the answer. That is what I thought too. The inconsistency is due to different pixel density on devices but the weird thing is that when I multiply the pixel return by the staticLayout.height() by the density the device from the first image fit fine with the text. However, the second device it becomes so large that it is more than necessary for the text inside. I think I mention above about me multiplying it by the density. – Wowzer Apr 05 '16 at 15:41