美文网首页iOS安卓Android
TextView-不等字数两端对齐

TextView-不等字数两端对齐

作者: 积木Blocks | 来源:发表于2016-06-29 16:01 被阅读7972次

前言

~


项目截图

最近同事在项目中遇到,TextView文字两端对齐的问题,就如同上图的效果5个字和4个字的文字首尾对齐。当然上图的实现方式是承载的H5页面,并不是原生的TextView。可是这个问题一直困扰着我,想试试用原生的TextView能不能做出这个效果,于是就有了今天这篇文章。


1.初步实现效果

~


原生TextView实现对齐效果

效果还不错吧,使用起来也是非常的简单:

tv1.setText(AlignedTextUtils.formatText("手 机 号"));
tv2.setText(AlignedTextUtils.formatText("密   码"));
tv3.setText("再次确认密码");
tv4.setText(AlignedTextUtils.formatText("个性签名"));
tv5.setText(AlignedTextUtils.formatText("编不下去了"));
特别说明:文字中的“空格”一定要是全角模式下的空格,因为全角模式下汉子,数字,符号等所占比例是一致的。

2.关键工具类

~ 目前这个工具类支持2-6个数字的对齐(如果你有其他需求可以参照这个思路自行编写)

/** 
  * 不同文字数目2端对齐工具类 (支持2-6个数字) 
  * 
  * @author yuhao 
  * @time 2016年6月28日 */
public class AlignedTextUtils {   

 private static int n = 0;// 原Str拥有的字符个数     
 private static SpannableString spannableString;
 private static double multiple = 0;// 放大倍数    

/**     
  * 对显示的字符串进行格式化 比如输入:出生年月 输出结果:出正生正年正月     
  */    
public static String formatStr(String str) {       
      if (TextUtils.isEmpty(str)) {            
             return "";        
      }        
      n = str.length();        
      if (n >= 6) {            
            return str;        
      }       
      StringBuilder sb = new StringBuilder(str);       
      for (int i = n - 1; i > 0; i--) {            
            sb.insert(i, "正");        
       }        
       return sb.toString();    
      }    

     /**     
       * 对显示字符串进行格式化 比如输入:安正卓正机正器正人 输出结果:安 卓 机 器 人    
       *     
       * @param str     
       * @return     */    
 public static SpannableString formatText(String str){        
    if (TextUtils.isEmpty(str)) {            
    return null;        
    }        
    str = formatStr(str);        
    if (str.length()<=6){            
    return null;        
    }        
    spannableString = new SpannableString(str);           
    switch (n) {            
    case 2:                
         multiple = 4;                
      break;            
    case 3:                
         multiple = 1.5;                
       break;            
    case 4:                
        multiple =   0.66666666666666666666666666666666667;                   
      break;            
    case 5:                
        multiple = 0.25;                
      break;            
    default:                
       break;        
    }        
    for (int i = 1; i < str.length(); i = i + 2) 
   {            
    spannableString.setSpan(new RelativeSizeSpan((float) multiple), i, i + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);            
    spannableString.setSpan(new ForegroundColorSpan(Color.TRANSPARENT), i, i + 1,  Spanned.SPAN_INCLUSIVE_EXCLUSIVE);        
   }       
   return spannableString;    
}
}

3.实现思路详解

~ TextView自带有行间距可是并没有字间距,所以我想到了利用SpannableString的RelativeSizeSpan和ForegroundColorSpan以及StringBuilder来模拟字间距的效果,相信看了下面这张图,你就基本明白实现的原理了

原理图
步骤一:转换字符串

~
利用formatStr(String str)方法来格式化字符串,每隔一个字符插入一个字符,上面的工具类我写的是“正”字,是为了显示的更清楚。而这个“正”字的作用就是为了称当字间距的作用。

代码:

tv1.setText(AlignedTextUtils.formatStr("安卓初学者"));

效果:

转换字符串后的效果
步骤二:修改“字间距”大小

~
经过上一步之后我们需要做的就是缩放“正”字,那么到底应该缩放多少呢?

抽象派的图片

如上图,虽说丑了点,但是可以明显看出5个字的字符串是由6个字的字符串多出来的那个字符平分成4份,所以每一个字符的缩放比为1/4倍.
以此类推可以得出一个公式缩放倍数:

(6-n)/(n-1)

