2012-01-02 56 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