ListView 在与交互之前不会呈现所有项目
Posted
技术标签:
【中文标题】ListView 在与交互之前不会呈现所有项目【英文标题】:ListView does not render all items until interacted with 【发布时间】:2012-07-13 03:17:18 【问题描述】:我在使用 ListView 时遇到了一个非常奇怪的问题。
我的适配器项目只有一部分呈现在屏幕上的列表视图中,但是当我与列表视图交互(即尝试滚动它)时,所有项目都正确呈现。
只有当我的项目比屏幕显示的少时才会出现这种情况。看看下面的这些屏幕截图。
互动前:
互动后:
添加物品的activity源代码:
String[] jRests = getResources().getStringArray(R.array.j_restaurants);
String[] lRests = getResources().getStringArray(R.array.l_restaurants);
items = new ArrayList<Object>();
items.add(getString(R.string.campus_j));
for(String item : jRests)
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
items.add(getString(R.string.campus_l));
for(String item : lRests)
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
adapter = new BaseSectionAdapter(this, R.layout.list_item_fragment_header);
if(!isTabletView())
adapter.setSelectedItem(-1);
adapter.setItems(items);
适配器代码:
public class BaseSectionAdapter extends AmazingAdapter
private LayoutInflater inflater;
private int selectedItem = 0;
private List<Object> items;
private List<SectionItem> sections = new ArrayList<SectionItem>(10);
private List<Class> itemTypes = new ArrayList<Class>();
private List<Integer> sectionPositions = new ArrayList<Integer>();
private int listHeaderLayoutId;
private View headerView;
public static interface ISectionListItem
public void setProps(View convertView, int position, int selectedItem);
public View getLayout(LayoutInflater inflater);
private class SectionItem implements Serializable
private static final long serialVersionUID = -8930010937740160935L;
String text;
int position;
public SectionItem(String text, int position)
this.text = text;
this.position = position;
public BaseSectionAdapter(Context context, int listHeaderLayoutId)
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
public BaseSectionAdapter(Context context, int listHeaderLayoutId, List<Object> listItems)
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
initListItems(listItems);
private void init(Context context)
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
public void setSelectedItem(int position)
selectedItem = position;
// public List<ListItem> getItems()
// return items;
//
private void initListItems(List<Object> itemList)
int curSection = -1;
//int curPosition = 0;
//curSection = 0;
this.items = itemList;
itemTypes.clear();
sections.clear();
sectionPositions.clear();
int listSize = itemList.size();
for(int i = 0; i < listSize; i++)
Object currentItem = items.get(i);
if(currentItem instanceof String)
sections.add(new SectionItem((String) currentItem,i));
curSection++;
if(!itemTypes.contains(currentItem.getClass()))
itemTypes.add(currentItem.getClass());
sectionPositions.add(curSection);
Log.d("test", "No of items = "+items.size());
Log.d("test", "No of itemtypes = "+itemTypes.size());
Log.d("test", "View type count = "+getViewTypeCount());
public void setItems(List<Object> itemList)
initListItems(itemList);
public int getCount()
return items==null?0:items.size();
@Override
public int getViewTypeCount()
return (itemTypes.size() == 0)?1:itemTypes.size();
@Override
public int getItemViewType(int position)
return itemTypes.indexOf(items.get(position).getClass());
@Override
public boolean isEnabled(int position)
return !(items.get(position) instanceof String || items.get(position) instanceof EmptySectionListItem);
@Override
public Object getItem(int position)
return items.get(position);
public long getItemId(int position)
return position;
@Override
protected void onNextPageRequested(int page)
// TODO Auto-generated method stub
@Override
protected void bindSectionHeader(View view, int position,
boolean displaySectionHeader)
// TextView lSectionTitle = (TextView) view
// .findViewById(R.id.txt_list_header);
// if (displaySectionHeader)
// lSectionTitle.setVisibility(View.VISIBLE);
// lSectionTitle
// .setText(getSections()[getSectionForPosition(position)]);
// else
// lSectionTitle.setVisibility(View.GONE);
//
@Override
public View getAmazingView(int position, View convertView, ViewGroup parent)
Object curItemObject = items.get(position);
boolean isHeader = (curItemObject instanceof String);
if(convertView == null)
if(isHeader && headerView != null)
convertView = headerView;
else if(isHeader)
convertView = inflater.inflate(listHeaderLayoutId, null);
headerView = convertView;
else
convertView = ((ISectionListItem) curItemObject).getLayout(inflater);
if(isHeader)
TextView header = ((TextView)convertView.findViewById(R.id.txt_list_header));
header.setText((String)curItemObject);
else
((ISectionListItem)curItemObject).setProps(convertView, position, selectedItem);
return convertView;
@Override
public void configurePinnedHeader(View header, int position, int alpha)
TextView textView = ((TextView)header.findViewById(R.id.txt_list_header));
textView.setText(getSections()[getSectionForPosition(position)]);
@Override
public int getPositionForSection(int section)
if(section >= sections.size())
return 0;
return sections.get(section).position;
@Override
public int getSectionForPosition(int position)
return sectionPositions.get(position);
@Override
public String[] getSections()
String[] res = new String[sections.size()];
for (int i = 0; i < res.length; i++)
res[i] = sections.get(i).text;
return res;
布局代码:
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
FrameLayout listLayout = new FrameLayout(this);
LinearLayout.LayoutParams listParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
listParams.weight = 1;
listLayout.setId(LIST_FRAGMENT_VIEW_ID);
FrameLayout detailLayout = new FrameLayout(this);
LinearLayout.LayoutParams detailParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
detailParams.weight = 2;
detailLayout.setId(DETAIL_FRAGMENT_VIEW_ID);
layout.addView(listLayout, listParams);
layout.addView(detailLayout, detailParams);
if(savedInstanceState == null)
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(listLayout.getId(), (Fragment) listFragment, TWO_PANEL_LIST_FRAGMENT_TAG);
ft.add(detailLayout.getId(), detailFragment);
ft.commit();
setContentView(layout);
【问题讨论】:
你能添加一些适配器的代码吗..? 将要添加项目的源代码添加到列表视图的后备数据源,并创建适配器 也显示您的 ListView 的布局源。 :) 添加了你要求的所有东西,虽然结构相当复杂:) 你能分享一下你做了什么改变吗?我也面临同样的问题 【参考方案1】:尝试在 runOnUIThread() 方法中调用 notifyDataSetChanged(),如下所示,它会像魅力一样工作。 :)
runOnUiThread(new Runnable()
@Override
public void run()
messageAdapter.notifyDataSetChanged();
);
【讨论】:
显然不是原始问题的解决方案,但这为我解决了同样的问题。从另一个线程调用 notifyDataSetChanged() 不可靠。【参考方案2】:我不知道是什么导致了这个问题,但如果你没有找到一个合乎逻辑的解决方案,你可以尝试这样的事情:
无论何时启动ListView
,都会以编程方式触发onTouchEvent()
。
ListView 启动后立即以编程方式向下滚动和备份。
等等。
【讨论】:
【参考方案3】:将 ListView 小部件添加到 layout.xml 并将列表内容添加到其中。不要使用 FrameLayout,因为它可能是问题的原因。它在触摸后更新内容,因此它所在的布局没有像 ListView 小部件那样实现正确的 onCreate() 设置。
【讨论】:
你的意思是它没有实现正确的onCreate?我以编程方式创建布局,然后将我的片段添加到其中。试过把两个FrameLayout改成LinearLayout,没区别:/ @Richard 你在哪里添加 ListView?根据您的代码,您没有实现 ListView。ft.add(listLayout.getId(), (Fragment) listFragment, TWO_PANEL_LIST_FRAGMENT_TAG);
我正在添加一个列表片段【参考方案4】:
添加新项目后,您是否在适配器上调用方法 notifyDataSetChanged()?这会导致列表视图在基础数据集更改时刷新其视图。
如果还是不行,试试 notifyDataSetInvalidated(),它会导致 listview 完全重绘。
【讨论】:
试过这个。没有效果。开始认为 listfragment 可能是这里的问题。我正在添加【参考方案5】:解决了!!!
问题在于适配器试图重用相同的部分项目。不好!!!
将其更改为每次我们点击一个部分时都会膨胀部分项目!
【讨论】:
你能帮帮我吗,我也有同样的问题,你能解释一下你是怎么解决的吗?我必须点击屏幕才能加载列表视图 正确的答案应该详细说明如何解决问题,而不仅仅是提示。特别是如果您回答自己的问题...以上是关于ListView 在与交互之前不会呈现所有项目的主要内容,如果未能解决你的问题,请参考以下文章
具有网络数据的 UICollectionView 在与交互之前不显示单元格
React Native ListView 不会通过单击重新呈现状态更改