使用外部xml文件作为自定义列表视图适配器?

3

我目前正在开发我的第一个Android应用程序。在该应用程序中,应该有一个listView,左侧显示一张图片,旁边是两个textViews。

listView的xml如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="?android:attr/listPreferredItemHeight"
            android:padding="6dip" >

<ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="6dip"
        android:contentDescription="TODO"
        android:src="@drawable/ic_launcher" />

<TextView
        android:id="@+id/secondLine"
        android:layout_width="fill_parent"
        android:layout_height="26dip"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@id/icon"
        android:ellipsize="marquee"
        android:singleLine="true"
        android:text="Description"
        android:textSize="12sp" />

<TextView
        android:id="@+id/firstLine"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/secondLine"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_alignWithParentIfMissing="true"
        android:layout_toRightOf="@id/icon"
        android:gravity="center_vertical"
        android:text="Example application"
        android:textSize="16sp" />

</RelativeLayout>

MainActivity的XML如下所示:
<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:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
            android:paddingBottom="@dimen/activity_vertical_margin"
            tools:context=".MainActivity">

<ListView xmlns:android="rowlayout"
          android:id="@+id/list"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" />

</RelativeLayout>

我的MainActivity.java代码如下:

import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends ListActivity {
    public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
            "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
            "Linux", "OS/2" };
    String[] values2 = new String[] {"good","bad","medium","not yet tested","don't know it","very cool","Just Windows","piece of shit","very cool","don't know it too"};
    ListView listView = (ListView) findViewById(R.id.listview);
    ListViewAdapter adapter1 = new ListViewAdapter (values,values2,android.R.id.list);
    listView.setAdapter(adapter1);
    }
}

我的当前自定义适配器如下:

import android.widget.BaseAdapter;
import android.widget.TextView;

public class ListViewAdapter extends BaseAdapter {

String[] values;
String[] values2;
Context ctxt;
LayoutInflater layoutInflater;

public ListViewAdapter (String [] Values,String [] Values2, Context context) {
    values = Values;
    values2 = Values2;
    ctxt = context;
    layoutInflater = (LayoutInflater) context.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return values.length;
}

@Override
public Object getItem(int position) {
    String [] res = new String [] {values [position],values2 [position]};
    return res;
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    TextView name1 = (TextView)convertView.findViewById(android.R.id.text1);
    TextView name2 = (TextView)convertView.findViewById(android.R.id.text2);
    name1.setText(values [position]);
    name2.setText(values2 [position]);
    return convertView;
}
}

启动应用程序时出现以下错误:

进程:de.gotthold.myapplication2.app,PID:16723 java.lang.RuntimeException:无法启动组件ComponentInfo{de.gotthold.myapplication2.app/de.gotthold.myapplication2.app.MainActivity}: java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2411) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474) 在 android.app.ActivityThread.access$800(ActivityThread.java:144) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:155) 在 android.app.ActivityThread.main(ActivityThread.java:5727) 在 java.lang.reflect.Method.invoke(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824) 导致:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' 在 de.gotthold.myapplication2.app.MainActivity.onCreate(MainActivity.java:19) 在 android.app.Activity.performCreate(Activity.java:5961) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)             在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)             在 android.app.ActivityThread.access$800(ActivityThread.java:144)             在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)             在 android.os.Handler.dispatchMessage(Handler.java:102)             在 android.os.Looper.loop(Looper.java:155)             在 android.app.ActivityThread.main(ActivityThread.java:5727)             在 java.lang.reflect.Method.invoke(Native Method)             在 java.lang.reflect.Method.invoke(Method.java:372)             在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)             在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824) 02-06 12:45:27.641 16723-16723/? D/Process﹕ killProcess,pid=16723 02-06 12:45:27.641 16723-16723/? D/Process﹕ com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException:138 java.lang.ThreadGroup.uncaughtException:693 java.lang.ThreadGroup.uncaughtException:690

