本文转载于:http://niufc.iteye.com/blog/1729792

ndroid的TextView在显示文字的时候有个问题就是一行还没显示满就跳到下一行,原因是:

1) TextView在显示中文的时候 标点符号不能显示在一行的行首和行尾,如果一个标点符号刚好在一行的行尾,该标点符号就会连同前一个字符跳到下一行显示;

2)一个英文单词不能被显示在两行中( TextView在显示英文时,标点符号是可以放在行尾的,但英文单词也不能分开 );

如果只是想让标点符号可以显示在行尾,有一个简单的方法就是在标点符号后加一个空格,则该标点符号就可以显示在行尾了;

如果想要两端对齐的显示效果,有两种方法:

1)修改Android源代码;将frameworks/base/core/java/android/text下的StaticLayout.java文件中的如下代码:

if (c == ' ' || c == '/t' ||

                            ((c == '.'  || c == ',' || c == ':' || c == ';') &&

                             (j - 1 < here || !Character.isDigit(chs[j - 1 - start])) &&

                             (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||

                            ((c == '/' || c == '-') &&

                             (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||

                            (c >= FIRST_CJK && isIdeographic(c, true) &&

                             j + 1 < next && isIdeographic(chs[j + 1 - start], false))) {

                            okwidth = w;

                            ok = j + 1;



                            if (fittop < oktop)

                                oktop = fittop;

                            if (fitascent < okascent)

                                okascent = fitascent;

                            if (fitdescent > okdescent)

                                okdescent = fitdescent;

                            if (fitbottom > okbottom)

                                okbottom = fitbottom;

                        }

去掉就可以了。去掉后标点符号可以显示在行首和行尾,英文单词也可以被分开在两行中显示。

但是我师傅说修改框架不美气,会影响其它应用程序,www.linuxidc.com 最好是能在应用层面解决问题。 所以就有了方法2;

2)自定义View显示文本

网上就有达人采用自定义View来解决这个问题,我做了实验并总结了一下:

自定义View的步骤:

1)继承View类或其子类,例子继承了TextView类;

2)写构造函数,通过XML获取属性(这一步中可以自定义属性,见例程);

3)重写父类的某些函数,一般都是以on开头的函数,例子中重写了onDraw()和onMeasure()函数;

=========================CYTextView.java=============================

public class CYTextView extends TextView {

    public  static  int m_iTextHeight; //文本的高度

    public  static  int m_iTextWidth;//文本的宽度

    

    private Paint mPaint = null;

    private String string="";

    private float LineSpace = 0;//行间距

        

    public CYTextView(Context context, AttributeSet set) 

    {       

        super(context,set);  



        TypedArray typedArray = context.obtainStyledAttributes(set, R.styleable.CYTextView);



        int width = typedArray.getInt(R.styleable. CY TextView_textwidth, 320);

        float textsize = typedArray.getDimension(R.styleable. CY TextView_textSize, 24);

        int textcolor = typedArray.getColor(R.styleable. CY TextView_textColor, -1442840576);

        float linespace = typedArray.getDimension(R.styleable. CY TextView_lineSpacingExtra, 15);

        int typeface = typedArray.getColor(R.styleable. CY TextView_typeface, 0);

        

        typedArray.recycle();

        

        //设置 CY TextView的宽度和行间距www.linuxidc.com

        m_iTextWidth=width;

        LineSpace=linespace;

        

        // 构建paint对象      

        mPaint = new Paint();

        mPaint.setAntiAlias(true);

        mPaint.setColor(textcolor);

        mPaint.setTextSize(textsize);

        switch(typeface){

        case 0:

            mPaint.setTypeface(Typeface.DEFAULT);

            break;

        case 1:

            mPaint.setTypeface(Typeface.SANS_SERIF);

            break;

        case 2:

            mPaint.setTypeface(Typeface.SERIF);

            break;

        case 3:

            mPaint.setTypeface(Typeface.MONOSPACE);

            break;

        default:

            mPaint.setTypeface(Typeface.DEFAULT);    

            break;

        }

        

    }

  

    @Override

    protected void onDraw(Canvas canvas) 

    {  

       super.onDraw(canvas);       

        

        char ch;

        int w = 0;

        int istart = 0;

        int m_iFontHeight;

        int m_iRealLine=0;

        int x=2;

        int y=30;

        

        Vector    m_String=new Vector();

        

        FontMetrics fm = mPaint.getFontMetrics();        

        m_iFontHeight = (int) Math.ceil(fm.descent - fm.top) + (int)LineSpace;//计算字体高度(字体高度+行间距)



        for (int i = 0; i < string.length(); i++)

        {

            ch = string.charAt(i);

            float[] widths = new float[1];

            String srt = String.valueOf(ch);

            mPaint.getTextWidths(srt, widths);



            if (ch == '/n'){

                m_iRealLine++;

                m_String.addElement(string.substring(istart, i));

                istart = i + 1;

                w = 0;

            }else{

                w += (int) (Math.ceil(widths[0]));

                if (w > m_iTextWidth){

                    m_iRealLine++;

                    m_String.addElement(string.substring(istart, i));

                    istart = i;

                    i--;

                    w = 0;

                }else{

                    if (i == (string.length() - 1)){

                        m_iRealLine++;

                        m_String.addElement(string.substring(istart, string.length()));

                    }

                }

            }

        }

        m_iTextHeight=m_iRealLine*m_iFontHeight+2;

        canvas.setViewport(m_iTextWidth, m_iTextWidth);

        for (int i = 0, j = 0; i < m_iRealLine; i++, j++)

        {

            canvas.drawText((String)(m_String.elementAt(i)), x,  y+m_iFontHeight * j, mPaint);

        }

    }  

   

    

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 

