iOS:如何实现在文字上添加拼音
一、介绍
最近项目有一个需求,需要给朗诵的文字添加对应的拼音,而且要求使用原生的控件实现。一开始听到这个需求挺懵逼的,感觉有点难。后来,静下来想一下,其实还是可以实现的,无非就是自定义了。下面,就来说说思想。
二、思想
server端首先返回汉字和拼音一一对应的字符串,我们根据需要分别截取存入数组。一个汉字要添加拼音,拼音使用一个view显示,汉字也使用一个view显示,那么包含这两个控件的则是一个父view。许多个父view根据横向瀑布流的布局排列,就可以实现需要的汉字添加拼音的效果。结构图如下:
具体步骤如下:
1、创建一个textView,继承自UIScrollView,因为内容可能很多,需要滚动才能显示完;
2、在textView中接收模型时,动态创建很多的contanerView, 拼音View,汉字View,并使用masonry约束;
3、采用横向瀑布流算法对很多的contanerView进行布局;
4、在viewController中创建并添加textView,最后设置它的contentSize即可。
三、特点
优点:采用原生的控件实现,效果很流畅,用户体验好。
缺点:因为是一次性创建并添加很多的控件,如果文字特别多时,view渲染的过程比较耗时,建议放到自动释放池中进行创建。
四、代码
核心算法:
#pragma mark - layout subviews -(void)setupSubviewsConstraints { //(子视图采用横向瀑布流布局) CGFloat margin = 2.5; CGFloat viewHeight = (kFont.pointSize+5) * 2; CGFloat sumWidth = 0; CGFloat limitWidth = kScreenWidth-2*margin; CGFloat viewX = margin; CGFloat viewY = margin; CGFloat row = 0; for (int i=0 ; i<self.contentArray.count; i++) { //实际宽度 CGFloat chineseWidth = [self layoutListNameLength:self.contentArray[i]]; CGFloat pinYinWidth = [self layoutListNameLength:self.pinYinArray[i]]; CGFloat maxWidth = MAX(chineseWidth, pinYinWidth); //添加容器 UIView *containerView = [[UIView alloc] init]; [self addSubview:containerView]; //添加拼音 UILabel *pinYinLabel = [[UILabel alloc] init]; pinYinLabel.textColor = [UIColor grayColor]; pinYinLabel.font = kFont; pinYinLabel.text = self.pinYinArray[i]; pinYinLabel.textAlignment = NSTextAlignmentCenter; [containerView addSubview:pinYinLabel]; //添加汉字 UILabel *chineseLabel = [[UILabel alloc] init]; chineseLabel.textColor = [UIColor blackColor]; chineseLabel.font = kFont; chineseLabel.text = self.contentArray[i]; chineseLabel.textAlignment = NSTextAlignmentCenter; [containerView addSubview:chineseLabel]; //设置约束 [containerView mas_makeConstraints:^(MASConstraintMaker *make) { make.height.equalTo(@(viewHeight)); make.width.equalTo(@(maxWidth)); make.left.equalTo(@(viewX)); make.top.equalTo(@(viewY)); }]; [pinYinLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.top.right.equalTo(containerView); make.height.equalTo(containerView.mas_height).multipliedBy(0.5); }]; [chineseLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.bottom.right.equalTo(containerView); make.height.equalTo(containerView.mas_height).multipliedBy(0.5); }]; //计算坐标 sumWidth += (maxWidth + margin); if (i < self.contentArray.count-1) { chineseWidth = [self layoutListNameLength:self.contentArray[i+1]]; pinYinWidth = [self layoutListNameLength:self.pinYinArray[i+1]]; maxWidth = MAX(chineseWidth, pinYinWidth); } if (limitWidth - sumWidth >= maxWidth) { ///不换行 viewX = sumWidth + margin; } else{ ///换行 row++; sumWidth = 0; viewX = margin; if (i==self.contentArray.count-1) { row--; } } viewY = (viewHeight + 6*margin)*row + margin; } self.realHeight = viewY + viewHeight + 1.5*margin; }
完整代码:(在github上,觉得有用就给个star吧,😜)
https://github.com/xiayuanquan/ReadPinYinEssayDemo
五、效果
程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!