news 2026/5/20 5:16:28

EasyWatermark核心组件揭秘:从WaterMark模型到UI面板的完整架构解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
EasyWatermark核心组件揭秘:从WaterMark模型到UI面板的完整架构解析

EasyWatermark核心组件揭秘:从WaterMark模型到UI面板的完整架构解析

【免费下载链接】EasyWatermark🔒 🖼 Securely, easily add a watermark to your sensitive photos. 安全、简单地为你的敏感照片添加水印,防止被人泄露、利用项目地址: https://gitcode.com/gh_mirrors/ea/EasyWatermark

EasyWatermark是一款开源Android水印应用,专注于为敏感照片添加安全水印。本文将深入解析其核心架构,从数据模型到UI面板的完整实现。这款应用采用现代化Android架构,结合Kotlin协程和Jetpack组件,为用户提供流畅的水印添加体验。

🔍 核心数据模型:WaterMark类

data/model/WaterMark.kt文件中,定义了应用的核心数据模型。WaterMark类包含了水印的所有配置属性:

data class WaterMark( val text: String, // 水印文本 val textSize: Float, // 文字大小 val textColor: Int, // 文字颜色 val textStyle: TextPaintStyle, // 文字样式 val textTypeface: TextTypeface, // 字体类型 val alpha: Int, // 透明度 val degree: Float, // 旋转角度 val hGap: Int, // 水平间距 val vGap: Int, // 垂直间距 val iconUri: Uri, // 图标URI val markMode: WaterMarkRepository.MarkMode, // 水印模式 val enableBounds: Boolean, // 是否启用边界 val tileMode: Shader.TileMode // 平铺模式 )

这个数据模型是应用的核心,所有水印配置都通过这个类进行管理。通过@Keep注解确保在ProGuard混淆时保持完整性。

📱 UI层架构:MainActivity与ViewModel

MainActivity:用户交互中心

MainActivity.kt作为应用的主界面,负责处理用户交互和UI展示。它采用MVVM架构,通过LaunchView自定义视图管理不同的界面状态:

@AndroidEntryPoint class MainActivity : AppCompatActivity() { private val viewModel: MainViewModel by viewModels() private lateinit var launchView: LaunchView // 功能面板列表 private val contentFunList: List<FuncTitleModel> by lazy { listOf( FuncTitleModel(FuncTitleModel.FuncType.Text, "文字水印", R.drawable.ic_func_text), FuncTitleModel(FuncTitleModel.FuncType.Icon, "图片水印", R.drawable.ic_func_sticker) ) } }

MainViewModel:业务逻辑处理

MainViewModel.kt负责处理所有业务逻辑,包括图片处理、水印生成和状态管理:

@HiltViewModel class MainViewModel @Inject constructor( private val userRepo: UserConfigRepository, private val waterMarkRepo: WaterMarkRepository, private val templateRepo: TemplateRepository ) : ViewModel() { // 核心数据流 val waterMark: LiveData<WaterMark> = waterMarkRepo.waterMark.asLiveData() val selectedImage: LiveData<ImageInfo> = waterMarkRepo.selectedImage.asLiveData() val imageList: LiveData<Pair<List<ImageInfo>, Boolean>> = ... // 水印生成核心方法 private suspend fun generateImage( contentResolver: ContentResolver, viewInfo: ViewInfo, imageInfo: ImageInfo ): Result<Uri> = ... }

🎨 水印渲染引擎:WaterMarkImageView

核心渲染组件

WaterMarkImageView.kt是应用的核心渲染组件,负责将水印应用到图片上。它继承自AppCompatImageView并实现了CoroutineScope

class WaterMarkImageView : androidx.appcompat.widget.AppCompatImageView, CoroutineScope { // 水印配置 var config: WaterMark? = null // 渲染水印的核心方法 override fun onDraw(canvas: Canvas) { super.onDraw(canvas) if (config?.text.isNullOrEmpty() || layoutShader == null) { return } // 根据平铺模式绘制水印 if (config?.obtainTileMode() == Shader.TileMode.CLAMP) { // 单次绘制模式 canvas.translate(...) canvas.drawRect(...) } else { // 平铺模式 canvas.drawRect(...) } } }

水印Shader生成

应用支持两种水印模式:文字水印和图片水印,通过不同的Shader生成策略实现:

companion object { // 生成文字水印Shader suspend fun buildTextBitmapShader( imageInfo: ImageInfo, config: WaterMark, textPaint: TextPaint, coroutineContext: CoroutineContext ): WaterMarkShader? { // 使用StaticLayout处理多行文本 val staticLayout = StaticLayout.Builder.obtain(...).build() // 计算旋转后的尺寸 val fixWidth = textWidth * cos(radians) + textHeight * sin(radians) val fixHeight = textWidth * sin(radians) + textHeight * cos(radians) // 创建位图Shader val bitmapShader = BitmapShader(bitmap, tileMode, tileMode) } // 生成图片水印Shader suspend fun buildIconBitmapShader( imageInfo: ImageInfo, srcBitmap: Bitmap, config: WaterMark, textPaint: Paint, scale: Boolean, coroutineContext: CoroutineContext ): WaterMarkShader? { // 缩放图片水印 val scaleRatio = config.textSize / 14f val targetBitmap = Bitmap.createBitmap(...) // 应用旋转和绘制 canvas.rotate(config.degree, ...) canvas.drawBitmap(scaleBitmap, ...) } }

🔧 功能面板系统

模块化面板设计

应用采用模块化的面板设计,每个功能都有独立的Fragment:

  1. 文字内容面板-TextContentDisplayFragment.kt
  2. 颜色选择面板-ColorFragment.kt
  3. 透明度调节面板-AlphaPbFragment.kt
  4. 旋转角度面板-DegreePbFragment.kt
  5. 文字样式面板-TextStyleFragment.kt
  6. 平铺模式面板-TileModeFragment.kt

每个面板都通过BaseBindFragment基类实现,确保一致的UI体验和状态管理。

数据持久化

WaterMarkRepository.kt负责水印配置的持久化存储,使用Android DataStore进行轻量级数据存储:

@Singleton class WaterMarkRepository @Inject constructor( @Named("WaterMarkPreferences") private val dataStore: DataStore<Preferences> ) { val waterMark: Flow<WaterMark> = dataStore.data .map { WaterMark( text = it[KEY_TEXT] ?: "默认水印文本", textSize = (it[KEY_TEXT_SIZE] ?: 14f).coerceAtLeast(1f), textColor = it[KEY_TEXT_COLOR] ?: Color.parseColor("#FFB800"), // ... 其他属性 ) } }

🚀 性能优化策略

1. 图片加载优化

应用使用decodeSampledBitmapFromResource进行图片采样,避免内存溢出:

val inSample = calculateInSampleSize( mutableBitmap.width, mutableBitmap.height, WaterMarkImageView.calculateDrawLimitWidth(...), WaterMarkImageView.calculateDrawLimitHeight(...) )

2. 协程异步处理

所有耗时的图片处理操作都在协程中执行,确保UI流畅:

private suspend fun generateImage(...): Result<Uri> = withContext(Dispatchers.IO) { // 图片处理逻辑 }

3. 内存管理

  • 使用Bitmap.Config.ARGB_8888确保高质量输出
  • 及时回收不再使用的Bitmap对象
  • 使用inSampleSize减少内存占用

📊 项目架构总结

EasyWatermark采用清晰的架构分层:

  1. 数据层-data/model/data/repo/

    • WaterMark数据模型
    • Repository数据访问层
    • DataStore持久化存储
  2. 业务逻辑层-ui/MainViewModel.kt

    • 处理图片选择、水印生成
    • 管理应用状态和配置
    • 协调数据层和UI层
  3. UI层-ui/ui/panel/

    • MainActivity主界面
    • 功能面板Fragment
    • 自定义视图组件
  4. 工具层-utils/

    • 文件处理工具
    • 图片处理工具
    • 扩展函数

💡 开发技巧与最佳实践

1. 状态管理

应用使用StateFlowLiveData进行响应式状态管理,确保UI与数据同步:

private val _selectedImage = MutableStateFlow(ImageInfo.empty()) val selectedImage: StateFlow<ImageInfo> = _selectedImage val waterMark: Flow<WaterMark> = dataStore.data .map { preferences -> // 映射配置到WaterMark对象 }

2. 依赖注入

使用Hilt进行依赖注入,简化组件管理:

@HiltViewModel class MainViewModel @Inject constructor( private val userRepo: UserConfigRepository, private val waterMarkRepo: WaterMarkRepository, private val templateRepo: TemplateRepository ) : ViewModel()

3. 错误处理

完善的错误处理机制,包括内存溢出、文件不存在等情况:

try { // 图片处理逻辑 } catch (fne: FileNotFoundException) { info.result = Result.failure(null, code = TYPE_ERROR_FILE_NOT_FOUND) } catch (oom: OutOfMemoryError) { info.result = Result.failure(null, code = TYPE_ERROR_SAVE_OOM) }

🎯 核心功能亮点

1. 灵活的平铺模式

支持多种Shader.TileMode:

  • CLAMP- 边缘拉伸
  • REPEAT- 重复平铺
  • MIRROR- 镜像平铺

2. 实时预览

水印效果实时预览,所有修改立即反映在图片上。

3. 批量处理

支持多张图片批量添加水印,提高工作效率。

4. 模板系统

内置水印模板系统,可以保存常用水印配置。

🔮 未来扩展方向

基于当前架构,EasyWatermark可以轻松扩展以下功能:

  1. 更多水印样式- 支持渐变、阴影等效果
  2. AI智能水印- 基于内容的水印位置推荐
  3. 云端同步- 水印配置云端备份
  4. 批量导出- 支持多种格式批量导出

📚 学习资源

  • 官方文档:docs/official.md
  • 核心源码:app/src/main/java/me/rosuh/easywatermark/
  • UI组件:app/src/main/java/me/rosuh/easywatermark/ui/widget/

EasyWatermark的架构设计体现了现代Android应用开发的最佳实践,通过清晰的层次分离和模块化设计,实现了功能丰富且性能优秀的水印应用。无论是学习Android架构设计,还是开发类似的应用,这个项目都提供了宝贵的参考价值。

【免费下载链接】EasyWatermark🔒 🖼 Securely, easily add a watermark to your sensitive photos. 安全、简单地为你的敏感照片添加水印,防止被人泄露、利用项目地址: https://gitcode.com/gh_mirrors/ea/EasyWatermark

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 5:14:58

SimVision波形调试实战:从抓信号、设断点到快速定位RTL代码bug

SimVision波形调试实战&#xff1a;从抓信号到快速定位RTL代码缺陷 在数字电路设计流程中&#xff0c;仿真调试往往占据项目周期的30%以上时间。当NC-Verilog仿真器抛出"X态传播"或"时序违例"警告时&#xff0c;如何从海量波形中快速锁定问题源头&#xff…

作者头像 李华
网站建设 2026/5/20 5:14:27

Markdown Resume代码解析:Assetic资源管理与模板系统架构

Markdown Resume代码解析&#xff1a;Assetic资源管理与模板系统架构 【免费下载链接】markdown-resume Generate a responsive CSS3 and HTML5 resume with Markdown, with optional PDF output. 项目地址: https://gitcode.com/gh_mirrors/mar/markdown-resume 你是否…

作者头像 李华
网站建设 2026/5/20 5:12:52

ReactQL与WebSocket集成指南:如何实现实时数据更新

ReactQL与WebSocket集成指南&#xff1a;如何实现实时数据更新 【免费下载链接】reactql Universal ReactGraphQL starter kit: React 16, Apollo 2, MobX, Emotion, Webpack 4, GraphQL Code Generator, React Router 4, PostCSS, SSR 项目地址: https://gitcode.com/gh_mir…

作者头像 李华
网站建设 2026/5/20 5:11:54

终极指南:如何用免费C工具快速管理天龙八部单机版游戏数据

终极指南&#xff1a;如何用免费C#工具快速管理天龙八部单机版游戏数据 【免费下载链接】TlbbGmTool 某网络游戏的单机版本GM工具 项目地址: https://gitcode.com/gh_mirrors/tl/TlbbGmTool 还在为《天龙八部》单机版的数据管理而烦恼吗&#xff1f;TlbbGmTool是一款专为…

作者头像 李华