一手遮天 Android - Animation: Matrix 变换(通过自定义控件实现)

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

一手遮天 Android - Animation: Matrix 变换(通过自定义控件实现)

示例如下:

/animation/MatrixDemo2.java

/**
 * Matrix 变换(通过自定义控件实现)
 *
 * ImageView 有设置其 Matrix 变换的方法(需要将其 scaleType 设置为 matrix),但是其他控件都没有,那么如何设置其他控件的 Matrix 变换呢
 * 本例演示如何重写 TextView 控件的 onDraw() 方法,以使其支持 Matrix 变换(详细代码参见:animation/MatrixDemo2CustomView.java)
 *
 * 注:对于非 ImageView 控件的 Matrix 变换来说,除了用本例的方法外,也可以用其他方法实现。比如调用控件的 setTranslationX(), setScaleX() 之类的方法,或者用 0 秒动画
 */

package com.webabcd.androiddemo.animation;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

import com.webabcd.androiddemo.R;

public class MatrixDemo2 extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animation_matrixdemo2);
    }
}

\animation\MatrixDemo2CustomView.java

/**
 * 本例演示如何重写 TextView 控件的 onDraw() 方法,以使其支持 Matrix 变换
 *
 *
 * 注意:
 * 1、因为每一次进 onDraw() 都是在上一次 canvas 的基础上 draw 的,所以如果对 canvas 做了 matrix 变换的话,那么下一次再 draw 的话就是针对上一次 matrix 变换后的 canvas 做 draw 的
 *    如果希望的是每次 draw 都是在初始 canvas 上进行的话,则需要对 canvas 进行 save()/restore() 操作
 * 2、对于类似 LinearLayout 之类的控件来说,其本身是不会调用 onDraw() 的,因为绘制部分都是通过它的子控件来完成的
 *    如果需要调用 onDraw() 做一些额外绘制的话,则需要在构造函数中调用 setWillNotDraw(false),但是是无法在 LinearLayout 的 onDraw() 中对整个 LinearLayout 做 matrix 变换
 * 3、对于类似 LinearLayout 之类的控件来说,有一些类似 setRotation(), setScaleX(), setTranslationX() 之类的方法可以调用
 * 4、另外也可以考虑用 Animation 的方式实现类似的变换
 */

package com.webabcd.androiddemo.animation;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;

// 自定义 TextView 控件
public class MatrixDemo2CustomView extends androidx.appcompat.widget.AppCompatTextView {

    public MatrixDemo2CustomView(Context context) {
        super(context);
    }

    public MatrixDemo2CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MatrixDemo2CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 保存 canvas 的状态,之后可以通过 restore() 恢复
        canvas.save();

        // 对 canvas 做 matrix 变换
        Matrix matrix = new Matrix();
        matrix.setTranslate(10f, 10f);
        matrix.postSkew(0.1f, 0.3f);
        canvas.setMatrix(matrix);

        // 绘制 matrix 变换后的 canvas
        super.onDraw(canvas);

        // 恢复 canvas 的调用 save() 之前的状态
        canvas.restore();
    }
}

/layout/activity_animation_matrixdemo2.xml

<?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.webabcd.androiddemo.animation.MatrixDemo2CustomView
        android:id="@+id/myView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="@color/red"
        android:textSize="32dp"
        android:text="TextView"/>

</LinearLayout>

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

posted @ 2021-06-02 08:56  webabcd  阅读(170)  评论(0编辑  收藏  举报