Views in the custom ViewGroup are not displayed.

I recently delved into creating custom view groups and ran into a problem that I cannot understand.

I have 2 ViewGroups - ViewManager and article

ViewManager simply sets out the article below the previous article (e.g., vertical LinearLayout)

The article arranges several TextView and ImageView, as you can see in the image. Creating a separate article and adding it to the ViewManager works fine, and everything appears, but when I add the second article, none of the contents of the article are visible.

Illustrates second view not showing

So, why none of the TextViews or ImageView appears (note that the blue bar is drawn using canvas.drawRect () in onDraw ()). I also printed (via logcat) the associated values ​​of the child views (i.e. GetLeft () / Top () / Right () / Bottom () in drawChild () and they all look great

FIRST TextView FIRST left 5 right 225 top 26 bottom 147 FIRST TextView FIRST left 5 right 320 top 147 bottom 198 FIRST TextView FIRST left 5 right 180 top 208 bottom 222 FIRST ImageView FIRST left 225 right 315 top 34 bottom 129 SECOND TextView SECOND left 10 right 53 top 238 bottom 257 SECOND TextView SECOND left 5 right 325 top 257 bottom 349 SECOND TextView SECOND left 5 right 320 top 349 bottom 400 SECOND TextView SECOND left 5 right 180 top 410 bottom 424 

And does anyone have any idea what I did wrong?

method onMeasure articles

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); specWidth = widthSpecSize; int totalHeight=0; int width = 0; if(mImage!=null&&mImage.getParent()!=null){ measureChild(mImage,MeasureSpec.makeMeasureSpec(100, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(100, MeasureSpec.AT_MOST)); width=widthSpecSize-mImage.getWidth(); imageWidth = mImage.getMeasuredWidth(); } for(int i = 0;i<this.getChildCount();i++){ final View child = this.getChildAt(i); //get the width of the available view minus the image width if(imageWidth > 0) width =widthSpecSize- imageWidth; else width = widthSpecSize; //measure only the textviews if(!(child instanceof ImageView)){ measureChild(child, MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), heightMeasureSpec); //calculate total height of the views, used to set the dimension totalHeight+=child.getMeasuredHeight(); } } //if the title height is greater than the image then the snippet //can stretch to full width if(mTitle.getMeasuredHeight()>mImage.getMeasuredHeight()) measureChild(mSnippet, MeasureSpec.makeMeasureSpec(widthSpecSize, MeasureSpec.AT_MOST), heightMeasureSpec); //measure source to make it full width measureChild(mSource,MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.AT_MOST), heightMeasureSpec); setMeasuredDimension(widthSpecSize, totalHeight); } 

and onLayout method

 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int newLeft = left+outerMargin; int newTop = top+marginTop; int prevHeight = 0; if(mEngine!=null){ int height = mEngine.getMeasuredHeight(); int childRight = newLeft+mEngine.getMeasuredWidth(); mEngine.layout(newLeft+marginLeft, newTop+prevHeight+2, childRight+marginLeft, newTop+height+prevHeight+2); maxRight = Math.max(maxRight, childRight); prevHeight += height+2; topBarHeight = mEngine.getMeasuredHeight()+(marginLeft*2); maxBottom = Math.max(maxBottom, mEngine.getBottom()); } if(mTitle!=null){ int height = mTitle.getMeasuredHeight(); int childRight = newLeft+mTitle.getMeasuredWidth(); mTitle.layout(newLeft, newTop+prevHeight, childRight, newTop+height+prevHeight); maxRight = Math.max(maxRight, childRight); prevHeight += height; maxBottom = Math.max(maxBottom, mTitle.getBottom()); } if(mSnippet!=null){ int height = mSnippet.getMeasuredHeight(); int childRight = newLeft+mSnippet.getMeasuredWidth(); mSnippet.layout(newLeft, newTop+prevHeight, right, newTop+height+prevHeight); maxRight = Math.max(maxRight, childRight); prevHeight += height; maxBottom = Math.max(maxBottom, mSnippet.getBottom()); } if(mSource !=null){ int height = mSource.getMeasuredHeight(); int childRight = newLeft+mSource.getMeasuredWidth(); mSource.layout(newLeft, newTop+prevHeight+(marginTop*2), childRight, newTop+height+prevHeight+(marginTop*2)); maxRight = Math.max(maxRight, childRight); prevHeight += height; maxBottom = Math.max(maxBottom, mSource.getBottom()); } if(mImage!=null){ int height = mImage.getMeasuredHeight(); log("mxW "+maxRight); int childRight = maxRight+mImage.getMeasuredWidth(); mImage.layout(right-mImage.getMeasuredWidth()+5, newTop+topBarHeight, right-5, height+topBarHeight); totalWidth = childRight; maxBottom = Math.max(maxBottom, mImage.getBottom()); }else totalWidth = maxRight; } 

On the side of the note, is it good to use LayoutParams.WRAP_CONTENT as a parameter for makeMeasureSpec (), like this?

 MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.AT_MOST) 
+6
source share
1 answer

In onLayout children should be relative to their parent. You add top (and left ) to the coordinates of the children. This is not a problem for the first article, because top and left are zero. For the second article, left is still zero, but top is the top of the second article in ViewManager. Just get rid of newTop and newLeft and use marginTop and outerMargin .

Regarding your attention: the first argument to makeMeasureSpec should be a dimension. Using WRAP_CONTENT, you set the maximum size to -2, which is probably not what you want to do.

+8
source

Source: https://habr.com/ru/post/904868/


All Articles