解决ListView列表setEmptyView无效问题及源码解析

解决ListView列表setEmptyView无效问题及源码解析

2023年7月15日发(作者:)

解决ListView列表setEmptyView⽆效问题及源码解析很多童鞋们认为ListView的setEmptyView设置空界⾯⽆效的。通常在⽹上查了查,然后来按照⽹谁上的做法直接复制粘贴⼀下。效果出来就OK了。⾝为⼀个开发者,我们既要知其然,也要知道其所以然。⽬前我们⼤部分是这样做的:View view; inflater = (this); view =e(_nodata,null); ((ViewGroup)llr_recycleView_ent()).addView(emptyView); lr_recycleView_tyView(emptyView);setEmptyView()其实是AdapterView的⽅法,⽽我们开发中常⽤到的ListView, GridView, ExpandableListView等都是继承于AdapterView的,所以可以直接调⽤这个⽅法。so问题来了。为什么⼀定要加上((ViewGroup)llr_recycleView_ent()).addView(emptyView);这⾏代码呢?请看源码: /** * Sets the view to show if the adapter is empty */ @bleViewMethod public void setEmptyView(View emptyView) { mEmptyView = emptyView; // If not explicitly specified this view is important for accessibility. if (emptyView != null && ortantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { ortantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } final T adapter = getAdapter(); final boolean empty = ((adapter == null) || y()); updateEmptyStatus(empty); }从上⾯可以看出当emptyView部位空时,先通过updateEmptyStatus(empty);进⾏更新当前的View。在setEmptyView⽅法中将传过来的emptyView赋值给全局的mEmptyView。在其他地⽅也可以对其进⾏处理。接下来是看⼀下updateEmptyStatus(empty)的源码:/** * Update the status of the list based on the empty parameter. If empty is true and * we have an empty view, display it. In all the other cases, make sure that the listview * is VISIBLE and that the empty view is GONE (if it's not null). */ private void updateEmptyStatus(boolean empty) { if (isInFilterMode()) { empty = false; } if (empty) { if (mEmptyView != null) { ibility(E); setVisibility(); } else { // If the caller just removed our empty view, make sure the list view is visible setVisibility(E); } // We are now GONE, so pending layouts will not be dispatched. // Force one here to make sure that the state of the list matches // the state of the adapter. if (mDataChanged) {

ut(false, mLeft, mTop, mRight, mBottom);

} } else { if (mEmptyView != null) ibility(); setVisibility(E); } }updateEmptyStatus源码很简单,根据empty这个状态值进⾏设定mEmptyView 是否是显⽰。

