自定义TextView,解决文字换行,\n换行符换行,导致高度计算不对问题(计算ListView高度)
2016-11-15 10:22
1036 查看
刚遇到一个问题,如题,我有2个ListView嵌套,所以需要计算嵌套中的ListView高度,然后就发现,TextView 中的文字换行会导致高度计算有误,只算到一行,So,上网查解决方法,找到的方法都是一个
基本找到所有资料都是以上的代码,并不知道原作者到底是谁,自定义TextView计算高度,但是我用了之后发现有几个问题
一、当TextView没有占据一行时,显示会不全,也就是TextView左边或者右边还有控件占据了宽度,那么就会有部分数据不显示
二、没有考虑文本中含有\n换行符,计算行数有误
三、没有计算TextView本身的Padding
四、获取屏幕密度方式有误,使用以下方法强转是有风险的,且方法已经过时
解决办法就是当你的TextView旁边还有其他控件占据宽度时,把TextView的宽度定死,或使用weight,是TextView与其他View按比例分配宽度。
修改后的版本
如果有更好的解决办法,或代码中有忽略的问题,bug请留言。
另,可能有人会问RelativeLayout怎么办,我想说,计算ListView高度如果有RelativeLayout,那么是计算不了的,估计只能再次重写RelativeLayout…
public class myTextView extends TextView { private Context context; public myTextView(Context context) { super(context); // TODO Auto-generated constructor stub this.context = context; } public myTextView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub this.context = context; } public myTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub this.context = context; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Layout layout = getLayout(); if (layout != null) { int height = (int)FloatMath.ceil(getMaxLineHeight(this.getText().toString())) + getCompoundPaddingTop() + getCompoundPaddingBottom(); int width = getMeasuredWidth(); setMeasuredDimension(width, height); } } private float getMaxLineHeight(String str) { float height = 0.0f; float screenW = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth(); float paddingLeft = ((LinearLayout)this.getParent()).getPaddingLeft(); float paddingReft = ((LinearLayout)this.getParent()).getPaddingRight(); //这里具体this.getPaint()要注意使用,要看你的TextView在什么位置,这个是拿TextView父控件的Padding的,为了更准确的算出换行 int line = (int) Math.ceil( (this.getPaint().measureText(str)/(screenW-paddingLeft-paddingReft))); height = (this.getPaint().getFontMetrics().descent-this.getPaint().getFontMetrics().ascent)*line; return height;} }
基本找到所有资料都是以上的代码,并不知道原作者到底是谁,自定义TextView计算高度,但是我用了之后发现有几个问题
一、当TextView没有占据一行时,显示会不全,也就是TextView左边或者右边还有控件占据了宽度,那么就会有部分数据不显示
二、没有考虑文本中含有\n换行符,计算行数有误
三、没有计算TextView本身的Padding
四、获取屏幕密度方式有误,使用以下方法强转是有风险的,且方法已经过时
float screenW = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth(); float paddingLeft =
解决办法就是当你的TextView旁边还有其他控件占据宽度时,把TextView的宽度定死,或使用weight,是TextView与其他View按比例分配宽度。
修改后的版本
public class MTextView extends TextView { private Context context; public MTextView(Context context) { super(context); // TODO Auto-generated constructor stub this.context = context; } public MTextView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub this.context = context; } public MTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub this.context = context; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int mode = MeasureSpec.getMode(heightMeasureSpec); Layout layout = getLayout(); if (layout != null) { int height = (int) Math.ceil(getMaxLineHeight(this.getText().toString(), mode)) + getCompoundPaddingTop() + getCompoundPaddingBottom(); int width = getMeasuredWidth(); setMeasuredDimension(width, height); } } private float getMaxLineHeight(String str, int mode) { float height = 0.0f; float width = getMeasuredWidth(); float widthPixels = context.getResources().getDisplayMetrics().widthPixels; //这里具体this.getPaint()要注意使用,要看你的TextView在什么位置, // 这个是拿TextView父控件的Padding的,为了更准确的算出换行 float pLeft = ((LinearLayout) getParent()).getPaddingLeft(); float pRight = ((LinearLayout) getParent()).getPaddingRight(); //检测字符串中是否包含换行符,获得换行的次数,在之后计算高度时加上 int br = 0; if (str.contains("\n")) br = str.split("\n").length - 1; /** * wrap_content/未指定宽度(MeasureSpec.UNSPECIFIED),则用屏幕宽度计算 * 否则就使用View自身宽度计算,并且无需计算Parent的Padding */ int line; if (mode == MeasureSpec.UNSPECIFIED) line = (int) Math.ceil((this.getPaint().measureText(str) / (widthPixels - getPaddingLeft() - pLeft - pRight - getPadd 9cf9 ingRight()))); else { line = (int) Math.ceil((this.getPaint().measureText(str) / (width - getPaddingLeft() - getPaddingRight()))); } height = (this.getPaint().getFontMetrics().descent - this.getPaint().getFontMetrics().ascent) * (line + br); return height; } }
如果有更好的解决办法,或代码中有忽略的问题,bug请留言。
另,可能有人会问RelativeLayout怎么办,我想说,计算ListView高度如果有RelativeLayout,那么是计算不了的,估计只能再次重写RelativeLayout…
相关文章推荐
- 通过自定义TextView,拉伸每行解决自动换行文字排版参差不齐问题
- 自定义View控件解决android文字排版和换行的问题
- Android自定义TextView根据控件高度和宽度,解决字体适配问题
- 解决listview中的textview设置了setMovementMethod导致onItemclick无效的问题
- Android TextView中图文混排设置行间距导致高度不一致问题解决
- 解决ListView里TextView设置LinkMovementMethod后导致其ItemClick失效的问题
- ScrollView与ListView合用(TextView多行显示时计算不正确)的问题解决
- 自定义TextView解决超长文字显示的问题
- android自定义View画文字的换行问题的解决
- 自定义View控件解决android文字排版和换行的问题
- 解决TextView排版自动换行问题
- TextView 来对文字在listview中的问题
- 自定义viewgroup实现自动换行的布局,同时解决自定义布局在wrapcontent下高度不能自适应的问题,plus一些关于Component重写的基础知识
- android中画文字的换行 办法(对于遇到canvas.drawText(String s )无法实现换行问题的解决)
- 自定义TextView,解决布局乱的问题
- 解决TextView在中文和标点存在情况下一行没显示满就换行问题
- android中画文字的换行 办法(对于遇到canvas.drawText(String s )无法实现换行问题的解决)
- 解决 ListView的Item里TextView设置超链接后ListView 的OnItemClick失效的问题
- android textView设置html,解决图片和文字不对齐的问题
- android 自定义TextView支持微博功能后在ListView占用了Item点击的解决办法