The implementation code for the round/rounded corners of the Android custom control _android

Source: Internet
Author: User
Tags getcolor

A. Where is the problem?

The problem comes from a very common scenario in app development--the user avatar to be displayed round:

Two, how to engage?

Wit me, the first idea is, cut a middle round transparent, with the same background, size and head of the same mask picture, covered in the avatar is not finished, ha ha!

In the background of solid color, this can really solve the problem, but if the background is not so simple?

In this irregular setting, there are two problems:

1, the background map is often adapted to mobile phone width scaling, and the size of the head is fixed wide and high DP, so the fixed mask picture is not guaranteed on different models are consistent with the background pattern.

2, in this kind of non-pure color background, which day want to adjust the avatar position will have to change the picture mask, it is too difficult to maintain ...

So, since the picture of the Avatar is definitely square, then let ImageView round up.

Three, get to work.

The basic idea is to customize a imageview by rewriting the OnDraw method to draw a circular picture:

public class Imageviewplus extends imageview{private Paint mpaintbitmap = new Paint (Paint.anti_alias_flag);
 Private Bitmap Mrawbitmap;
 Private Bitmapshader Mshader;
 
 Private Matrix Mmatrix = new Matrix ();
 Public Imageviewplus (context, AttributeSet attrs) {Super (context, attrs);
 } @Override protected void OnDraw (Canvas Canvas) {Bitmap Rawbitmap = Getbitmap (getdrawable ());
  if (Rawbitmap!= null) {int viewwidth = getwidth ();
  int viewheight = GetHeight ();
  int viewminsize = Math.min (Viewwidth, viewheight);
  float dstwidth = viewminsize;
  float dstheight = viewminsize;
  if (Mshader = null | |!rawbitmap.equals (MRAWBITMAP)) {mrawbitmap = Rawbitmap;
  Mshader = new Bitmapshader (Mrawbitmap, Tilemode.clamp, Tilemode.clamp);
  } if (Mshader!= null) {Mmatrix.setscale (Dstwidth/rawbitmap.getwidth (), Dstheight/rawbitmap.getheight ());
  Mshader.setlocalmatrix (Mmatrix);
  } mpaintbitmap.setshader (Mshader);
  float radius = viewminsize/2.0f; Canvas.draWcircle (RADIUS, radius, radius, mpaintbitmap);
 else {super.ondraw (canvas); } private Bitmap Getbitmap (drawable drawable) {if (drawable instanceof bitmapdrawable) {return (bitmapdrawable) Dr
 awable). Getbitmap ();
  else if (drawable instanceof colordrawable) {Rect Rect = Drawable.getbounds ();
  int width = Rect.right-rect.left;
  int height = rect.bottom-rect.top;
  int color = ((colordrawable) drawable). GetColor ();
  Bitmap Bitmap = bitmap.createbitmap (width, height, Bitmap.Config.ARGB_8888);
  Canvas Canvas = new Canvas (bitmap);
  Canvas.drawargb (Color.alpha (color), color.red (color), color.green (color), Color.Blue (color));
 return bitmap;
 else {return null;
 }
 }
}

Analyze the Code:

Canvas.drawcircle decided to draw the shape is round, and the contents of the round is through the Mpaintbitmap.setshader to fix.

Where Bitmapshader needs to set the way bitmap fills ImageView (clamp: extrude edges, MIRROR: mirrors, REPEAT: whole-graph repeats).

It doesn't matter what this is really about, because what we really need is to scale the bitmap to ImageView as large as it is, rather than the three effects of the preset.

So, don't forget to use Mmatrix.setscale and Mshader.setlocalmatrix, zoom in on the picture.

Four, more play--support borders

Look at the picture below, if you want to add a border to the head of the circle, how to do it?

public class Imageviewplus extends imageview{private Paint mpaintbitmap = new Paint (Paint.anti_alias_flag);
 Private Paint Mpaintborder = new Paint (Paint.anti_alias_flag);
 Private Bitmap Mrawbitmap;
 Private Bitmapshader Mshader;
 Private Matrix Mmatrix = new Matrix ();
 private float mborderwidth = dip2px (15);
 
 private int mbordercolor = 0XFF0080FF;
 Public Imageviewplus (context, AttributeSet attrs) {Super (context, attrs);
 } @Override protected void OnDraw (Canvas Canvas) {Bitmap Rawbitmap = Getbitmap (getdrawable ());
  if (Rawbitmap!= null) {int viewwidth = getwidth ();
  int viewheight = GetHeight ();
  int viewminsize = Math.min (Viewwidth, viewheight);
  float dstwidth = viewminsize;
  float dstheight = viewminsize;
  if (Mshader = null | |!rawbitmap.equals (MRAWBITMAP)) {mrawbitmap = Rawbitmap;
  Mshader = new Bitmapshader (Mrawbitmap, Tilemode.clamp, Tilemode.clamp); } if (Mshader!= null) {Mmatrix.setscale (Dstwidth-mborderwidth * 2)/RAWBITMAP.GETWIdth (), (Dstheight-mborderwidth * 2)/rawbitmap.getheight ());
  Mshader.setlocalmatrix (Mmatrix);
  } mpaintbitmap.setshader (Mshader);
  Mpaintborder.setstyle (Paint.Style.STROKE);
  Mpaintborder.setstrokewidth (Mborderwidth);
  Mpaintborder.setcolor (Mbordercolor);
  float radius = viewminsize/2.0f;
  Canvas.drawcircle (radius, radius, radius-mborderwidth/2.0f, mpaintborder);
  Canvas.translate (Mborderwidth, mborderwidth);
 Canvas.drawcircle (Radius-mborderwidth, Radius-mborderwidth, Radius-mborderwidth, Mpaintbitmap);
 else {super.ondraw (canvas); } private Bitmap Getbitmap (drawable drawable) {if (drawable instanceof bitmapdrawable) {return (bitmapdrawable) Dr
 awable). Getbitmap ();
  else if (drawable instanceof colordrawable) {Rect Rect = Drawable.getbounds ();
  int width = Rect.right-rect.left;
  int height = rect.bottom-rect.top;
  int color = ((colordrawable) drawable). GetColor (); Bitmap Bitmap = bitmap.createbitmap (width, height, Bitmap.Config.ARGB_8888);
  Canvas Canvas = new Canvas (bitmap);
  Canvas.drawargb (Color.alpha (color), color.red (color), color.green (color), Color.Blue (color));
 return bitmap;
 else {return null;
 } private int dip2px (int dipval) {Float scale = getresources (). Getdisplaymetrics (). density;
 return (int) (Dipval * scale + 0.5f);
 }
}

Looking at the code, the plus border is actually a solid-colored Paint draw a round edge, on this basis to draw the original head.

There are three places to take note of:

1), the radius of the circle box is not radius, but should be radius-mborderwidth/2.0f. Imagine taking a pen to draw a line, which is actually the position of the white circle in the right picture, but it is very thick.

2, on the basis of the ImageView size, the actual size of the avatar is smaller than the time frame, so mmatrix.setscale to remove the width of the border.

3, painting Avatar Bitmap can not be directly canvas.drawcircle (radius, radius, radius-mborderwidth, mpaintbitmap), so you will find the avatar's right and lower edge is stretched (right)

Why, then? Because Paint is drawn by default on the upper left corner, the actual area of the avatar is the red box in the right figure, and more than the red box (the right and lower part of the circle), which is naturally stretched by the tilemode.clamp effect along the edge.

Therefore, you need to move the coordinate system position and adjust the center, in order to draw the picture in the correct area (right figure green box).

Five more play--support XML configuration

Now that you have a border, what if you want to configure the width and color of the border?

Basically two ideas:

1) to Imageviewplus Plus set interface, set up after the completion of the invalidate (); Re-painting can be;

2 The configuration of some custom attributes is supported in XML, which makes it much easier to use.

Here's the key to supporting XML configuration customization properties.

Custom controls to support XML configuration custom attributes, you first need to define attributes in the \res\values:

<?xml version= "1.0" encoding= "Utf-8"?> 
<resources> 
 <attr name= "bordercolor" format= "Color" >
 <attr name= "BorderWidth" format= "Dimension"/> <declare-styleable name=

 "Imageviewplus" > 
 <attr name= "bordercolor"/>
 <attr name= "BorderWidth"/>
 </declare-styleable> 
</resources> 

View Attrs_imageviewplus.xml
The custom attributes are then read in the Imageviewplus constructor:

private static final int default_border_color = color.transparent;
 private static final int default_border_width = 0;
 
 Public Imageviewplus (context, AttributeSet attrs) {
 Super (context, attrs);
 Take the parameters set in the XML file
 TypedArray ta = context.obtainstyledattributes (attrs, r.styleable.imageviewplus);
 Mbordercolor = Ta.getcolor (R.styleable.imageviewplus_bordercolor, default_border_color);
 Mborderwidth = Ta.getdimensionpixelsize (R.styleable.imageviewplus_borderwidth, dip2px (DEFAULT_BORDER_WIDTH));
 Ta.recycle ();
 }

To use custom attributes in an XML layout:

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
 xmlns:tools= "http:// Schemas.android.com/tools "
 xmlns:snser=" Http://schemas.android.com/apk/res/cc.snser.imageviewplus
 " Android:layout_width= "Match_parent"
 android:layout_height= "match_parent"
 android:background= "@drawable /wallpaper "
 android:orientation=" vertical "
 tools:context=" ${relativepackage}.${activityclass} ">
 
 <cc.snser.imageviewplus.imageviewplus
 android:id= "@+id/imgplus"
 android:layout_width= "200DP"
 android:layout_height= "300DP"
 android:layout_marginbottom= "50DP"
 android:layout_ Centerhorizontal= "true"
 android:layout_alignparentbottom= "true"
 android:src= "@drawable/img_square"
 snser:bordercolor= "#FF0080FF"
 snser:borderwidth= "15DP"/>
 
</RelativeLayout>


Six, more play--rounded corner ImageView

With the rounded imageview and the corresponding border, how do you achieve the ImageView of the following rounded corners?

In fact, the same principle, the canvas.drawcircle corresponding to the canvas.drawroundrect on the OK, directly affixed to the code:

public class Imageviewplus extends imageview{/** * Android.widget.ImageView/public static final int type_none = 0
 ;
 /** * Circular/public static final int type_circle = 1; 
 
 /** * Rounded Rectangle * * public static final int type_rounded_rect = 2;
 private static final int default_type = Type_none;
 private static final int default_border_color = color.transparent;
 private static final int default_border_width = 0;
 
 private static final int default_rect_round_radius = 0;
 private int mtype;
 private int mbordercolor;
 private int mborderwidth;
 
 private int Mrectroundradius;
 Private Paint Mpaintbitmap = new Paint (Paint.anti_alias_flag);
 
 Private Paint Mpaintborder = new Paint (Paint.anti_alias_flag);
 Private RECTF Mrectborder = new RECTF ();
 
 Private RECTF Mrectbitmap = new RECTF ();
 Private Bitmap Mrawbitmap;
 Private Bitmapshader Mshader;
 
 Private Matrix Mmatrix = new Matrix ();
 Public Imageviewplus (context, AttributeSet attrs) {Super (context, attrs); Set in XML fileFixed parameters TypedArray ta = context.obtainstyledattributes (attrs, R.styleable.imageviewplus);
 Mtype = Ta.getint (R.styleable.imageviewplus_type, Default_type);
 Mbordercolor = Ta.getcolor (R.styleable.imageviewplus_bordercolor, Default_border_color);
 Mborderwidth = Ta.getdimensionpixelsize (R.styleable.imageviewplus_borderwidth, dip2px (DEFAULT_BORDER_WIDTH)); Mrectroundradius = Ta.getdimensionpixelsize (R.styleable.imageviewplus_rectroundradius, dip2px (DEFAULT_RECT_ROUND_
 RADIUS));
 Ta.recycle ();
 
 } @Override protected void OnDraw (Canvas Canvas) {Bitmap Rawbitmap = Getbitmap (getdrawable ());
  if (rawbitmap!= null && mtype!= type_none) {int viewwidth = getwidth ();
  int viewheight = GetHeight ();
  int viewminsize = Math.min (Viewwidth, viewheight); float Dstwidth = Mtype = = type_circle?
  Viewminsize:viewwidth; float Dstheight = Mtype = = type_circle?
  Viewminsize:viewheight;
  float halfborderwidth = mborderwidth/2.0f;
  
float doubleborderwidth = mborderwidth * 2;  if (Mshader = null | |!rawbitmap.equals (MRAWBITMAP)) {mrawbitmap = Rawbitmap;
  Mshader = new Bitmapshader (Mrawbitmap, Tilemode.clamp, Tilemode.clamp); } if (Mshader!= null) {Mmatrix.setscale (dstwidth-doubleborderwidth)/Rawbitmap.getwidth (), Dstheight-doublebor
  Derwidth)/Rawbitmap.getheight ());
  Mshader.setlocalmatrix (Mmatrix);
  } mpaintbitmap.setshader (Mshader);
  Mpaintborder.setstyle (Paint.Style.STROKE);
  Mpaintborder.setstrokewidth (Mborderwidth);
  
  Mpaintborder.setcolor (mborderwidth > 0 MBorderColor:Color.TRANSPARENT);
  if (mtype = = type_circle) {Float radius = viewminsize/2.0f;
  Canvas.drawcircle (radius, radius, radius-halfborderwidth, mpaintborder);
  Canvas.translate (Mborderwidth, mborderwidth);
  Canvas.drawcircle (Radius-mborderwidth, Radius-mborderwidth, Radius-mborderwidth, Mpaintbitmap); else if (mtype = = Type_rounded_rect) {mrectborder.set (Halfborderwidth, Halfborderwidth, Dstwidth-halfborderwidth, DS Theight-halFborderwidth);
  Mrectbitmap.set (0.0f, 0.0f, Dstwidth-doubleborderwidth, dstheight-doubleborderwidth); float Borderradius = mrectroundradius-halfborderwidth > 0.0f?
  mrectroundradius-halfborderwidth:0.0f; float Bitmapradius = mrectroundradius-mborderwidth > 0.0f?
  mrectroundradius-mborderwidth:0.0f;
  Canvas.drawroundrect (Mrectborder, Borderradius, Borderradius, Mpaintborder);
  Canvas.translate (Mborderwidth, mborderwidth);
  Canvas.drawroundrect (Mrectbitmap, Bitmapradius, Bitmapradius, Mpaintbitmap);
 } else {Super.ondraw (canvas);
 } private int dip2px (int dipval) {Float scale = getresources (). Getdisplaymetrics (). density;
 return (int) (Dipval * scale + 0.5f); Private Bitmap Getbitmap (drawable drawable) {if (drawable instanceof) {return (bitmapdrawable) bitmapdrawable
 able). Getbitmap ();
  else if (drawable instanceof colordrawable) {Rect Rect = Drawable.getbounds ();
  int width = Rect.right-rect.left; int height = Rect.bottom -Rect.top;
  int color = ((colordrawable) drawable). GetColor ();
  Bitmap Bitmap = bitmap.createbitmap (width, height, Bitmap.Config.ARGB_8888);
  Canvas Canvas = new Canvas (bitmap);
  Canvas.drawargb (Color.alpha (color), color.red (color), color.green (color), Color.Blue (color));
 return bitmap;
 else {return null;
 }
 }
}

View Imageviewplus.java

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
 xmlns:tools= "http:// Schemas.android.com/tools "
 xmlns:snser=" Http://schemas.android.com/apk/res/cc.snser.imageviewplus
 " Android:layout_width= "Match_parent"
 android:layout_height= "match_parent"
 android:background= "@drawable /wallpaper "
 android:orientation=" vertical "
 tools:context=" ${relativepackage}.${activityclass} ">
 
 <cc.snser.imageviewplus.imageviewplus
 android:id= "@+id/imgplus"
 android:layout_width= "200DP"
 android:layout_height= "300DP"
 android:layout_marginbottom= "50DP"
 android:layout_ Centerhorizontal= ' true '
 android:layout_alignparentbottom= ' true '
 android:src= ' @drawable/img_rectangle "
 snser:type=" Rounded_rect "
 snser:bordercolor=" #FF0080FF "
 snser:borderwidth=" 10DP "
 Snser: rectroundradius= "30DP"/>
 
</RelativeLayout>

View layout 


<?xml version= "1.0" encoding= "Utf-8"?> 
<resources> 
 <attr name= "type" > 
 <enum name= "None" value= "0"/> 
 <enum name= "Circle" value= "1"/> <enum name= 
 "Rounded_rect" value= "2"/>
 </attr>
 <attr name= "bordercolor" format= "color"/> <attr name=
 "BorderWidth" Dimension "/> <attr name= Rectroundradius" format= "Dimension"/> <declare-styleable name=

 " Imageviewplus "> 
 <attr name=" type/>
 <attr name= "bordercolor"/> <attr name= "
 BorderWidth "/>
 <attr name= rectroundradius"/>
 </declare-styleable>
</resources > 

View attrs_imageviewplus.xml

This is the entire content of this article, I hope to learn more about Android software programming help.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.