2012-01-02 92 views
6

我最近研究了创建自定义ViewGroups并遇到了一个我无法弄清楚的问题。自定义ViewGroup中的视图不显示

我有2个ViewGroups - ViewManager条和第

ViewManager简单地勾画出以前的文章下面的文章(即像一个垂直的LinearLayout)

第二十安排几个TextViews,正如你可以在看到一个ImageView的图片。创建一篇文章并将其添加到ViewManager中可以正常工作,并且所有内容都显示出来,但是当我添加第二篇文章时,文章的内容都不可见。

Illustrates second view not showing

那么,为什么没有TextViews或显示出的ImageView的(注意蓝色条画有canvas.drawRect()中的onDraw())。我还通过logChild()打印了(通过logcat)子视图的绑定值(即getLeft()/ Top()/ Right()/ Bottom(),并且它们看起来都很好看

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 

因此,没有人有什么我做错了的想法?

的文章onMeasure方法

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

和onLayout方法

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; 

} 

在附注中,可以使用LayoutParams.WRAP_CONTENT作为makeMeasureSpec()的参数吗?

MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.AT_MOST) 
+0

你能发表正确的答案吗?我不明白 – 2015-06-25 08:59:07

回答

8

onLayout,孩子们应定位相对于他们的父母。您正在将top(和left)添加到孩子的坐标中。对于第一篇文章,这不是问题,因为topleft为零。对于第二篇文章,left仍为零,但top是ViewManager中第二篇文章的顶部。只需摆脱newTopnewLeft并分别使用marginTopouterMargin替代。

关于你的撇开:makeMeasureSpec的第一个参数应该是一个维度。通过使用WRAP_CONTENT,您将最大维数设置为-2,这可能不是您想要的。

+0

感谢,在这两个方面,直接工作 – triggs 2012-01-02 20:34:49

+2

Upvote for *在onLayout中,孩子应该相对于他们的父母*定位。 – neevek 2013-03-03 10:26:49

+1

对我来说,问题在于我重写了自定义视图的OnLayout方法,因为我从ViewGroup继承了,但是我没有将任何实现代码添加到OnLayout中。我不必在OnLayout中编写令人讨厌的定位代码,而是从RelativeLayout继承,然后完全删除OnLayout方法。 – Justin 2014-07-01 19:56:54