Android browser image, click to enlarge to Full Screen Effect

Source: Internet
Author: User

Recently, I made a project similar to the QQ space to achieve the photo browsing function. I clicked images in the QQ space to zoom in to the full screen, and the effect was very good, so I made a similar effect. As follows.

Signature + signature/qx + signature/XC1L3nw + signature + cq + tcTV/Signature + 1 vczus + signature/nS1NKqsaPWpNXiuPbM + Neqtq + signature + juw.vcd4kpha + Signature /Second + 2qLK70rvR + TwvcD4KPHA + second/Second/nNvM/uyr61xm1_n3h + second/second + second/O1xKGjy/second + CjxwPtaxvdPM + second = "brush: java; "> package com. roamer. ui. view; import android. animation. animator; import android. animation. propertyValuesHolder; import android. animation. valueAnimator; import android. app. activity; import android. content. context; import android. graphics. bitmap; import android. graphics. canvas; import android. graphics. matrix; import android. graphics. paint; import android. graphics. paint. style; import android. graphics. drawable. bitmapDrawable; import android. util. attributeSet; import android. util. log; import android. view. animation. accelerateDecelerateInterpolator; import android. widget. imageView;/*** the ImageView of the 2d smoothly changed display image * is only used for: switch from an ImageView with ScaleType == CENTER_CROP to another ImageView with ScaleType = * FIT_CENTER, or vice versa (of course, it is best to use the same image) ** @ author Dean Tao **/public class SmoothImageView extends ImageView {private static final int STATE_NORMAL = 0; private static final int STATE_TRANSFORM_IN = 1; private static final int STATE_TRANSFORM_OUT = 2; private int mOriginalWidth; private int mOriginalHeight; private int mOriginalLocationX; private int success; private int mState = STATE_NORMAL; private Matrix mSmoothMatrix; private Bitmap mBitmap; private boolean mTransformStart = false; private Transfrom mTransfrom; private final int mBgColor = 0xFF000000; private int mBgAlpha = 0; private Paint mPaint; public SmoothImageView (Context context) {super (context); init ();} public SmoothImageView (Context context, AttributeSet attrs) {super (context, attrs); init ();} public SmoothImageView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); init () ;}private void init () {mSmoothMatrix = new Matrix (); mPaint = new Paint (); mPaint. setColor (mBgColor); mPaint. setStyle (Style. FILL); // setBackgroundColor (mBgColor);} public void setOriginalInfo (int width, int height, int locationX, int locationY) {mOriginalWidth = width; mOriginalHeight = height; orientation = locationX; mOriginalLocationY = locationY; // convert the screen coordinates to the coordinates in the view. Because the view I use is MATCH_PARENT, you do not need to locate the position of the view, if not, you also need to locate the view and calculate mOriginalLocationX and mOriginalLocationYmOriginalLocationY = mOriginalLocationY-getStatusBarHeight (getContext ());} /*** get the status bar height ** @ return */public static int getStatusBarHeight (Context context) {Class C = null; Object obj = null; java. lang. reflect. field field = null; int x = 0; int statusBarHeight = 0; try {c = Class. forName ("com. android. internal. r$ dimen "); obj = c. newInstance (); field = c. getField ("status_bar_height"); x = Integer. parseInt (field. get (obj ). toString (); statusBarHeight = context. getResources (). getDimensionPixelSize (x); return statusBarHeight;} catch (Exception e) {e. printStackTrace ();} retur N statusBarHeight;}/*** is used to start the entry method. Before calling this method, you must call setOriginalInfo */public void transformIn () {mState = STATE_TRANSFORM_IN; mTransformStart = true; invalidate () ;}/ *** to start the exit method. Before calling this method, you must have called setOriginalInfo */public void transformOut () {mState = STATE_TRANSFORM_OUT; mTransformStart = true; invalidate ();} private class Transfrom {float startScale; // float endScale of the image; // float scale of the image end; // LocationSizeF startRect of the ValueAnimator attribute; // LocationSizeF endRect of the starting region; // The ending region LocationSizeF rect; // void initStartIn () {scale = startScale; try {rect = (Loca TionSizeF) startRect. clone ();} catch (CloneNotSupportedException e) {e. printStackTrace () ;}} void initStartOut () {scale = endScale; try {rect = (LocationSizeF) endRect. clone ();} catch (CloneNotSupportedException e) {e. printStackTrace () ;}}/ *** initialize the variable information */private void initTransform () {if (getDrawable () = null) {return ;} if (mBitmap = null | mBitmap. isRecycled () {mBitmap = (BitmapDrawable) getDr Awable (). getBitmap ();} // prevents mTransfrom from repeating the same initialization if (mTransfrom! = Null) {return;} if (getWidth () = 0 | getHeight () = 0) {return;} mTransfrom = new Transfrom (); /** The following is the scaling calculation * // * calculates the initial scaling value. The initial value is the result of CENTR_CROP, therefore, ensure that at least one image width and height can match the original width and height, and the other is greater than */float xSScale = mOriginalWidth/(float) mBitmap. getWidth (); float ySScale = mOriginalHeight/(float) mBitmap. getHeight (); float startScale = xSScale> ySScale? XSScale: ySScale; mTransfrom. startScale = startScale;/* the zoom value at the end of the calculation. To achieve the FIT_CENTER effect, make sure that at least one width and height of the image can match the original width and height, the other one is less than */float xEScale = getWidth ()/(float) mBitmap. getWidth (); float yEScale = getHeight ()/(float) mBitmap. getHeight (); float endScale = xEScale <yEScale? XEScale: yEScale; mTransfrom. endScale = endScale;/*** calculate the range of the Canvas Clip, that is, the display range of the image, because the image grows slowly and is proportional, therefore, you need to cut the area * of the image to display the effect, and the change range of the display area is in the range of the original CENTER_CROP effect * to the final range of FIT_CENTER, I use LocationSizeF for better CALCULATION OF THE REGION *, which includes the coordinates of the top left vertex, and the width and height, and finally converts it to the Rect of the Canvas cut. * // * Start Region */mTransfrom. startRect = new LocationSizeF (); mTransfrom. startRect. left = mOriginalLocationX; mTransfrom. startRect. top = mOriginalLocationY; mTransfrom. StartRect. width = mOriginalWidth; mTransfrom. startRect. height = mOriginalHeight;/* end area */mTransfrom. endRect = new LocationSizeF (); float bitmapEndWidth = mBitmap. getWidth () * mTransfrom. endScale; // The final width of the image float bitmapEndHeight = mBitmap. getHeight () * mTransfrom. endScale; // The final width of the image, mTransfrom. endRect. left = (getWidth ()-bitmapEndWidth)/2; mTransfrom. endRect. top = (getHeight ()-bitmapEndHeight )/ 2; mTransfrom. endRect. width = bitmapEndWidth; mTransfrom. endRect. height = bitmapEndHeight; mTransfrom. rect = new LocationSizeF ();} private class LocationSizeF implements Cloneable {float left; float top; float width; float height; @ Overridepublic String toString () {return "[left: "+ left +" top: "+ top +" width: "+ width +" height: "+ height +"] ";}@ Overridepublic Object clone () throws CloneNotSupportedException {// DO Auto-generated method stubreturn super. clone () ;}}/* the Matrix that implements the CENTER_CROP function is no longer used in the optimization process */private void getCenterCropMatrix () {if (getDrawable () = null) {return;} if (mBitmap = null | mBitmap. isRecycled () {mBitmap = (BitmapDrawable) getDrawable ()). getBitmap ();}/* implements the CENTER_CROP function */float xScale = mOriginalWidth/(float) mBitmap. getWidth (); float yScale = mOriginalHeight/(float) MBitmap. getHeight (); float scale = xScale> yScale? XScale: yScale; mSmoothMatrix. reset (); mSmoothMatrix. setScale (scale, scale); mSmoothMatrix. postTranslate (-(scale * mBitmap. getWidth ()/2-mOriginalWidth/2),-(scale * mBitmap. getHeight ()/2-mOriginalHeight/2);} private void getbmp matrix () {if (getDrawable () = null) {return;} if (mTransfrom = null) {return;} if (mBitmap = null | mBitmap. isRecycled () {mBitmap = (BitmapDrawable) getDrawabl E ()). getBitmap ();}/* implements the CENTER_CROP function */mSmoothMatrix. setScale (mTransfrom. scale, mTransfrom. scale); mSmoothMatrix. postTranslate (-(mTransfrom. scale * mBitmap. getWidth ()/2-mTransfrom. rect. width/2),-(mTransfrom. scale * mBitmap. getHeight ()/2-mTransfrom. rect. height/2) ;}@ Overrideprotected void onDraw (Canvas canvas) {if (getDrawable () = null) {return; // couldn't resolve the URI} if (mStat E = STATE_TRANSFORM_IN | mState = STATE_TRANSFORM_OUT) {if (mTransformStart) {initTransform ();} if (mTransfrom = null) {super. onDraw (canvas); return;} if (mTransformStart) {if (mState = STATE_TRANSFORM_IN) {mTransfrom. initStartIn ();} else {mTransfrom. initStartOut () ;}} if (mTransformStart) {Log. d ("Dean", "mTransfrom. startScale: "+ mTransfrom. startScale); Log. d ("Dean", "mTransfrom. startScale: "+ mTransfro M. endScale); Log. d ("Dean", "mTransfrom. scale: "+ mTransfrom. scale); Log. d ("Dean", "mTransfrom. startRect: "+ mTransfrom. startRect. toString (); Log. d ("Dean", "mTransfrom. endRect: "+ mTransfrom. endRect. toString (); Log. d ("Dean", "mTransfrom. rect: "+ mTransfrom. rect. toString ();} mPaint. setAlpha (mBgAlpha); canvas. drawPaint (mPaint); int saveCount = canvas. getSaveCount (); canvas. save (); // first obtain the image Matrix getbmp matri at the moment X (); canvas. translate (mTransfrom. rect. left, mTransfrom. rect. top); canvas. clipRect (0, 0, mTransfrom. rect. width, mTransfrom. rect. height); canvas. concat (mSmoothMatrix); getDrawable (). draw (canvas); canvas. restoreToCount (saveCount); if (mTransformStart) {mTransformStart = false; startTransform (mState) ;}} else {// after Transform In is changed, change the background to black, make the Activity opaque mPaint. setAlpha (1, 255); canvas. drawPaint (mPaint); super. onDraw (Canvas) ;}} private void startTransform (final int state) {if (mTransfrom = null) {return;} ValueAnimator valueAnimator = new ValueAnimator (); valueAnimator. setDuration (300); valueAnimator. setInterpolator (new AccelerateDecelerateInterpolator (); if (state = STATE_TRANSFORM_IN) {PropertyValuesHolder scaleHolder = PropertyValuesHolder. ofFloat ("scale", mTransfrom. startScale, mTransfrom. endScale); PropertyV AluesHolder leftHolder = PropertyValuesHolder. ofFloat ("left", mTransfrom. startRect. left, mTransfrom. endRect. left); PropertyValuesHolder topHolder = PropertyValuesHolder. ofFloat ("top", mTransfrom. startRect. top, mTransfrom. endRect. top); PropertyValuesHolder widthHolder = PropertyValuesHolder. ofFloat ("width", mTransfrom. startRect. width, mTransfrom. endRect. width); PropertyValuesHolder heightHolder = Prop ErtyValuesHolder. ofFloat ("height", mTransfrom. startRect. height, mTransfrom. endRect. height); PropertyValuesHolder alphaHolder = PropertyValuesHolder. ofInt ("alpha", 0,255); valueAnimator. setValues (scaleHolder, leftHolder, topHolder, widthHolder, heightHolder, alphaHolder);} else {PropertyValuesHolder scaleHolder = PropertyValuesHolder. ofFloat ("scale", mTransfrom. endScale, mTransfrom. startScale); Prope RtyValuesHolder leftHolder = PropertyValuesHolder. ofFloat ("left", mTransfrom. endRect. left, mTransfrom. startRect. left); PropertyValuesHolder topHolder = PropertyValuesHolder. ofFloat ("top", mTransfrom. endRect. top, mTransfrom. startRect. top); PropertyValuesHolder widthHolder = PropertyValuesHolder. ofFloat ("width", mTransfrom. endRect. width, mTransfrom. startRect. width); PropertyValuesHolder heightHolder = PropertyValuesHolder. ofFloat ("height", mTransfrom. endRect. height, mTransfrom. startRect. height); PropertyValuesHolder alphaHolder = PropertyValuesHolder. ofInt ("alpha", 255, 0); valueAnimator. setValues (scaleHolder, leftHolder, topHolder, widthHolder, heightHolder, alphaHolder);} valueAnimator. addUpdateListener (new ValueAnimator. animatorUpdateListener () {@ Overridepublic synchronized void onAnimationUpda Te (ValueAnimator animation) {mTransfrom. scale = (Float) animation. getAnimatedValue ("scale"); mTransfrom. rect. left = (Float) animation. getAnimatedValue ("left"); mTransfrom. rect. top = (Float) animation. getAnimatedValue ("top"); mTransfrom. rect. width = (Float) animation. getAnimatedValue ("width"); mTransfrom. rect. height = (Float) animation. getAnimatedValue ("height"); mBgAlpha = (Integer) animation. getAnimat EdValue ("alpha"); invalidate (); (Activity) getContext ()). getWindow (). getDecorView (). invalidate () ;}}); valueAnimator. addListener (new ValueAnimator. animatorListener () {@ Overridepublic void onAnimationStart (Animator animation) {}@ Overridepublic void Merge (animation or animation) {}@ Overridepublic void onAnimationEnd (Animator animation) {/** if you want to enter, you certainly want to stay in the center_crop region. However, if it is out, it should not be the position of center_crop *, but it should be the position of the last change, because when the out ends, the view is Normal, otherwise, there will be a bug * // TODO. You can modify if (state = STATE_TRANSFORM_IN) {mState = STATE_NORMAL;} if (mTransformListener! = Null) {mTransformListener. onTransformComplete (state) ;}@overridepublic void onAnimationCancel (Animator animation) {}}); valueAnimator. start ();} public void setOnTransformListener (TransformListener listener) {mTransformListener = listener;} private TransformListener mTransformListener; public static interface TransformListener {/*** @ param mode * STATE_TRANSFORM_IN 1, STATE_TRANSFORM_OUT 2 */void onTransformComplete (int mode); // mode 1 }}
When used, the previous Activity passes the following information to the details Activity:

Intent intent = new Intent (MainActivity. this, SpaceImageDetailActivity. class); intent. putExtra ("images", (ArrayList
 
  
) Datas); // non-essential intent. putExtra ("position", position); int [] location = new int [2]; imageView. getLocationOnScreen (location); intent. putExtra ("locationX", location [0]); // intent is required. putExtra ("locationY", location [1]); // intent is required. putExtra ("width", imageView. getWidth (); // intent is required. putExtra ("height", imageView. getHeight (); // The value must be startActivity (intent); overridePendingTransition (0, 0 );
 

When Activity details receives these parameters, and initializes the location information of the SmoothImageView, you can change it.

mDatas = (ArrayList
 
  ) getIntent().getSerializableExtra("images");mPosition = getIntent().getIntExtra("position", 0);mLocationX = getIntent().getIntExtra("locationX", 0);mLocationY = getIntent().getIntExtra("locationY", 0);mWidth = getIntent().getIntExtra("width", 0);mHeight = getIntent().getIntExtra("height", 0);imageView = new SmoothImageView(this);imageView.setOriginalInfo(mWidth, mHeight, mLocationX, mLocationY);imageView.transformIn();imageView.setLayoutParams(new ViewGroup.LayoutParams(-1, -1));imageView.setScaleType(ScaleType.FIT_CENTER);setContentView(imageView);ImageLoader.getInstance().displayImage(mDatas.get(mPosition), imageView);
 



The scaling effect of the above image has been completed, but you still need to set the Activity transparent style to make the alpha effect experience better.

Set the following style for the Activity. In addition, the position of the view is not located in SmoothImageView, but the status bar is processed. Therefore, set the Activity to NotitleBar. The style is as follows:

 



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.