【Android】兼容Scrollview的可動態設置高度Listview

常用 Scrollview嵌套Listview寫法如下:

public class NoScrollListView extends ListView {
	
	/**
	 * 構造
	 */
	public NoScrollListView(Context context) {
		super(context);
	}
	
	/**
	 * 構造
	 */
	public NoScrollListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	/**
	 * 構造
	 */
	public NoScrollListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	/**
	 * makeMeasureSpec第一個參數size給出父佈局能容納的最大高度,這裏取約定俗成的無限大一半,
	 * 第二個參數mode取wrap_content,包裹自己item數目。
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
		super.onMeasure(widthMeasureSpec, expandSpec);
	}

}

現在有一個需求,是要在Scrollview嵌套之下的Listview,可摺疊item數目(默認顯示2個item,展開顯示全部),固不可採用上面的高度寫死方法,採用如下寫法:

/**
 * Created by Luzj on 2018/8/16.
 *
 * 禁止滑動的Listview,可動態設置寬高
 */
public class ScrollDisabledListView extends ListView {
    private int mPosition;

    public ScrollDisabledListView(Context context) {
        super(context);
    }

    public ScrollDisabledListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollDisabledListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;

        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // 記錄手指按下時的item
            mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
            return super.dispatchTouchEvent(ev);
        }

        if (actionMasked == MotionEvent.ACTION_MOVE) {
            // 最關鍵的地方,忽略MOVE 事件
            // ListView onTouch獲取不到MOVE事件所以不會發生滾動處理
            return true;
        }

        // 手指擡起時
        if (actionMasked == MotionEvent.ACTION_UP
                || actionMasked == MotionEvent.ACTION_CANCEL) {
            // 手指按下與擡起都在同一個視圖內,交給父控件處理,這是一個點擊事件
            if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {
                super.dispatchTouchEvent(ev);
            } else {
                // 如果手指已經移出按下時的Item,說明是滾動行爲,清理Item pressed狀態
                setPressed(false);
                invalidate();
                return true;
            }
        }

        return super.dispatchTouchEvent(ev);
    }
}

另外,給出摺疊listview寫法:

/**
     * 自繪高度兼容scrollview下的歷史記錄listview
     * @param isExpand 是否要摺疊,true顯示全部,false摺疊成2個item
     * 注意,listview的item根佈局高度必須是wrap_content
     * 原因是listview的item高度要在xml裏面起效,都必須套一層wrap的父佈局
     */
    private void changeHisListViewHeight(boolean isExpand) {
        int itemNum;
        if(isExpand || mCommunityData.size() < 2) {//小於兩個情況下不折疊
            itemNum = mAdapter.getCount();
        } else {
            itemNum = 2;
        }
        View listItem = mAdapter.getView(0, null, historyList);
        listItem.measure(0, 0);
        int itemHeight = listItem.getMeasuredHeight();
        int totalHeight = itemHeight * (itemNum);
        totalHeight += (historyList.getDividerHeight() * (itemNum - 1))
                + historyList.getPaddingTop() + historyList.getPaddingBottom();
        ViewGroup.LayoutParams params = historyList.getLayoutParams();
        params.height = totalHeight;
        historyList.setLayoutParams(params);
        mAdapter.notifyDataSetChanged();
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章