2

I have written a subclass of View and I have included a method to set a field. The value of the field affects the the size of the View and the contents of the View.

What do I have to write in the set method to ensure that the view will be properly updated with immediate effect? I am asking because when I use my own custom views as part of a layout of a ListView item, I find that when I try to recycle my own views by using the convertView argument of an ArrayAdapter's getView method, sometimes the set method doesn't seem to work.

Here is a contrived example of the kind of thing I am trying to do. I have only just started learning how to extend View, so there may be other problems with this code.

public final class SpotsView extends View {

    private final MyActivity activity;
    private int numberOfSpots;

    public SpotsView(MyActivity activity) {
        super(activity);
        this.activity = activity;
    }

    public void setNumberOfSpots(int numberOfSpots) {
        this.numberOfSpots = numberOfSpots;
        // What do I have to write here?? invalidate()? forceLayout()?
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Resources resources = activity.getResources();
        setMeasuredDimension(
            (int) (numberOfSpots * resources.getDimension(R.dimen.block_width)),
            (int) resources.getDimension(R.dimen.spots_view_height)
        );
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int height = getHeight();
        int width = getWidth();
        float radius = activity.getResources().getDimension(R.dimen.network_outer_radius);
        for (int i = 0; i < numberOfSpots; i++)
            canvas.drawCircle((i + 0.5F) * (width / numberOfSpots), height * 0.5F, radius, activity.spotPaint());
    }
} 
Paul Boddington
  • 37,127
  • 10
  • 65
  • 116

1 Answers1

1

It seems you have to call

invalidate();
requestLayout();

according to the source code of TextView#setCompoundDrawablePadding(), a method which affects content and size of the view.

Ridcully
  • 23,362
  • 7
  • 71
  • 86
  • It seems to work. The trouble is `forceLayout()` seems to work too. I'm not sure if "requesting" a layout is strong enough. If requesting a layout guarantees a layout, what is the point of `forceLayout()`? Also the diagram in this answer http://stackoverflow.com/a/25846243/3973077 suggests `requestLayout()` without `invalidate()` should be enough. – Paul Boddington Sep 10 '15 at 19:33
  • When it works, you should go with it. Calling invalidate() alone, only triggers the draw() method but not a recalculation of the layout as shown here: http://stackoverflow.com/questions/13856180/usage-of-forcelayout-requestlayout-and-invalidate#25846243 The difference between requestLayout() and forceLayout() is not very clear, but requestLayout() is surely the nicer variation. – Ridcully Sep 11 '15 at 18:21