【PAG】一个PAGView和多个PAGImageView分别渲染多个pag文件
1 PAGView 和 PAGImageView 的区别
PAGView 继承 TextureView,运行时实时渲染,矢量渲染,缩放无损;PAGImageView 继承 View,预渲染为位图序列后播放,位图渲染,缩放会模糊。
特性维度 | PAGView | PAGImageView |
设计目标 | 全功能、高性能的动画播放器 | 轻量级、静态的动画帧提取器 |
渲染方式 | 使用硬件加速(通常是 OpenGL/Vulkan/Metal)逐帧实时渲染动画。 | 使用软件渲染将动画的某一帧或某一时刻渲染为静态的 Bitmap/UIImage。 |
动画效果 | 支持 PAG 文件的所有特性:矢量图形、位图、文本、视频序列帧、图层特效(如模糊、渐变、蒙版)等。 | 功能受限。主要支持矢量图形和位图。不支持文本的实时编辑、不支持视频序列帧、不支持某些图层特效(如模糊)。 |
性能特点 | 播放动画时性能极高,CPU/GPU 占用与动画复杂度相关。适合频繁播放的动画。 | 首次加载和渲染特定帧时需要计算,可能有短暂延迟。渲染成位图后,显示该位图本身性能开销极低。 |
内存占用 | 运行时占用内存相对较低,因为不需要预加载所有帧。 | 渲染出的位图会保存在内存中,如果位图尺寸很大或数量很多,内存占用会显著增加。 |
本文完整源码详见 → 基于Android平台的PAG案例集合。
2 一个 PAGView 渲染多个 pag 文件
MultiPAGFileActivity.java
package com.zhyan8.pagDemo;import android.graphics.Matrix;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.WindowManager;import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;import org.libpag.PAGComposition;
import org.libpag.PAGFile;
import org.libpag.PAGView;public class MultiPAGFileActivity extends AppCompatActivity {private static final int COL_NUM = 4;private static final float ITEM_HEIGHT = 400f;private PAGView mPAGView;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_multi_pag_file);mPAGView = findViewById(R.id.pagView);loadPAGFile();mPAGView.setRepeatCount(0);mPAGView.play();}private void loadPAGFile() {WindowManager manager = this.getWindowManager();DisplayMetrics outMetrics = new DisplayMetrics();manager.getDefaultDisplay().getMetrics(outMetrics);int width = outMetrics.widthPixels;int height = outMetrics.heightPixels;PAGComposition pagComposition = PAGComposition.Make(width, height);float itemWidth = 1f * width / COL_NUM;String basePath = "grid/";for (int i = 0; i < 23; i++) {int row = i / COL_NUM;int col = i % COL_NUM;String path = basePath + i + ".pag";PAGFile pagFile = getPagFile(row, col, path, itemWidth, ITEM_HEIGHT);pagComposition.addLayer(pagFile);}mPAGView.setComposition(pagComposition);}private PAGFile getPagFile(int row, int col, String path, float itemWidth, float itemHeight) {PAGFile pagFile = PAGFile.Load(getAssets(), path);Matrix matrix = new Matrix();float scaleX = itemWidth / pagFile.width();matrix.preScale(scaleX, scaleX);matrix.postTranslate(itemWidth * col, row * itemHeight);pagFile.setMatrix(matrix);pagFile.setDuration(10000000);return pagFile;}
}
activity_multi_pag_file.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:gravity="center"><org.libpag.PAGViewandroid:id="@+id/pagView"android:layout_width="300dp"android:layout_height="600dp" />
</LinearLayout>
运行效果如下。
3 多个 PAGImageView 渲染多个 pag 文件
MultiPAGImageViewActivity.java
package com.zhyan8.pagDemo;import android.os.Bundle;import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;import org.libpag.PAGImageView;
import org.libpag.PAGView;public class MultiPAGImageViewActivity extends AppCompatActivity {private static final int ROW_NUM = 5;private static final int COL_NUM = 4;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_multi_pag_image_view);loadViews();}private void loadViews() {String baseName = "pagView";String basePath = "assets://grid/";for (int i = 0; i < ROW_NUM; i++) {for (int j = 0; j < COL_NUM; j++) {int num = (i * COL_NUM + j);String name = baseName + num;int resId = getResources().getIdentifier(name, "id", getPackageName());PAGImageView view = findViewById(resId);String path = basePath + num + ".pag";view.setPath(path);view.setRepeatCount(0);view.play();}}}
}
activity_multi_pag_image_view.xml
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="50dp"android:layout_marginBottom="50dp"android:rowCount="4"android:columnCount="4"><org.libpag.PAGImageViewandroid:id="@+id/pagView0"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView1"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView2"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView3"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView4"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView5"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView6"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView7"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView8"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView9"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView10"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView11"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView12"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView13"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView14"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView15"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView16"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView17"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView18"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/><org.libpag.PAGImageViewandroid:id="@+id/pagView19"android:layout_width="0dp"android:layout_height="0dp"android:layout_rowWeight="1"android:layout_columnWeight="1"android:layout_margin="10dp"/>
</GridLayout>
运行效果如下。