Androidclipsquare android for Square avatar cropping

Source: Internet
Author: User
Tags gety

Android achieves square avatar cropping

Realize the idea. The visible area of the interface is a 2-layer view

The top-most view is the display layer, which mainly draws a translucent border area and a white clipping area, which is easier to code.

The second layer inherits ImageView, uses the ImageView matrix to realize the display part picture, and moves, zooms in and so on the operation.

More complex is the effect of multi-finger operation on ImageView, see the code:

Clipsquareimageview.java

Package Com.h3c.androidclipsquare;import Android.annotation.targetapi;import Android.content.context;import Android.graphics.bitmap;import Android.graphics.canvas;import Android.graphics.matrix;import Android.graphics.rectf;import Android.graphics.drawable.drawable;import Android.os.build;import Android.util.attributeset;import Android.view.gesturedetector;import Android.view.motionevent;import Android.view.scalegesturedetector;import Android.view.velocitytracker;import Android.view.View;import Android.view.viewconfiguration;import Android.view.viewtreeobserver;import android.widget.imageview;/** * Created by H3C on 12/13/14. */public class Clipsquareimageview extends ImageView implements View.ontouchlistener,    Viewtreeobserver.ongloballayoutlistener {private static final int borderdistance = clipsquareview.borderdistance;    public static final Float Default_max_scale = 4.0f;    public static final Float Default_mid_scale = 2.0f; public static final Float Default_min_scale = 1.0F    private float Minscale = Default_min_scale;    private float midscale = Default_mid_scale;    private float Maxscale = Default_max_scale;    Private Multigesturedetector Multigesturedetector; Private Boolean isiniting;//is initializing private matrix Defaultmatrix = new Matrix ();//initialized picture matrix, control picture full screen and display area private Mat Rix Dragmatrix = new Matrix ()//drag-and-drop the dynamic matrix in the process of the private matrix Finalmatrix = new Matrix ();//finally display the Matrix private final REC    TF displayrect = new RECTF ();//The real size of the picture private final float[] matrixvalues = new FLOAT[9];    private int borderlength;        Public Clipsquareimageview (context context, AttributeSet Attrs) {Super (context, attrs);        Super.setscaletype (Scaletype.matrix);        Setontouchlistener (this);    Multigesturedetector = new Multigesturedetector (context);        } @Override protected void Onattachedtowindow () {Super.onattachedtowindow ();    Getviewtreeobserver (). Addongloballayoutlistener (this); } @SuppressWarnings ("Deprecation ") @Override protected void Ondetachedfromwindow () {Super.ondetachedfromwindow ();    Getviewtreeobserver (). Removeglobalonlayoutlistener (this);        } @Override public void Ongloballayout () {if (isiniting) {return;    }//Adjust view position initbmpposition ();        }/** * Initialize picture position */private void Initbmpposition () {isiniting = true;        Super.setscaletype (Scaletype.matrix);        drawable drawable = getdrawable ();        if (drawable = = null) {return;        } final Float viewwidth = getwidth ();        Final float viewheight = GetHeight ();        Final int drawablewidth = Drawable.getintrinsicwidth ();        Final int drawableheight = Drawable.getintrinsicheight ();        if (Viewwidth < viewheight) {borderlength = (int) (VIEWWIDTH-2 * borderdistance);        } else {borderlength = (int) (VIEWHEIGHT-2 * borderdistance);       } float Screenscale = 1f; Images smaller than the screen will be filled with screen if (Drawablewidth <= drawableheight) {//Portrait picture Screenscale = (float) borderlength/dr        Awablewidth;        } else {//Horizontal picture Screenscale = (float) borderlength/drawableheight;        } defaultmatrix.setscale (Screenscale, Screenscale);  if (drawablewidth <= drawableheight) {//Vertical picture float Heightoffset = (viewheight-drawableheight * screenscale)            /2.0f;            if (viewwidth <= viewheight) {//Vertical photo vertical screen defaultmatrix.posttranslate (borderdistance, Heightoffset);            } else {//Vertical photo Horizontal screen defaultmatrix.posttranslate ((viewwidth-borderlength)/2.0f, heightoffset);            }} else {float Widthoffset = (viewwidth-drawablewidth * screenscale)/2.0f; if (viewwidth <= viewheight) {//Horizontal photo, vertical screen defaultmatrix.posttranslate (Widthoffset, (Viewheight-borderlen            GTH)/2.0f); } else {//horizontal photo, horizontal screen Defaultmatrix.posttranslAte (Widthoffset, borderdistance);    }} resetmatrix ();        }/** * Resets the Matrix back to Fit_center, and then displays IT.S */private void Resetmatrix () {        if (Dragmatrix = = null) {return;        } dragmatrix.reset ();    Setimagematrix (Getdisplaymatrix ());        } private Matrix Getdisplaymatrix () {finalmatrix.set (Defaultmatrix);        Finalmatrix.postconcat (Dragmatrix);    return Finalmatrix; } @Override Public Boolean OnTouch (view view, Motionevent motionevent) {return Multigesturedetector.ontouche    Vent (motionevent); } private class Multigesturedetector extends Gesturedetector.simpleongesturelistener implements Scalegesture        Detector.onscalegesturelistener {private final scalegesturedetector scalegesturedetector;        Private final Gesturedetector Gesturedetector;        Private final float Scaledtouchslop;        Private Velocitytracker Velocitytracker; PRivate Boolean isdragging;        private float Lasttouchx;        private float Lasttouchy; Private float lastpointercount;//Last time was a few fingers event public multigesturedetector (context context) {Scalegesture            Detector = new Scalegesturedetector (context, this);            Gesturedetector = new Gesturedetector (context, this);            Gesturedetector.setondoubletaplistener (this);            Final Viewconfiguration Configuration = viewconfiguration.get (context);        Scaledtouchslop = Configuration.getscaledtouchslop (); } @Override public boolean onscale (Scalegesturedetector scalegesturedetector) {Float scale = get            Scale ();            float scalefactor = Scalegesturedetector.getscalefactor (); if (getdrawable () = null && ((Scale < Maxscale && scalefactor > 1.0f) | | (Scale > Minscale && scalefactor < 1.0f))) {if (Scalefactor * Scale < Minscale) {Scalefactor = Minscale/scale;                } if (Scalefactor * scale > Maxscale) {scalefactor = Maxscale/scale;                } dragmatrix.postscale (Scalefactor, Scalefactor, GetWidth ()/2, GetHeight ()/2);            Checkanddisplaymatrix ();        } return true;         } @Override public boolean onscalebegin (Scalegesturedetector scalegesturedetector) {return true; } @Override public void Onscaleend (Scalegesturedetector scalegesturedetector) {} public Boole            An ontouchevent (Motionevent event) {if (Gesturedetector.ontouchevent (event)) {return true;            } scalegesturedetector.ontouchevent (event);            /* Get the center x, y of all the pointers */float x = 0, y = 0;            Final int pointercount = Event.getpointercount ();  for (int i = 0; i < Pointercount; i++) {              x + = Event.getx (i);            Y + = event.gety (i);            } x = X/pointercount;            y = Y/pointercount; /* * If the pointer count has changed cancel the drag */if (pointercount! = Lastpointe                Rcount) {isdragging = false;                if (velocitytracker! = null) {velocitytracker.clear ();                } LASTTOUCHX = x;                Lasttouchy = y;            Lastpointercount = Pointercount; } switch (Event.getaction ()) {Case MotionEvent.ACTION_DOWN:if (Velocitytrac                    Ker = = null) {Velocitytracker = Velocitytracker.obtain ();                    } else {velocitytracker.clear ();                    } velocitytracker.addmovement (event);                    Lasttouchx = x;                    Lasttouchy = y; ISdragging = false;                Break                    Case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:lastPointerCount = 0;                        if (velocitytracker! = null) {velocitytracker.recycle ();                    Velocitytracker = null;                } break;                    Case Motionevent.action_move: {final float dx = x-lasttouchx, dy = y-lasttouchy;                        if (isdragging = = False) {//use Pythagoras to see if drag length is larger than                    Touch Slop isdragging = math.sqrt (DX * dx) + (dy * dy)) >= scaledtouchslop;                            } if (isdragging) {if (getdrawable () = null) {                            Dragmatrix.posttranslate (dx, dy);                        Checkanddisplaymatrix ();          }              Lasttouchx = x;                        Lasttouchy = y;                        if (velocitytracker! = null) {velocitytracker.addmovement (event);                }} break;        }} return true; } @Override public boolean Ondoubletap (Motionevent event) {try {float scale = ge                TScale ();                float x = getwidth ()/2;                Float y = getheight ()/2;                if (Scale < Midscale) {post (the new animatedzoomrunnable (scale, Midscale, X, y)); } else if (scale >= Midscale) && (Scale < Maxscale)) {post (new animatedzoomrunnable (SCA                Le, Maxscale, x, y));                } else {//double-click to zoom out less than the minimum value of post (new animatedzoomrunnable (scale, Minscale, X, y)); }} catch (Exception e) {//Can SometimEs happen when GetX () and GetY () are called} return true; }} Private class Animatedzoomrunnable implements Runnable {//These is ' postscale ' values, means they ' re C        Ompounded each iteration static final float animation_scale_per_iteration_in = 1.07f;        Static final float animation_scale_per_iteration_out = 0.93f;        Private final float focalx, focaly;        Private final float targetzoom;        Private final float Deltascale; Public animatedzoomrunnable (final float currentzoom, final float targetzoom, final Floa            T Focalx, final float focaly) {this.targetzoom = Targetzoom;            This.focalx = Focalx;            This.focaly = Focaly;            if (Currentzoom < targetzoom) {Deltascale = animation_scale_per_iteration_in;            } else {deltascale = animation_scale_per_iteration_out; }} @Override PubLIC void Run () {Dragmatrix.postscale (Deltascale, Deltascale, Focalx, focaly);            Checkanddisplaymatrix ();            Final float Currentscale = Getscale (); if (((Deltascale > 1f) && (Currentscale < targetzoom)) | | ((Deltascale < 1f) && (Targetzoom < Currentscale))) {//We haven ' t hits our target scale yet, so post ourselves//again Postonan            Imation (Clipsquareimageview.this, this); } else {//we ' ve scaled past our target zoom, so calculate the//necessary scale so We ' re                Back at Target zoom final float delta = targetzoom/currentscale;                Dragmatrix.postscale (Delta, Delta, Focalx, Focaly);            Checkanddisplaymatrix (); }}} @TargetApi (Build.version_codes. Jelly_bean) private void postonanimation (view view, Runnable Runnable) {if (Build.VERSION.SDK_INT &Gt;= Build.version_codes.        Jelly_bean) {view.postonanimation (runnable);        } else {view.postdelayed (runnable, 16);  }}/** * Returns the current scale value * * @return float-current Scale value */public final        Float Getscale () {dragmatrix.getvalues (matrixvalues);    return matrixvalues[matrix.mscale_x]; }/** * Helper method that simply checks the Matrix, and then displays the result */private void Checkanddi        Splaymatrix () {checkmatrixbounds ();    Setimagematrix (Getdisplaymatrix ());        } private void Checkmatrixbounds () {final RECTF rect = Getdisplayrect (Getdisplaymatrix ());        if (null = = rect) {return;        } float deltax = 0, DeltaY = 0;        Final float viewwidth = getwidth ();        Final float viewheight = GetHeight ();        After inference is moved or scaled, the picture is displayed beyond the crop box boundary final float Heightborder = (viewheight-borderlength)/2; Final float weightBorder = (viewwidth-borderlength)/2;        if (Rect.top > Heightborder) {deltay = Heightborder-rect.top;        } if (Rect.bottom < (Viewheight-heightborder)) {deltay = Viewheight-heightborder-rect.bottom;        } if (Rect.left > Weightborder) {deltax = Weightborder-rect.left;        } if (Rect.right < Viewwidth-weightborder) {deltax = Viewwidth-weightborder-rect.right;    }//Finally actually translate the matrix dragmatrix.posttranslate (DeltaX, DeltaY); }/** * Get pictures relative to matrix distance * * @param matrix *-matrix to map drawable against * @return R        ectf-displayed Rectangle */private RECTF Getdisplayrect (Matrix matrix) {drawable d = getdrawable ();            if (null! = d) {displayrect.set (0, 0, d.getintrinsicwidth (), D.getintrinsicheight ());            Matrix.maprect (Displayrect);        return displayrect;} return null; /** * Cut the picture and return the clipped Bitmap object * * @return */public Bitmap clip () {Bitmap Bitmap = bitmap.creat        Ebitmap (GetWidth (), GetHeight (), Bitmap.Config.ARGB_8888);        Canvas canvas = new canvas (bitmap);        Draw (canvas); Return Bitmap.createbitmap (Bitmap, (GetWidth ()-borderlength)/2, (GetHeight ()-borderlength)/2, Borderlength, border    length); }}


Code Download: Https://github.com/h3clikejava/AndroidClipSquare

Androidclipsquare android for Square avatar cropping

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.