0

I have a simple custom view that I am adding to a layout pragmatically. The view does not draw. Values from onMeasure and onLayout suggest that the view is not drawing because it doesn't have a height. I tried applying the view with constants for layout params, but that didn't fix the problem. I tried setting different combinations of layout params, overriding onMeasure, onDraw, onLayout, setting setMeasuredDimension, setting setWillNotDraw to false, and nothing seems to work.

The layout that this view is being attached it is set to wrap content, and is being created in an adapter. I've posted my source code.

private void addGuessNumeral(RowHolder row) {       
    LinearLayout.LayoutParams numeral_view_params = new LinearLayout.LayoutParams(100, 100); 

    NumeralView numeral_view = new NumeralView(context);
    numeral_view.setLayoutParams(numeral_view_params);
    Log.d("MyGamesAdapter", "row.game.getGuesses.length = " + row.game.getGuesses().length);
    numeral_view.setCount(row.game.getGuesses().length);

    row.layout_numeral.addView(numeral_view);       
}

public class NumeralView extends View {

    private static final int BAR_SPACING = 5;
    private static final int BAR_WIDTH = 5;
    private static final int BAR_HEIGHT = 15;
    private static final int PADDING = 5;

    private static final String TAG = "NumeralView";

    private int count;
    private Paint paint;
    private int width;
    private int height;

    public NumeralView(Context context) {
        super(context);

        paint = new Paint (Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(BAR_WIDTH);

        setWillNotDraw(false);          
    }

    public void setCount(int count) {           
        this.count = count;

    //  this.setLayoutParams(new LayoutParams((PADDING*2) + (count * (BAR_SPACING + BAR_WIDTH)), 
    //          BAR_HEIGHT + (PADDING*2)));
    }

    @Override
    protected void onDraw(Canvas canvas) {          
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

        for(int i = 0; i < count; i++) {
            //algorithm: each bar will occupy on tenth of the width.  Bars are spaced with one tenth of the width apart
            canvas.drawLine(i * (BAR_SPACING + BAR_WIDTH), 0, i * (BAR_SPACING + BAR_WIDTH) + BAR_WIDTH,  height, paint);               
            if (i%5 == 0) {                 
                canvas.drawLine(0, 0, width, height, paint);
            }
        }           
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {            
        Log.d("NumeralView", "left = " + left);
        Log.d("NumeralView", "top = " + top);
        Log.d("NumeralView", "right  = " + right);
        Log.d("NumeralView", "bottom = " + bottom);

        height = bottom - top;
        width = right - left;

        Log.d("NumeralView", "height = " + height);
        Log.d("NumeralView", "width = " + width);

        super.onLayout(changed, left, top, right, bottom);
    }

    /* (non-Javadoc)
     * @see android.view.View#onMeasure(int, int)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.AT_MOST);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightMeasureSpec, MeasureSpec.AT_MOST);

        Log.d("NumeralView", "widthMeasureSpec = " +  widthMeasureSpec);
        Log.d("NumeralView", "heightMeasureSpec = " +  heightMeasureSpec);

        setMeasuredDimension(heightMeasureSpec, heightMeasureSpec);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /* (non-Javadoc)
     * @see android.view.View#onSizeChanged(int, int, int, int)
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);          
    }           
}

If anybody knows of a good resource that goes in depth into how the Android View system works, step by step, and explains how to avoid these problems; I'll be extremely grateful.

Thank you,

Shivam Kumar
  • 1,892
  • 2
  • 21
  • 33
user1164429
  • 241
  • 5
  • 16

1 Answers1

0
  1. if you call setMeasuredDimension , you shouldn't call super.onMeasure , since that would call the default measuring.
  2. inside the onMeasure method , be sure to save the width and height of the view , to be used later by the onDraw .
  3. getting the width and height of the view before the views that contain it "look" at its layout params is impossible , since those containers need to decide what size to give it based on its surroundings.
  4. onLayout - "Called when this view should assign a size and position to all of its children." this means that it's intended only for views that contain other views (ViewGroup) .

see the next links for more info:

http://developer.android.com/guide/topics/ui/custom-components.html

http://developer.android.com/guide/topics/ui/how-android-draws.html

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • Thanks! I'll make changes and let you know. I also noticed that I'm adding the children of the contianer before I'm adding the container to its container. Could that also be a cause of the problem? – user1164429 May 20 '12 at 17:56
  • the order doesn't matter . however , in order to get the size of the views , you will have to do it after the layout has finished and not while you still put things together. – android developer May 20 '12 at 19:07
  • I'm not quite sure I understand. What do you mean by putting things together? How do I garuntee that the layout has finished? – user1164429 May 20 '12 at 21:51
  • well you can use this solution which i've given for fetching the size of a view after the layout phase , but before the view is being drawn: http://stackoverflow.com/a/10433386/878126 . "putting things together" - i meant the whole initializations that you usually do on the onCreate method . those don't do anything but store stuff for the views , only later they really do layout calculations and such. – android developer May 20 '12 at 22:07