[英]Custom ListView doesn't show anything
I'm trying to populate a ListView
with Strings (food item names) on the left side, and item count numbers on the right. 我试图在ListView
的左侧填充字符串(食品项目名称),在右侧添加项目计数数字。 I've made a CustomAdapter
class (see below) which extends BaseAdapter
after following some tutorials, where I could see (via print statements) that at least the getCount()
method is called, but my getView()
method doesn't get called and my ListView
doesn't appear on my app. 我制作了一个CustomAdapter
类(请参见下文), BaseAdapter
在遵循一些教程之后扩展了BaseAdapter
,在这里我可以看到(通过打印语句)至少调用了getCount()
方法,但是没有调用我的getView()
方法。并且我的ListView
没有出现在我的应用中。 What am I doing wrong? 我究竟做错了什么? I assume that it's because I don't know how to make getView()
run in the right place. 我认为这是因为我不知道如何使getView()
在正确的位置运行。 It works fine when I use a normal ArrayAdapter
with an array of strings. 当我使用带有字符串数组的普通ArrayAdapter
时,它可以正常工作。
Here is how I tried populating the ListView in my MainActivity class: 这是我尝试在MainActivity类中填充ListView的方法:
CustomAdapter customAdapter = new CustomAdapter();
ListView lv1 = (ListView) findViewById(R.id.listView);
lv1.setAdapter(customAdapter);
customAdapter.notifyDataSetChanged();
Now, here is my CustomAdapter class: 现在,这是我的CustomAdapter类:
import java.util.ArrayList;
import java.util.List;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class CustomAdapter extends BaseAdapter {
List<foodItem> mItemList = getDataForListView();
public CustomAdapter(List<foodItem> list){
this.mItemList = list;
// tried this as an alternative
}
@Override
public int getCount() {
return mItemList.size();
}
@Override
public foodItem getItem(int arg0) {
return mItemList.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int arg0, View arg1, ViewGroup parent) {
System.out.println("Item list size: " + mItemList.size()); // doesn't show anything in console
if(arg1==null) {
LayoutInflater inflater = (LayoutInflater) LayoutInflater.from(parent.getContext());
arg1 = inflater.inflate(R.layout.listrow, parent ,false);
// R.layout.listrow is an XML file defined and formatted at 60sp tall
// as that is how tall I want each item in the ListView to be
}
TextView foodItem = (TextView)arg1.findViewById(R.id.foodTitle);
TextView likeCount = (TextView)arg1.findViewById(R.id.likeCount);
foodItem i = mItemList.get(arg0);
foodItem.setText(i.getItem());
likeCount.setText(i.getLikes());
return arg1;
}
public List<foodItem> getDataForListView() {
List<foodItem> itemList = new ArrayList<foodItem>();
// Test method populating with some data
for(int i=0; i<50; i++) {
itemList.add(new foodItem(i, "Item " + i));
}
return itemList;
}
}
I also tried adding my own constructor, but the result was the same. 我也尝试添加自己的构造函数,但结果是相同的。 Any help would be greatly appreciated! 任何帮助将不胜感激!
EDIT: The layout for my main activity: 编辑:我主要活动的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.inventoryList.MainActivity" >
<ListView
android:id="@+id/foodOptions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp" />
</RelativeLayout>
Last, here is my listrow.xml file: 最后,这是我的listrow.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="60sp"
android:orientation="horizontal"
android:padding="5sp" >
<TextView
android:id="@+id/foodTitle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:textSize="12sp"
android:text="123"
android:gravity="center" />
<TextView
android:id="@+id/likeCount"
android:layout_width="12sp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:text="@+string/likeCount"
android:textSize="10sp"
tools:ignore="SmallSp" />
</RelativeLayout>
You are Re-declaring List<foodItem> itemList
in getDataForListView
. 您正在getDataForListView
中重新声明List<foodItem> itemList
。 This overrides the member variable. 这将覆盖成员变量。 Change to 改成
itemList = new ArrayList<>();
Also you should do this in the constructor, not a member method and prepending an m
(so mItemList
) to your member variables is good style and helps prevent this problem. 另外,您应该在构造函数中执行此操作,而不是在成员方法中执行此操作,并且将m
(so mItemList
) mItemList
添加到您的成员变量中是很好的样式,它有助于防止此问题。 So all together: 所以一起:
private class CustomAdapter extends BaseAdapter {
private List<foodItem> mItemList; //camel case isn't usually applied to classes os this should be FoodItem
public CustomAdapter() {
mItemList = new ArrayList<>();
for (...) {
...
}
}
...
}
Better still, pass the List
to the Constructor: 更好的是,将List
传递给构造函数:
private class CustomAdapter extends BaseAdapter {
private List<FoodItem> mItemList;
public CustomAdapter(List<FoodItem> itemList) {
mItemList = itemList;
}
...
}
I fixed it. 我修好了它。 My Main Activity has three tabs, and for each I set a tab listener that changes what's in the adapter. 我的主要活动有三个选项卡,每个选项卡都设置了一个选项卡侦听器,用于更改适配器的内容。 I had assumed that these tab listeners wouldn't be invoked upon starting the app, but apparently that was not true. 我以为启动应用程序时不会调用这些选项卡侦听器,但是显然这是不正确的。 In consequence, from things I had commented out in testing, I had been called setAdapter() and passing in an empty adapter. 结果,根据我在测试中注释掉的内容,我被称为setAdapter()并传入一个空适配器。
Thanks for the help all, sorry that it turned out to be a mistake in code that I hadn't provided. 谢谢大家的帮助,很抱歉,这是我没有提供的代码中的错误。
I had the similar problem, and I resolved by putting 我遇到了类似的问题,我解决了
adapter.notifyDataSetChanged();
OUTSIDE of my try-catch block. 我try-catch块之外 。
Implement a constructor for your adapter so you can pass an items list to it: 为您的适配器实现一个构造函数,以便您可以向其传递项目列表:
public CustomAdapter(List<foodItem> itemList) {
this.itemList = itemList;
}
Create your list beforehand and pass it to the adapter constructor: 预先创建列表并将其传递给适配器构造函数:
ArrayList<foodItem> items = buildItemsList();
CustomAdapter customAdapter = new CustomAdapter(items);
ListView lv1 = (ListView) findViewById(R.id.listView);
lv1.setAdapter(customAdapter);
If you need a mutable adapter, implement a method (in the adapter) to add items and notify data set changes after that: 如果需要可变适配器,请在适配器中实现一种方法来添加项并在此之后通知数据集更改:
public void add(foodItem item) {
itemList.add(item);
notifyDataSetChanged();
}
You can do the same to remove and update items, just remember to notify changes so the list view will refresh. 您可以执行相同的操作来删除和更新项目,只是记得要通知更改,以便列表视图将刷新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.