我希望你能解释这个问题,而不是给我一个教程链接,因为我已经尝试过它们,但还是出现了这个问题。我也阅读了多个stackoverflow线程,但没有一个能够解决我的问题。
感谢您的帮助, 学校小伙子
附言:这不是我正在开发的应用程序,而是另一个我正在尝试新学习知识的应用程序。
3个回答

1
在你的Activity中没有调用setContentView。因此,

ListView listView = (ListView) findViewById(R.id.listview);

返回null。由于你正在扩展ListActivity,所以不需要查找ListViewListActivity内部已经有一个了。您可以通过调用setListAdapter提交适配器。删除即可。
  ListView listView = (ListView) findViewById(R.id.listview);
  listView.setAdapter(adapter1)

直接调用
   setListAdapter(adapter1);

如果您决定在活动中使用自己的 ListView,请确保在 super.onCreate 之后调用 setContentView,将 ListView 的 id 更改为 @android:id/list,并寻找 android.R.id.list 而不是 R.id.listview。这些是 ListActivity 的限制。

你能看一下我在15:17的评论吗?因为这似乎与你建议的更改有关 @Blackbelt - school_guy

1
当您使用ListActivity时,需要按照特定模式在布局中声明一个列表并获取对其的引用。
您必须使用android:id="@android:id/list"作为列表视图的ID。
要获取对列表的引用:
而不是这样做 -
ListView listView = (ListView) findViewById(R.id.list);

使用getListView()便捷方法的方式如下 -

ListView listView = getListView();

1
你的代码中有很多错误。让我指出来。
错误1:
设置适配器。你不能在没有调用setContentView()的情况下调用它。
 ListView listView = (ListView) findViewById(R.id.listview);
 listView.setAdapter(adapter1);

你应该调用

 setListAdapter(adapter1);

更好的做法是:
使用Activity而不是ListActivity。然后在onCreate()中执行以下操作:
setConetentView(R.id.Your_main_View);
ListView listView = (ListView) findViewById(R.id.listview);
ListViewAdapter adapter1 = new ListViewAdapter (values,values2,this);
listView.setAdapter(adapter1);

错误2

您的ListViewAdapter构造函数具有参数

 (String[] Values,String [], Context)

但是你正在发送

 (values,values2,android.R.id.list)

You should instead send

 (values,values2,this) 

错误 3

您没有在适配器中填充视图。如果没有填充listView.xml视图,则无法将其转换为View类型对象,因此无法使用它创建自定义列表视图。

您应该执行以下操作:

public static class Holder  //holder class containing view components/widgets
{

    TextView name1,name2;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder=new Holder(); 
View convertView=inflater.inflate(R.layout.row_list, null);
holder.name1 = convertView.(TextView)convertView.findViewById(R.id.text1);
holder.name2 = convertView.(TextView)convertView.findViewById(R.id.text2);
holder.name1.setText(values [position]);
holder.name2.setText(values2 [position]);
return convertView;
}

为了更好地理解,我写了一个例子在这里


好的,很好,但是为什么我需要第二个参数来处理错误3呢? - school_guy
是的,我在某个地方读到过这个,但无论您使用什么对象作为参数,您都必须将其设置为View convertView=inflater.inflate(R.layout.row_list, null);。 - school_guy
我已经添加了代码的占位符。你可以看到编辑。但我真的建议你查看以下链接以更好地理解。在SO上如此广泛地解释事情是很困难的。http://www.codedisect.com/?p=100 @school_guy - Zahan Safallwa
一切似乎都没问题,但现在出现了这个错误:java.lang.RuntimeException: Unable to start activity ComponentInfo{de.gotthold.myapplication2.app/de.gotthold.myapplication2.app.MainActivity}: java.lang.RuntimeException: Your content must have a ListView whose id attribute is 'android.R.id.list' @Zahan Safallwa - school_guy
让我们在聊天中继续这个讨论 - Zahan Safallwa
显示剩余3条评论

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