Android uses the Bitmapshader class to make rounded corners of various pictures _android

Source: Internet
Author: User

Public Bitmapshader (Bitmap bitmap,shader.tilemode tilex,shader.tilemode Tiley)

Call this class to produce a renderer (Shader) that has a bitmap painted.

Bitmap: Bitmaps used within the renderer
(1) tilex:the tiling mode for x to draw the bitmap in. X-direction tile mode on bitmap
(2) tiley:the tiling mode for y-draw the bitmap in. Y-Direction tile mode on bitmap

Tilemode: (a total of three)

(1) Clamp: If the renderer exceeds the original boundary range, it will replicate the range of edge staining.

(2) REPEAT: Horizontal and vertical Repeat renderer picture, tiled.

(3) MIRROR: Horizontal and vertical Repeat renderer picture, this and repeat repeat the way is different, he is tiled in a mirrored way.

Still don't get it? Then look at the effect chart!

For our rounded corners and circles, we set the pattern to be clamp, but would you have a question:
Is the view wider or taller than the width or height of our bitmap stretching?
Well, we'll set up a matrix for bitmapshader to zoom in or out of the picture, not to make "view wider or taller than our bitmap wide or high" condition.
The principle of our basic introduction finished, get drawable into bitmap, and then directly initialize Bitmapshader, brush set shader, finally in the OnDraw inside to draw a circle on the line.

Basic usage and examples
Let's take a look at the rounded or rounded corners that are implemented using Bitmapshader.
We are here to inherit ImageView directly, so that the code to set up the picture will be more familiar; but we need to support two modes, then we need custom attributes:
1, custom properties
Values/attr.xml

<?xml version= "1.0" encoding= "Utf-8"?> 
<resources> <attr name= "Borderradius" format= " 
 
 Dimension "/> 
 <attr name=" type "> 
  <enum name=" Circle "value=" 0 "/> <enum 
  " Name= " value= "1"/> 
 </attr> 
 
 
 <declare-styleable name= "Roundimageview" > 
  <attr name= " Borderradius "/> 
  <attr name=" type "/> 
 </declare-styleable> 
 
</resources> 

We define an enumeration and a rounded corner size Borderradius.

2. Get Custom properties

