Android中的列表视图无法工作

3

我正在为我的大学项目尝试制作一个通知应用程序。

我正在尝试为ListView创建一个自定义适配器,但包含ListView的活动没有显示任何内容。我认为在CustomAdapter.java的getView()方法中做错了什么。

CustomAdapter类用于为ListView创建子视图。listviewchild.xml定义了ListView中单行的布局,并与xml文件listactivity.xml一起使用。

    package com.example.client_nic;

    import java.util.ArrayList;

    import android.content.Context;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
    import android.widget.Toast;

    public class CustomAdapter extends BaseAdapter {
        public Context context =null;
        public ArrayList<String> nam = null;
        public ArrayList<String> date= null;
        public ArrayList<String> time = null;
        LayoutInflater inflater =null;

        public CustomAdapter(Context context, ArrayList<String> nam,
                ArrayList<String> date, ArrayList<String> time) {
            super();
            nam = new ArrayList<String>();
            date = new ArrayList<String>();
            time = new ArrayList<String>();

            this.context = context;
            this.nam = nam;
            this.date = date;
            this.time = time;

            inflater =(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        }

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return nam.size();
        }

        @Override
        public Object getItem(int arg0) {
            // TODO Auto-generated method stub
            return arg0;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return arg0;
        }

        @Override
        public View getView(int pos, View view, ViewGroup arg2) {

            // TODO Auto-generated method stub
            Log.e("name",nam.get(pos));
            Log.e("date",date.get(pos));
            Log.e("time", time.get(pos));

            view = inflater.inflate(R.layout.listviewchild, arg2,false);
            if(view.isActivated()){
                Toast.makeText(context, "yes",Toast.LENGTH_SHORT).show();
            }

            TextView nametv = (TextView)view.findViewById(R.id.textView1);
            TextView datetv = (TextView)view.findViewById(R.id.textView2);
            TextView timetv = (TextView)view.findViewById(R.id.textView3);

            nametv.setText(nam.get(pos));
            datetv.setText(date.get(pos));
            timetv.setText(time.get(pos));
            return view;
        }

    }






listviewchild.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >

  <TextView
      android:id="@+id/textView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:height="30dp" />
  <TextView android:id="@+id/textView2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:height="20dp"
      android:layout_below="@+id/textView1"
      />
  <TextView android:id="@+id/textView3"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:height="20dp"
      android:layout_marginLeft="30dp"
      android:layout_toRightOf="@+id/textView2"
      android:layout_below="@+id/textView1"

      />

</RelativeLayout>

listactivity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
<ListView android:id="@+id/list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">

</ListView>    

</LinearLayout>

1
将使用此适配器并附加到ListView的活动链接起来。我怀疑缺少setAdapter调用或传递了空数据。 - Lucas Crawford
2个回答

2
请尝试以下操作:

包 com.example.client_nic;

import java.util.ArrayList;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class CustomAdapter extends BaseAdapter {
    public Context context =null;
    public ArrayList<String> nam = null;
    public ArrayList<String> date = null;
    public ArrayList<String> time = null;
    LayoutInflater inflater = null;

    public CustomAdapter(Context context, ArrayList<String> nam,
            ArrayList<String> date, ArrayList<String> time) {
        nam = new ArrayList<String>();
        date = new ArrayList<String>();
        time = new ArrayList<String>();

        this.context = context;
        this.nam = nam;
        this.date = date;
        this.time = time;

        inflater = LayoutInflater.from(context);

    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return nam.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public View getView(int pos, View view, ViewGroup arg2) {

        // TODO Auto-generated method stub
        Log.e("name",nam.get(pos));
        Log.e("date",date.get(pos));
        Log.e("time", time.get(pos));

        view = inflater.inflate(R.layout.listviewchild, arg2, false);
        if(view.isActivated()){
            Toast.makeText(context, "yes",Toast.LENGTH_SHORT).show();
        }

        TextView nametv = (TextView)view.findViewById(R.id.textView1);
        TextView datetv = (TextView)view.findViewById(R.id.textView2);
        TextView timetv = (TextView)view.findViewById(R.id.textView3);

        nametv.setText(nam.get(pos));
        datetv.setText(date.get(pos));
        timetv.setText(time.get(pos));
        return view;
    }

}

这应该可以正确地填充您的视图并正常工作。如果有其他问题,可能是将空数据传递给Adapter。
几个注意事项:
1)您正在传递三个ArrayList以填充ListView的数据。为什么不只传递一个带有自定义Java对象的ArrayList? Java对象的字段将是名称,数据和时间。
例如:
public class MyObject{
    public String name;
    public String date;
    public String time;

    MyObject(String name, String date, String time){
        this.name = name;
        this.date = date;
        this.time = time;
    }

    //define getters and setters...
}

并且:

 public CustomAdapter(Context context, ArrayList<MyObject> objs) {
     ...
     ...
 }

2) 每次都会膨胀视图,而应该使用ViewHolder Pattern来保存视图数据,而不是在应用程序中每次重复绘制和查找资源。Android利用回收视图,因此您需要最大程度地利用它,并节省资源并减少每次加载视图时的延迟(大量开销!)。我不会为您提供示例,但请查看该链接以了解如何自己执行此操作!


请问为什么您没有将ViewGroup传递给LayoutInflater?我知道调用inflate(R.resource, null)等同于inflate(R.resource, null, false),但是查看inflate方法的源代码,它需要ViewGroup来获取父布局参数,否则它将从属性集创建生成的参数。我对Android有点生疏,但是使用这种方法创建的视图会与父视图匹配,也就是手机的尺寸,对吗? - engineercoding
LayoutInflater.from(context).inflate(id, null) 会导致高度自适应并且宽度填充父布局,所以在这里我们可能不想要这种情况。相反,我们应该使用 LayoutInflater.from(context).inflate(id, parent, false); 实际上,这将从 id 下定义的布局中获取布局参数并将其应用于高度和宽度。编辑时固定。他需要更改的仅仅是实例化 inflater。 - Lucas Crawford
有趣的是,现在的代码与 OP 的代码完全相同,只是获取 inflater 的方式更加优雅。 (基本上与 OP 所做的相同,但更易于阅读,再次查看了源代码 :P)。 但是,您的额外注释非常有帮助! 我想知道这段代码是否解决了 OP 遇到的问题。 - engineercoding
应该可以工作(我以前做过!)...唯一可能会出现问题的是适配器的不正确使用(即未设置setAdapter)或传递空数据。 - Lucas Crawford
我同意你的观点,不过我在想 OP 是否已经将适配器附加到 ListView 上了。这是一个非常愚蠢的错误,但确实会发生(我可以分享一些自己的经验 xD)。 - engineercoding

1

通过查看您的代码,我认为CustomAdapter类的实例变量(ArrayList s)nam,date和time没有填充相应传递给构造函数的ArrayList的内容,导致包含ListView的Activity未显示任何内容。 请使用以下代码替换构造函数

public CustomAdapter(Context context, ArrayList<String> nam,
            ArrayList<String> date, ArrayList<String> time) {
        super();

        this.context = context;
        this.nam.addAll(nam);
        this.date.addAll(date); 
        this.time.addAll(time);

        inflater =LayoutInflater.from(context);

    }

我认为这将解决你的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接