Files
peko-ios/YuMi/Modules/YMRoom/View/MessageContainerView/UNIFIED_TEXT_LAYOUT_README.md

198 lines
7.0 KiB
Markdown
Raw Normal View History

# 统一文本尺寸计算实现
## 概述
本次修改统一了应用中的文本尺寸计算方法,解决了阿拉伯文本显示问题,提高了 RTL从右到左文本的渲染精度。
## 主要修改
### 1. XPNetImageYYLabel.m
**修改前:**
- 使用条件分支RTL 文本使用 `boundingRectWithSize`,非 RTL 文本使用 `YYTextLayout`
- 导致 RTL 文本计算不准确
**修改后:**
- 统一使用 `YYTextLayout` 进行所有文本尺寸计算
- 新增 `createTextContainerForText:` 方法,根据文本方向配置容器
- RTL 文本使用 `YYTextTruncationTypeStart`LTR 文本使用 `YYTextTruncationTypeEnd`
### 2. XPMessageInfoModel.m
**修改前:**
- 检测到阿拉伯字符时额外增加 20 点高度
- 可能导致高度计算不准确
**修改后:**
- 移除额外的阿拉伯文本高度调整
- 优化 `YYTextContainer` 配置,根据文本方向设置截断类型
- 依赖 `YYTextLayout` 的精确计算
### 3. 新增测试文件
- `XPTextLayoutTest.h/m`:提供测试方法验证修改效果
- 包含纯阿拉伯文本、混合文本、长文本的测试用例
## 技术细节
### YYTextContainer 配置
```objc
- (YYTextContainer *)createTextContainerForText:(NSAttributedString *)text {
YYTextContainer *container = [YYTextContainer new];
container.size = CGSizeMake(kRoomMessageMaxWidth, MAXFLOAT);
// 根据文本方向配置容器
if (isMSRTL()) {
container.truncationType = YYTextTruncationTypeStart;
} else {
container.truncationType = YYTextTruncationTypeEnd;
}
return container;
}
```
### 统一计算逻辑
```objc
- (void)updateLayoutWithAttributedText:(NSAttributedString *)attributedText {
// 统一使用 YYTextLayout 进行文本尺寸计算
YYTextContainer *container = [self createTextContainerForText:attributedText];
YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:attributedText];
CGSize finalSize = layout.textBoundingSize;
if (self.updateLayoutSize) {
self.updateLayoutSize(finalSize);
}
}
```
## 优势
1. **精确性**`YYTextLayout` 对复杂文本(包括 RTL有更好的支持
2. **一致性**:统一的计算方法确保所有文本类型的一致性
3. **可维护性**:减少条件分支,代码更简洁
4. **性能**:避免重复计算和额外的高度调整
## 测试
运行测试验证修改效果:
```objc
#import "XPTextLayoutTest.h"
// 在适当的地方调用
[XPTextLayoutTest runAllTests];
```
## 注意事项
1. 确保 `YYText` 库版本支持所需功能
2. 测试各种文本场景,特别是长文本和混合文本
3. 验证在不同设备和系统版本上的表现
4. 关注性能影响,特别是在大量文本的场景下
## 后续优化建议
1. **字体优化**:为阿拉伯文本自动选择合适的字体(如 "GeezaPro"
2. **缓存机制**:为频繁计算的文本添加缓存
3. **性能监控**:添加性能指标监控文本计算耗时
4. **更多测试**:增加边界情况和性能测试
## 问题修复记录
### 2025-08-14 修复文本截断问题
**问题描述:**
- 阿拉伯语正常显示,但其他语言(中文/英文/土耳其文)可能出现显示不全尾截断情况
**根本原因:**
1. `XPNetImageYYLabel.m` 中的 `setAttributedText` 方法缺少 `maximumNumberOfRows = 0` 设置
2. 截断类型配置不一致,部分地方硬编码为 `YYTextTruncationTypeEnd`
**修复方案:**
1.`createTextContainerForText` 方法中添加 `container.maximumNumberOfRows = 0`
2.`setAttributedText` 方法中统一文本方向配置逻辑
3. 确保所有 `YYTextContainer` 都正确设置 `maximumNumberOfRows = 0`
**修复后效果:**
- 所有语言的长文本都能完整显示,不会被意外截断
- 保持阿拉伯语的正确显示效果
- 统一了文本容器的配置逻辑
## 多行文本显示问题修复 (2024-01-XX)
### 问题描述
在聊天室消息显示中发现多行文本无法完整显示的问题,特别是包含多语言内容(阿拉伯语、中文、英文、土耳其语等)的长文本消息。
### 发现的问题
#### 1. XPNetImageYYLabel.m 中的问题
- **问题1 (第71行)**: 使用了错误的 `YYTextLayout` 创建方法
```objc
// 错误的方式
YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:maxSize text:attributedTextCopy];
// 正确的方式
YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:attributedTextCopy];
```
- **问题2 (第62行)**: 容器尺寸设置不准确
```objc
// 错误使用计算出的size.width
container.size = CGSizeMake(size.width, MAXFLOAT);
// 正确:使用统一的最大宽度
container.size = CGSizeMake(kRoomMessageMaxWidth, MAXFLOAT);
```
#### 2. XPMessageInfoModel.m 中的问题
- **问题3 (第36-38行)**: 多余的 `boundingRectWithSize` 调用
```objc
// 错误:存在未使用的计算,浪费性能
CGSize size = [content boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
options:NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin
context:nil].size;
// 后续使用 YYTextLayout 计算size 变量未被使用
// 正确:移除多余调用,统一使用 YYTextLayout
// 直接使用 YYTextLayout 进行所有文本尺寸计算
```
#### 3. XPRoomMessageTableViewCell.m 中的问题
- **问题5 (第178行)**: 错误的宽度约束设置
```objc
// 错误使用textBoundingSize.width作为宽度约束可能导致多行文本显示不完整
make.width.mas_lessThanOrEqualTo(size.width).priority(UILayoutPriorityDefaultHigh);
// 正确移除此约束让Label根据preferredMaxLayoutWidth自然确定宽度
// 保留trailing约束来限制最大宽度即可
```
### 修复内容
1. **修复 YYTextLayout 创建方式**: 改用 `layoutWithContainer:text:` 方法,确保 `maximumNumberOfRows=0``truncationType` 设置生效
2. **统一容器尺寸设置**: 在所有地方都使用 `kRoomMessageMaxWidth - 24` 作为容器宽度,正确处理 contentLabel 边距
3. **移除冗余计算**: 移除 `XPMessageInfoModel.m` 中未使用的 `boundingRectWithSize` 调用,提高性能并避免混淆
4. **优化外部约束逻辑**: 移除基于 `textBoundingSize.width` 的宽度约束,避免约束冲突和多行文本显示不完整
5. **修复边距计算**: 文本容器宽度减去 contentLabel 的左右边距UIEdgeInsetsMake(4, 12, 4, 12) 中的各12px
### 预期效果
- ✅ 多行文本能够完整显示
- ✅ 支持多语言文本布局阿拉伯语RTL、中文、英文、土耳其语等
- ✅ 统一的文本布局策略
- ✅ 提高文本尺寸计算的准确性和性能
- ✅ 避免约束冲突导致的布局异常
- ✅ 修复 preferredMaxLayoutWidth 与文本容器宽度不一致导致的截断问题
## 风险评估
- **低风险**:核心逻辑修改,但使用成熟的 `YYTextLayout`
- **兼容性**:保持现有 API 不变
- **回滚**:如有问题可快速回滚到原有逻辑