public class Roundimageview extends ImageView {/** * picture type, round or rounded/private int type; 
 private static final int type_circle = 0; 
 
 private static final int type_round = 1; 
 /** * The default value for fillet size * * private static final int boder_radius_default = 10; 
 
 /** * The size of the rounded angle * * private int mborderradius; 
 /** * Drawing Paint * * Private Paint mbitmappaint; 
 /** * The radius of the rounded corner * * private int mradius; 
 /** * 3x3 matrix, mainly used to reduce amplification * * Private matrix Mmatrix; 
 /** * Rendering images, using images for drawing graphics coloring * * Private bitmapshader Mbitmapshader; 
 /** * View Width * * private int mwidth; 
 
 Private RECTF Mroundrect; 
  Public Roundimageview (context, AttributeSet attrs) {Super (context, attrs); 
  Mmatrix = new Matrix (); 
  Mbitmappaint = new Paint (); 
 
  Mbitmappaint.setantialias (TRUE); 
 
  TypedArray a = Context.obtainstyledattributes (Attrs, R.styleable.roundimageview); Mborderradius = A.getdimensionpixelsize (R.styleable.roundimageview_borderradius, (int) Typedvalue applydimension (Typedvalue.complex_unit_dip, Boder_radius_default, Getresources () 
 
  . Getdisplaymetrics ());//default 10DP type = A.getint (R.styleable.roundimageview_type, type_circle);//default to CIRCLE 
 A.recycle (); 

 }

We can see some of our member variables, basically annotated, and then we get our custom attributes in the constructor and the initialization of some of the variables.

3, Onmeasure

@Override 
 protected void onmeasure (int widthmeasurespec, int heightmeasurespec) 
 { 
  log.e ("TAG", " Onmeasure "); 
  Super.onmeasure (Widthmeasurespec, heightmeasurespec); 
 
  /** 
   * If the type is circular, it forces the view to change the width-height consistency, with a decimal value of quasi- 
   * 
  /if (type = = type_circle) 
  { 
   mwidth = math.min ( Getmeasuredwidth (), Getmeasuredheight ()); 
   Mradius = MWIDTH/2; 
   Setmeasureddimension (Mwidth, mwidth); 
  } 
 
  

We have made a onmeasure method, which is mainly used when setting the type to circular, we force the view width and height to be consistent.
The next step is to set the Bitmapshader and draw the

4, set Bitmapshader

/** 
  * Initialize Bitmapshader/ 
 private void Setupshader () 
 { 
  drawable drawable = getdrawable (); 
  if (drawable = = null) 
  {return 
   ; 
  } 
 
  Bitmap bmp = Drawabletobitamp (drawable); 
  BMP as a shader, is in the specified area to draw bmp 
  Mbitmapshader = new Bitmapshader (BMP, Tilemode.clamp, tilemode.clamp); 
  float scale = 1.0f; 
  if (type = = type_circle) 
  { 
   //Get bitmap width or high small value 
   int bsize = Math.min (Bmp.getwidth (), Bmp.getheight ()); 
   Scale = Mwidth * 1.0f/bsize; 
 
  } else if (type = = Type_round) 
  { 
   //if the width or height of the picture does not match the width of the view, calculate the scale that needs to be scaled; the width of the scaled picture must be greater than the width of our view; so we take the big value here; 
   scale = Math.max (getwidth () * 1.0f/bmp.getwidth (), getheight () 
     * 1.0f/bmp.getheight ()); 
  Shader transformation matrix, where we are mainly used to enlarge or shrink 
  mmatrix.setscale (scale, scale); 
  Setting the transformation matrix 
  Mbitmapshader.setlocalmatrix (Mmatrix); 
  Set shader 
  Mbitmappaint.setshader (mbitmapshader); 
  

In the Setupshader, first to drawable into our bitmap;
Then initialize

Mbitmapshader = new Bitmapshader (BMP, Tilemode.clamp, Tilemode.clamp);

Next, compute the scale according to the type and the width of the bitmap and view;
About the calculation of scale:
(1) When the circle: Take the bitmap width or high value as the benchmark, if the use of large value, scaling must not fill our rounded area. Then, the view of the mwidth/bsize; Get is scale.
(2) Fillet: Because the design to the wide/high proportion, we respectively getwidth () * 1.0f/bmp.getwidth () and GetHeight () * 1.0f/bmp.getheight (); The final large value, because we want to make the final zoom complete the picture must be The area larger than our view, somewhat similar to the Centercrop;
(3) For example: view of the width of 10*20; the width of the picture is 5*100; In the end, we should enlarge it by a wide scale, not by a high proportion, because we need to make the scaled picture, the custom larger than our view wide, and guarantee the original ratio.
With the scale, you can set the matrix to us;
Then use Mbitmapshader.setlocalmatrix (Mmatrix);
Finally, set the Bitmapshader to paint.
About drawable to bitmap code:

/** 
  * drawable Bitmap * 
  * 
  * @param drawable 
  * @return 
 /private Bitmap Drawabletobitamp ( Drawable drawable) 
 { 
  if (drawable instanceof bitmapdrawable) 
  { 
   bitmapdrawable bd = (bitmapdrawable) drawable; 
   return Bd.getbitmap (); 
  } 
  int w = drawable.getintrinsicwidth (); 
  int h = drawable.getintrinsicheight (); 
  Bitmap Bitmap = Bitmap.createbitmap (W, H, Bitmap.Config.ARGB_8888); 
  Canvas Canvas = new Canvas (bitmap); 
  Drawable.setbounds (0, 0, W, h); 
  Drawable.draw (canvas); 
  return bitmap; 
 } 

Finally we will call Setupshader () in the OnDraw and then draw.

5. Draw
here, the last step is drawn, because our range, as well as the scaling, is done, so it's really just a draw.

@Override 
 protected void OnDraw (Canvas Canvas) 
 { 
  if (getdrawable () = null) 
  {return 
   ; 
  } 
  Setupshader (); 
 
  if (type = = Type_round) 
  { 
   canvas.drawroundrect (mroundrect, Mborderradius, Mborderradius, 
     mbitmappaint ); 
  } else 
  { 
   canvas.drawcircle (Mradius, Mradius, Mradius, mbitmappaint); 
   Drawsomething (canvas); 
  } 
  
 @Override 
 protected void onsizechanged (int w, int h, int oldw, int oldh) 
 { 
  super.onsizechanged (W, H, OLDW, OLDH); 
  Fillet picture Range 
  if (type = = Type_round) 
   mroundrect = new RECTF (0, 0, getwidth (), getheight ()); 
  

Drawing is very simple, draw a circle, rounded rectangle or something. The bounded range of rounded rectangles is mroundrect in the onsizechanged.
6, the state of storage and recovery
of course, if there is not enough memory and it happens that our activity is in the background, it is unfortunately restarted, or the user spins the screen causing the activity to restart, our view should also be able to save its own attributes as much as possible.
What is the use of State preservation? For example, now one of the fillet size is 10DP, the user clicks into 50DP, after the user rotated, or after a long time in the background, return to our activity should still be 50dp;
We simply store the current type as well as the Mborderradius

 private static final String state_instance =" State_instance "; 
 private static final String State_type = "State_type"; 
 
 private static final String State_border_radius = "State_border_radius"; 
  @Override protected parcelable onsaveinstancestate () {Bundle Bundle = new Bundle (); 
  Bundle.putparcelable (State_instance, Super.onsaveinstancestate ()); 
  Bundle.putint (State_type, TYPE); 
  Bundle.putint (State_border_radius, Mborderradius); 
 return bundle; } @Override protected void Onrestoreinstancestate (parcelable state) {if (state instanceof Bundle) {Bun 
   Dle bundle = (bundle) state; 
   Super.onrestoreinstancestate ((Bundle) state). Getparcelable (state_instance)); 
   This.type = Bundle.getint (State_type); 
  This.mborderradius = Bundle.getint (State_border_radius); 
  else {super.onrestoreinstancestate (state); } 
 
 } 

The code is relatively simple. The demo in our article, the first one, the fourth one can be clicked, click will change, you can click, then rotate the screen to test.

At the same time, we have published two methods for dynamically modifying the fillet size and type

public void Setborderradius (int borderradius) 
 { 
  int pxval = dp2px (Borderradius); 
  if (This.mborderradius!= pxval) 
  { 
   This.mborderradius = pxval; 
   Invalidate (); 
  } 
 
 public void SetType (int type) 
 { 
  if (this.type!= type) 
  { 
   this.type = type; 
   if (this.type!= type_round && this.type!= type_circle) 
   { 
    this.type = type_circle; 
   } 
   Requestlayout (); 
  } 
 
 public int dp2px (int dpval) 
 {return 
  (int) typedvalue.applydimension (Typedvalue.complex_unit_dip, 
    Dpval, Getresources (). Getdisplaymetrics ()); 
  

Finally, stick to our layout files and mainactivity.

6. Call
Layout file:

<scrollview xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http:// Schemas.android.com/tools "xmlns:zhy=" Http://schemas.android.com/apk/res/com.zhy.variousshapeimageview "Android: Layout_width= "Match_parent" android:layout_height= "wrap_content" > <linearlayout android:layout_width= "MATC" H_parent "android:layout_height=" match_parent "android:orientation=" vertical "> <com.zhy.view.roundimagev Iew android:id= "@+id/id_qiqiu" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" an Droid:layout_margin= "10DP" android:src= "@drawable/qiqiu" > </com.zhy.view.RoundImageView> <com.zhy . View. Roundimageview android:layout_width= "200DP" android:layout_height= "200DP" android:layout_margin= "10DP" and roid:src= "@drawable/aa" > </com.zhy.view.RoundImageView> <com.zhy.view.roundimageview Android:layo Ut_width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_margin= "10DP" android:src= "@drawable/icon" > </com.zhy.view.roundimageview > <com.zhy.view.roundimageview android:id= "@+id/id_meinv" android:layout_width= "Wrap_content" Andro id:layout_height= "Wrap_content" android:layout_margin= "10DP" android:src= "@drawable/aa" zhy:borderradius= "20DP "Zhy:type=" Round "> </com.zhy.view.RoundImageView> <com.zhy.view.roundimageview android:layou T_width= "Wrap_content" android:layout_height= "wrap_content" android:layout_margin= "10DP" android:src= "@drawabl E/icon "zhy:borderradius=" 40DP "zhy:type=" Round "> </com.zhy.view.RoundImageView> <com.zhy.vie W.roundimageview android:layout_width= "wrap_content" android:layout_height= "Wrap_content" Android:layout_margi N= "10DP" android:src= "@drawable/qiqiu" zhy:borderradius= "60DP" zhy:type= "Round" > </com.zhy.view.roun Dimageview> </liNearlayout> </ScrollView> 

 

No, scrollview inside a linear layout, inside a bunch of roundimageview.

Mainactivity

 package com.zhy.variousshapeimageview; 
Import android.app.Activity; 
Import Android.os.Bundle; 
Import Android.view.View; 
 
Import Android.view.View.OnClickListener; 
 
Import Com.zhy.view.RoundImageView; 
 public class Mainactivity extends activity {private Roundimageview Mqiqiu; 
 
 Private Roundimageview MMEINV; 
  @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
   
  Setcontentview (R.layout.activity_main); 
  Mqiqiu = (Roundimageview) Findviewbyid (R.id.id_qiqiu); 
   
  MMEINV = (Roundimageview) Findviewbyid (R.ID.ID_MEINV); Mqiqiu.setonclicklistener (New Onclicklistener () {@Override public void OnClick (View v) {Mqiqiu.setty 
   PE (ROUNDIMAGEVIEW.TYPE_ROUND); 
   
  } 
  }); Mmeinv.setonclicklistener (New Onclicklistener () {@Override public void OnClick (View v) {Mmeinv. 
   Setborderradius (90); 
 } 
  }); } 
 
} 


The final effect chart:

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.