0

I am not so sure why my custom viewgroup won't render the textview wihtin its child which is a linear layout:

This is my viewgroup code:

import android.content.Context;
import android.graphics.Color;
import android.graphics.RectF;
import android.view.View;
import android.view.ViewGroup;

public class noteLayout extends ViewGroup {
    float leftOrientationSize = 0;
    float rightOrientationSize=0;
    public noteLayout(Context activityContext)
    {
        super(activityContext);
    }
    @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 = 300;
            rect.top = 20;
            rect.left = 50;
            rect.right = (getWidth()/2)-20;
            childView.layout((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom);
        }
    }
}

I have created a simple linear layout with a textview inside. This file is in xml and it is called test3.

Also, the following code is used to add the test3 layout into the custom viewgroup.

   private void layoutNoteView() {
        noteLayout noteLayout = new noteLayout(this);
        noteLayout.addView((View) getLayoutInflater().inflate(R.layout.test3,null));
        RelativeLayout.LayoutParams noteLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        noteLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            noteLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
        }
        noteLayoutParams.addRule(RelativeLayout.BELOW, R.id.StartRelativeLayout);
        relativeLayoutMain.addView(noteLayout,noteLayoutParams);
    }

My question is I am not so sure why my custom viewgroup won't even render the textview inside the linear layout. All it renders is just the linear layout of the test3 layout file. I am so desperately trying to figure out how can I get the textview to get rendered.

Please note that if I have a textView alone without putting it into the linearlayout, my custom viewgroup renders that textview perfectly fine. It only happens when I have it within a layout and then put it in my custom viewgroup layout.

Wowzer
  • 1,103
  • 2
  • 12
  • 26
  • Are you measuring your views? Just extending viewgroup will not call any measuring methods as far as i know – David Medenjak Mar 05 '16 at 23:12
  • no I am actually not measuring my view. I am kinda new to viewgroup that is why I am dabbling with it trying to learn things so can you explain to me what am I suppose to do? – Wowzer Mar 05 '16 at 23:14
  • look how the measurement works on other views, and look for tutorials on cusomt viewgroups, e.g. FrameLayout here http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.2_r1/android/widget/FrameLayout.java#FrameLayout – David Medenjak Mar 05 '16 at 23:17
  • Thanks for answering, but do I have to measure my linearlayout in order for it to display the text view within my viewgroup? Cause alone without the textview being in the linear layout the textview displays just fine on my view group it is when I try to put both the linear layout and the text view within the linear layout that is when the problem occurs. – Wowzer Mar 05 '16 at 23:19
  • The linearlayout will render fine if you just lay it out in `onLayout`, the textview inside wont, because the linear layout itself did not measure how to lay out the textview...which is why you need to measure it, so that it can measure its children as well – David Medenjak Mar 05 '16 at 23:27
  • But when you create an xml layout file and add a textview shouldn't the linear layout already knows where to render the textview? Cause all I did was go to my res folder create a new layout resource file then drag and drop in a textview. So shouldn't the linear layout knows where to put the textview in this case? I can definitely see the textview being rendered within the linearlayout – Wowzer Mar 05 '16 at 23:33
  • measurement and layout goes from the root of the layout to the bottom. it happens "automatically" if you don't break the chain and also measure and layout your views :) – David Medenjak Mar 05 '16 at 23:40
  • Aw oh my god I think I kinda get it now. So when I actually break the root of the layout by adding that layout into another layout I am essentially nullifying the measurement right? so then I need to re do the measurement. Am I correct in this clarification? – Wowzer Mar 05 '16 at 23:43
  • Yes. Just add measurement and it should work. – David Medenjak Mar 05 '16 at 23:45
  • Hey Thanks by any chance you can put your comment as answer so I can check it off? – Wowzer Mar 05 '16 at 23:46
  • Oh really quick question OnMeasure returns how much the custom viewgroup should be right? If so I am not so sure how does it has anything to do with the measurement of the linearlayout – Wowzer Mar 06 '16 at 00:21

1 Answers1

1

Drawing a ViewGroup to the screen requires 2 steps:

  1. measure the ViewGroup and its children to get the correct size

  2. layout the children where they should draw themselves

Measure is about finding out how big a view is. After measuring, you should have a value indicating how big a view needs to be.

Layout is about actually assigning position and size to a view. You can, but shouldn't, ignore the values returned by the measurement. Making it bigger usually is no problem, but making it smaller will most likely cut something off.

By not calling the measuring methods on the children of your ViewGroup they have no knowledge of how big they can be, or how much space they will get.

Just layouting a TextView to the full width/height will render correctly, since it gets enough size to render correctly.

Layouting a LinearLayout without prior measurement, the LinearLayout itself has no knowledge about its children. For layouting purpose, it is looking at getMeasuredHeight() but will find no value there, hence be not able to layout its children. This is why the LinearLayout will 'draw' but its children not.


Always include measurement, or extend from an existing layout that you want to extend, e.g. FrameLayout if you just want to set positions yourself, but children may overlap. Without measuring, some things will work fine, while others won't, and this would mostly just be trial and error about finding out what will.

David Medenjak
  • 33,993
  • 14
  • 106
  • 134
  • Thanks for the thorough response but I there are little things that I didn't quite understand. You said making it bigger wouldn't affect the rendering process but making it smaller would cut something off. I tried making the layout bigger but it still won't render the textview properly. Also, how does onmeasure give the linear layout knowledge about its children. This doesn't make sense to me because shouldn't the linearlayout already know that there is a children in it already and should lay that children out? – Wowzer Mar 06 '16 at 17:02
  • @Wowzer It knows about the children, but the size it needs to lay them out is calculated in onMeasure. No measurment - No size - Wrong Layout. It **needs** the measurement pass. So do most other views and viewgroups. – David Medenjak Mar 06 '16 at 17:08
  • I been playing around with the onmeasure method but I can't seem to get it to display the textview still. I write SetMeasuredDimension(200,200) and also have tried out different value for it and still can't get the a part of the textview to even show. – Wowzer Mar 06 '16 at 18:50
  • see http://stackoverflow.com/questions/33912473/android-designing-the-view-for-a-calendar-app/33923513#33923513 for an example of how to measure / layout, you have to call measure on the children – David Medenjak Mar 06 '16 at 19:08
  • Hey thanks for the great link but there is a couple of thing that is not explained in the link that confuse me. Precisely what exactly is int widthMeasureSpec, int heightMeasureSpec passed into the onmeasure and what is passed into the child.measure method? – Wowzer Mar 06 '16 at 19:59
  • @Wowzer I can't give you a full blown tutorial, please try googling and look through other source code, like frame layout and linear layout – David Medenjak Mar 06 '16 at 20:21