Android uses the Xfermode graphics rendering method to implement custom circles, rounded corners, and ellipses ImageView

Source: Internet
Author: User
Tags transparent color null null stub xmlns

One: Introduction:

In the previous "Android using Bitmapshader Graphics rendering to achieve circular, rounded and elliptical custom picture view", using the Bitmapshader method to achieve custom round, fillet, and other custom ImageView, In this article we will use the more common Xfermode rendering scheme to achieve the imageview of circles, rounded corners and elliptical styles, and this example is also directly inherited ImageView,

This can save a lot of things, such as measurement steps, and do not need to write their own way to set up pictures, this article uses the dst_in mode in Xfermode mode to achieve the effect, of course, we can also use other models, such as src_in can achieve the effect.

(as usual complete source code at the end of the article to give the download address ha)

Two: Effect chart:

Three, Xfermode rendering mode introduction:

Xfermode affects how new colors are plotted on canvas already existing images

* Under normal circumstances, a new shape is drawn on the image, and if the new paint is not transparent, the color below will be obscured.

* If the new paint is transparent, it will be dyed to the following color

The following Xfermode subclasses can change this behavior:

AVOIDXFERMODE specifies a color and tolerance that forces the paint to avoid drawing on it (or drawing only on it).

Pixelxorxfermode a simple pixel XOR operation is applied when overwriting an existing color.

Porterduffxfermode This is a very powerful conversion mode, which allows you to use any of the 16 porter-duff rules of the image to control how paint interacts with existing canvas images.

Here we have to mention the classic diagram:

The above 16 modes are described as follows:

From the above we can see that Porterduff.mode is an enumeration class, with a total of 16 enumerated values:

1.porterduff.mode.clear

The drawing is not submitted to the canvas.

2.porterduff.mode.src

Show Upper Drawing Pictures

3.porterduff.mode.dst

Show lower drawing picture

4.porterduff.mode.src_over

The normal drawing display, the upper and lower layers draw the overlay.

5.porterduff.mode.dst_over

The upper and lower layers are displayed. The lower ranks show.

6.porterduff.mode.src_in

Draws the intersection of two layers. Displays the upper layer.

7.porterduff.mode.dst_in

Draws the intersection of two layers. Shows the lower level.

8.porterduff.mode.src_out

Draws a non-intersection portion of the upper layer.

9.porterduff.mode.dst_out

Remove the layer to draw the non intersection part.

10.porterduff.mode.src_atop

To remove the disjoint portion of a layer from the upper part

11.porterduff.mode.dst_atop

Take the upper part of the non-intersection and the lower intersection

12.porterduff.mode.xor

XOR: Removing the two Layer intersection section

13.porterduff.mode.darken

Take two layer all area, the intersection part color deepens

14.porterduff.mode.lighten

Take two layers all, light the intersection part of the color

15.porterduff.mode.multiply

Take two layer intersection part overlay color

16.porterduff.mode.screen

Take two layer all area, the intersection part becomes transparent color

The realization of the imageview of the custom circle, fillet and Ellipse

1, measuring the size of the view, the circle for special treatment

The code is as follows Copy Code
/**
* Measure the size of the view
*/
@Override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
TODO auto-generated Method Stub
Super.onmeasure (Widthmeasurespec, Heightmeasurespec);
If the type is circular, force the view's width to be consistent, and take a smaller value with a wide height
if (mtype = = type_circle) {
int width = math.min (Getmeasuredwidth (), Getmeasuredheight ());
Setmeasureddimension (width, width);
}
}

2, draw the bitmap of different graphics, for OnDraw () to draw the time with

The code is as follows Copy Code
/**


* Draw different graphics bitmap


*/


Private Bitmap Getdrawbitmap () {


Bitmap Bitmap = Bitmap.createbitmap (GetWidth (), GetHeight (),


Bitmap.Config.ARGB_8888);


Canvas Canvas = new Canvas (bitmap);


Paint Paint = new Paint (Paint.anti_alias_flag);


Paint.setcolor (Color.Black);





if (mtype = = type_circle)


{//Draw Circle


Canvas.drawcircle (GetWidth ()/2, getwidth ()/2, getwidth ()/2,


Paint);


}else if (mtype = = Type_round)


{//Draw rounded Rectangle


Canvas.drawroundrect (New RECTF (0, 0, getwidth (), GetHeight ()),


Mroundborderradius, Mroundborderradius, paint);


}else if (mtype = = Type_oval) {


Draw Ellipse


Canvas.drawoval (New RECTF (0, 0, getwidth (), GetHeight ()), mpaint);


}





return bitmap;


}

