简体   繁体   English

自定义ListView不显示任何内容

[英]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 mItemListmItemList添加到您的成员变量中是很好的样式,它有助于防止此问题。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM