# Android View武器库 **Repository Path**: toolfox/android-view-utils ## Basic Information - **Project Name**: Android View武器库 - **Description**: Android平台的View控件集合 - **Primary Language**: Android - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-06-25 - **Last Updated**: 2025-07-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # EGLSurfaceView EGLSurfaceView 是一个专为 Android 平台设计的轻量级 OpenGL ES 渲染视图。它提供了一个简单的接口,用于在 Android 应用中进行 EGL 初始化、渲染和资源管理。 ## 演示效果 Demo Screenshot ## 特性 - 支持 EGL 初始化与销毁 - 支持设置渲染模式(连续渲染或按需渲染) - 提供线程安全的渲染机制 - 简单易用的接口设计,方便快速集成到 Android 项目中 - 提供示例渲染器,便于学习与使用 ## 构成 项目主要分为以下部分: - **Java 层**:定义了 EGLSurfaceView 类和渲染器接口,负责与 Android SDK 交互。 - **C++ 层**:实现了 EGL 的具体逻辑,包括显示初始化、上下文创建、表面管理、渲染线程等。 - **构建文件**:支持使用 CMake 或 Android.mk 构建。 ## 快速开始 ### 1. 在 Android 项目中集成 确保你已将 `EGLSurfaceView` 作为模块引入到你的 Android 项目中。你可以通过以下方式集成: - 将项目作为子模块添加到你的 Git 仓库 - 直接复制 `library` 模块到你的项目中 ### 2. 在布局中使用 在你的 XML 布局文件中添加 `EGLSurfaceView`: ```xml ``` ### 3. 在 Activity 中设置渲染器 在你的 `Activity` 中初始化 `EGLSurfaceView` 并设置渲染器: ```java public class MainActivity extends AppCompatActivity { private EGLSurfaceView eglSurfaceView; private CppGLRendererSample renderer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化EGLSurfaceView eglSurfaceView = findViewById(R.id.egl_surface_view); renderer = new CppGLRendererSample(); // 设置渲染器 eglSurfaceView.setRenderer(renderer.getNativePtr()); // 设置渲染模式为连续渲染 eglSurfaceView.setRenderMode(EGLSurfaceView.RENDERMODE_CONTINUOUSLY); // 设置目标帧率为60FPS eglSurfaceView.setTargetFPS(60); // 添加Touch事件监听器 eglSurfaceView.addOnTouchListener(new EGLSurfaceView.OnTouchListener() { @Override public boolean onTouch(EGLSurfaceView view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i("Touch", "Touch DOWN at (" + event.getX() + ", " + event.getY() + ")"); break; case MotionEvent.ACTION_MOVE: Log.d("Touch", "Touch MOVE to (" + event.getX() + ", " + event.getY() + ")"); break; case MotionEvent.ACTION_UP: Log.i("Touch", "Touch UP at (" + event.getX() + ", " + event.getY() + ")"); break; } return true; // 表示事件已处理 } }); // 示例:获取当前FPS new Thread(() -> { while (!isFinishing()) { try { Thread.sleep(1000); float currentFPS = eglSurfaceView.getCurrentFPS(); Log.i("MainActivity", "SurfaceView FPS: " + currentFPS); } catch (InterruptedException e) { break; } } }).start(); } @Override protected void onDestroy() { super.onDestroy(); if (renderer != null) { renderer.onDestroy(); } if (eglSurfaceView != null) { eglSurfaceView.onPause(); } } @Override protected void onResume() { super.onResume(); if (eglSurfaceView != null) { eglSurfaceView.onResume(); } } @Override protected void onPause() { super.onPause(); if (eglSurfaceView != null) { eglSurfaceView.onPause(); } } } ``` ## API 文档 ### Java API #### `EGLSurfaceView` 类 `EGLSurfaceView` 是一个继承自 `SurfaceView` 的自定义视图,用于进行 EGL 渲染。 ##### 方法 - `setRenderer(long renderer)`:设置本地渲染器对象 - `setRenderMode(int mode)`:设置渲染模式(`RENDERMODE_CONTINUOUSLY` 或 `RENDERMODE_WHEN_DIRTY`) - `getRenderMode()`:获取当前的渲染模式 - `requestRender()`:请求渲染 - `setTargetFPS(int targetFPS)`:设置目标帧率(0表示不限制帧率) - `getCurrentFPS()`:获取当前帧率 - `addOnTouchListener(OnTouchListener listener)`:添加Touch事件监听器 - `removeOnTouchListener(OnTouchListener listener)`:移除Touch事件监听器 - `clearOnTouchListeners()`:清除所有Touch事件监听器 - `onResume()`:恢复渲染 - `onPause()`:暂停渲染 ##### Touch事件接口 - `OnTouchListener`:Touch事件监听器接口 - `boolean onTouch(EGLSurfaceView view, MotionEvent event)`:Touch事件回调方法,返回true表示事件已处理 #### `Renderer` 接口 `Renderer` 是一个接口,用于实现渲染逻辑。示例渲染器为 `CppGLRendererSample`。 ### EGLTextureView `EGLTextureView` 是基于 `TextureView` 的 EGL 渲染视图,提供与 `EGLSurfaceView` 类似的功能,但支持变换、动画等操作。 #### 在布局中使用 在你的 XML 布局文件中添加 `EGLTextureView`: ```xml ``` #### 在 Activity 中设置渲染器 ```java public class MainActivity extends AppCompatActivity { private EGLTextureView eglTextureView; private CppGLRendererSample renderer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化EGLTextureView eglTextureView = findViewById(R.id.egl_texture_view); renderer = new CppGLRendererSample(); // 设置渲染器 eglTextureView.setRenderer(renderer.getNativePtr()); // 设置渲染模式为连续渲染 eglTextureView.setRenderMode(EGLTextureView.RENDERMODE_CONTINUOUSLY); // 设置目标帧率为60FPS eglTextureView.setTargetFPS(60); // 添加Touch事件监听器 eglTextureView.addOnTouchListener(new EGLTextureView.OnTouchListener() { @Override public boolean onTouch(EGLTextureView view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i("Touch", "Touch DOWN at (" + event.getX() + ", " + event.getY() + ")"); break; case MotionEvent.ACTION_MOVE: Log.d("Touch", "Touch MOVE to (" + event.getX() + ", " + event.getY() + ")"); break; case MotionEvent.ACTION_UP: Log.i("Touch", "Touch UP at (" + event.getX() + ", " + event.getY() + ")"); break; } return true; // 表示事件已处理 } }); // 示例:获取当前FPS new Thread(() -> { while (!isFinishing()) { try { Thread.sleep(1000); float currentFPS = eglTextureView.getCurrentFPS(); Log.i("MainActivity", "TextureView FPS: " + currentFPS); } catch (InterruptedException e) { break; } } }).start(); } @Override protected void onDestroy() { super.onDestroy(); if (renderer != null) { renderer.onDestroy(); } if (eglTextureView != null) { eglTextureView.onPause(); } } @Override protected void onResume() { super.onResume(); if (eglTextureView != null) { eglTextureView.onResume(); } } @Override protected void onPause() { super.onPause(); if (eglTextureView != null) { eglTextureView.onPause(); } } } ``` #### Java API ##### 主要方法 - `setRenderer(long renderer)`:设置渲染器 - `setRenderMode(int renderMode)`:设置渲染模式(连续渲染或按需渲染) - `getRenderMode()`:获取当前渲染模式 - `requestRender()`:请求渲染 - `setTargetFPS(int targetFPS)`:设置目标帧率(0表示不限制帧率) - `getCurrentFPS()`:获取当前帧率 - `addOnTouchListener(OnTouchListener listener)`:添加Touch事件监听器 - `removeOnTouchListener(OnTouchListener listener)`:移除Touch事件监听器 - `clearOnTouchListeners()`:清除所有Touch事件监听器 - `onResume()`:恢复渲染 - `onPause()`:暂停渲染 ##### Touch事件接口 - `OnTouchListener`:Touch事件监听器接口 - `boolean onTouch(EGLTextureView view, MotionEvent event)`:Touch事件回调方法,返回true表示事件已处理 ##### 与EGLSurfaceView的区别 - **变换支持**:`EGLTextureView` 支持缩放、旋转、平移等变换操作 - **动画支持**:可以应用属性动画(如透明度、位置变化等) - **合成性能**:在某些情况下可能有更好的合成性能 - **内存使用**:相比 `SurfaceView` 可能使用更多内存 - **渲染目标**:使用 `SurfaceTexture` 而不是直接的 `Surface` #### 变换和动画示例 `EGLTextureView` 支持标准的 View 变换操作: ```java // 缩放 eglTextureView.setScaleX(1.5f); eglTextureView.setScaleY(1.5f); // 旋转 eglTextureView.setRotation(45f); // 平移 eglTextureView.setTranslationX(100f); eglTextureView.setTranslationY(100f); // 透明度 eglTextureView.setAlpha(0.8f); // 属性动画 ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(eglTextureView, "rotation", 0f, 360f); rotationAnimator.setDuration(2000); rotationAnimator.setRepeatCount(ObjectAnimator.INFINITE); rotationAnimator.start(); ``` ## EGLSurfaceView vs EGLTextureView 选择指南 ### 何时使用 EGLSurfaceView **推荐场景:** - 游戏开发或高性能图形应用 - 需要最佳渲染性能的场景 - 全屏或大部分屏幕的渲染内容 - 不需要复杂UI变换的应用 **优势:** - 更好的渲染性能 - 更低的内存使用 - 硬件加速支持更好 - 适合高帧率渲染 **限制:** - 不支持View变换(缩放、旋转、平移) - 不支持属性动画 - 在某些布局中可能有Z-order问题 ### 何时使用 EGLTextureView **推荐场景:** - 需要应用View变换的场景 - 需要属性动画效果 - 复杂UI布局中的嵌入式渲染 - 需要与其他View进行复杂交互 **优势:** - 支持所有标准View变换 - 支持属性动画 - 更好的UI集成 - 更灵活的布局选项 **限制:** - 相对较高的内存使用 - 可能的性能开销 - 在某些设备上可能有兼容性问题 ### 性能对比 | 特性 | EGLSurfaceView | EGLTextureView | |------|----------------|----------------| | 渲染性能 | 优秀 | 良好 | | 内存使用 | 低 | 中等 | | 变换支持 | 无 | 完整 | | 动画支持 | 无 | 完整 | | UI集成 | 基础 | 优秀 | | 兼容性 | 优秀 | 良好 | ### C++ API #### `EGLSurfaceView` 类 `EGLSurfaceView` 是一个 C++ 类,负责 EGL 的初始化、销毁、渲染管理。 ##### 方法 - `setRenderer(std::shared_ptr)`:设置渲染器 - `setRenderMode(RenderMode)`:设置渲染模式(连续渲染或按需渲染) - `requestRender()`:请求渲染 - `setTargetFPS(int targetFPS)`:设置目标帧率(0表示不限制帧率) - `getCurrentFPS()`:获取当前帧率 - `surfaceCreated(ANativeWindow*)`:创建 EGL 表面 - `surfaceChanged(int width, int height)`:调整视图尺寸 - `surfaceDestroyed()`:销毁 EGL 表面 - `pause()`:暂停渲染线程 - `resume()`:恢复渲染线程 - `initEGL()`:初始化 EGL - `createEGLSurface()`:创建 EGL 渲染表面 - `destroyEGLSurface()`:销毁 EGL 渲染表面 - `renderThreadFunc()`:渲染线程的主函数 - `doRender()`:执行一帧的渲染 ## 示例渲染器 示例渲染器 `CppGLRendererSample` 是一个简单的 OpenGL ES 渲染器,用于演示如何使用 EGLSurfaceView。 ### 使用示例渲染器 `CppGLRendererSample` 提供了基本的 OpenGL 初始化、着色器编译与渲染逻辑。你可以通过继承此类或使用其方法来构建你自己的渲染器。 ## 构建说明 ### 使用 CMake 构建 确保你已配置 `CMakeLists.txt` 文件,并正确设置所有依赖项。使用以下命令进行构建: ```bash cmake . make ``` ### 使用 Android.mk 构建 你也可以使用 `Android.mk` 构建项目: ```bash ndk-build -C jni ``` ## 依赖库 - Android NDK - OpenGL ES 2.0 或以上 - C++ STL 支持 ## 注意事项 - 确保在主线程中创建 EGLSurfaceView - 在 Activity 的生命周期中正确调用 `onResume()` 和 `onPause()` - 使用 `requestRender()` 时确保渲染模式为 `RENDERMODE_WHEN_DIRTY` ## 性能优化建议 - 尽量减少频繁的 `requestRender()` 调用 - 合理管理 OpenGL 资源的创建与销毁 - 避免在渲染线程中执行耗时操作 ## 故障排除 ### 常见问题 1. **EGL 初始化失败**:请检查设备是否支持 OpenGL ES 2.0 或以上版本 2. **渲染线程卡死**:确保没有阻塞渲染线程的操作 3. **Surface 创建失败**:请检查 `ANativeWindow` 是否有效 ### 调试技巧 - 使用 `checkEGLError()` 检查 EGL 错误 - 使用 `checkShaderCompileStatus()` 和 `checkProgramLinkStatus()` 检查着色器编译与链接状态 - 使用日志记录关键函数的调用流程 ## 许可证 本项目基于 [MIT License](LICENSE) 开源。 ## 贡献 欢迎贡献代码!请提交 PR 或 Issue 到项目仓库。