Android 使用graphics.Camera類實現自定義旋轉飄落

walkeZ發表於2018-04-23
        俺是一名小菜鳥,這是俺第一篇部落格。在文中有引用個別前輩大神的部落格。如有侵權請告知,俺會盡快處理。

需求:

        前段時間有個需求:做一個類似跑酷的綵帶散落動畫效果。

查資料:

        按照初始想法+同事模糊建議,先在網上收羅了一堆雪花飄落效果。發現並不滿足需求,網上大多數案例都是平面的飄落效果。缺少一點靈動(旋轉)。在一個查詢資料裡的偶然中發現一個好東西:使用Camera實現3D旋轉飄落的效果部落格:模仿荷包啟動動畫點選開啟連結。發現一個之前從未用過的好東西graphics.Camera類。Camera可以實現普通雪花飄落沒有的旋轉效果,該的具體介紹及使用就不做格外介紹了。需要詳細瞭解的朋友們自行找一下度娘了。

想法:

        最初想法將Camera的旋轉效果合成到網上已有的雪花飄落專案即可。因為兩個專案都不是自己寫的遇到一些列的困難。最後選擇了一步一步的,自己用自己掌握的自定義view去實現。

    1.寫一個FallView 繼承View,實現單個雪花圖片旋轉飄落。

    2.寫一個SnowFallView繼承RelativeLayout用於存放List<FallView>以實現多個雪花圖片飄落效果。

實現:

        注:由於俺的水平有限,無暫未考慮效能優化的深入問題。僅求實現效果。

        因為時間問題、程式碼成熟度不夠好等原因,本文只講第1點FallView的實現,直接上程式碼,裡面有詳細註釋

package com.walke.anim.camera;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.walke.anim.R;

/**
 * Created by walke.Z on 2018/4/20.
 * 雪花飄落效果:
 * 1,單個飄落效果
 * a.onDraw 使用 canvas.drawBitmap()方法繪製雪花
 * b.改變繪製位置實現動畫效果
 */

public class FallView extends View {

    private Bitmap mSnow;

    /**
     * 控制元件寬度
     */
    private int mWidth;
    /**
     * 控制元件高度
     */
    private int mHeight;

    /**
     * 畫筆
     */
    private Paint mPaint;
    /**
     *
     */
    private float mX1;
    /**
     *
     */
    private float mY1 = 0;

    /**
     * graphics 包中的類,用於實現旋轉
     */
    Camera mCamera;
    /**
     * 飄落速度
     */
    private float mSpeed = 1.5f;

    public FallView(Context context) {
        this(context, null);
    }

    public FallView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FallView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mSnow = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.image_snow_96);
        mPaint = new Paint();
        mCamera = new Camera();
    }

    private void resizeBitmap(float scale) {
        Matrix m = new Matrix();
        m.setScale(scale, scale);
        mSnow = Bitmap.createBitmap(mSnow, 0, 0, mSnow.getWidth(), mSnow.getHeight(), m, true);
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        mX1 = (mWidth - mSnow.getWidth()) / 2;
    }

    private float degrees = 0;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //使用 graphics.Camera -------
        Matrix mMatrix = new Matrix();
        mCamera.save(); // 記錄一下初始狀態。save()和restore()可以將影像過渡得柔和一些。

        //旋轉角度
        if (degrees < 360) {
            degrees += 6;
        } else {
            degrees = 0;
        }
        mCamera.rotateY(degrees);

        // 平移--下落
        if (mY1 > -(mHeight - mSnow.getHeight())) {
            mY1 -= mSpeed;//注意這裡是 -
        }
        mCamera.translate(mX1, mY1, 0);// mY1: -50


        mCamera.getMatrix(mMatrix);
        int centerX = (mWidth) / 2;
        int centerY = mSnow.getHeight() / 2;

        mMatrix.preTranslate(-centerX, -centerY);
        mMatrix.postTranslate(centerX, centerY);

        mCamera.restore();
//        Log.i("walke", "FallView draw: -------> mX1 = "+mX1+" ---> mY1 = "+mY1 );
        canvas.drawBitmap(mSnow, mMatrix, mPaint);// 畫圖由左上角開始

        // 普通圖片向下應用用以下兩行程式碼即可
        // canvas.drawBitmap(mSnow, mX1, mY1, mPaint);// 畫圖由左上角開始
        // mY1+=2;

        invalidate();//60幀每秒
    }
}

佈局使用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <com.walke.anim.camera.FallView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="#79a1f7"/>


</LinearLayout>

效果圖片截圖,沒弄gif圖

       

分享一個線上mp4轉git的連結:



相關文章