首页 > 代码库 > Android转载五:TextView换行问题

Android转载五:TextView换行问题

Android的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;} 

 

 

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

 

2)自定义View显示文本

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

自定义View的步骤:

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

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

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

=========================StartCustomTextView.java=============================

public class StartCustomTextView extends TextView {    public  static  int m_iTextHeight; //文本的高度    public  static  int m_iTextWidth;//文本的宽度        private Paint mPaint = null;    private String string="";    private float LineSpace = 0;//行间距    private int left_Margin;    private int right_Margin;    private int bottom_Margin;            public StartCustomTextView(Context context, AttributeSet set)     {               super(context,set);          DisplayMetrics displayMetrics = getResources().getDisplayMetrics();        TypedArray typedArray = context.obtainStyledAttributes(set, R.styleable.CYTextView);        int width = displayMetrics.widthPixels;        left_Margin = 29;        right_Margin = 29;        bottom_Margin = 29;        width = width - left_Margin -right_Margin;        float textsize = typedArray.getDimension(R.styleable.CYTextView_textSize, 34);        int textcolor = typedArray.getColor(R.styleable.CYTextView_textColor, getResources().getColor(R.color.white));        float linespace = typedArray.getDimension(R.styleable.CYTextView_lineSpacingExtra, 15);        int typeface = typedArray.getColor(R.styleable.CYTextView_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);        LayoutParams layout = new LinearLayout.LayoutParams(measuredWidth,measuredHeight);        layout.leftMargin= left_Margin;        layout.rightMargin= right_Margin;        layout.bottomMargin= bottom_Margin;        this.setLayoutParams(layout);        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)    {        string = text;       // requestLayout();       // invalidate();    }   } 

 

 

=======================attrs.xml===============================

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

<resources><attr name="textwidth" format="integer"/><attr name="typeface"><enum name="normal" value="http://www.mamicode.com/0"/><enum name="sans" value="http://www.mamicode.com/1"/><enum name="serif" value="http://www.mamicode.com/2"/><enum name="monospace" value="http://www.mamicode.com/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"?><ScrollViewxmlns: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. */@Overridepublic void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        this.setContentView(R.layout.main);        mCYTextView = (CYTextView)findViewById(R.id.mv);        mCYTextView.SetText(text);    }}                     

转自:http://hi.baidu.com/java_rose/blog/item/2940a030d1ec7f3e96ddd847.html

Android转载五:TextView换行问题