我最近已经深入研究创建自定义ViewGroups并遇到了一个我无法弄清楚的问题。
我有2个ViewGroups - ViewManager和文章
ViewManager只是在前一篇文章下面放置一篇文章(例如像一个垂直的LinearLayout)
文章可以在图像中看到几个TextView和ImageView。创建单个文章并将其添加到ViewManager工作正常,一切都会显示,但是当我添加第二篇文章时,文章的内容都不可见。
那么为什么没有TextViews或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)
答案 0 :(得分:9)
在onLayout
中,孩子应该与父母相关。您正在将top
(和left
)添加到子项的坐标中。这对第一篇文章来说不是问题,因为top
和left
为零。对于第二篇文章,left
仍为零,但top
是其ViewManager中第二篇文章的顶部。只需摆脱newTop
和newLeft
,然后分别使用marginTop
和outerMargin
。
关于你的旁白:makeMeasureSpec
的第一个参数应该是一个维度。通过使用WRAP_CONTENT,您将最大尺寸设置为-2,这可能不是您想要做的。