3, in the OnDraw () to draw out

The code is as follows Copy Code
/**


* Draw the contents of the view


*/


@Override


protected void OnDraw (Canvas Canvas) {


TODO auto-generated Method Stub


Remove the bitmap from the cache


Bitmap bmp = (Mbufferbitmap = null null:mBufferBitmap.get ());


if (bmp = null | | bmp.isrecycled ()) {


If there is no cache presence


Get drawable


drawable drawable = getdrawable ();


Get the width and height of the drawable


int dwidth = Drawable.getintrinsicwidth ();


int dheight = Drawable.getintrinsicheight ();


LOG.V ("Czm", "dwidth=" +dwidth+ ", Width=" +getwidth ());


if (null!= drawable) {


BMP = Bitmap.createbitmap (GetWidth (), GetHeight (),


config.argb_8888);


float scale = 1.0f;


Create Canvas


Canvas Drawcanvas = new Canvas (BMP);


Calculates the scaling ratio according to the width of the bitmap and the height of the view; because the src width is set


The proportions may be different from the imageview ratio, where we don't want the picture to be distorted;





if (mtype = = type_circle)


{//If it's a circle


Scale = GetWidth () * 1.0f/math.min (Dwidth, dheight);


}else if (mtype = = Type_round | | mtype = = type_oval)


{//If a rounded rectangle or ellipse


If the width or height of the picture does not match the width of the view, calculate the proportion that needs to be scaled;


The height of the scaled picture must be greater than the width of our view; So here we take the big value;


Scale = Math.max (getwidth () * 1.0f/dwidth, GetHeight ()


* 1.0f/dheight);


}


LOG.V ("Czm", "scale=" +scale);


Depending on the scaling, set the bounds, which is equivalent to zooming the picture


Drawable.setbounds (0, 0, (int) (scale * dwidth), (int) (scale * dheight));


Drawable.draw (Drawcanvas);


Gets the bitmap, that is, the bitmap of a circle, fillet, or ellipse


if (Mmaskbitmap = null | | mmaskbitmap.isrecycled ()) {


Mmaskbitmap = Getdrawbitmap ();


}


Set Xfermode rendering mode for paint


Mpaint.reset ();


Mpaint.setfilterbitmap (FALSE);


Mpaint.setxfermode (Mxfermode);


Draw different shapes


Drawcanvas.drawbitmap (mmaskbitmap, 0, 0,mpaint);


Mpaint.setxfermode (NULL);





Draw the prepared bitmap.


Canvas.drawbitmap (BMP, 0, 0, NULL);


Bitmap cache to avoid allocating memory every time OnDraw is called


Mbufferbitmap = new weakreference<bitmap> (BMP);


}





}else{


If the cache still exists


Mpaint.setxfermode (NULL);


Canvas.drawbitmap (BMP, 0.0f, 0.0f, Mpaint);


Return


}


}

4, because of the use of weak reference caching technology, you need to rewrite the invalidate () method to do some of the release of recycling resources, such as processing:

The code is as follows Copy Code
/**
* Because caching technology is used, it is necessary to do some recycling and release resources in invalidate
*/
@Override
public void invalidate () {
TODO auto-generated Method Stub
Mbufferbitmap = null;
if (Mmaskbitmap!= null) {
Mmaskbitmap.recycle ();
Mmaskbitmap = null;
}
Super.invalidate ();
}

Implementation of view layout:

The code is as follows Copy Code

<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. using and Testing custom ImageView

The custom imageview that is drawn directly above is finished, the following is the use of this custom ImageView, using the same method as normal ImageView, as a normal control.

The code is as follows Copy Code

Package Com.czm.myroundimageview;

Import android.app.Activity;
Import Android.os.Bundle;

public class Mainactivity extends activity {

Private Xcroundimageviewbyxfermode circleimageview;//Circular picture


Private Xcroundimageviewbyxfermode roundrectimageview;//rounded rectangular picture


Private Xcroundimageviewbyxfermode ovalimageview;//Oval picture


@Override


protected void OnCreate (Bundle savedinstancestate) {


Super.oncreate (savedinstancestate);


Setcontentview (R.layout.activity_main);


Initviews ();


}


/**


* Initialize views


*/


private void Initviews () {


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);





}

}

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.