android - 自定义 ViewGroup 中的 View 未显示

标签 android android-layout android-custom-view viewgroup

我最近深入研究了创建自定义 ViewGroup 并遇到了一个我无法弄清楚的问题。

我有 2 个 ViewGroups - ViewManager 和 Article

ViewManager 简单地在上一篇文章下方布置一篇文章(即像一个垂直的 LinearLayout)

Article 安排了几个 TextView 和一个 ImageView,如您在图像中所见。创建单个文章并将其添加到 ViewManager 工作正常,所有内容都会显示,但是当我添加第二篇文章时,文章的任何内容都不可见。

Illustrates second view not showing

那么为什么没有显示 TextView 或 ImageView(请注意,蓝色条是在 onDraw() 中使用 canvas.drawRect() 绘制的)。我还打印了(通过 logcat) subview 的绑定(bind)值(即 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)

最佳答案

onLayout 中,子元素应该相对于它们的父元素定位。您正在将 top(和 left)添加到子项的坐标中。这对于第一篇文章来说不是问题,因为 topleft 为零。对于第二篇文章,left 仍为零,但 top 是其 ViewManager 中第二篇文章的顶部。只需去掉 newTopnewLeft 并分别使用 marginTopouterMargin 代替它们。

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

关于android - 自定义 ViewGroup 中的 View 未显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8696899/

相关文章:

android - 我可以删除工具 :context from the activity layouts?

java - Gradle 错误 Could not find com.actionbarsherlock :actionbarsherlock:4. 4.0 with Eclipse exported project in Android Studio

Android 安装基数在 2 天内大幅下降。如何查明发生了什么?

Android BitmapShader改变颜色

android - 使用掩码显示具有 2 种不同颜色的 TextView

android - 从 xml 布局文件创建自定义 View 类的最佳方法?

Android:自定义选项菜单

安卓数据库加密

android - 键盘出现时如何防止滑动布局

android - 工作线程与后台线程android有什么区别?