在递归自定义Listview适配器中找不到TextView

时间:2013-11-16 19:02:46

标签: android listview android-listview android-arrayadapter android-adapter

我创建了这个名为GeoArea的类,它假设存储了具有子地理区域的“地理区域”,这是相当勉强的:

public class GeoArea {
    public String id;
    public String name;
    public List<GeoArea> subGeoAreas;
    public GeoArea parentGeoArea;

    public GeoArea(String id) {
        this.id = id;
        name = id;
        subGeoAreas = new LinkedList<GeoArea>();
    }

    @Override
    public String toString() {
        return name;
    }
}

我已经创建了以下布局来在Android上渲染它,这里的想法是让每个GeoArea以递归方式呈现它,然后在listView中使用它的子GeoArea:

//layout_geo_area.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/txtGeoAreaName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:gravity="left"
        android:text="Geo Area Name"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <ListView
        android:id="@+id/listViewChildGeoAreas"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/txtGeoAreaName"
        android:gravity="left" >
    </ListView>


</RelativeLayout>

这是我为GeoArea创建的适配器,它将显示在listView:

public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
    private ArrayList<GeoArea> _myGeoArea;
    private Context _myContext;

    LayoutInflater _inflater;
    public AdapterGeoArea(Context context, ArrayList<GeoArea> myGeoArea) {
        super(context, 0, myGeoArea);
        _myGeoArea = myGeoArea;
        _inflater = LayoutInflater.from(context);
        _myContext = context;
    }

    public int getCount() {
        return _myGeoArea.size();
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        GeoAreaLayoutHolder holder;
        if (convertView == null) { 
            convertView = _inflater.inflate(R.layout.layout_geo_area,parent,false);
            holder = new GeoAreaLayoutHolder();
            holder.txtGeoAreaName = (TextView)convertView.findViewById(R.id.txtGeoAreaName); 
            holder.txtGeoAreaName.setTag(convertView);
            holder.listViewChildGeoAreas = (ListView)convertView.findViewById(R.id.listViewChildGeoAreas); 
            holder.listViewChildGeoAreas.setTag(convertView);

        } else { 
            holder = (GeoAreaLayoutHolder) convertView.getTag(); 
        } 

        GeoArea curGeoArea = _myGeoArea.get(position);
        holder.txtGeoAreaName.setText(curGeoArea.name);
        if(curGeoArea.subGeoAreas.size()>0){
            ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
            AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
            for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
                testList.add(childGeoArea);
            }
            holder.listViewChildGeoAreas.setAdapter(adapter);
        }

        return convertView;
    }

    static class GeoAreaLayoutHolder { 
        public TextView txtGeoAreaName;
        public ListView listViewChildGeoAreas;
    }
}

这是我用来设置一切的活动:

public class ActivityGeoAreas extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_geo_area);

        GeoArea.searchTerm =  "Bar & Grill";

        GeoArea torontoArea = new GeoArea("cityOfToronto");

        ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
        testList.add(torontoArea);

        AdapterGeoArea adapter = new AdapterGeoArea(this, testList);

        ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
        lv.setAdapter(adapter);

    }

}

当我尝试运行它时,我在行上得到错误nullPointerException:

holder.txtGeoAreaName.setText(curGeoArea.name);

我做错了什么?

1 个答案:

答案 0 :(得分:0)

您可能希望检查ExpandableListView可能更适合您的需求

http://developer.android.com/reference/android/widget/ExpandableListView.html

示例@ http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/

继续我之前对你的问题的回答(虽然这解决了你的问题)

仅在列表视图中显示名称

list_row.xml //这是要在getView中充气的textview布局。

每一行都有textview

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

<TextView
    android:id="@+id/textGeoArea"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="14dp"
    android:text="Choose Area"
    android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

layout_geo_area.xml //只有listview no textview

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@+id/listViewChildGeoAreas"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:gravity="left" >
    </ListView>


</RelativeLayout>

现在你的适配器类

public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {  
            convertView = inflater.inflate(R.layout.list_row,parent,false);
            // inflate list_row.xml with textview
            holder = new ViewHolder();
            holder.tv = (TextView)convertView.findViewById(R.id.textGeoArea); 
            holder.setTag(convertView);

        }
        else { 
                holder = (ViewHolder) convertView.getTag(); 
        } 
        GeoArea curGeoArea = _myGeoArea.get(position);
        holder.tv.setText(curGeoArea.name);

        return convertView;
    }

static class ViewHolder  // use a view holder for smooth scrolling an performance
{
TextView tv;
}

您有自定义适配器。

public class AdapterGeoArea extends ArrayAdapter<GeoArea>{

现在您将适配器设置为listview,如下所示

 AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
 ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
 lv.setAdapter(adapter);

那你为什么需要以下呢?删除这些

  if(curGeoArea.subGeoAreas.size()>0){
        ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
        AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
        for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
            testList.add(childGeoArea);
        }
        holder.listViewChildGeoAreas.setAdapter(adapter);