12/08/2018, 11:05

Animation trong Android

Tổng quan Animation là các phép biến đổi màu sắc, vị trí, kích thước hay hướng của một đối tượng trên màn hình theo thời gian. Android cung cấp các API hỗ trợ rất tốt cho việc áp dụng animation cho các thành phần UI và vẽ đồ họa 2D, 3D. Android 2.3 và các phiên bản trước đó hỗ trợ kiểu ...

  1. Tổng quan

    Animation là các phép biến đổi màu sắc, vị trí, kích thước hay hướng của một đối tượng trên màn hình theo thời gian. Android cung cấp các API hỗ trợ rất tốt cho việc áp dụng animation cho các thành phần UI và vẽ đồ họa 2D, 3D.

    Android 2.3 và các phiên bản trước đó hỗ trợ kiểu View Animation.

    Android 3.0 và các phiên bản sau đã tăng cường khả năng Animation cho phép tạo hiệu ứng động cho các thuộc tính của thành phần UI thông qua kiểu Property Animation.

  2. Drawable Animation

    Drawable Animation là quá trình đơn giản, hiển thị một chuỗi các hình ảnh liên tiếp trong các khoảng thời gian ngắn để tạo ra hiệu ứng cuối cùng là đối tượng di chuyển hoặc thay đổi.

    Trong Android, việc thực hiện kiểu animation này được thông qua lớp AnimationDrawable.

    Để sử dụng lớp AnimationDrawable, đầu tiên chúng ta tạo file XML định nghĩa danh sách các frame:

    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    	android:oneshot="true">
        <item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
        <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
        <item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>
Các tag trong animation-list về căn bản sẽ được chuyển thành các đối tượng AnimationDrawable đại diện cho tập các hình ảnh. Sau đó, cần thiết lập Drawable này như là background resource cho một ImageView:
    	image.setBackgroundResource(R.drawable.rocket_thrust);
Sau khi thiết lập, ta có thể truy cập đối tượng AnimationDrawable như sau:
    	AnimationDrawable animation = (AnimationDrawable) rocketImage.getBackground();
Khi đã có đối tượng AnimationDrawable, ta có thể sử dụng hai phương thức start() và stop() để bắt đầu hay kết thúc animation.
    	animation.start();
Hai phương thức quan trọng khác là `setOneShot()` (chạy animation một lần, sau đó dừng lại) và `addFrame()` (thêm một frame mới sử dụng một đối tượng Drawable và thiết lập thời gian hiển thị của nó).

Một chú ý quan trọng là phương thức `start()` của đối tượng AnimationDrawable không thể gọi trong phương thức `onCreate()` của Activity bởi vì đối tượng AnimationDrawable chưa được attach vào màn hình của activity đó.
  1. View Animation

    View animation cho phép ta tạo hiệu ứng động với view tùy ý bằng việc thao tác với ma trận biến đổi.

    Trong Android, việc hiển thị và biểu diễn sự thay đổi của một đối tượng view thông qua phép biến đổi ma trận. Với một tập các tọa độ đầu vào, chúng ta có thể biểu diễn những phép biến đổi đó thông qua phép nhân ma trận.

    Android đưa ra ma trận biến đổi của một view bằng việc cho phép bạn đăng ký một đối tượng animation với view đó.

    3.1. Các kiểu Tweening Animation cơ bản:

    • Scale animation (co): làm cho một view nhỏ hơn hoặc lớn hơn dọc theo trục x hoặc trục y. Ta có thể chỉ định animation diễn ra xung quanh một điểm chốt (pivot point).
    • Rotate animation (quay): quay một view quanh một điểm chốt theo một góc quay xác định.
    • Translate animation (tịnh tiến): tịnh tiến một view dọc theo trục x hoặc trục y.
    • Alpha animation (alpha): thay đổi độ trong suốt của một view.
    <set android:shareInterpolator="false">
        <scale
            android:interpolator="@android:anim/accelerate_decelerate_interpolator"
            android:fromXScale="1.0"
            android:toXScale="1.4"
            android:fromYScale="1.0"
            android:toYScale="0.6"
            android:pivotX="50%"
            android:pivotY="50%"
            android:fillAfter="false"
            android:duration="700" />
        <set android:interpolator="@android:anim/decelerate_interpolator">
            <scale
               android:fromXScale="1.4"
               android:toXScale="0.0"
               android:fromYScale="0.6"
               android:toYScale="0.0"
               android:pivotX="50%"
               android:pivotY="50%"
               android:startOffset="700"
               android:duration="400"
               android:fillBefore="false" />
            <rotate
               android:fromDegrees="0"
               android:toDegrees="-45"
               android:toYScale="0.0"
               android:pivotX="50%"
               android:pivotY="50%"
               android:startOffset="700"
               android:duration="400" />
        </set>
    </set>
