我最近深入研究创建自定义 ViewGroups 并遇到了一个我无法解决的问题。
我有 2 个 ViewGroups - ViewManager 和 Article
ViewManager 只是在上一篇文章下方布置一篇文章(即像垂直 LinearLayout)
正如您在图像中看到的那样,文章排列了几个 TextView 和一个 ImageView。创建一篇文章并将其添加到 ViewManager 工作正常,所有内容都会显示,但是当我添加第二篇文章时,该文章的所有内容都不可见。
那么为什么 TextView 或 ImageView 都没有显示出来(注意蓝色条是用 onDraw() 中的 canvas.drawRect() 绘制的)。我还打印了(通过logcat)子视图的绑定值(即drawChild()中的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
那么有人知道我做错了什么吗?
测量方法文章
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)