本文转载于: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. C语言中输入输出函数

    1.1.1 格式化输入输出函数Turbo C2.0 标准库提供了两个控制台格式化输入. 输出函数printf() 和scanf(), 这两个函数可以在标准输入输出设备上以各种不同的格式读写数据.pri ...

  2. shell指令expr和test指令

    通过expr指令可以进行+.-.*.\.%等运算,但是有一点值得注意,使用乘法时,要在*前加上一个\符号. 通过test指令可以进行逻辑测试,进行测试的情况有四种: 1.整数测试 a.判断两个整数是否 ...

  3. SharePoint 2013 开发——获取用户配置文件属性内容(User Profile)

    博客地址:http://blog.csdn.net/FoxDave 本篇我们应用SharePoint CSOM(.NET)来读取用户配置文件的信息,个人开始逐渐倾向于客户端模型,因为不用远程登录到 ...

  4. hdu2196 树的直径 + bfs

    //Accepted 740 KB 15 ms //树的直径 //距离一个顶点最远的点一定是树的直径的一个端点 #include <cstdio> #include <cstring ...

  5. IIS使用问题

    1.System.Data.SQLite”或它的某一个依赖项.试图加载格式不正确的程序:修改IIS应用程序池的高级设置将32位设置成true

  6. 使用iskindofclass来发现对象是否是某类或其子类的实例

    发现对象是否是特定类或其子类的实例 要发现对象是否是某类或其子类的实例,请在对象上调用 isKindOfClass: 方法.当应用程序需要发现其响应的消息(实现的或继承的),它有时进行以上的检查. s ...

  7. Tips about Object-oriented programming

    1, Return subinterface For example, we have a parent interface: public interface A<T extends A< ...

  8. 升级IOS 9 和 XCode 7 引起的问题

    问题一: 升级xcode 7最低的系统配置要求 升级了ios9 后使用 xcode 6.1 已经不能用了,必须升级 xcode 7才行,原先的系统是OSX 10.10.1 版本.而xcode 7.0 ...

  9. Android Glide加载图片时转换为圆形、圆角、毛玻璃等图片效果

     Android Glide加载图片时转换为圆形.圆角.毛玻璃等图片效果 附录1简单介绍了Android开源的图片加载框架.在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬 ...

  10. [转]<Unity3D>Unity3D的四种坐标系

    http://blog.csdn.net/zuoyamin/article/details/8813424 World Space(世界坐标):我们在场景中添加物体(如:Cube),他们都是以世界坐标 ...