您的位置:首页 > 其它

自定义TextView,解决文字换行,\n换行符换行,导致高度计算不对问题(计算ListView高度)

2016-11-15 10:22 1036 查看
刚遇到一个问题,如题,我有2个ListView嵌套,所以需要计算嵌套中的ListView高度,然后就发现,TextView 中的文字换行会导致高度计算有误,只算到一行,So,上网查解决方法,找到的方法都是一个

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…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