Listview 設置Item之間間隔不起作用的原因,以及解決方案

最近根據設計圖寫listView 的時候,listView個item 之間存在間距,左右上下都有,一開始的想法是在item 的根佈局 設置margin 屬性,但是在listView 中margin 無法生效,所以在此研究下失效的原因。而解決辦法就是在加一層佈局,作爲根佈局 設置padding ,或者 新增根佈局的下一次佈局設置margin.

爲什麼設置margin不起作用呢?

這是我看到的一段解釋, 
The fact is that, the margin of LinearLayout (child) asks its parent layout (container) to give child layout a margin of x value.

So if the parent layouts’ LayoutParams support the margins then that margin is honored and applied.

ListView uses AbsListView.LayoutParams by default, which doesn’t include any margin support, just the height and width, thats why, it simply ignores the params value for margins.


ListView extends AbsListView 查看 AbsListView 如何加入佈局參數的

  1.  

private void setItemViewLayoutParams(View child, int position) {
        final ViewGroup.LayoutParams vlp = child.getLayoutParams(); //直接使用子佈局的佈局參數
        LayoutParams lp;
        if (vlp == null) {
            lp = (LayoutParams) generateDefaultLayoutParams();
        } else if (!checkLayoutParams(vlp)) {
            lp = (LayoutParams) generateLayoutParams(vlp);
        } else {
            lp = (LayoutParams) vlp;
        }

        if (mAdapterHasStableIds) {
            lp.itemId = mAdapter.getItemId(position);
        }
        lp.viewType = mAdapter.getItemViewType(position);
        lp.isEnabled = mAdapter.isEnabled(position);
        if (lp != vlp) {
          child.setLayoutParams(lp);
        }
    }

有一個MarginLayoutParams,ViewGroup中的margin參數有這個類計算

在ViewGroup有一個測量子類Margin的方法measureChildWithMargins

protected void measureChildWithMargins(View child,
            int parentWidthMeasureSpec, int widthUsed,
            int parentHeightMeasureSpec, int heightUsed) {
        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); 
        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                        + widthUsed, lp.width); //---------獲取margin參數-----------
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
                        + heightUsed, lp.height);
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

在ListView的父類AbsListView中沒有實現這個類,不會計算子控件的Margin.所以在ListView的ItemView設置Margin是無效的。

 

padding有效的原因

下面是AblistView的onMeasure , 裏面對selection的padding邊距進行了處理。

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mSelector == null) {
            useDefaultSelector();
        }
        final Rect listPadding = mListPadding;
        listPadding.left = mSelectionLeftPadding + mPaddingLeft;
        listPadding.top = mSelectionTopPadding + mPaddingTop;
        listPadding.right = mSelectionRightPadding + mPaddingRight;
        listPadding.bottom = mSelectionBottomPadding + mPaddingBottom;

        // Check if our previous measured size was at a point where we should scroll later.
        if (mTranscriptMode == TRANSCRIPT_MODE_NORMAL) {
            final int childCount = getChildCount();
            final int listBottom = getHeight() - getPaddingBottom();
            final View lastChild = getChildAt(childCount - 1);
            final int lastBottom = lastChild != null ? lastChild.getBottom() : listBottom;
            mForceTranscriptScroll = mFirstPosition + childCount >= mLastHandledItemCount &&
                    lastBottom <= listBottom;
        }
    }

 

 

 

 

 

 


 

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