效果
序言
很喜欢黑客帝国里面那种代码雨的效果,为了锻炼自己的特效编写能力就尝试了一下,花了一下午写出来了。有需要的小伙伴拿去参考.
代码
package com.zgh.myapplication;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;import androidx.annotation.Nullable;import java.util.ArrayList;
import java.util.List;
import java.util.Random;/*** <pre>* Created by zhuguohui* Date: 2024/7/4* Time: 16:38* Desc:代码雨* </pre>*/
public class CodeRainView extends View {private Paint paint;private float fontSize = 30;private Random random;private Handler handler = new Handler();public CodeRainView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}private void init() {fontSize = 15 * getResources().getDisplayMetrics().density + 0.5f;paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(Color.WHITE);paint.setStyle(Paint.Style.FILL);paint.setTextSize(fontSize);random = new Random();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);int colum = (int) (getWidth() / fontSize);codeList.clear();for (int i = 0; i < colum; i++) {float offset = -random.nextInt(getHeight() / 2);Code code = new Code(offset, h, i * fontSize, fontSize);codeList.add(code);}startAnimation();}private Runnable updateRunnable = new Runnable() {@Overridepublic void run() {invalidate();handler.postDelayed(updateRunnable, 16);}};private void startAnimation() {//要保证60fps 需要16毫秒执行一次handler.removeCallbacks(updateRunnable);handler.post(updateRunnable);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLACK);for (Code code : codeList) {code.draw(canvas, paint);}}List<Code> codeList = new ArrayList<>();private class Code {private final int[] colors;long startTime;long duration;float offset;float moveY;float x;private String[] toShowStrArray;public Code(float offset, int height, float x, float fontSize) {startTime = System.currentTimeMillis();this.duration = getRandomDuration();this.offset = offset;this.moveY = (height + str.length() * fontSize) - offset;colors = new int[str.length()];getRandomContent();getRandomColors();this.x = x;}private void getRandomColors() {for (int i = 0; i < str.length(); i++) {//255-0;int alpha = (int) (255 - ((i * 1.0) / (str.length() - 1)) * 255);colors[i] = getRandomColor(alpha);}}float lastRatio;void draw(Canvas canvas, Paint paint) {final long now = System.currentTimeMillis();//当前时间final float ratio = ((now - startTime) % duration) * 1.0f / duration; //计算动画比例for (int i = 0; i < str.length(); i++) {String toShowStr = toShowStrArray[i];float y = ratio * moveY + offset - (i * fontSize);paint.setColor(colors[i]);canvas.drawText(toShowStr, x, y, paint);}if (ratio - lastRatio > 0.1) {getRandomContent();lastRatio = ratio;}if (ratio >= 0.99) {//重新随机一个速度startTime = System.currentTimeMillis();getRandomColors();duration = getRandomDuration();getRandomContent();lastRatio = 0;}}private int getRandomColor(int alpha) {return Color.argb(alpha, random.nextInt(255), random.nextInt(255), random.nextInt(255));}private final String str = "0123456789abcdefghijklmnopqrstuvwxyz";private String getRandomText() {return str.charAt(random.nextInt(str.length())) + "";}private void getRandomContent() {toShowStrArray = new String[str.length()];for (int i = 0; i < str.length(); i++) {toShowStrArray[i] = getRandomText();}}}private int getRandomDuration() {return random.nextInt(3000) + 3000;}
}
总结
一切纷繁复杂的效果,都要学会拆解。要用面向对象思想的来开发特效,把功能拆解到各种类中,以小胜换大胜。而驱动一切的就是时间。