如果adapter部位空,则执⾏:if (mEmptyView != null) ibility(); setVisibility(E);为空时的时候: if (mEmptyView != null) { ibility(E); setVisibility(); } else { // If the caller just removed our empty view, make sure the list view is visible setVisibility(E); }源码中仅仅只是对mEmptyView进⾏了隐藏和显⽰。并未对其进⾏说明。这就表明了,

mEmptyView和当前的list或者是GridView及其其他View是同⼀级的关系。同时也说明了为什么需要⽤到((ViewGroup)llr_recycleView_ent()).addView(emptyView); 才能起到效果。这也可能是Android源码时的⼀个不⾜之处。针对于Android上的有些⽼早的⽼司机早就想好了对策。⽐如说PullToRefreshAdapterViewBase就重写了setemptyView⽅法。public final void setEmptyView(View newEmptyView) { FrameLayout refreshableViewWrapper = getRefreshableViewWrapper(); if (null != newEmptyView) { // New view needs to be clickable so that Android recognizes it as a // target for Touch Events ckable(true); ViewParent newEmptyViewParent = ent(); if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) { ((ViewGroup) newEmptyViewParent).removeView(newEmptyView); } // We need to convert any LayoutParams so that it works in our // FrameLayout Params lp = convertEmptyViewLayoutParams(outParams()); if (null != lp) { w(newEmptyView, lp); } else { w(newEmptyView); } } if (mRefreshableView instanceof EmptyViewMethodAccessor) { ((EmptyViewMethodAccessor) mRefreshableView).setEmptyViewInternal(newEmptyView); } else { tyView(newEmptyView); } mEmptyView = newEmptyView; }这既是为什么有些时候不做处理也可以有效果。对EmptyView的封装** * 功能: 列表空界⾯显⽰ * ⽤于listView ,GridView ,RecycleView 的setEmpety⽅法 * @author yuyahao * 备注: 其他童鞋们可对其进⾏拓展 eg: 添加监听,切换布局 */public class EmptyView extends LinearLayout { private TextView tv_no_message; private ImageView iv_empety_mageger; private LinearLayout ll_no_manager; private LinearLayout ll_no_message_root; public EmptyView(Context context) { super(context); init(); // TODO Auto-generated constructor stub } public EmptyView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { // TODO Auto-generated method stub LayoutInflater inflater = (getContext()); View view = e(_view, null); iv_empety_mageger = (ImageView) ewById(_empety_mageger); tv_no_message = (TextView) ewById(_no_message); ll_no_manager = (LinearLayout) ewById(_no_manager); ll_no_message_root = (LinearLayout) ewById(_no_message_root); ll_no_message_root = (LinearLayout) ewById(_no_message_root); addView(view); } /** * ⼀定要调⽤该⽅法 * @param */ public View mustCallInitWay(View view){ if(view != null){ Params params = ll_no_message_outParams(); = eenIntWidth(text()); = eenIntHeight(text()) - 2px(text(),50); ((ViewGroup)ent()).addView(this,params); } return this; } public void setNoMessageText(CharSequence text) { tv_no_t(text); tv_no_ibility(E); } /********修改⽂字的颜⾊**********/ public void setMessageTextColor2(int colorResId) { tv_no_tColor(colorResId); tv_no_ibility(E); } /** * 显⽰不同的⽂字提⽰及其图⽚提⽰ */ public View setMyManager(String showNoTip,int showNoIamgeViewResId,int textSize,int colorResId){ iv_empety_geResource(showNoIamgeViewResId); tv_no_tColor(colorResId); tv_no_t(showNoTip); tv_no_tSize(textSize); tv_no_ibility(E); return this; } /** * 显⽰不同的⽂字提⽰及其图⽚提⽰ */ public View setMyManager(String showNoTip,int showNoIamgeViewResId){ iv_empety_geResource(showNoIamgeViewResId); tv_no_t(showNoTip); tv_no_ibility(E); return this; } /** * 显⽰不同的⽂字提⽰及其图⽚提⽰ */ public View setMyManager(int showNoIamgeViewResId){ iv_empety_geResource(showNoIamgeViewResId); iv_empety_ibility(E); return this; } /** * 显⽰不同的⽂字提⽰ */ public View setMyManager(String showNoTip){ tv_no_t(showNoTip); tv_no_ibility(E); return this; } /** /** * 是否显⽰⽂字 */ public View isShowTextTipMassager(boolean isShow){ if(isShow){ tv_no_ibility(E); } return this; } /** * 是否显⽰⽂字 */ public View isShowTextTipMassager(boolean isShow,String showNoTip){ if(isShow){ tv_no_ibility(E); tv_no_t(showNoTip); }else{ tv_no_ibility(); tv_no_t(showNoTip); } return this; } /** * 是否显⽰图⽚ */ public View isShowIamgeMassager(boolean isShow,int showNoIamgeViewResId){ if(isShow){ iv_empety_ibility(E); iv_empety_geResource(showNoIamgeViewResId); }else{ iv_empety_ibility(); } return this; } /** * 是否显⽰图⽚ */ public View isShowIamgeMassager(boolean isShow){ if(isShow){ iv_empety_ibility(E); }else{ iv_empety_ibility(); } return this; }}如何调⽤: EmptyView emptyView = new EmptyView(this); llInitWay(lr_recycleView_query); lr_recycleView_tyView(emptyView);注意:如果你的⼦布局中有剁成⽗布局进⾏嵌套,这个时候((ViewGroup)ent()).addView(this);这个⽅法是⽆效的。addView的时候布局中的⼤⼩match_parent是没有效果的,它总是以包裹内容进⾏填充的。显⽰效果:这个时候⼀定要调⽤((ViewGroup)ent()).addView(this,params);对整体布局⽤代码进⾏设置⼤⼩才起到效果。

调⽤addView(this,params)之后正确显⽰:这⾥的params是最外层的布局⼤⼩: Params params = ll_no_message_outParams(); = eenIntWidth(text()); = eenIntHeight(text())

- 2px(text(),50);((ViewGroup)ent()).addView(this,params);该⼯具类封装好之后可⽤于ListView,GridView,RecycleView,PullToRefreshView及其⾃定义相关的组件的应⽤。直接调⽤其⽅法setEmptyView()即可。曾经踩过的坑:addView调⽤之后导致⼦布局的android:layout_width=”match_parent”属性或者 android:layout_width=”fll_parent”((ViewGroup)ent()).addView(params);属性⽆效。我们先看源码addView(View view):public void addView(View child) {

addView(child, -1);

}

public void addView(View child, int index) {

LayoutParams params = outParams();

if (params == null) {

params = generateDefaultLayoutParams();

if (params == null) {

throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");

}

}

addView(child, index, params);

}

从源码中可以知道,如果不传⼊ 的话,就会有⼀个默认的params。那么再看看源码:/**

* Returns a set of default layout parameters. These parameters are requested

* when the View passed to {@link #addView(View)} has no layout parameters

* already set. If null is returned, an exception is thrown from addView.

*

* @return a set of default layout parameters or null

*/

protected LayoutParams generateDefaultLayoutParams() {

return new LayoutParams(_CONTENT, _CONTENT);

}

到这⾥我们就可以清楚的看到:如果⼀个View没有set LayoutParams,在该View被添加到⼀个ViewGroup⾥时,ViewGroup会为该View创建⼀个默认的LayoutParams。所以如果题中的view已经存在于⼀个ViewGroup中,outParams()便会得到ViewGroup为其创建的默认LayoutParams。⽽这个默认LayoutParams会因ViewGroup⽽变,⽽这⾥的ViewGroup是指得当前的LinearLayout。LayoutParams是_CONTENT将会是⼦布局的包裹内容。因此如果只调⽤addView(View v)不设置params参数将会⽆效。SwipeRefreshLayout和ListView的EmptyView共存冲突的问题最好的⽅式是: 将ListView和EmptyView分离,让他们两个分别被两个SwipeRefreshLayout包裹参考链接:相信⾃⼰,没有做不到的,只有想不到的如果你觉得此⽂对您有所帮助,欢迎⼊群 QQ交流群 :232203809

微信公众号:终端研发部(欢迎关注学习和交流)

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1689430592a247030.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信