-
一般情况下Item布局中写法如下
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="80dp"> <TextView android:id="@+id/tv_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="item" /> </android.support.constraint.ConstraintLayout>
-
但是上面的写法在运行之后并不能达到ListView的每个
Item
都是80dp的效果,而是所有的Item
高度自适应了,这是什么原因呢?来看看源码。ListView在layout
的时候会调用一个方法用于获取View,这个方法就是makeAndAddView(...)
,部分源码如下:private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, boolean selected) { ... ... // Make a new view for this position, or convert an unused view if // possible. 获取View final View child = obtainView(position, mIsScrap); // This needs to be positioned and measured. setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]); return child; }
-
可以看到
makeAndAddView
中调用了obtainView
方法,这个方法是ListView父类AbsListView
中的方法,部分源码如下:View obtainView(int position, boolean[] outMetadata) { ... ... ... //设置Item的LayoutParams setItemViewLayoutParams(child, position); if (AccessibilityManager.getInstance(mContext).isEnabled()) { if (mAccessibilityDelegate == null) { mAccessibilityDelegate = new ListItemAccessibilityDelegate(); } if (child.getAccessibilityDelegate() == null) { child.setAccessibilityDelegate(mAccessibilityDelegate); } } Trace.traceEnd(Trace.TRACE_TAG_VIEW); return child; }
-
再继续看setItemViewLayoutParams方法,源码如下:
private void setItemViewLayoutParams(View child, int position) { //这里的child指的是item,也就是上面xml中的 ...ConstraintLayout 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); } }
-
setItemViewLayoutParams
中的vlp
默认是为null的,所以会进入到第一个if
语句中的generateDefaultLayoutParams
方法,如下://生成一个AbsListView.LayoutParams,宽:MATCH_PARENT,高:WRAP_CONTENT protected ViewGroup.LayoutParams generateDefaultLayoutParams() { return new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0); }
generateDefaultLayoutParams
方法会生成一个宽为MATCH_PARENT
,高为WRAP_CONTENT
的AbsListView.LayoutParams
,所以你在item的xml中设置的高度没有生效,因为ListView默认给每个Item
设置了LayoutParams
-
解决方法
- 在xml里面多嵌套一次布局
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:layout_width="match_parent" android:layout_height="80dp"> <TextView android:id="@+id/tv_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="item" /> </RelativeLayout> </android.support.constraint.ConstraintLayout>
- 或者在Adapter中的getView方法里面手动给convertView设置一个AbsListView.LayoutParams
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (null == convertView) { holder = new ViewHolder(); convertView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_demo1, null, false); //设置convertView的LayoutParams convertView.setLayoutParams(new AbsListView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 300) ); holder.textView = convertView.findViewById(R.id.tv_item); convertView.setTag(holder); System.out.println(convertView.getLayoutParams() == null); } else { holder = (ViewHolder) convertView.getTag(); } holder.textView.setText(list.get(position).getDesc()); return convertView; }
ListView中Item高度问题
?著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 一、适用场景 ListViewListview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用...
- 在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自...