A: Introduction:
In the previous article, "Android realizes round, fillet and ellipse custom picture view (using Bitmapshader Graphics Rendering method)" , the Bitmapshader method is used to implement custom imageview such as round and rounded corners, In this article, we will use the more common Xfermode rendering mode scheme to realize the imageview of circular, rounded and elliptical styles, and this example is also directly inheriting ImageView,
This can save a lot of things, such as measuring steps, and do not need to write the method of setting the picture, this article uses the dst_in mode in the Xfermode mode to achieve the effect, of course, you can also use other modes, such as src_in can achieve this effect.
(as usual the full source code at the end of the article given ha)
Two::
Three, Xfermode rendering mode introduction:
Xfermode affects how new colors are drawn on canvas-already-existing images
* Under normal circumstances, draw a new shape on the image, and if the new paint is not transparent, it will obscure the color below.
* If the new paint is transparent, it will be dyed to the following color
The following subclass of Xfermode can change this behavior:
AVOIDXFERMODE specifies a color and tolerance, forcing paint to avoid drawing on it (or just drawing on it).
Pixelxorxfermode a simple pixel XOR operation is applied when the existing color is overwritten.
Porterduffxfermode This is a very powerful conversion mode, using it, you can use any of the 16 porter-duff rules of the image composition to control how paint interacts with existing canvas images.
I have to mention the classic picture here:
The above 16 modes are described below:
From the above we can see that Porterduff.mode is an enumeration class with a total of 16 enumeration values:
1.porterduff.mode.clear
The drawing is not submitted to the canvas.
2.porterduff.mode.src
Show Top Draw picture
3.porterduff.mode.dst
Show Lower drawing pictures
4.porterduff.mode.src_over
Normal drawing shows that the upper and lower layers are drawn with overlapping covers.
5.porterduff.mode.dst_over
The upper and lower layers are displayed. The lower level is shown on the home.
6.porterduff.mode.src_in
Draw the intersection of two layers. Displays the upper layer.
7.porterduff.mode.dst_in
Draw the intersection of two layers. Displays the lower layer.
8.porterduff.mode.src_out
Draw the non-intersecting portion of the upper layer.
9.porterduff.mode.dst_out
Remove the layer to draw the non-intersecting part.
10.porterduff.mode.src_atop
Remove the non-intersecting part of the layer from the upper intersection section
11.porterduff.mode.dst_atop
Take the upper non-intersecting part and the lower part of the intersection
12.porterduff.mode.xor
XOR: Remove the two Layer intersection section
13.porterduff.mode.darken
Take two layers of all areas, the intersection part of the color deepened
14.porterduff.mode.lighten
Take two layers all, light the intersection part color
15.porterduff.mode.multiply
Take two layer intersection part overlay color
16.porterduff.mode.screen
Take two layers of all areas, the intersection part becomes transparent color
Iv. implementation of custom ImageView for circular, rounded corners and ellipses
1, measuring the size of the view, the circle for special treatment
/*** Measure the size of the view*/@Overrideprotected voidOnmeasure (intWidthmeasurespec,intHeightmeasurespec) { //TODO auto-generated Method Stub Super. Onmeasure (Widthmeasurespec, Heightmeasurespec); //if the type is circular, force the width and height of the view to be consistent and take a smaller value with a wide height if(Mtype = =type_circle) { intwidth =math.min (Getmeasuredwidth (), Getmeasuredheight ()); Setmeasureddimension (width, width); } }
2, Draw different graphics bitmap, for OnDraw () to draw the time with
/*** Draw different graphics bitmap*/ PrivateBitmap Getdrawbitmap () {Bitmap Bitmap=Bitmap.createbitmap (GetWidth (), GetHeight (), Bitmap.Config.ARGB_8888); Canvas Canvas=NewCanvas (bitmap); Paint Paint=NewPaint (Paint.anti_alias_flag); Paint.setcolor (Color.Black); if(Mtype = =type_circle) {//Draw a circleCanvas.drawcircle (GetWidth ()/2, getwidth ()/2, getwidth ()/2, paint); }Else if(Mtype = =type_round) {//Draw rounded rectanglesCanvas.drawroundrect (NewRECTF (0, 0, GetWidth (), GetHeight ()), Mroundborderradius, Mroundborderradius, paint); }Else if(Mtype = =type_oval) { //Draw EllipseCanvas.drawoval (NewRECTF (0, 0, GetWidth (), GetHeight ()), mpaint); } returnbitmap; }
3. Draw in OnDraw ()
/*** Draw the contents of the View*/@Overrideprotected voidOnDraw (canvas canvas) {//TODO auto-generated Method Stub//Remove the bitmap from the cacheBitmap bmp = (Mbufferbitmap = =NULL?NULL: Mbufferbitmap.get ()); if(BMP = =NULL||bmp.isrecycled ()) { //If there are no cache conditions//Get drawableDrawable drawable =getdrawable (); //get drawable's wide height intDwidth =drawable.getintrinsicwidth (); intDheight =drawable.getintrinsicheight (); LOG.V ("Czm", "dwidth=" +dwidth+ ", width=" +getwidth ()); if(NULL!=drawable) {BMP=Bitmap.createbitmap (GetWidth (), GetHeight (), config.argb_8888); floatScale = 1.0f; //Create a canvasCanvas Drawcanvas =NewCanvas (BMP); //Calculates the zoom ratio according to the width of the bitmap and the width of the view, because the src width is set to a high//The ratio may be different from the imageview ratio, where we do not want the picture to be distorted; if(Mtype = =type_circle) {//if it's a circleScale = GetWidth () * 1.0F/math.min (Dwidth, dheight); }Else if(mtype = = Type_round | | mtype = =type_oval) {//If it is a rounded rectangle or ellipse//if the width or height of the picture does not match the width and height of the view, the scale that needs to be scaled is calculated;//The width of the scaled image must be greater than the width of our view, so we take a large value here;Scale = Math.max (getwidth () * 1.0f/Dwidth, getheight ()* 1.0f/dheight); } log.v ("Czm", "scale=" +Scale ); //set bounds based on scale, which is equivalent to zooming the pictureDrawable.setbounds (0, 0, (int) (Scale * dwidth), (int) (Scale *dheight)); Drawable.draw (Drawcanvas); //gets the bitmap, which is the bitmap of a circle, fillet, or ellipse if(Mmaskbitmap = =NULL||mmaskbitmap.isrecycled ()) {Mmaskbitmap=Getdrawbitmap (); } //set Xfermode rendering mode for paintMpaint.reset (); Mpaint.setfilterbitmap (false); Mpaint.setxfermode (Mxfermode); //Draw different ShapesDrawcanvas.drawbitmap (mmaskbitmap, 0, 0, Mpaint); Mpaint.setxfermode (NULL); //draw the prepared bitmap .Canvas.drawbitmap (BMP, 0, 0,NULL); //bitmap cache, avoid each call to OnDraw, allocate memoryMbufferbitmap =NewWeakreference<bitmap>(BMP); } }Else{ //if the cache still existsMpaint.setxfermode (NULL); Canvas.drawbitmap (BMP,0.0f, 0.0f, Mpaint); return; } }
4, because of the use of weak reference caching technology, so you need to rewrite the invalidate () method to do some release of recycling resources, such as processing:
/** * because caching technology is used, So we need to do some recycling in invalidate. */ public void invalidate () { // TODO auto-generated m Ethod stub mbufferbitmap = null if (mmaskbitmap! = null ) {mmaskbitmap.recycle (); Mmaskbitmap = null ; super .invalidate (); }
V. Implementation of the View layout:
<scrollview xmlns:android= "Http://schemas.android.com/apk/res/android"Xmlns:tools= "Http://schemas.android.com/tools"Android:layout_width= "Match_parent"Android:layout_height= "Match_parent" > <LinearLayout android:layout_width= "Match_parent"Android:layout_height= "Wrap_content"android:gravity= "Center_horizontal"Android:layout_margintop= "10DP"Android:layout_marginbottom= "55DP"android:orientation= "Vertical" > <Com.czm.myroundimageview.XCRoundImageViewByXfermode Android:id= "@+id/cicleimageview"Android:layout_width= "150DP"Android:layout_height= "150DP"android:src= "@drawable/img1"/> <Com.czm.myroundimageview.XCRoundImageViewByXfermode Android:id= "@+id/roundrectimageview"Android:layout_width= "125DP"Android:layout_height= "145DP"Android:layout_margintop= "15DP"android:src= "@drawable/img2"/> <Com.czm.myroundimageview.XCRoundImageViewByXfermode Android:id= "@+id/ovalimageview"Android:layout_width= "140DP"Android:layout_height= "184DP"Android:layout_margintop= "15DP"android:src= "@drawable/img3"/> </LinearLayout></ScrollView>
Vi. use and testing of custom ImageView
The custom imageview that are drawn directly above is written, and the following is the custom ImageView, using the same method as normal ImageView, as normal controls.
PackageCom.czm.myroundimageview;Importandroid.app.Activity;ImportAndroid.os.Bundle; Public classMainactivityextendsActivity {PrivateXcroundimageviewbyxfermode Circleimageview;//Circular Picture PrivateXcroundimageviewbyxfermode Roundrectimageview;//Rounded Rectangle Picture PrivateXcroundimageviewbyxfermode Ovalimageview;//Oval Image@Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate); Setcontentview (R.layout.activity_main); Initviews (); } /*** Initialize views*/ Private voidinitviews () {Circleimageview=(Xcroundimageviewbyxfermode) Findviewbyid (R.id.cicleimageview); Roundrectimageview=(Xcroundimageviewbyxfermode) Findviewbyid (R.id.roundrectimageview); Ovalimageview=(Xcroundimageviewbyxfermode) Findviewbyid (R.id.ovalimageview); Roundrectimageview.settype (Xcroundimageviewbyxfermode.type_round); Roundrectimageview.setroundborderradius (100); Ovalimageview.settype (Xcroundimageviewbyxfermode.type_oval); Ovalimageview.setroundborderradius (50); } }
Seven, as usual, finally provide full source download
Real Theme Park net :http://www.zhentiyuan.com
Download Now:http://download.csdn.net/detail/jczmdeveloper/8311659
Android implements custom round, fillet, and Ellipse imageview (using Xfermode Graphics Rendering method)