Androip Tip: create Digital Rain Effect (Matrix Effect)

    You must be familiar with Matrix Effect which has green codes float on black screen (very popular in Matrix film series). In Android, Matrix Effect has been implemented in various applications often as a Live Wallpaper. Through this tip, I would like to present a type of Matrix Effect called Digital Rain Effect - the codes is falling and like rain tears represents the activity of the virtual reality environment.

Custom Matrix effect class

    We will create a custom view based on View class. Firstly, we define some variables for the Digital Rain Effect with the size of the code, the size of a column, the position of the bottom text for each column and then the characters that will be used for the code (I will use only alphabet chars). Note that you can put the characters you want here or why not a custom font:
public class MatrixEffect extends View {

    private static Random random;
    private int width, height;
    private Canvas canvas;
    private Bitmap canvasBmp;
    private int fontSize = 40;
    private int columnSize;
    private char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWSYZabcdefghijklmnopqrstuvwyz".toCharArray();
    private int[] txtPosByColumn;
    private Paint paintTxt, paintBg, paintBgBmp, paintInitBg;
}
    Now, in the constructor, we'll initialize all Paint variables, which define that the text (running code) color is green, the background is black. You also need to create a new Random object here (to random text codes later):
public MatrixEffect(Context context, AttributeSet attrs) {
        super(context, attrs);
        random = new Random();

        paintTxt = new Paint();
        paintTxt.setStyle(Paint.Style.FILL);
        paintTxt.setColor(Color.GREEN);
        paintTxt.setTextSize(fontSize);

        paintBg = new Paint();
        paintBg.setColor(Color.BLACK);
        paintBg.setAlpha(5);
        paintBg.setStyle(Paint.Style.FILL);

        paintBgBmp = new Paint();
        paintBgBmp.setColor(Color.BLACK);

        paintInitBg = new Paint();
        paintInitBg.setColor(Color.BLACK);
        paintInitBg.setAlpha(255);
        paintInitBg.setStyle(Paint.Style.FILL);
    }
    To get view width and height, we override the onSizeChanged() method of the View class. We initialize the position of the first character for each column. We use a random position between the top of the screen and the middle of the screen and save in the txtPosByColumn array:
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;

        canvasBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(canvasBmp);
        canvas.drawRect(0, 0, width, height, paintInitBg);
        columnSize = width / fontSize;

        txtPosByColumn = new int[columnSize + 1];

        for (int x = 0; x < columnSize; x++) {
            txtPosByColumn[x] = random.nextInt(height / 2) + 1;
        }
    }
    Finally, we override the onDraw() of our custom view, call the drawCanvas method and invalidate the view to force a redraw. With that call, the Matrix Effect could progress from top to bottom in infinite mode. Inside drawCanvas(), call drawText() method used to draw a random character for each column at the position indicated by txtPosByColumn variable above:
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(canvasBmp, 0, 0, paintBgBmp);
        drawCanvas();
        invalidate();
    }

    private void drawText() {
        for (int i = 0; i < txtPosByColumn.length; i++) {
            canvas.drawText("" + chars[random.nextInt(chars.length)], i * fontSize, txtPosByColumn[i] * fontSize, paintTxt);

            if (txtPosByColumn[i] * fontSize > height && Math.random() > 0.975) {
                txtPosByColumn[i] = 0;
            }
            txtPosByColumn[i]++;
        }
    }

    private void drawCanvas() {
        canvas.drawRect(0, 0, width, height, paintBg);
        drawText();
    }

Usage in Activity/Fragment

    In order to use this view, please declaring a MatrixEffectView in your activity/fragment layout (XML) file:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="info.devexchanges.androidmatrixeffect.MainActivity">

    <info.devexchanges.androidmatrixeffect.MatrixEffectView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
    And there is no special point in your activity programmatically code, just need setContentView():
MainActivity.java
package info.devexchanges.androidmatrixeffect;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
    You may have this output when running this application:



References: from original post in Ssaurel's blog.

Share


Previous post
« Prev Post
Next post
Next Post »