textview是否超过一行_Android TextView 自动换行,每行排满的问题

编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识、前端、后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过!

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

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

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19if (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=============================

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208public 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.jcodecraeer.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下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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

Android:layout_width="320px"

Android:layout_height="320px"

Android:background="#ffffffff"

>

Android:orientation="vertical"

Android:layout_width="fill_parent"

Android:layout_height="fill_parent">

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">

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

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

1

2

3

4

5

6

7

8

9

10

11

12public 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);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值