3.2. **Thêm animation**

Để thêm animation cho một view, ta cần một class ViewAnimation kế thừa từ class android.view.animation.Animation. Sau đó, ta override phương thức applyTransformation để sửa ma trận biến đổi. Khi đã có class ViewAnimation, ta có thể thêm animation cho một view như sau:
    view.startAnimation(new ViewAnimation());
Đoạn code cho class ViewAnimation:
    public class ViewAnimation extends Animation {

       @Override
       public void initialize(int awidth, int height, int parentWidth, int parentHeight) {
           super.initialize(awidth, height, parentWidth, parentHeight);
           setDuration(2500);
           setFillAfter(true);
           setInterpolator(new LinearInterpolator());
       }

       @Override
       protected void applyTransformation(float interpolatedTime, Transformation t) {
           final Matrix matrix = t.getMatrix();
           matrix.setScale(interpolatedTime, interpolatedTime);
       }
    }
Khi chạy đoạn mã `view.startAnimation(new ViewAnimation());`, thay vì lớn dần từ giữa màn hình, view lại lớn dần từ góc trên bên trái. Để có được hiệu ứng mong muốn, bạn phải chuyển toàn bộ view sao cho trung tâm của view khớp với trung tâm của animation (trên cùng bên trái). Sau đó, áp dụng ma trận và di chuyển view trở lại trung tâm trước đó.
    public class ViewAnimation2 extends Animation {

       float centerX, centerY;

       @Override
       public void initialize(int awidth, int height, int parentWidth, int parentHeight) {
           super.initialize(awidth, height, parentWidth, parentHeight);
           centerX = awidth/2.0f;
           centerY = height/2.0f;
           setDuration(2500);
           setFillAfter(true);
           setInterpolator(new LinearInterpolator());
       }

       @Override
       protected void applyTransformation(float interpolatedTime, Transformation t) {
           final Matrix matrix = t.getMatrix();
           matrix.setScale(interpolatedTime, interpolatedTime);
           matrix.preTranslate(-centerX, -centerY);
           matrix.postTranslate(centerX, centerY);
       }
    }
Các phương thức preTranslate và postTranslate sẽ thiết lập một ma trận trước khi scale và sau khi scale.

3.3. **Một số chú ý về ma trận biến đổi**

Ma trận là chìa khóa để biến đổi view và animation. Dưới đây là một số phương thức chủ yếu trên một ma trận:
- `matrix.reset()`: reset ma trận về một ma trận đơn vị, nó sẽ không gây ra thay đổi khi áp dụng vào view.
- `matrix.setScale()`: thực hiện việc thay đổi kích thước ma trận.
- `matrix.setTranslate()`: thực hiện việc thay đổi vị trí để mô phỏng chuyển động.
- `matrix.setRotate()`: thực hiện việc thay đổi hướng.
- `matrix.setSkew()`: thực hiện việc "bóp méo" một view.

Ví dụ, với m1, m2, m3 là các ma trận:
    m1.setScale();
    m2.setTranslate();
    m3.concat(m1, m2);
Việc chuyển đổi một view bởi m1 để được một view mới, sau đó chuyển đổi view mới đó với m2 thì cũng tương đương với việc chuyển đổi view ban đầu với m3.

Một preTranslate như `m1.preTranslate(m2)` tương đương với `m1.concat(m2, m1)`.

Tương tự, `m1.postTranslate(m2)` tương đương với `m1.concat(m1, m2)`.

Mở rộng, đoạn code dưới đây:
    matrix.setScale(interpolatedTime, interpolatedTime);
    matrix.preTranslate(-centerX, -centerY);
    matrix.postTranslate(centerX, centerY);
tương đương với:
    Matrix matrixPreTranslate = new Matrix();
    matrixPreTranslate.setTranslate(-centerX, -centerY);

    Matrix matrixPostTranslate = new Matrix();
    matrixPostTranslate.setTranslate(centerX, centerY);

    matrix.concat(matrixPreTranslate, matrix);
    matrix.postTranslate(matrix, matrixPostTranslate);

Tham khảo tại: http://developer.android.com/guide/topics/graphics/overview.html

0