实现仿知乎的开场动画,图片zoomin的效果,实现原理,没加动效
知乎等应用的开场动画是:全屏显示一副图像,并以图像的中间为原点,实现放大(也就是zoomin)的动画,让等待的过程不再单调乏味。
最近不是很忙,因此想了下如何实现这种效果,方案是:采用调整imageview的matrix的方式来实现此效果。
这个例子中我只是简单的将原理实现,没有对效果进行任何的优化。如果想达到比较完美的效果,需要添加动画,如使用valueAnimator,在updatelistener中不断的更新matrix或者float[]即可。
为了演示方便,我将其实现过程拆分为两部:
1.调整图片,使图片位于屏幕的正中间。由于android手机屏幕尺寸多种多样,而图片的大小也不甚相同,为了灵活的使用此效果,需要将任意尺寸比例的图片显示在任意尺寸比例的手机屏幕的正中间,同时不使图片扭曲变形
2.采用点击button模拟zoomin的效果,当然可以优化成使用valueanimator的方式,由于这不是本篇文章的重点,因此不进行优化了
实现的效果:[屏幕截图有点问题,所以显得有点卡]
原理在代码中进行说明:
主界面:
package com.carbs.testandroidimage; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity implements View.OnClickListener { private ImageView iv; private Button bt1_refine; private Button bt2_zoomin; private int iv_height = 0; private int iv_width = 0; private int dr_height = 0; private int dr_width = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_main); iv = (ImageView) this.findViewById(R.id.iv); bt1_refine = (Button) this.findViewById(R.id.bt1); bt2_zoomin = (Button) this.findViewById(R.id.bt2); bt1_refine.setOnClickListener(this); bt2_zoomin.setOnClickListener(this); iv.post( new Runnable() { @Override public void run() { //获取imageview的宽和高、获取drawable的宽和高 Drawable d = iv.getDrawable(); //drawable的宽高,存储到全局变量中 dr_width = d.getIntrinsicWidth(); dr_height = d.getIntrinsicHeight(); //imageview的宽高,存储到全局变量中 iv_height = iv .getMeasuredHeight(); iv_width = iv.getMeasuredWidth(); Log. d("a", "onClick() --> dr_width is " + dr_width + " | dr_height is " + dr_height + " | iv_height is " + iv_height + " | iv_width is " + iv_width); } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt1 : if((iv_height * dr_width > dr_height * iv_width)){ //如果iv更细高,也就是我们需要调整其中图片的高度,使其高度和imageview的高度一致,这样算出scale后,使drawable的宽高同时放大scale倍。由于matrix模式下,调整scale后imageview显示图片依然是从左上角开始显示的,因此需要调整imageview的左右平移,使显示的drawable正好位于正中间。另一种情况(如果iv更宽扁)同理 //计算出高度需要放大多少倍 float scale1 = ((float)iv_height )/((float)dr_height); //计算出左右平移多少 float offset1 = (dr_width *scale1 - (float)iv_width )/2; Log. d("1223", "offset1 is " + offset1); Matrix matrix1 = new Matrix(); matrix1.postScale(scale1, scale1); matrix1.postTranslate(-offset1, 0); iv.setImageMatrix(matrix1); } else{ //如果iv更宽扁,同理 float scale2 = ((float)iv_width )/((float)dr_width); float offset2 = (dr_height *scale2 - (float)iv_height )/2; Log. d("1223", "offset2 is " + offset2); //产生新的大小但Bitmap对象 Matrix matrix2 = new Matrix(); matrix2.postScale(scale2, scale2); matrix2.postTranslate(0, -offset2); iv.setImageMatrix(matrix2); } break; case R.id.bt2 : Matrix ma = iv.getImageMatrix(); float[] dValues = new float[9]; ma.getValues(dValues); dValues[0] = dValues[0] + 0.1f; dValues[4] = dValues[4] + 0.1f; float offsetheight = (dr_height *dValues[0] - (float)iv_height )/2; dValues[5] = - offsetheight; float offsetwidth = (dr_width *dValues[0] - (float)iv_width )/2; dValues[2] = - offsetwidth; Matrix m = new Matrix(); m.setValues(dValues); iv.setImageMatrix(m); break; } } public String printMyMatrix(Matrix m){ String s = ""; float[] valueFloat = new float[9]; m.getValues(valueFloat); for(int i = 0; i < 9; i++){ s = s + " [ " + valueFloat[i] + " ] " ; } return s; } }
Matrix的使用说明:
android.graphics.Matrix;包下的Matrix类主要用于imageview的图形变换,主要包括平移、缩放、旋转等,具体的使用方法可以参考如下这片博客:http://blog.csdn.net/hahajluzxb/article/details/8165258
Matrix可以由一个包含9个float类型的float数组构成,下标为[0]和[4]控制x轴和y轴的伸缩,大于1为放大,小于1为缩小。下标为[2]和[5]分别控制宽和高的平移,正数为图片向左平移,负数为图片向右平移。
点击button进行zoomin效果的原理就是不断的设置imageview的matrix,使其按照float[]数组的值进行变换,在放大的情况下同时进行平移,从而达到了zoomin的效果
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "match_parent" android:gravity= "center_horizontal" android:orientation= "vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop= "@dimen/activity_vertical_margin" > <ImageView android:id="@+id/iv" android:layout_width="1200px" android:layout_height="700px" android:background="@drawable/background_stroke" android:scaleType="matrix" android:src="@drawable/dog" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:id="@+id/bt1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button 1" /> <Button android:id="@+id/bt2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button 2" /> </LinearLayout > </LinearLayout>