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

来源:互联网 发布:淘宝会员等级v6 编辑:程序博客网 时间:2024/06/01 21:41

刚遇到一个问题,如题,我有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 - getPaddingRight())));        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…

0 0
原创粉丝点击