【问题标题】:Custom listview adapter for android - how to get proper view in getView()?android 的自定义列表视图适配器 - 如何在 getView() 中获得正确的视图?
【发布时间】:2013-01-16 05:57:11
【问题描述】:

我正在尝试编写一个自定义适配器来将一个简单的类适配到 ListView 中。该类用于 SMS 消息,它包含简单的字段,如正文、发件人地址等。下面,请参阅我的适配器布局:

<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" >

    <ImageView
    android:id="@+id/imgContactPhoto"
    android:contentDescription="Contact photo"
    android:layout_width="90sp"
    android:layout_height="90sp" />

    <TextView
    android:id="@+id/lblMsg"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/imgContactPhoto" 
    android:paddingLeft="10sp" />

</RelativeLayout>

还有我的自定义适配器类:

public class SmsListAdapter extends ArrayAdapter{

  private int resource;
  private LayoutInflater inflater;
  private Context context;

  @SuppressWarnings("unchecked")
  public SmsListAdapter(Context ctx, int resourceId, List objects) {
      super(ctx, resourceId, objects);
      resource = resourceId;
      inflater = LayoutInflater.from( ctx );
      context=ctx;
  }

  @Override
  public View getView (int position, View convertView, ViewGroup parent) {
        //create a new view of the layout and inflate it in the row
        convertView = ( RelativeLayout ) inflater.inflate( resource, null );

        // Extract the object to show 
        Sms msg = (Sms) getItem(position);

        // Take the TextView from layout and set the message
        TextView lblMsg = (TextView) convertView.findViewById(R.id.lblMsg);
        lblMsg.setText(msg.getBody());

        //Take the ImageView from layout and set the contact image
        long contactId = fetchContactId(msg.getSenderNum());
        String uriContactImg = getPhotoUri(contactId).toString();
        ImageView imgContactPhoto = (ImageView) convertView.findViewById(R.id.imgContactPhoto);
        int imageResource = context.getResources().getIdentifier(uriContactImg, null, context.getPackageName());
        Drawable image = context.getResources().getDrawable(imageResource);
        imgContactPhoto.setImageDrawable(image);
        return convertView;
  }
}

当我尝试激活适配器时,我在 getView() 的第一行收到错误消息,指出无法将 TextView 强制转换为 RelativeLayout。

我不清楚的是为什么首先是 TextView。我的列表项布局设置为RelativeLayout,这就是应该被夸大的,除非我弄错了。谁能帮我调试一下?

【问题讨论】:

  • 你如何初始化你的 SmsListAdapter?
  • 具体发给它的resourceId是什么?
  • 这没有意义...尝试清理您的项目。 (我不知道您为什么要尝试将其转换为 RelativeLayout,因为 convertView 只是一个视图,但这不是问题。)
  • 如果这没有帮助,请尝试移除对 RelativeLayout 的显式转换,在这种情况下它是多余的。
  • 您应该观看此Google Talk 以了解 View 回收、ViewHolders 和其他编写高效适配器的技巧。

标签: android android-layout android-adapter


【解决方案1】:

在这一行:

       convertView = ( RelativeLayout ) inflater.inflate( resource, null );

而不是资源,尝试使用布局的完整 id-R.layout.whatever

另外,你应该只在传入的视图为空时膨胀布局。否则视图已经膨胀,你应该覆盖它的所有值。

【讨论】:

  • 最终,resource 的值等于R.layout.whatever
  • 我输入了完整的 ID,但我得到了相同的结果。相当肯定它被正确传递了。
  • 从另一个评论线程的声音,有一个日食搞砸和清理项目工作。但是你确实需要这个空检查,否则你会失去很多列表视图给你的效率。如果没有 null 检查,您每次调用时都会创建一个新行,使用它您只需在第一次初始化时创建一个新行,然后重新分配它们(膨胀可能会很昂贵)。
【解决方案2】:

使用 BaseAdapter 创建您的自定义适配器。这从一开始就有点难以管理,但可以让您以后的工作更轻松。

public class GeneralAdapter extends BaseAdapter{

private LayoutInflater mInflater    = null;
private ArrayList<String> info      = null;

public GeneralAdapter( ArrayList<String> info ) {
    this.info = info;
}

@Override
public int getCount() {
    return info.size();
}

@Override
public Object getItem(int position) {
    return info.get(position);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.YOURLAYOUT, null);

        holder                  = new ViewHolder();
        holder.generalTV        = (TextView) convertView.findViewById(R.id.lblMsg);
        holder.generalIV        = (ImageView) convertView.findViewById(R.id.imgContactPhoto);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.generalTV.setText(info.getBody());
    holder.generalIV.setBackgroundResource(R.id.YOURIMAGE);

    return null;
}

private class ViewHolder {
    TextView generalTV;
    ImageView generalIV;
}

}

【讨论】:

    【解决方案3】:

    删除 convertViewRelativeLayout 的显式转换应该会有所帮助。

    【讨论】:

    • 错了,事实上我认为如果我们知道我们总是希望这个视图是一个RelativeLayout,它应该是为了类型安全。还可以查看下面 Gabe Sechan 的回答中所示的回收情况。
    • @zyklonSport 首先,findViewById() 仅适用于简单视图,它不需要是RelativeLayout,因此这里不违反类型安全。其次,它有帮助。第三,视图回收确实有用,但与问题无关。
    猜你喜欢
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 2015-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多