NSMutableParagraphStyle /NSParagraphStyle 文本属性Attributes

本文详细介绍了iOS开发中 NSAttributedString 的使用方法,包括如何通过 NSMutableParagraphStyle 设置文本的段落样式,如行间距、首行缩进、对齐方式等,并展示了如何结合 NSFontAttributeName 和 NSKernAttributeName 完成字体大小及字间距的定制。

http://blog.youkuaiyun.com/u010241322/article/details/40894069
  1. typedef NS_ENUM(NSInteger, NSLineBreakMode) {/* What to do with long lines */  
  2.     NSLineBreakByWordWrapping = 0,     /* Wrap at word boundaries, default */  
  3.     NSLineBreakByCharWrapping,/* Wrap at character boundaries */  
  4.     NSLineBreakByClipping,/* Simply clip */剪掉后面显示不了的部分  
  5.     NSLineBreakByTruncatingHead,/* Truncate at head of line: "...wxyz" */头部分的内容以……方式省略  
  6.     NSLineBreakByTruncatingTail,/* Truncate at tail of line: "abcd..." */结尾部分的内容以……方式省略  
  7.     NSLineBreakByTruncatingMiddle/* Truncate middle of line:  "ab...yz" */中间部分的内容以……方式省略  
  8. } NS_ENUM_AVAILABLE_IOS(6_0);  
  9.   
  10.   
  11.   
  12.   
  13.   
  14. typedef NS_ENUM(NSInteger, NSWritingDirection) {  
  15.     NSWritingDirectionNatural       = -1,    // Determines direction using the Unicode Bidi Algorithm rules P2 and P3  
  16.     NSWritingDirectionLeftToRight   =  0,    // Left to right writing direction 左到右的书写方向  
  17.     NSWritingDirectionRightToLeft   =  1    // Right to left writing direction 右到左的书写方向  
  18. } NS_ENUM_AVAILABLE_IOS(6_0);  
  19.   
  20.   
  21.   
  22.   
  23.   
  24.   
  25.   
  26.  //   NSParagraphStyleAttributeName 段落的风格(设置首行,行间距,对齐方式什么的)看自己需要什么属性,写什么  
  27.     NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];  
  28.     paragraphStyle.lineSpacing = 10;// 字体的行间距  
  29.     paragraphStyle.firstLineHeadIndent = 20.0f;//首行缩进  
  30.     paragraphStyle.alignment = NSTextAlignmentJustified;//(两端对齐的)文本对齐方式:(左,中,右,两端对齐,自然)  
  31.     paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;//结尾部分的内容以……方式省略 ( "...wxyz" ,"abcd..." ,"ab...yz")  
  32.     paragraphStyle.headIndent = 20;//整体缩进(首行除外)  
  33.     paragraphStyle.tailIndent = 20;//  
  34.     paragraphStyle.minimumLineHeight = 10;//最低行高  
  35.     paragraphStyle.maximumLineHeight = 20;//最大行高  
  36.     paragraphStyle.paragraphSpacing = 15;//段与段之间的间距  
  37.     paragraphStyle.paragraphSpacingBefore = 22.0f;//段首行空白空间/* Distance between the bottom of the previous paragraph (or the end of its paragraphSpacing, if any) and the top of this paragraph. */  
  38.     paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;//从左到右的书写方向(一共➡️三种)  
  39.     paragraphStyle.lineHeightMultiple = 15;/* Natural line height is multiplied by this factor (if positive) before being constrained by minimum and maximum line height. */  
  40.     paragraphStyle.hyphenationFactor = 1;//连字属性 在iOS,唯一支持的值分别为0和1  
  41.   
  42.   
  43.   
  44.   
  45.   
  46.   
  47.   
  48. /* 
  49.      NSFontAttributeName 字体大小 
  50.      NSParagraphStyleAttributeName 段落的风格(设置首行,行间距,对齐方式什么的) 
  51.      NSKernAttributeName 字间距 
  52.      */  
  53.     NSDictionary *attributes = @{  
  54.                                  NSFontAttributeName:[UIFont systemFontOfSize:15],  
  55.                                  NSParagraphStyleAttributeName:paragraphStyle,  
  56.                                  NSKernAttributeName:@(10),  
  57.                                                                 
  58.                                  };  
  59.     textView.attributedText = [[NSAttributedString alloc] initWithString:textView.text attributes:attributes];  

