很多的app的进入主页的页面是这样的,一张静态图片居中显示并且充满屏幕,同时不断放大图片中间部分,形成一种图片不断向中间放大的动画效果。AutoZoomInImageView继承ImageView并且实现了这种动画效果。
功能:
1.图像居中显示(图像覆盖整个AutoZoomInImageView),并可以使其进行中心放大显示的动画。
2.可以设置动画放大的时长。
3.可以设置动画放大的比例,设置其动画效果达到的最终尺寸是其初始化尺寸的增大倍数。
原理:
1.调整图片,使图片位于屏幕正中间。由于Android手机屏幕尺寸多样,而图片的大小也不甚相同,为了灵活的使用此效果,需要将任意尺寸比例的图片显示在任意尺寸比例的手机屏幕正中间,同时不使图片扭曲变形。
2.更改float[]的值,然后更新Matrix并应用到ImageView中,从而达到图片zoomin的效果。
添加至工程:
compile 'cn.carbs.android:AutoZoomInImageView:1.0.1'
使用方法可以详细看:
https://github.com/Carbs0126/AutoZoomInImageView
这里不再介绍
下面来看一个图:
主要看这个动画三秒后跳转,看代码
<pre name="code" class="html">import com.ss.b.view.AutoZoomInImageView;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
public class TwinActivity extends Activity {
AutoZoomInImageView iv;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_twin);
initView();
}
private void initView() {
iv = (AutoZoomInImageView) findViewById(R.id.view);
tv = (TextView) findViewById(R.id.textview);
iv.post(new Runnable() {
@Override
public void run() {
// 简单方式启动放大动画
// iv.init()
// .startZoomInByScaleDeltaAndDuration(0.3f, 1000,
// 1000);//放大增量是0.3,放大时间是1000毫秒,放大开始时间是1000毫秒以后
// 使用较为具体的方式启动放大动画
iv.init()
.setScaleDelta(0.3f)
// 放大的系数是原来的(1 + 0.3)倍
.setDurationMillis(3000)
// 动画的执行时间为1000毫秒
.setOnZoomListener(
new AutoZoomInImageView.OnZoomListener() {
@Override
public void onStart(View view) {
// 放大动画开始时的回调
handler.sendEmptyMessageDelayed(0, 1000);
}
@Override
public void onUpdate(View view,
float progress) {
// 放大动画进行过程中的回调 progress取值范围是[0,1]
}
@Override
public void onEnd(View view) {
// 放大动画结束时的回调
// vanishView(iv);
Intent intent = new Intent(
TwinActivity.this,
MainActivity.class);
finish();
startActivity(intent);
}
}).start(1000);// 延迟1000毫秒启动
}
});
}
@SuppressLint("HandlerLeak")
private final Handler handler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0:
tv.setText("2");
handler.sendEmptyMessageDelayed(1, 1000);
break;
case 1:// 显示界面
tv.setText("3");
break;
default:
break;
}
};
};
}
注意:动画开始是是延迟一秒,所以实际还有两秒的时间就要跳转页面,这里时间我直接给了一个string型的值。实际中应该用时间的累加值,根据实际需要进行灵活变动。
下面是AutoZoomInImageView这个类的源码,不想去github上看的可以参考这个
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
public class AutoZoomInImageView extends ImageView{
private int mDrawableW;
private int mDrawableH;
private int mImageViewW;
private int mImageViewH;
private long mDurationMillis = 700;
private float[] mValues = new float[9];
private float mScaleDelta = 0.2f;
private Drawable mDrawable;
private Matrix mMatrix;
public AutoZoomInImageView(Context context) {
super(context);
this.setScaleType(ScaleType.MATRIX);
}
public AutoZoomInImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setScaleType(ScaleType.MATRIX);
}
public AutoZoomInImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setScaleType(ScaleType.MATRIX);
}
public AutoZoomInImageView init(){
initInternalValues();
initPicturePosition();
return this;
}
public void init(Drawable drawable){
initInternalValues(drawable);
initPicturePosition();
}
private void initInternalValues(){
mDrawable = getDrawable();
if(mDrawable == null){
throw new IllegalArgumentException("please set the source of AutoZoomInImageView");
}
mDrawableW = mDrawable.getIntrinsicWidth();
mDrawableH = mDrawable.getIntrinsicHeight();
mImageViewW = getMeasuredWidth();
mImageViewH = getMeasuredHeight();
mMatrix = getImageMatrix();
mMatrix.getValues(mValues);
}
private void initInternalValues(Drawable drawable){
mDrawable = drawable;
if (mDrawable == null) {
throw new IllegalArgumentException("please set the source of AutoZoomInImageView");
}
mDrawableW = mDrawable.getIntrinsicWidth();
mDrawableH = mDrawable.getIntrinsicHeight();
mImageViewW = getMeasuredWidth();
mImageViewH = getMeasuredHeight();
mMatrix = getImageMatrix();
mMatrix.getValues(mValues);
}
private void initPicturePosition(){
updateMatrixValuesOrigin(mMatrix, mValues, mDrawableW, mDrawableH, mImageViewW, mImageViewH);
setImageMatrix(mMatrix);
}
private void startZoomInByScaleDelta(final float scaleDelta, long duration){
final float oriScaleX = mValues[0];
final float oriScaleY = mValues[4];
ValueAnimator va = ValueAnimator.ofFloat(0, scaleDelta);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float)animation.getAnimatedValue();
if(mOnZoomListener != null) mOnZoomListener.onUpdate(AutoZoomInImageView.this, value / scaleDelta);
updateMatrixValuesSpan(mValues, mDrawableW, mDrawableH, mImageViewW, mImageViewH,
oriScaleX, oriScaleY, value);
mMatrix.setValues(mValues);
setImageMatrix(mMatrix);
}
});
va.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
if(mOnZoomListener != null) mOnZoomListener.onStart(AutoZoomInImageView.this);
}
@Override
public void onAnimationEnd(Animator animation) {
if(mOnZoomListener != null) mOnZoomListener.onEnd(AutoZoomInImageView.this);
}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
});
va.setDuration(duration);
va.start();
}
/**
* start zooming in
* @param scaleDelta
* the scale that the image will add to original scale
* @param durationMillis
* the duration of zoomin animation, in millisecond.
* @param delayMillis
* the delayed time of starting zoomin animation, in millisecond.
*/
public void startZoomInByScaleDeltaAndDuration(final float scaleDelta, final long durationMillis, long delayMillis){
if(scaleDelta < 0){
throw new IllegalArgumentException("scaleDelta should be larger than 0, now scaleDelta is " + scaleDelta);
}
if(durationMillis < 0){
throw new IllegalArgumentException("durationMillis should not be less than 0, now durationMillis is " + durationMillis);
}
if(delayMillis < 0){
throw new IllegalArgumentException("delayMillis should not be less than 0, now delayMillis is " + delayMillis);
}
postDelayed(new Runnable() {
@Override
public void run() {
startZoomInByScaleDelta(scaleDelta, durationMillis);
}
}, delayMillis);
}
/**
* the scale that the image will add to original scale
* @param scaleDelta
* @return
*/
public AutoZoomInImageView setScaleDelta(float scaleDelta){
mScaleDelta = scaleDelta;
return this;
}
/**
* the duration of zoomin animation, in millisecond.
* @param durationMillis
* @return
*/
public AutoZoomInImageView setDurationMillis(long durationMillis){
mDurationMillis = durationMillis;
return this;
}
/**
* callback when zoomin animation finished
* @param onZoomListener
* @return
*/
public AutoZoomInImageView setOnZoomListener(OnZoomListener onZoomListener){
mOnZoomListener = onZoomListener;
return this;
}
/**
* start animation of zoomin
* @param delayMillis
* the delayed time of starting zoomin animation, in millisecond.
*/
public void start(long delayMillis){
postDelayed(new Runnable() {
@Override
public void run() {
startZoomInByScaleDelta(mScaleDelta, mDurationMillis);
}
}, delayMillis);
}
private void updateMatrixValuesOrigin(Matrix outMatrix, float[] outValues, float drawW, float drawH, float imageW, float imageH){
if(outMatrix == null || outValues == null){
throw new IllegalArgumentException("please set the source of AutoZoomInImageView's matrix and values");
}
outMatrix.reset();
if ((imageH * drawW > drawH * imageW)) {
float scale1 = (imageH)/(drawH);
float offset1 = (drawW * scale1 - imageW)/2;
outMatrix.postScale(scale1, scale1);
outMatrix.postTranslate(-offset1, 0);
} else {
float scale2 = (imageW)/(drawW);
float offset2 = (drawH * scale2 - imageH)/2;
outMatrix.postScale(scale2, scale2);
outMatrix.postTranslate(0, -offset2);
}
outMatrix.getValues(outValues);
}
private void updateMatrixValuesSpan(float[] outValues,
float drawW, float drawH,
float imageW, float imageH,
float oriScaleX, float oriScaleY,
float scaleDelta){
outValues[0] = oriScaleX * (1 + scaleDelta);
outValues[4] = oriScaleY * (1 + scaleDelta);
float offsetwidth = (drawW * outValues[0] - imageW)/2;
outValues[2] = - offsetwidth;
float offsetHeight = (drawH * outValues[4] - imageH)/2;
outValues[5] = - offsetHeight;
}
private OnZoomListener mOnZoomListener;
public interface OnZoomListener{
/**
* callback when zoom in animation is updating
* @param view AutoZoomInImageView
* @param progress return the progress of animation, scope is [0,1]
*/
void onUpdate(View view, float progress);
void onEnd(View view);
void onStart(View view);
}
}
注:把这个类放在哪个包下在xml文件里就用哪个包名.类名引用即可。还有就是使用这个类要注意 minSdkVersion 11