zoukankan      html  css  js  c++  java
  • [Android]TextView实现分散对齐(两端对齐)

    TextView是个特别基础的Android控件,只要有文本基本就少不了它。但是最近在项目开发的过程中我发现TextView存在很多局限性,其中最令我头疼的就是TextView文本排版方面的问题。我们都知道在word中文字对齐方式有靠左、靠右、居中、分散对齐等,但是TextView中就偏偏没有分散对齐这个属性设置。这就导致了TextView中一段文字会出现右边参差不齐的问题,中文由于每个字等宽看起来还不是特别糟糕,英文看起来就比较过分了。

    为了解决这个问题,一个常用的解决方法是在TextView内使用html来实现文本样式的设定,或者干脆放弃TextView而使用WebView来实现。但是,凡事都应该敢于解决问题,而不是回避问题,我相信即使仅用TextView一样是可以实现,后来我发现stackoverflow上有个回答提供了一种思路,我按照这种思路果然实现了TextView文本的分散对齐。原地址链接如下:http://stackoverflow.com/questions/8644649/full-text-justification-in-android/17807828#17807828,原回答有点问题,导致没人点赞,亏我还能发现它。

    以下是我的实现过程:

    MainActivity中:

    Display display = getWindowManager().getDefaultDisplay();            
    DisplayMetrics dm = new DisplayMetrics();            
    display.getMetrics(dm);            
    width = dm.widthPixels;                        
    //根据屏幕调整文字大小
    mArticleTextView.setLineSpacing(0f, 1.5f);
    mArticleTextView.setTextSize(8*(float)width/320f);                        
    //设置TextView
    mArticleTextView.setText("TextView需要显示的文本内容");    
                
    TextJustification.justify(mArticleTextView,mArticleTextView.getWidth());

    首先设置TextView的显示字体大小和文本内容,这里设置字体大小根据屏幕尺寸调整。然后调用自定义的类Textustification中的justify方法来实现TextView的分散对齐,两个参数分别是TextView控件以及控件的宽度。

    自定义的类TextJustification内容如下:

    import java.util.ArrayList;
    
    import android.graphics.Paint;
    import android.text.TextUtils;
    import android.widget.TextView;
    import android.widget.TextView.BufferType;
    
    public class TextJustification {
    
        public static void justify(TextView textView, float contentWidth) {
            String text=textView.getText().toString();
            String tempText;
            String resultText = "";
            Paint paint=textView.getPaint();
    
            ArrayList<String> paraList = new ArrayList<String>();        
            paraList = paraBreak(text);        
            for(int i = 0; i<paraList.size(); i++) {            
                ArrayList<String> lineList=lineBreak(paraList.get(i).trim(),paint,contentWidth);            
                tempText = TextUtils.join(" ", lineList).replaceFirst("\s*", "");            
                resultText += tempText.replaceFirst("\s*", "") + "
    ";        
            }                
            
            textView.setText(resultText);
        }
        //分开每个段落
        public static ArrayList<String> paraBreak(String text, TextView textview) {
            ArrayList<String> paraList = new ArrayList<String>();
            String[] paraArray = text.split("\n+");
               for(String para:paraArray) {
                   paraList.add(para);
            }
            return paraList;
        }
    
        //分开每一行,使每一行填入最多的单词数
        private static ArrayList<String> lineBreak(String text, Paint paint, float contentWidth){
            String [] wordArray=text.split("\s"); 
            ArrayList<String> lineList = new ArrayList<String>();
            String myText="";
    
            for(String word:wordArray){
                if(paint.measureText(myText+" "+word)<=contentWidth)
                    myText=myText+" "+word;
                else{
                    int totalSpacesToInsert=(int)((contentWidth-paint.measureText(myText))/paint.measureText(" "));
                    lineList.add(justifyLine(myText,totalSpacesToInsert));
                    myText=word;
                }
            }
            lineList.add(myText);
            return lineList;
        }
        //已填入最多单词数的一行,插入对应的空格数直到该行满
        private static String justifyLine(String text,int totalSpacesToInsert){
            String[] wordArray=text.split("\s");
            String toAppend=" ";
    
            while((totalSpacesToInsert)>=(wordArray.length-1)){
                toAppend=toAppend+" ";
                totalSpacesToInsert=totalSpacesToInsert-(wordArray.length-1);
            }
            int i=0;
            String justifiedText="";
            for(String word:wordArray){
                if(i<totalSpacesToInsert)
                    justifiedText=justifiedText+word+" "+toAppend;
    
                else                
                    justifiedText=justifiedText+word+toAppend;
    
                i++;
            }
    
            return justifiedText;
        }
        
    
    
    }

    这个类完成了TextView内部文字的排版工作,主要分3个步骤:
    1、将一篇文章按段落分成若干段(如果只有一段可以略去该步骤);

    2、将每一段的文字拆分成各个单词,然后根据控件长度确定每一行最多可以填入的单词数,并且算出排满该行还需要填入几个空格。

    3、填入空格。

    注意代码中用到了一些正则表达式进行文章内容操作,若不清楚可以自行搜索含义。

    这样就完成了TextView内部文字分散对齐的排版过程。总结一下,这样操作还是有点蛋疼的,虽然不算复杂,但还是对文本内容进行了完全的重新处理;并且仅是使用了已有的文本和空格数来实现对齐,并不是严格的分散对齐。但不管怎么说,终究是用TextView自身的操作来实现了,并且效果还算不错。

  • 相关阅读:
    Qt对文件的删除、复制、移动、可执行文件位置
    qt关于窗口关闭触发函数/信号
    QString.toUtf8().data()的问题 & char *转换到QByteArray注意
    Qt中类型之间的转换
    C++中auto和decltype的区别和功能
    Delphi 系统[11]关键字和保留字 goto、label
    Delphi 系统[10]关键字和保留字 with
    Delphi 系统[9]关键字和保留字 for、to、downto、do、while、repeat、until
    Delphi 系统[8]关键字和保留字 if、then、else、case
    Delphi 系统[7]关键字和保留字 begin、end
  • 原文地址:https://www.cnblogs.com/lcyty/p/3265335.html
Copyright © 2011-2022 走看看