代码:

spannableString.setSpan(new RelativeSizeSpan((float) multiple), i, i + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);     

效果:

缩放比例后的效果
步骤三:修改“字间距”颜色

~
隐藏字间距,将颜色设置和背景一致即可。

代码:

spannableString.setSpan(new ForegroundColorSpan(Color.TRANSPARENT), i, i + 1,        Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

效果:

最终效果

4.后记

  • 这个工具类,仅仅是提供一个思路,也可能存在很多问题,如果问题欢迎联系我,大家一起完善。
  • 目前的问题:23个字的时候,由于缩放倍数大于1,造成了文本框变大问题。解决方法是:用全角字符的“空格”将23个字的字符转换成5个字的字符
  • 如果不是很了解SpannableString可以参考码农小阿飞《用SpannableString打造绚丽多彩的文本显示效果》

相关文章

  • TextView-不等字数两端对齐

    前言 ~ 最近同事在项目中遇到,TextView文字两端对齐的问题,就如同上图的效果5个字和4个字的文字首尾对齐。...

  • 2019-12-27Day 7 彻底搞定对齐和分页

    一、段落对齐 左对齐、右对齐、居中对齐、两端对齐、分散对齐。两端对齐会让文章看起来更整齐 调整缩进时,需勾选出标尺...

  • ios 多个垂直显示的UILabel文字两端对齐

    多行垂直显示的UILabel文字两端对齐 在开发中我们会遇到这样的UI,需要我们对齐字数不同的标题: 我的思路是需...

  • antd flex布局

    两端对齐 justify="space-between" 两端对齐,中间各项间隔: 设置gutter

  • CSS对齐方式和格式

    对齐:text-align:left | right | center | justify(两端对齐)垂直对齐:v...

  • Flex 布局介绍

    HTML 多个元素在一行 CSS 多个元素水平居中对齐 多个元素水平两端对齐 多行多个元素水平两端对齐 多个元素在...

  • 对齐方式

    文字对齐:text-align:left|right|center|justify(两端对齐) 垂直对齐:vert...

  • iOS 实现UIlabel的两端对齐效果

    未进行两端对齐格式时,文字显得参差不齐 设置两端对齐后的效果 废话不多说,直接上代码

  • 文字两端对齐

    在制作表单时,常常会遇到label标签需要两端对齐。两端对齐首先想到的是text-align: justify属性...

  • 文两行少量数字对齐方式技巧

    文字两端对齐 2018-05-19

网友评论

  • 周蛋蛋:用占位符很好解决,何必这样
  • 刻舟求剑KJ:<string name="name">姓\u3000\u3000名</string>
    tv.setText(R.string.name);
    我用这种方法,但是奇数个文字的时候就不行了
  • c4d5e299aa48:我想说,在text里面直接用全角空格调整间距就行了。。
  • Alex_Cin:好棒
  • a3f2be388634:很有想法,太聪明了 :+1:
    积木Blocks:@寒江烧烤 :joy:评论有个程田的评论,他优化了方法。你可以去试试。
  • 程田:楼主厉害,我发现可以一个更好的方法,使用ScaleXSpan可以达到更好的效果,共享一下代码:
    /**
    * 将给定的字符串给定的长度两端对齐
    *
    * @param str 待对齐字符串
    * @param size 汉字个数,eg:size=5,则将str在5个汉字的长度里两端对齐
    * @Return
    */
    public static SpannableStringBuilder justifyString(String str, int size) {
    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
    if (TextUtils.isEmpty(str)) {
    return spannableStringBuilder;
    }
    char[] chars = str.toCharArray();
    if (chars.length >= size || chars.length == 1) {
    return spannableStringBuilder.append(str);
    }
    int l = chars.length;
    float scale = (float) (size - l) / (l - 1);
    for (int i = 0; i < l; i++) {
    spannableStringBuilder.append(chars[i]);
    if (i != l - 1) {
    SpannableString s = new SpannableString(" ");//全角空格
    s.setSpan(new ScaleXSpan(scale), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannableStringBuilder.append(s);
    }
    }
    return spannableStringBuilder;
    }
    醉酒肆之:挺好的,就是+了全角冒号:不大适合了。
    积木Blocks:@程田 :+1: 挺不错的,大神啊!
    积木Blocks:@程田 :smile:等下班后去试试
  • HaKu:看完,表示挺有意思~ 喜欢编程,尤其实现需求的思路总能给人一种小惊喜~
    积木Blocks:@HaKu 每个程序员都是惊喜制造者,也有可能有惊吓(bug).:smile:
  • hackware:我以前搞过,自定义View,用FontMetrics自己测量,自己画
    积木Blocks:@hackware :smile:没做过,不过听起来很不错,希望以后可以分享下。
    hackware:@自导自演的机器人 我以前在学校做个一个项目,做一个能打开excel文件的电子表格程序,支持了分散对齐、两端对齐、居中对齐等excel中的所有对齐方式
    积木Blocks:@hackware :+1:等以后,去研究下
  • 醉酒肆之:这个太需要了😂
    积木Blocks:@醉酒肆之 :grin:
  • from0:可以 思路很巧妙:+1:
  • 68b17a088e55:以前总是遇到这种。正准备研究下看看。
    积木Blocks:@JohnChou1290 希望对你有帮助
  • coco猫:刚好需要这种,研究一下
    积木Blocks:@coco猫 :grin:
  • 包牙齿:或许参考这个demo,可能会有点帮助:https://github.com/baoyachi/WrapTextView :stuck_out_tongue_closed_eyes:
    积木Blocks:@包牙齿 我这个空格是因为2~3个字数缩放比会超过1,会把TextView给撑大,所以加入了全角字符(一定要是全角)。如果是服务器的字,你也可以和服务器约定让他们如果2.3个字的时候加入全角的字符最少变成4个字符。我这是一个思路,你可以自己参考优化哟。
    包牙齿:@包牙齿 这是你本地写好的文字,可以使用“空格”,要是是从服务端传过来的文字,那还是要自己包一层吧?
    积木Blocks:@包牙齿 多谢
  • 606fd5f5448c:英吹思婷~
    积木Blocks:@Andrman :flushed: 你和楼上那位有啥关系
  • SScience: :+1: 我都是文字+冒号用相对布局搞。期待完美适配方案 :smile:
    积木Blocks:@幸运Science :joy:尽力
  • NewChar:/t 帮你忙
    积木Blocks:@NewLq :grin:
  • 妙法莲花1234:像这种密码,手机号,账号都是固定的文本,我都字节在布局里写死的 :grin: ,哈哈
    积木Blocks:@追风917 主要就是4个字数的不是很好处理
  • cccccccxxxxxx:谢谢分享:stuck_out_tongue_winking_eye:
    积木Blocks:@BUBUBUHAHAHA :smile:
  • 采蘑菇的里奥马:上班打开简书看到的第一篇文章,真是非常巧合哈 ! 多谢支持哦 !
    其实,想法真心不错的呢,不过有局限性,字数上应该会是一个比较大的问题,另一个只能用于显示,如果用getText()的话就会暴露无遗,建议尝试继承TextView重写onDraw()方法试试看 ! :grin:
    现提出一个问题:
    1.文中有错别字哦 ! :smile:
    积木Blocks:@码农小阿飞 :grin:等闲下来就可以了,你们的都是精品文章哟~期待
    采蘑菇的里奥马:@自导自演的机器人 哈哈 还是很有创意的呢 ! 继续加油啊 ! 最近一直加班, 都有大半个月没有更新简书了。 :sob:
    积木Blocks:@码农小阿飞 这个主要是做标题用的。我这也就是提供一个想法,比较治标不治本。使用的局限性确实挺大。
  • As_Javen:不错,学习了。
    积木Blocks:@As_Javen 😬
  • 曾经的你呀:不错了啦
    积木Blocks:@iSnowFlake :grin:
  • 漂在海上的风筝:好
    积木Blocks:@漂在海上的风筝 :grin:
  • JaydenHo:好想法
    积木Blocks:@JaydenHo 局限性比较多,不过应该也可以适用了。
  • 捡淑:英吹思婷~
    积木Blocks:@捡淑 :joy:
    捡淑:@自导自演的机器人 卧槽 神!我只服 自导自演的机器人。。。
    积木Blocks:@捡淑 :smirk:你改名字了吧,我记得你这个风骚的头像

本文标题:TextView-不等字数两端对齐

本文链接:https://www.haomeiwen.com/subject/rjtxjttx.html