Android Imitation QQ avatar custom intercept function _android

Source: Internet
Author: User
Tags gety

Look at the Android version of QQ custom Avatar function, decided to achieve their own, casually familiar with the Android drawing and image processing this piece of knowledge.

First look at the effect:

Thinking Analysis:

This effect can be done with two view, the top view is a cover, draw translucent color, a circle dug in the middle, the lower view is used to display pictures, have the ability to move and zoom, and can intercept pictures in a region.

The knowledge points involved:

1.Matrix, moving and zooming of pictures

The Setxfermode method of 2.Paint

3. After the picture enlarged move, intercepts a part

Encoding implementation:

Custom Three view:

1. Lower View:clipphotoview

2. Top cover View:clipphotocircleview

3. layout file: Clipphotolayout, to achieve the layout of two-level view, and as a façade of the entire function

Clipphotocircleview Code:

@Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas); Drawmask (Canvas);}/** * Draw mask */private void DRA
Wmask (Canvas Canvas) {//Draw background color Bitmap Bitmap = Bitmap.createbitmap (GetWidth (), GetHeight (), Bitmap.Config.ARGB_8888);
Canvas C1 = new Canvas (bitmap);
C1.drawargb (150, 0, 0, 0);
Paint strokepaint = new Paint ();
Strokepaint.setantialias (TRUE);
Strokepaint.setcolor (Color.White);
Strokepaint.setstyle (Paint.Style.STROKE);
Strokepaint.setstrokewidth (Stroke_width);
C1.drawcircle (GetWidth ()/2, GetHeight ()/2, Getradius (), strokepaint);
Draw round Bitmap Circlebitmap = Bitmap.createbitmap (GetWidth (), GetHeight (), Bitmap.Config.ARGB_8888);
Canvas C2 = new Canvas (CIRCLEBITMAP);
Paint circlepaint = new Paint ();
Circlepaint.setstyle (Paint.Style.FILL);
Circlepaint.setcolor (color.red);
Circlepaint.setantialias (TRUE);
C2.drawcircle (GetWidth ()/2, GetHeight ()/2, Getradius (), circlepaint);
Two layers synthesized Paint Paint = new Paint (); Paint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.DST_out));
C1.drawbitmap (circlebitmap, 0, 0, paint);
Paint.setxfermode (NULL);
Canvas.drawbitmap (bitmap, 0, 0, NULL); }

Using the Setxfermode,mode as Dst_out, the following figure:

Clipphotoview Code:

