ListView的Item根布局layout_margin无效分析

listView每个item之间的边距设置 ,一开始的想法是在item 的根布局设置margin 属性,但是在listView 中margin无法生效,padding是有效的,所以在此研究下失效的原因。
解决办法就是在根布局中再加一层布局, 新增根布局的下一次布局设置margin. 如果可以给根布局设置padding解决问题的话,设置padding也可


解决方法

第一种,设置padding

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_margin="30dp"  //设置无效
    android:padding="30dp"   //设置有效
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/list_item_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

第二种 增加一层布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

   //根布局下增加一层
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="30dp"
        >

    <TextView
        android:id="@+id/list_item_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    </RelativeLayout>

</LinearLayout>

问题分析

对于这个问题的分析是参考博客 https://blog.csdn.net/android_freshman/article/details/52077323

layout_margin根布局失效原因:

ListView extends AbsListView
查看 AbsListView 如何加入布局参数的

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);
        }
    }

ViewGroup中有一个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;
        }
    }

猜你喜欢

转载自blog.csdn.net/ysq_chris/article/details/80775212