动态计算ListView高度,item中TextView换行高度

2019-03-19  本文已影响0人  xixi哈哈笑笑

前言

很多时候因业务需要,必须在ScrollView中嵌套ListViewRecyclerView的item中包含ListViewListView的item中包含高度不定的TextView。那么这时候就需要动态的计算ListViewTextView的高度。

如下图:RecyclerView的item中包含ListView,ListView的item又有换行的TextView



具体实现代码如下:

一、动态计算ListView高度

public static int setListViewHeightBasedOnChildren(ListView listView) {
        // 获取ListView对应的Adapter
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            return 0;
        }
        int totalHeight = 0;
        for (int i = 0, len = listAdapter.getCount(); i < len; i++) {
            // listAdapter.getCount()返回数据项的数目
            View listItem = listAdapter.getView(i, null, listView);
            // 计算子项View 的宽高
            listItem.measure(0, 0);
            // 统计所有子项的总高度
            totalHeight += listItem.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        // listView.getDividerHeight()获取子项间分隔符占用的高度
        // params.height最后得到整个ListView完整显示需要的高度
        listView.setLayoutParams(params);
        return params.height;
}

二、动态计算换行TextView高度

public class MTextView extends TextView {

    private Context context;

    public MTextView(Context context) {
        super(context);
        this.context = context;
    }

    public MTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public MTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        Layout layout = getLayout();
        if (layout != null) {
            int height = (int) Math.ceil(getMaxLineHeight(ToDBC(this.getText().toString()), mode))
                    + getCompoundPaddingTop() + getCompoundPaddingBottom();
            int width = getMeasuredWidth();
            setMeasuredDimension(DisplayUtil.px2px(context, width), DisplayUtil.px2px(context, 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;
        float pRight;
        try {
            pLeft = ((LinearLayout) getParent()).getPaddingLeft();
            pRight = ((LinearLayout) getParent()).getPaddingRight();
        } catch (Exception e) {
            pLeft = 0;
            pRight = 0;
        }
        //检测字符串中是否包含换行符,获得换行的次数,在之后计算高度时加上
        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;
    }

    public static String ToDBC(String input) {
        char c[] = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] == '\u3000') { //空格
                c[i] = ' ';
            } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {//半角与全角相差 65248
                c[i] = (char) (c[i] - 65248);

            }
        }
        return new String(c);
    }
}
<com.lin.widget.MTextView
    android:layout_width="276dp"
    android:layout_height="wrap_content"
    android:text="TextView" />
上一篇 下一篇

猜你喜欢

热点阅读