实现android知乎、一览等的开场动画图片放大效果
2016-01-18 14:58
633 查看
知乎等app的开场动画为:一张图片被显示到屏幕的正中央,并充满整个屏幕,过一小段时间后,开始慢慢方法,且图片的正中央始终处于屏幕的正中央,也就是“镜头缓慢放大”的效果
难点1.android手机屏幕碎片化。由于是全屏显示,因此一张图片需要放到不同大小的imageview中,且图片中央需要放到imageview中央;
难点2.放大时需要保证图片中央与imageview中央处于一点;
难点3.实现缓慢放大效果(这个可以利用valueanimator实现)
实现原理可以看我的博客博文:http://www.cnblogs.com/carbs/p/5071166.html
本篇文章抽象出一个新的view,以便于使用及修改,同时完善了上篇文章由于行文仓促而留下的多个未实现的需求。
实现效果如下:
代码如下:
1.主activity
2.主activity对应的布局文件
3.抽象的imageview的代码:
代码下载地址:
https://github.com/Carbs0126/AutoZoomInImageView
难点1.android手机屏幕碎片化。由于是全屏显示,因此一张图片需要放到不同大小的imageview中,且图片中央需要放到imageview中央;
难点2.放大时需要保证图片中央与imageview中央处于一点;
难点3.实现缓慢放大效果(这个可以利用valueanimator实现)
实现原理可以看我的博客博文:http://www.cnblogs.com/carbs/p/5071166.html
本篇文章抽象出一个新的view,以便于使用及修改,同时完善了上篇文章由于行文仓促而留下的多个未实现的需求。
实现效果如下:
代码如下:
1.主activity
package cn.carbs.autozoominimageview; import android.app.Activity; import android.os.Bundle; import android.view.Window; public class MainActivity extends Activity { AutoZoomInImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); iv = (AutoZoomInImageView) findViewById(R.id.iv); iv.post(new Runnable() { @Override public void run() { iv.init(); iv.startZoomInBySpanDelayed(1.0f, 1000, 1000); } }); } }
2.主activity对应的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <cn.carbs.autozoominimageview.AutoZoomInImageView android:id="@+id/iv" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/horse" /> </LinearLayout>
3.抽象的imageview的代码:
package cn.carbs.autozoominimageview; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Matrix; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.widget.ImageView; @SuppressLint("NewApi") public class AutoZoomInImageView extends ImageView{ private static final String TAG = "wang"; private Drawable mDrawable; private int mDrawableW; private int mDrawableH; private int mImageViewW; private int mImageViewH; private Matrix mMatrix; private float[] mValues = new float[9]; public AutoZoomInImageView(Context context) { this(context, null); } public AutoZoomInImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public AutoZoomInImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.setScaleType(ScaleType.MATRIX); } /** * 在view解析出来之后进行使用,以确保可以将图片置于中间,推荐在post中使用 */ public void init(){ initInternalValues(); initPicturePosition(); } /** * 在view解析出来之后进行使用,以确保可以将图片置于中间,推荐在post中使用 */ public void init(Drawable drawable){ initInternalValues(drawable); initPicturePosition(); } /** * 初始化成员变量,用于调整matrix的值 */ private void initInternalValues(){ mDrawable = getDrawable(); if(mDrawable == null){ throw new IllegalArgumentException("please set source of this ImageView"); } 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 source of this ImageView"); } mDrawableW = mDrawable.getIntrinsicWidth(); mDrawableH = mDrawable.getIntrinsicHeight(); mImageViewW = getMeasuredWidth(); mImageViewH = getMeasuredHeight(); mMatrix = getImageMatrix(); mMatrix.getValues(mValues); } /** * 根据图片大小以及imageview的大小,初始化图片的显示位置 */ private void initPicturePosition(){ updateMatrixValuesOrigin(mMatrix, mValues, mDrawableW, mDrawableH, mImageViewW, mImageViewH); setImageMatrix(mMatrix); } /** * 开始自动放大效果 * @param scaleSpan * @param duration */ public void startZoomInBySpan(float scaleSpan, long duration){ final float oriScaleX = mValues[0]; final float oriScaleY = mValues[4]; ValueAnimator va = ValueAnimator.ofFloat(0, scaleSpan); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Float span = (Float)animation.getAnimatedValue(); updateMatrixValuesSpan(mValues, mDrawableW, mDrawableH, mImageViewW, mImageViewH, oriScaleX, oriScaleY, span); mMatrix.setValues(mValues); setImageMatrix(mMatrix); } }); va.setDuration(duration); va.start(); } /** * 在delayed毫秒后,开始自动放大效果 * @param scaleSpan * @param duration * @param delayed */ public void startZoomInBySpanDelayed(final float scaleSpan, final long duration, long delayed){ postDelayed(new Runnable() { @Override public void run() { startZoomInBySpan(scaleSpan, duration); } }, delayed); } //初始化位置 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 source of this ImageView's matrix and values"); } outMatrix.reset(); if((imageH * drawW > drawH * imageW)){ //如果iv更细高 float scale1 = ((float)imageH)/((float)drawH); float offset1 = (drawW * scale1 - (float)imageW)/2; outMatrix.postScale(scale1, scale1); outMatrix.postTranslate(-offset1, 0); }else{ //如果iv更宽扁 float scale2 = ((float)imageW)/((float)drawW); float offset2 = (drawH * scale2 - (float)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 span){ //根据四个参数:图片的宽高、控件的宽高,动态的计算出输出的矩阵(float数组)的值 outValues[0] = oriScaleX + span; //y轴放大 outValues[4] = oriScaleY + span; //x轴平移 float offsetwidth = (drawW * outValues[0] - (float)imageW)/2; outValues[2] = - offsetwidth; //y轴平移 float offsetHeight = (drawH * outValues[0] - (float)imageH)/2; outValues[5] = - offsetHeight; } //function for log public String printMyMatrix(Matrix m){ float[] valueFloat = new float[9]; m.getValues(valueFloat); String s = ""; for(int i = 0; i < 9; i++){ s = s + " [ " + valueFloat[i] + " ] "; } return s; } //function for log public String printMyValue(float[] valueFloat){ String s = ""; for(int i = 0; i < 9; i++){ s = s + " [ " + valueFloat[i] + " ] "; } return s; } /** * 暂时无效的方法 * @param outValues * @param drawW * @param drawH * @param imageW * @param imageH * @param delta */ @Deprecated private void updateMatrixValuesDelta(float[] outValues, float drawW, float drawH, float imageW, float imageH, float delta){ //根据四个参数:图片的宽高、控件的宽高,动态的计算出输出的矩阵(float数组)的值 outValues[0] = outValues[0] + delta; //y轴放大 outValues[4] = outValues[4] + delta; //x轴平移 float offsetwidth = (drawW * outValues[0] - (float)imageW)/2; outValues[2] = - offsetwidth; //y轴平移 float offsetHeight = (drawH * outValues[0] - (float)imageH)/2; outValues[5] = - offsetHeight; } /** * 暂时无效的方法 * @param outValues * @param drawW * @param drawH * @param imageW * @param imageH * @param span */ @Deprecated private void updateMatrixValuesSpan(float[] outValues, float drawW, float drawH, float imageW, float imageH, float span){ //根据四个参数:图片的宽高、控件的宽高,动态的计算出输出的矩阵(float数组)的值 outValues[0] = span; //y轴放大 outValues[4] = span; //x轴平移 float offsetwidth = (drawW * outValues[0] - (float)imageW)/2; outValues[2] = - offsetwidth; //y轴平移 float offsetHeight = (drawH * outValues[0] - (float)imageH)/2; outValues[5] = - offsetHeight; } }
代码下载地址:
https://github.com/Carbs0126/AutoZoomInImageView
相关文章推荐
- android-如何通过接口回调来解决Fragment之间的交互
- 一张图搞定Android学习路线,非常全面
- android开发使用SDK与ANT实现自动打包(混淆、签名)
- android:View的setTag和getTag使用
- android anr trace.txt文件 抓取
- Yalantis 那些动画效果很炫的 Android 及 iOS 开源项目
- android - 自定义(组合)控件 + 自定义控件外观
- Android系统源码学习步骤
- android:layout_marginStart和android:paddingStart的区别
- 提升Android开发效率的5个经验总结【同行说技术】
- Android开发笔记(五十一)通过Messenger实现进程间通信
- Android百分比布局
- Android 常用六大框架
- android gradle引入nexus中的jar包
- Android SQLite
- GitHub android-crop 图片裁剪
- android gradle引入sdk下extras下libs中的jar包
- Android onActivityResult获取返回值的用法
- Android大图片裁剪终极解决方案 原理分析(概念)
- Android NDK开发之 与NEON相关的库