    {          

        int measuredHeight = measureHeight(heightMeasureSpec);          

        int measuredWidth = measureWidth(widthMeasureSpec);           

        this.setMeasuredDimension(measuredWidth, measuredHeight);

        this.setLayoutParams(new LinearLayout.LayoutParams(measuredWidth,measuredHeight));

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }  

                 

    private int measureHeight(int measureSpec) 

    {  

        int specMode = MeasureSpec.getMode(measureSpec);          

        int specSize = MeasureSpec.getSize(measureSpec);                   

        // Default size if no limits are specified.  

        initHeight();

        int result = m_iTextHeight;          

        if (specMode == MeasureSpec.AT_MOST){         

            // Calculate the ideal size of your          

            // control within this maximum size.          

            // If your control fills the available           

            // space return the outer bound.          

            result = specSize;           

        }else if (specMode == MeasureSpec.EXACTLY){           

            // If your control can fit within these bounds return that value.            

            result = specSize;           

        }           

        return result;            

    }  

    

    private void initHeight()

    {

        //设置 CY TextView的初始高度为0

        m_iTextHeight=0;

        

        //大概计算 CY TextView所需高度

        FontMetrics fm = mPaint.getFontMetrics();        

        int m_iFontHeight = (int) Math.ceil(fm.descent - fm.top) + (int)LineSpace;

        int line=0;

        int istart=0;

        

        int w=0;

        for (int i = 0; i < string.length(); i++)

        {

            char ch = string.charAt(i);

            float[] widths = new float[1];

            String srt = String.valueOf(ch);

            mPaint.getTextWidths(srt, widths);



            if (ch == '/n'){

                line++;

                istart = i + 1;

                w = 0;

            }else{

                w += (int) (Math.ceil(widths[0]));

                if (w > m_iTextWidth){

                    line++;

                    istart = i;

                    i--;

                    w = 0;

                }else{

                    if (i == (string.length() - 1)){

                        line++;

                    }

                }

            }

        }

        m_iTextHeight=(line)*m_iFontHeight+2;

    }

                 

    private int measureWidth(int measureSpec) 

    {  

        int specMode = MeasureSpec.getMode(measureSpec);           

        int specSize = MeasureSpec.getSize(measureSpec);             

          

        // Default size if no limits are specified.          

        int result = 500;          

        if (specMode == MeasureSpec.AT_MOST){          

            // Calculate the ideal size of your control           

            // within this maximum size.         

            // If your control fills the available space         

            // return the outer bound.         

            result = specSize;          

        }else if (specMode == MeasureSpec.EXACTLY){           

            // If your control can fit within these bounds return that value.           

            result = specSize;            

        }           

        return result;          

    }

    

    public void SetText(String text)(注:此函数目前只有在UI线程中调用才可以把文本画出来,在其它线程中

无法画文本,找了好久找不到原因,求高手解答) 

    {

        string = text;

       // requestLayout();

       // invalidate();

    }   

}

该文件是自定义的属性,放在工程的res/values下

<resources>

    <attr name="textwidth" format="integer"/>

    <attr name="typeface">

        <enum name="normal" value="0"/>

        <enum name="sans" value="1"/>

        <enum name="serif" value="2"/>

        <enum name="monospace" value="3"/>

    </attr>



    <declare-styleable name="CYTextView">    

        <attr name="textwidth" />        

        <attr name="textSize" format="dimension"/>

        <attr name="textColor" format="reference|color"/>

        <attr name="lineSpacingExtra" format="dimension"/>

        <attr name="typeface" />

        </declare-styleable>

</resources>

=======================main.xml==========================

<?xml version="1.0" encoding="utf-8"?>

<ScrollView

        xmlns:Android="http://schemas.android.com/apk/res/android"

        Android:layout_width="320px"

        Android:layout_height="320px"

        Android:background="#ffffffff"

        >

  <LinearLayout 

        xmlns:Android="http://schemas.android.com/apk/res/android"

        Android:orientation="vertical"

        Android:layout_width="fill_parent"

        Android:layout_height="fill_parent">

    <com.cy.CYTextView.CYTextView 

        xmlns:cy="http://schemas.Android.com/apk/res/ com.cy.CYTextView "

        Android:id="@+id/mv"

        Android:layout_height="wrap_content"

        Android:layout_width="wrap_content" 

        cy :textwidth="320"        

        cy :textSize="24sp"

        cy :textColor="#aa000000"

        cy :lineSpacingExtra="15sp"

        cy :typeface="serif">

    </com. cy .CYTextView.CYTextView>    

  </LinearLayout>