/** * Created by Caocong on 10/9/16.
* Display the view of the picture, you can support and zoom * * public class Clipphotoview extends ImageView implements View.ontouchlistener, Scalegesturedetector.onscalegesturelistener {private static final String TAG = ClipPhotoView.class.getSimpleName ();//
Max zoom ratio private static final float Max_scale = 4.0f;
Minimum scaling private static float Min_scale = 1.0f;
Matrix array private static final float matrix_arr[] = new FLOAT[9]; /** * State/private static final class Mode {//Initial state private static final int NONE = 0;//TODO private static final int DRA
G = 1;
Scale private static final int ZOOM = 2;
}//Current state private int mmode = Mode.none;
Zoom gesture Private Scalegesturedetector mscaledetector;
Matrix private matrices Mmatrix = new Matrix ();
When the finger presses the point private PointF mprevpointf = new PointF ();
The radius of the truncated circular box is private int mradius;
Private Boolean Firsttime = True for the first time; 
Public Clipphotoview {This (context, null);} public Clipphotoview (context, AttributeSet attrs) { this.TRS, 0); Public Clipphotoview (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); mscal
Edetector = new Scalegesturedetector (context, this);
Mradius = Util.getradius (GetContext ());
Must be set to trigger Setontouchlistener (this);
Setscaletype (Scaletype.matrix); }/** * Initialize/private void init () {drawable drawable = getdrawable (); if (drawable = null) {//throw new illegalargumen
Texception ("drawable can not be null");
Return
} initposandscale (); /** * Initialize scaling/private void Initposandscale () {if (firsttime) {drawable drawable = getdrawable (); int width = Getwid
Th ();
int height = getheight ();
Initialize int dw = Drawable.getintrinsicwidth ();
int dh = drawable.getintrinsicheight ();
float ScaleX = 1.0f;
float ScaleY = 1.0f;
Have you done zoom processing Boolean isscaled = false; 
if (Width < Getdiameter ()) {ScaleX = Getdiameter () * 1.0f/width; isscaled = true;} if (Height < Getdiameter ()) {
ScaleY = Getdiameter () * 1.0f/height;
Isscaled = true; Float scale = Math.max (ScaleX, ScaleY);  if (isscaled) {min_scale = SCALE;} else {Min_scale = Math.max ((Getdiameter () * 1.0f)/DW, Getdiameter () * 1.0F/DH) +
0.01f;
LOG.D (TAG, "scale=" + scale);
Mmatrix.postscale (scale, scale, getwidth ()/2, GetHeight ()/2);
Mmatrix.posttranslate ((WIDTH-DW)/2, (HEIGHT-DH)/2);
Setimagematrix (Mmatrix);
Firsttime = false; @Override public boolean Onscale (Scalegesturedetector detector) {Float scale = Getscale (); Float scalefactor = Detect
Or.getscalefactor ();
if ((Scale >= Min_scale && scalefactor > 1.0f) | | (Scale <= Max_scale && scalefactor < 1.0f)) {if (scale * Scalefactor <= min_scale) {scalefactor = Min_scale/scale;} else if (scale * Scalefactor >= Max_sca LE) {scalefactor = Max_scale/scale;} mmatrix.postscale (Scalefactor, Scalefactor, Detector.getfocusx (), Detector.getFo
Cusy ());
Checktrans ();
Setimagematrix (Mmatrix);
return true; @Override public boolean Onscalebegin (Scalegesturedetector detector) {mmode = Mode.zoom; return true;} @Override the public void Onscaleend (Scalegesturedetector detector) {mmode = Mode.none; @Override public boolean Ontouch (View V, motionevent event) {if (getdrawable () = null) {return false;} Mscaledetecto
R.ontouchevent (event);
Switch (event.getaction () & Motionevent.action_mask) {case MotionEvent.ACTION_DOWN:mMode = Mode.drag;
Mprevpointf.set (Event.getx (), event.gety ());
Break
Case MotionEvent.ACTION_UP:mMode = Mode.none;
Break Case MotionEvent.ACTION_MOVE:if (Mmode = = Mode.drag && event.getpointercount () = = 1) {Float x = Event.getx (); FL
Oat y = event.gety ();
float dx = event.getx ()-mprevpointf.x;
float dy = event.gety ()-mprevpointf.y;
RECTF RECTF = GETMATRIXRECTF (); If the width is less than the screen width, it is prohibited to move the left or right if (Rectf.width () <= getdiameter ()) {dx = 0;}///If the height of the screen is low, it is prohibited to move up or down if (rectf.height () <= ge
Tdiameter ()) {dy = 0;} mmatrix.posttranslate (dx, dy);
Checktrans ();
Boundary Judgment Setimagematrix (Mmatrix);
Mprevpointf.set (x, y);
} break; RetUrn true;  /** * Mobile boundary check/private void Checktrans () {RECTF rect = GETMATRIXRECTF (); float deltax = 0; float deltay = 0; int width
= GetWidth ();
int height = getheight ();
int horizontalpadding = (Width-getdiameter ())/2;
int verticalpadding = (Height-getdiameter ())/2; If the width or height is greater than the screen, the control range; The 0.001 here is because the loss of precision can cause problems if (rect.width () + 0.01 >= getdiameter ()) {if (Rect.left > horizontalpadding) {deltax =-rect
. Left + horizontalpadding;
} if (Rect.right < width-horizontalpadding) {deltax = Width-horizontalpadding-rect.right;}} 
if (Rect.height () + 0.01 >= getdiameter ()) {if (Rect.top > verticalpadding) {deltay =-rect.top + verticalpadding;
} if (Rect.bottom < height-verticalpadding) {DeltaY = Height-verticalpadding-rect.bottom;}}
Mmatrix.posttranslate (DeltaX, DeltaY); /** * Get diameter/public int getdiameter () {return Mradius * 2;}/** * Get zoom value * * @return * * Private float Getscale () {RET
Urn Getmatrixvalue (matrix.mscale_x); Private float GetmatrIxvalue (int index) {mmatrix.getvalues (Matrix_arr); return matrix_arr[index];/** * Get MATRIX RECTF * * Private RECTF Getm
ATRIXRECTF () {Matrix Matrix = Mmatrix;
RECTF rect = new RECTF ();
drawable d = getdrawable ();
if (null!= d) {rect.set (0, 0, d.getintrinsicwidth (), D.getintrinsicheight ()); Matrix.maprect (rect);} return rect;  @Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas); init ();}/** * Capture picture * * @return/Bitmap clip ()
{Bitmap Bitmap = Bitmap.createbitmap (GetWidth (), GetHeight (), Bitmap.Config.ARGB_8888);
Canvas Canvas = new Canvas (bitmap);
Draw (canvas);
int x = (getwidth ()-Getdiameter ())/2;
int y = (getheight ()-Getdiameter ())/2;
Return Bitmap.createbitmap (Bitmap, x, Y, Getdiameter (), Getdiameter ()); }
}

Scaling and moving using the Matrix Method Postscale () and posttranslate, pay attention to control boundaries.

Screenshot of the code in the clip () method, the principle: Create a blank bitmap, and the size of the screen as large, and then copy the current view drawn content into this bitmap, and then intercept the bitmap part.

Clipphotolayout Code:

public class Clipphotolayout extends Framelayout {private Clipphotocircleview mcircleview; private Clipphotoview Mphotov
Iew; Public Clipphotolayout {This (context, null);} public clipphotolayout, AttributeSet att RS) {This [context, attrs, 0];} public clipphotolayout (context, AttributeSet attrs, int defstyleattr) {super (con
Text, Attrs, defstyleattr);
Init (); 
private void Init () {Mcircleview = new Clipphotocircleview (GetContext ()); Mphotoview = new Clipphotoview (GetContext ()); Android.view.ViewGroup.LayoutParams LP = new Linearlayout.layoutparams (android.view.ViewGroup.LayoutParams.MATCH_
PARENT, Android.view.ViewGroup.LayoutParams.MATCH_PARENT);
AddView (Mphotoview, LP);
AddView (Mcircleview, LP); public void setimagedrawable (drawable drawable) {mphotoview.setimagedrawable (drawable);} public void setimagedrawable (int resid) {setimagedrawable (GetContext (). getdrawable (Resid));} public Bitmap Clipbitmap () {return
Mphotoview.clip (); }
}

Test mainactivity:

public class Mainactivity extends activity {
private clipphotolayout mclipphotolayout;
Private int[] Pictures = {R.drawable.mingren, r.drawable.cute, r.drawable.tuxi};
@Override
protected void onCreate (Bundle savedinstancestate) {
super.oncreate (savedinstancestate);
Setcontentview (R.layout.scale);
Settitle ("Move and Zoom");
Mclipphotolayout = (clipphotolayout) Findviewbyid (r.id.clip_layout);
Mclipphotolayout.setimagedrawable (Pictures[0]);
public void DoClick (view view) {
Bitmap Bitmap = Mclipphotolayout.clipbitmap ();
Intent Intent = new Intent (this, resultactivity.class);
Intent.putextra ("Photo", bitmap);
StartActivity (intent);
}

Mainactivity Layout file:

<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "Match_ Parent "
android:layout_height=" match_parent "
android:orientation=" vertical ">
< Com.caocong.image.widget.ClipPhotoLayout
android:id= "@+id/clip_layout"
android:layout_width= "Match_ Parent "
android:layout_height=" 0DP "
android:layout_weight=" 1.0 "/>
<button
android: Layout_width= "Match_parent"
android:layout_height= "wrap_content"
android:onclick= "DoClick
" android:text= "clip"/>
</LinearLayout>

The above is a small set to introduce the Android imitation QQ Avatar custom interception function, I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

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.