Android Studio Draw Circle on Imageview

Allow's deal with it. In near every app, we need this kind of circular image as a profile image for people. We should show the image with the user's initial while we load the original image.

Just, nosotros demand to accommodate a placeholder and the user epitome. So, how practise nosotros practise it?

Showtime we need to define placeholder. We tin use a TextView and set a drawable shape with some colour for the placeholder. For the original image, we can use an ImageView. But we got a problem here. The default implementation of ImageView is rectangle shaped. Simply nosotros demand round image. With a simple google search, we can go then many custom implementations of ImageView which provides circular image. We can utilize any of them.

At present we demand some logic to testify the initials while loading original prototype. Let'south put a Framelayout with the TextView and ImageView every bit children.

avatar_view.xml
Shape circumvolve drawable for background of textview

At present, we first fix the initials for the TextView, and so gear up the visibility of the imageView as INVISIBLE or GONE. I advise use some paradigm loading library like Glide or Picasso to load images from URL equally the library handles bitmap recycling, offline enshroud mechanism etc. I use Glide hither.

Every bit soon every bit the bitmap is ready, we gear up information technology to the ImageView, make it visible and make the placeholder invisible.

Logic to load avatar

Great. Everything is working fine.

At present your designer is giving some cool designs for multiple themes. In that theme, all the images are square instead of circle. So now we need to support circle images for i theme and rounded square images for some other theme.

Okay, we can add another normal ImageView within FrameLayout which would hold the rectangle image. For the placeholder, we demand to define some other shape drawable with square shape and set it as background dynamically for the TextView based on the theme.

Shape square drawable for background of textview
avatar_view.xml subsequently adding square image back up
Logic to load avatar

It does the job right? Merely can nosotros do it better somehow?

The problem here is, to bear witness a simple avatar, we are using three views although either one of them will be used at a fourth dimension. And also, information technology is non maintainable. What if the next 24-hour interval your designer asks you to make the rectangle images rounded rectangle with slight bit of curve on all edges?

So let'due south take a step back and retrieve of an some other approach.

Custom Views. Using custom views, we can accommodate all these various designs in a single view. If you don't know about custom views, I advise read some articles or watch some videos about it. It's good to know most it since in every project, y'all'll accept to apply some custom views someday to brand life a lot easier.

And then what are we gonna practice? We are gonna extend ImageView and put all our logic (circle, rounded rectangle, placeholder with initials) in there.

Member variables needed in AvatarView

These are the variables we are going to utilize in the custom view. Nosotros need to initialise each of these variables.

Initialising member variables

Hither, I'm going to use a POJO course named User which would comprise the proper name of the user, avatar url, groundwork colour of the placeholder image etc. What is gonna exist in the POJO class depends on you application architecture. Or y'all can besides laissez passer the URL, proper name through setters in the custom view.

We are storing the initials of the user in text field using a helper method.

Nosotros are returning first two alphabetic character if the name contains single give-and-take, else return commencement messages of first two words.

In the setDrawable method, we are drawing the text and background color on a canvas and store it in the drawable member variable.

If the avatar url is not null,

  • we get the paradigm and set it in the same view (Note that we are extending ImageView, and so this will brand the imageView to describe the image when information technology is fetched from Glide) and put the placeholder as the drawable we set before.
  • else, we prepare the drawable as the source to be drawn using setImageDrawable method.
Initializing drawable

We create a new Drawable, fill the sail with the groundwork color and then draw the text in center of the drawable canvas.

  1. First we measure the width and meridian required for the text to be drawn using measureText method and getFontMetrics().ascent field.
  2. Then we draw rounded rectangle or circle depends upon the theme in the canvas with paint contains the background color (The shape can be initialized using separate setter or using custom atrributes).
  3. Then we describe the text in the canvass. (Drawing text after cartoon background color ensures that the text will be in top and volition not exist overlapped past the background color. Consider cartoon operations like a stack).

That's all we have to do to initialize the placeholder drawable. Now we demand to initialize rectF which would contain the premises of the view. The best place to get premises of the view would be onMeasure().

At present comes the main part of the custom view. onDraw() method.

onDraw part

This is where the actual drawing happens. We already draw something (Initials and background color) in the canvass before correct? That was a drawable. That drawable itself will be drawn on the screen through this onDraw() method only.

In onDraw() method, nosotros will be provided a sail where we draw what needs to exist drawn.

We can simply use drawRoundedRect and drawCircle to draw paints into the canvas. But to draw and image, nosotros demand to convert it into bitmap and draw information technology. Even if we did similar that, we are gonna end up with white background on undrawn areas in the canvass. This is considering, in Android all views are rectangular (or foursquare).

So what'southward the solution for that? ClipPath.

We can clip the path of the canvas itself into any shape we desire, which will stop the framework from draw unclipped areas into white. Cool, isn't it?

All we need to practice is draw the path nosotros but demand and pass that path to clipPath method in the canvas and the framework volition practice the rest.

There is one trouble with clipPath method in canvas. From Honeycomb to API level 17, clipPath method is no longer supported in devices with hardware acceleration turned on. From API level 18, it is supported.

So, y'all will withal see white background on undrawn areas from Honeycomb to API level 17. The solution for this problem is discussed hither and as per the solution,

          /*
* Below Jelly Bean, clipPath on sheet would non work because lack of hardware acceleration
* support. Hence, we should explicitly say to apply software acceleration.
* */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setLayerType(LAYER_TYPE_SOFTWARE, cipher);
}

we should force it to utilise software dispatch. You tin place this snippet anywhere in the custom view which uses clipPath.

And then, our concluding view would exist wait like this.

AvatarView.java

Annotation that I extended AppCompatImageView instead of ImageView to utilize support library features. In xml, if you lot use just specify ImageView, TextView, EditText like that, on layout aggrandizement, if you lot use back up library, the framework inflates AppCompatImageView, AppCompatTextView, AppCompatEditText respectively (which contains custom implementations to backport lollipop features to pre-lollipop). Then, if you lot need to employ lollipop and to a higher place features to pre-lollipop like vector drawables, background tinting, and so extend AppCompatImageView instead of ImageView.

I declared the shapes as custom attributes and set them on xml based on theme. This is divers in attr.xml.

          <declare-styleable proper name="AvatarView">
<attr name="avatar_shape" format="cord" />
</declare-styleable>

And in strings.xml,

          <cord proper noun="circumvolve">Circle</string>
<string name="rectangle">Rectangle</cord>

And in styles.xml,

          <fashion name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
....
<particular name="avatarShape">@string/circle</item>
</manner>
<style proper name="AnotherTheme" parent="AppTheme">
....
<item name="avatarShape">@string/circle</item>
</style>

And in layout xmls,

          <com.example.customviews.AvatarView
android:id="@+id/avatar_view"
android:layout_width="@dimen/avatar_size"
android:layout_height="@dimen/avatar_size"
app:avatar_shape="?avatarShape" />

And in the activeness class,

                      AvatarView avatarView = (AvatarView) findViewById(R.id.avatar_view);
avatarView.setUser(user);

That's all. Of course, customize it based on your needs.

Happy coding :)

schriverdoemon.blogspot.com

Source: https://medium.com/android-news/avatarview-custom-implementation-of-imageview-4bcf0714d09d

0 Response to "Android Studio Draw Circle on Imageview"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel