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;
}
View Code

完整代码:(在github上,觉得有用就给个star吧,😜)

https://github.com/xiayuanquan/ReadPinYinEssayDemo

 

五、效果

 

posted @ 2018-04-09 13:45  XYQ全哥  阅读(1902)  评论(0编辑  收藏  举报