【问题标题】:Using an external xml file for custom list view adapter?为自定义列表视图适配器使用外部 xml 文件?
【发布时间】:2016-05-16 10:03:48
【问题描述】:

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

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(本机方法) 在 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(本机方法) 在 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/进程:com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException:138 java.lang.ThreadGroup.uncaughtException:693 java.lang.ThreadGroup.uncaughtException:690

我希望获得有关此问题的解释,而不是指向教程的链接,因为我尝试通过它们进行工作并且发生了这种情况。我还阅读了多个 stackoverflow 线程,但没有一个可以解决我的问题。

感谢您的帮助, 小学生

P.S.:这不是我正在开发的应用程序,这是一个不同的应用程序,我正在用我学到的新知识搞乱。

【问题讨论】:

    标签: android xml listview


    【解决方案1】:

    您的代码中有很多错误。让我指出他们

    错误 1

    设置适配器。没有setContentView()就不能打电话

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

    你应该打电话

     setListAdapter(adapter1);
    

    更好的方法是:

    使用 Acticity 而不是 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)
    

    你应该发送

     (values,values2,this) 
    

    错误 3

    您没有在 adpater 中膨胀视图。如果不膨胀 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;
    }
    

    为了更详细的理解我写了一个例子here

    【讨论】:

    • 好的,很好,但是为什么我需要错误 3 处的第二个参数?
    • 第二个参数是指哪一个? @school_guy
    • 当您创建自定义列表视图时,您需要设计每一行。因此,您的 listview.xml 实际上是列表视图的单行。现在您需要在适配器中将其转换为 View 对象返回到 Main listview,以便 mainlist 视图获取一个对象来填充自身。 R.layout.something 可供所有班级使用,您无需明确发送。 @school_guy
    • 是的,我在某处读到过,但无论您使用什么对象作为参数,您都已将其设置为 View convertView=inflater.inflate(R.layout.row_list, null);
    • 现在我收到这个错误:java.lang.RuntimeException: Unable to start activity ComponentInfo{de.gotthold.myapplication2.app/de.gotthold.myapplication2.app.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
    【解决方案2】:

    在您的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);
    

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

    【讨论】:

    • 你能看看我 15:17 的评论吗,因为这似乎与你建议的更改有关@Blackbelt
    【解决方案3】:

    当您使用ListActivity 时,您需要遵循特定模式在布局中声明一个 List 并获取对它的引用

    您必须使用android:id="@android:id/list" 作为列表视图的 ID。

    要获得对列表的引用:

    而不是这样做 -

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

    像这样使用getListView()方便的方法 -

    ListView listView = getListView();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-21
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多