</ScrollView>

蓝色代码即为自定义View,其中以cy命名空间开头的属性是自定义属性;

=======================Main.java=============================

public class Main extends Activity {

    CYTextView mCYTextView;

    String text = "Android提供了精巧和有力的组件化模型构建用户的UI部分。主要是基于布局类:View和        ViewGroup。在此基础上,android平台提供了大量的预制的View和xxxViewGroup子
类,即布局(layout)和窗口小部件(widget)。可以用它们构建自己的UI。";

    

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        this.setContentView(R.layout.main);

        

        mCYTextView = (CYTextView)findViewById(R.id.mv);

        mCYTextView.SetText(text);

    }



}

运行结果如下:

Android TextView换行问题的更多相关文章

  1. Android TextView 添加下划线的几种方式

    总结起来大概有5种做法:  1. 将要处理的文字写到一个资源文件,如string.xml(使用html用法格式化)   2. 当文字中出现URL.E-mail.电话号码等的时候,可以将TextView ...

  2. Android TextView图文混合编排

    Android TextView图文混合编排 实现技术细节不难,两个要点:1.html代码的混合编写.2,重写ImageGetter.例如:布局: <?xml version="1.0 ...

  3. Android:TextView 自动滚动(跑马灯) (转)

    Android:TextView 自动滚动(跑马灯)       TextView实现文字滚动需要以下几个要点: 1.文字长度长于可显示范围:android:singleLine="true ...

  4. android Textview动态设置大小

    import android.app.Activity; //import com.travelzen.tdx.BaseActivity; //import com.travelzen.tdx.uti ...

  5. Android TextView内容过长加省略号,点击显示全部内容

    在Android TextView中有个内容过长加省略号的属性,即ellipsize,用法如下: 在xml中:android:ellipsize="end"    省略号在结尾an ...

  6. android TextView多行文本(超过3行)使用ellipsize属性无效问题的解决方法

    这篇文章介绍了android TextView多行文本(超过3行)使用ellipsize属性无效问题的解决方法,有需要的朋友可以参考一下 布局文件中的TextView属性 复制代码代码如下: < ...

  7. Android - TextView Ellipsize属性

    Android - TextView Ellipsize属性 本文地址: http://blog.csdn.net/caroline_wendy android:ellipsize属性: If set ...

  8. Android TextView中有图片有文字混合排列

    Android TextView中有图片有文字混合排列 1.使用html.fromHtml 2.新建ImageGetter 3.使用<img src>标签 demo: 1.设置文字 ((T ...

  9. Android TextView背景颜色与背景图片设置

    Android TextView 背景颜色与背景图片设置,android textview 控件,android textview 背景, android textview 图片,android te ...

随机推荐

  1. Oracle GoldenGate 12c (12.1.2.0.1) for IBM DB2 iSeries

    OGG 12.1.2.0.1 for iSeries 在2014.2.15发布,主要新增如下功能: 本地交付(Native Delivery Replicat):新功能允许用户在IBM i服务器上安装 ...

  2. 《day16_多线程细节_Eclipse使用》

    多线程的一些细节: 1,面试题:sleep方法和wait方法异同点是什么? 相同点:可以让线程处于冻结状态. 不同点: 1, sleep必须指定时间. wait可以指定时间,也可以不指定时间. 2, ...

  3. Jquery中的prop()方法 全选或全不选

    注意: prop()在高版本才会有效, 低版本用attr(); $(function(){ // 元素checkbox var aChecked = $('.checkGoods'); // 全选 v ...

  4. 转载--Ubuntu设置环境变量

    Ubuntu设置环境变量并立即生效(以Ubuntu12.04为例) 标签: UbuntuLinux环境变量 2013-09-12 19:04 9961人阅读 评论(1) 收藏 举报  分类: Ubun ...

  5. mysql批量写入

    MySQL批量写入语法是: INSERT INTO table (field1,field2,field3) VALUES (“a”,”b”,”c”), (“a1”,”b1”,”c1”),(“a2”, ...

  6. golang函数调用计时

    package main import ( "log" "time" ) func f() { defer timeoutCheck("f slow& ...

  7. C#操作txt问件,进行清空添加操作

    //把txt清空 FileStream stream = File.Open(Adr,FileMode.OpenOrCreate,FileAccess.Write); stream.Seek(, Se ...

  8. Fractal Tree扩展

    之前的博客实现了最基础的分形树,在这个基础上略微调整一些参数可以得到很多有趣的由分形树发展出的图案. private void drawShape(Graphics g, double x1, dou ...

  9. 考古备份:a.out文件ELF文件头中魔数的由来

    来源: <程序员的自我修养>3.4节. 补充: http://wiki.osdev.org/ELF http://www.linux-mag.com/id/116/ http://en.w ...

  10. socket.io 入门教程

    转载自:http://deadhorse.me/nodejs/2011/12/29/socket.io_induction.html socket.io socket.io是一个以实现跨浏览器.跨平台 ...