Представления в пользовательской группе просмотра не отображаются

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

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

ViewManager просто размещает статью под предыдущей статьей (например, как вертикальный LinearLayout).

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

Показывает, что второй вид не отображается

Так почему же не отображаются ни TextView, ни 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

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

Статья о методе измерения

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)

person triggs    schedule 02.01.2012    source источник
comment
можешь опубликовать правильный ответ. я не понял   -  person Amrut Bidri    schedule 25.06.2015


Ответы (1)


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

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

person Ted Hopp    schedule 02.01.2012
comment
Проголосуйте за В onLayout дочерние элементы должны располагаться относительно их родителя. - person neevek; 03.03.2013
comment
Для меня проблема заключалась в том, что я переопределил метод OnLayout моего пользовательского представления, поскольку я унаследовал его от ViewGroup, и при этом я не добавил никакого кода реализации в OnLayout. Вместо того, чтобы писать неприятный код позиционирования в OnLayout, я унаследовал его от RelativeLayout, а затем смог полностью удалить метод OnLayout. - person Justin; 01.07.2014