Extending Circle Image View to Create Circle Avatar Image View

June 20, 2018

In this post I’m gonna create an circle avatar image custom view which is a subclass of circle image view, so before start reading this, make sure you’ve read and understand the post about [Creating Custom Circle Image View]({% post_url 2018-06-06-circle_image_view %}).

This is how circle avatar image view looks like.

figure1

It can show either an image or initial character.

The project is available here on Github

Reuse CircleImageView

Extend the CircleImageView class to reuse the functionality. Define two static final integer to represent two state for either showing an initial or an image.

public class AvatarImageView extends CircleImageView {
    public static final int SHOW_INITIAL = 1;
    public static final int SHOW_IMAGE = 2;
}

Define XML Attributes

This attributes is used to customize the view in xml layout.

<declare-styleable name="AvatarImageView">
    <attr name="avatarBackgroundColor" format="color"/>
    <attr name="textSize" format="dimension"/>
    <attr name="textColor" format="color"/>
    <attr name="text" format="string"/>
    <attr name="state" format="enum">
        <enum name="INITIAL" value="1"/>
        <enum name="IMAGE" value="2"/>
    </attr>
</declare-styleable>

Define member variables

public class AvatarImageView extends CircleImageView {
    // ...
    private Paint mTextPaint; // used to draw a text/initial character
    private Rect mTextBounds; // rectangle bounds of initial character

    private Paint mBackgroundPaint; // used to draw filled circle for text/initial background
    private RectF mBackgroundBounds; // bounds of the circle

    @NonNull
    private String mInitial; // holding a character to be drawn
    @NonNull
    private String mText; // holding whole text (in case we need it)

    private int mShowState; // the current state of avatar view
    // ...
}

Important methods

These are explanations of some methods that I consider more important.

Updating background circle bounds

When the view size changed the mBackgroundBounds needs to be updated to make size and position of bounds correct by calling the super class method updateCircleDrawBounds()

public class AvatarImageView extends CircleImageView {
    // ...
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        updateCircleDrawBounds(mBackgroundBounds);
    }
    // ...
}

Updating text bounds

Bounds or dimension of a character is needed to calculate the correct position for the character to be rendered in the center. This method would be called when the text changed, for example inside the setter method for text or text size and in constructor for initialization.

public class AvatarImageView extends CircleImageView {
    // ...
    private void updateTextBounds() {
        mTextPaint.getTextBounds(mInitial, 0, mInitial.length(), mTextBounds);
    }
    // ...
}

Drawing

If the state is SHOW_IMAGE then render straightly using parent onDraw() method. If it’s SHOW_INITIAL then render the text and background.

public class AvatarImageView extends CircleImageView {
    // ...
    @Override
    protected void onDraw(Canvas canvas) {
        if (mShowState == SHOW_INITIAL) {
        	// this is centered y coordinate for text
            float textBottom = mBackgroundBounds.centerY() - mTextBounds.exactCenterY();
            canvas.drawOval(mBackgroundBounds, mBackgroundPaint);
            canvas.drawText(mInitial, mBackgroundBounds.centerX(), textBottom, mTextPaint);
            drawStroke(canvas);
            drawHighlight(canvas);
        } else {
            super.onDraw(canvas);
        }
    }
    // ...
}

Profile picture

Hi there, 👋 I'm Aris

Find me on:
LinkedIn
Github

© 2021