實現仿知乎的開場動畫,圖片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>
相關文章
相關標籤/搜索