Представления в пользовательской группе не отображаются - PullRequest
7 голосов
/ 02 января 2012

Я недавно углубился в создание пользовательских ViewGroups и столкнулся с проблемой, которую не могу понять.

У меня есть 2 ViewGroups - ViewManager и Article

ViewManager просто выкладывает статью нижепредыдущая статья (то есть, как вертикальная LinearLayout)

Статья организует несколько TextViews и ImageView, как вы можете видеть на изображении.Создание отдельной статьи и добавление ее в ViewManager работает нормально, и все отображается, но когда я добавляю вторую статью, содержимое статьи не видно.

Illustrates second view not showing

Так почему жени один из TextViews или ImageView не появляется (обратите внимание, что синяя полоса рисуется с canvas.drawRect () в onDraw ()).Я также распечатал (через logcat) связанные значения дочерних представлений (то есть getLeft () / Top () / Right () / Bottom () в drawChild ()), и все они выглядят нормально

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

Так кто-нибудь имеет представление о том, что я сделал неправильно?

метод Article 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)

1 Ответ

9 голосов
/ 02 января 2012

В onLayout дети должны быть расположены относительно их родителей.Вы добавляете topleft) к координатам детей.Это не проблема для первой статьи, потому что top и left равны нулю.Для второй статьи left по-прежнему равен нулю, а top - верх второй статьи в ViewManager.Просто избавьтесь от newTop и newLeft и используйте, соответственно, marginTop и outerMargin на их месте.

Относительно вашего отступления: первый аргумент makeMeasureSpec должен быть измерением,Используя WRAP_CONTENT, вы устанавливаете максимальный размер -2, что, вероятно, не то, что вы хотите.

...