<think>### 解释:Android音频策略配置文件中的产品策略(Product Strategy) 在Android音频策略引擎中,产品策略(`ProductStrategy`)用于定义不同的音频使用场景(如媒体播放、通话、通知等)如何映射到具体的音频流类型(Stream)和音量组(Volume Group)。每个产品策略包含一个或多个`AttributesGroup`,每个组定义了匹配的音频属性(如Usage、ContentType)以及关联的流类型和音量组。 #### 示例配置解析 以下是一个名为`STRATEGY_MEDIA`的产品策略配置片段: ```xml <ProductStrategy name="STRATEGY_MEDIA"> <!-- 第一组:助手音频流 --> <AttributesGroup streamType="AUDIO_STREAM_ASSISTANT" volumeGroup="assistant"> <Attributes> <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes> </AttributesGroup> <!-- 第二组:音乐音频流 --> <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music"> <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes> <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes> <Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes> <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes> <Attributes></Attributes> <!-- 空属性可能匹配所有?需确认实现 --> </AttributesGroup> <!-- 第三组:系统音频流 --> <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system"> <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes> </AttributesGroup> </ProductStrategy> ``` #### 关键元素解释: 1. **`AttributesGroup`**: - **`streamType`**: 指定匹配的音频流类型(如`AUDIO_STREAM_MUSIC`)。 - **`volumeGroup`**: 指定关联的音量组(如`music`),用于独立控制音量。 2. **`Attributes`**: - 定义音频属性条件(AND关系)。当音频流的属性(Usage、ContentType等)匹配**任意一个**`Attributes`块时,整个`AttributesGroup`即匹配。 - 示例1: ```xml <Attributes> <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes> ``` 要求同时满足ContentType=SPEECH且Usage=ASSISTANT。 - 示例2: ```xml <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes> ``` 只要求Usage=MEDIA(ContentType任意)。 3. **匹配规则**: - 一个音频流(由Usage、ContentType等定义)会匹配**第一个**符合条件的`AttributesGroup`。 - 若一个`AttributesGroup`包含多个`Attributes`块,则只需匹配其中任意一个块即可。 --- #### 策略应用场景 - **媒体策略(STRATEGY_MEDIA)**:处理媒体、游戏、导航和语音助手等音频。 - 助手语音(ASSISTANT)被单独分组到`AUDIO_STREAM_ASSISTANT`流和`assistant`音量组。 - 媒体、游戏、导航等统一使用`AUDIO_STREAM_MUSIC`流和`music`音量组。 - 系统提示音(如导航提示)使用`AUDIO_STREAM_SYSTEM`流,但音量组独立(`system`)。 --- #### 空`Attributes`块的潜在含义 ```xml <Attributes></Attributes> ``` - 可能表示“匹配所有属性”,即作为兜底规则。但需注意:**空属性块可能匹配任何音频流**,因此必须谨慎使用(通常放在最后)。 --- ### 代码示例:解析策略配置(伪代码) 以下伪代码展示了如何解析上述XML配置并构建策略映射: ```cpp // 伪代码:解析ProductStrategy配置 void parseProductStrategy(XmlElement* strategyElement) { ProductStrategy strategy(strategyElement->getAttribute("name")); for (XmlElement* groupElement : strategyElement->getChildren("AttributesGroup")) { AttributesGroup group; group.streamType = parseStreamType(groupElement->getAttribute("streamType")); group.volumeGroup = groupElement->getAttribute("volumeGroup"); for (XmlElement* attrElement : groupElement->getChildren("Attributes")) { AudioAttributes attributes = {}; // 初始化为默认值(如AUDIO_USAGE_UNKNOWN) for (XmlElement* prop : attrElement->getChildren()) { if (prop->getName() == "Usage") { attributes.usage = parseUsage(prop->getAttribute("value")); } else if (prop->getName() == "ContentType") { attributes.contentType = parseContentType(prop->getAttribute("value")); } // ... 其他属性(如FLAGS) } group.attributesList.push_back(attributes); } strategy.addAttributesGroup(group); } // 存储策略 mProductStrategies.push_back(strategy); } ``` --- §§相关问题§§: 1. 在Android音频策略中,如何定义音量组(Volume Group)及其作用? 2. 解释音频属性(AudioAttributes)中的Usage和ContentType的区别。 3. 当多个产品策略匹配同一个音频流时,系统如何处理冲突? 4. 如何扩展产品策略以支持自定义音频路由规则? </think> ### 解释:Android音频策略配置文件中的产品策略(Product Strategy) 在Android音频策略引擎中,产品策略(`ProductStrategy`)用于定义不同的音频使用场景(如媒体播放、通话、通知等)如何映射到具体的音频流类型(Stream)和音量组(Volume Group)。每个产品策略包含一个或多个`AttributesGroup`,每个组定义了匹配的音频属性(如Usage、ContentType)以及关联的流类型和音量组。 #### 示例配置解析 以下是一个名为`STRATEGY_MEDIA`的产品策略配置片段: ```xml <ProductStrategy name="STRATEGY_MEDIA"> <!-- 第一组:助手音频流 --> <AttributesGroup streamType="AUDIO_STREAM_ASSISTANT" volumeGroup="assistant"> <Attributes> <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes> </AttributesGroup> <!-- 第二组:音乐音频流 --> <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music"> <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes> <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes> <Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes> <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes> <Attributes></Attributes> <!-- 空属性可能匹配所有?需确认实现 --> </AttributesGroup> <!-- 第三组:系统音频流 --> <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system"> <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes> </AttributesGroup> </ProductStrategy> ``` #### 关键元素解释: 1. **`AttributesGroup`**: - **`streamType`**: 指定匹配的音频流类型(如`AUDIO_STREAM_MUSIC`)。 - **`volumeGroup`**: 指定关联的音量组(如`music`),用于独立控制音量。 2. **`Attributes`**: - 定义音频属性条件(AND关系)。当音频流的属性(Usage、ContentType等)匹配**任意一个**`Attributes`块时,整个`AttributesGroup`即匹配。 - 示例1: ```xml <Attributes> <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes> ``` 要求同时满足ContentType=SPEECH且Usage=ASSISTANT。 - 示例2: ```xml <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes> ``` 只要求Usage=MEDIA(ContentType任意)。 3. **匹配规则**: - 一个音频流(由Usage、ContentType等定义)会匹配**第一个**符合条件的`AttributesGroup`。 - 若一个`AttributesGroup`包含多个`Attributes`块,则只需匹配其中任意一个块即可。 --- #### 策略应用场景 - **媒体策略(STRATEGY_MEDIA)**:处理媒体、游戏、导航和语音助手等音频。 - 助手语音(ASSISTANT)被单独分组到`AUDIO_STREAM_ASSISTANT`流和`assistant`音量组。 - 媒体、游戏、导航等统一使用`AUDIO_STREAM_MUSIC`流和`music`音量组。 - 系统提示音(如导航提示)使用`AUDIO_STREAM_SYSTEM`流,但音量组独立(`system`)。 --- #### 空`Attributes`块的潜在含义 ```xml <Attributes></Attributes> ``` - 可能表示“匹配所有属性”,即作为兜底规则。但需注意:**空属性块可能匹配任何音频流**,因此必须谨慎使用(通常放在最后)。 --- ### 代码示例:解析策略配置(伪代码) 以下伪代码展示了如何解析上述XML配置并构建策略映射: ```cpp // 伪代码:解析ProductStrategy配置 void parseProductStrategy(XmlElement* strategyElement) { ProductStrategy strategy(strategyElement->getAttribute("name")); for (XmlElement* groupElement : strategyElement->getChildren("AttributesGroup")) { AttributesGroup group; group.streamType = parseStreamType(groupElement->getAttribute("streamType")); group.volumeGroup = groupElement->getAttribute("volumeGroup"); for (XmlElement* attrElement : groupElement->getChildren("Attributes")) { AudioAttributes attributes = {}; // 初始化为默认值(如AUDIO_USAGE_UNKNOWN) for (XmlElement* prop : attrElement->getChildren()) { if (prop->getName() == "Usage") { attributes.usage = parseUsage(prop->getAttribute("value")); } else if (prop->getName() == "ContentType") { attributes.contentType = parseContentType(prop->getAttribute("value")); } // ... 其他属性(如FLAGS) } group.attributesList.push_back(attributes); } strategy.addAttributesGroup(group); } // 存储策略 mProductStrategies.push_back(strategy); } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值