一个适配器中有多个视图(充气器)

More than one views (inflaters) in one Adapter

如何在一个适配器中使用两个不同的视图?我需要一种布局中的 3 个字段和其他布局中的第 4 个字段。

如果我在屏幕上只有 1-5 个项目(扩展 Base 适配器),此代码工作正常:

@Override
public View getView (final int position, View convertView, ViewGroup parent) {
FieldsAndText p = getFields(position);

view = convertView;
    if (position != 3) {
      if (view == null) {
        view = lInflater.inflate(R.layout.addproduct_item, parent, false);
      }
    ((TextView) view.findViewById(R.id.addProductTextView)).setText(p.name);
    EditText editText = (EditText) view.findViewById(R.id.addProductEditText);
    editText.setText(p.value);
    }
    else if (position == 3) {
      if (view == null) {
        view = lInflater.inflate(R.layout.alternative_item, parent, false);
        TextView textView = (TextView) view.findViewById(R.id.alternative_textView1);
      }
    }
    return view;
}

但是当我向下滚动 5 个项目时,出现错误:

Null pointer exception in: ((TextView) view.findViewById(R.id.addProductTextView)).setText(p.name);

您需要实施 getViewTypeCount()getItemViewType() 来教导 AdapterView 关于您的多种类型的行。

例如,这里有一个 activity 和一个 ListAdapter,其中 header 和详细信息有单独的布局:

/***
  Copyright (c) 2008-2012 CommonsWare, LLC
  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  use this file except in compliance with the License. You may obtain   a copy
  of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
  by applicable law or agreed to in writing, software distributed under the
  License is distributed on an "AS IS" BASIS,   WITHOUT WARRANTIES OR CONDITIONS
  OF ANY KIND, either express or implied. See the License for the specific
  language governing permissions and limitations under the License.

  From _The Busy Coder's Guide to Android Development_
    http://commonsware.com/Android
 */

package com.commonsware.android.headerdetail;

import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class HeaderDetailListDemo extends ListActivity {
  private static final String[][] items= {
      { "lorem", "ipsum", "dolor", "sit", "amet" },
      { "consectetuer", "adipiscing", "elit", "morbi", "vel" },
      { "ligula", "vitae", "arcu", "aliquet", "mollis" },
      { "etiam", "vel", "erat", "placerat", "ante" },
      { "porttitor", "sodales", "pellentesque", "augue", "purus" } };

  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setListAdapter(new IconicAdapter());
  }

  class IconicAdapter extends BaseAdapter {
    @Override
    public int getCount() {
      int count=0;

      for (String[] batch : items) {
        count+=1 + batch.length;
      }

      return(count);
    }

    @Override
    public Object getItem(int position) {
      int offset=position;
      int batchIndex=0;

      for (String[] batch : items) {
        if (offset == 0) {
          return(Integer.valueOf(batchIndex));
        }

        offset--;

        if (offset < batch.length) {
          return(batch[offset]);
        }

        offset-=batch.length;
        batchIndex++;
      }

      throw new IllegalArgumentException("Invalid position: "
          + String.valueOf(position));
    }

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

    @Override
    public int getViewTypeCount() {
      return(2);
    }

    @Override
    public int getItemViewType(int position) {
      if (getItem(position) instanceof Integer) {
        return(0);
      }

      return(1);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      if (getItemViewType(position) == 0) {
        return(getHeaderView(position, convertView, parent));
      }

      View row=convertView;

      if (row == null) {
        row=getLayoutInflater().inflate(R.layout.row, parent, false);
      }

      ViewHolder holder=(ViewHolder)row.getTag();

      if (holder == null) {
        holder=new ViewHolder(row);
        row.setTag(holder);
      }

      String word=(String)getItem(position);

      if (word.length() > 4) {
        holder.icon.setImageResource(R.drawable.delete);
      }
      else {
        holder.icon.setImageResource(R.drawable.ok);
      }

      holder.label.setText(word);
      holder.size.setText(String.format(getString(R.string.size_template),
                                        word.length()));

      return(row);
    }

    private View getHeaderView(int position, View convertView,
                               ViewGroup parent) {
      View row=convertView;

      if (row == null) {
        row=getLayoutInflater().inflate(R.layout.header, parent, false);
      }

      Integer batchIndex=(Integer)getItem(position);
      TextView label=(TextView)row.findViewById(R.id.label);

      label.setText(String.format(getString(R.string.batch),
                                  1 + batchIndex.intValue()));

      return(row);
    }
  }
}

getViewTypeCount() returns 2,因为我有两种类型的行。 getItemViewType() returns 0 用于 header 行,1 用于详细信息行,基于具有 Integer 作为 headers 的模型数据和来自我的 array-of-arrays 的 String 作为详细信息行的模型数据。