【问题标题】:Listview with two different layouts具有两种不同布局的列表视图
【发布时间】:2012-07-03 01:30:48
【问题描述】:

应用程序在列表视图中滚动几秒钟后崩溃。

 String[] names = new String[] {"Cook","2/Person/15/5","Cashier","2/Person/15/5"};
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {


        ViewHolder holder;
        View rowView = convertView;
        LayoutInflater inflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        String[] info = names.get(position).split("/");

        if (rowView == null) {

                if (info.length != 1) {
                    rowView = inflater.inflate(R.layout.employee, null, true);
                    holder = new ViewHolder();
                    holder.name = (TextView) rowView.findViewById(R.id.name);
                    holder.money= (TextView) rowView.findViewById(R.id.money);
                    holder.rating = (RatingBar) rowView.findViewById(R.id.rating);
                    rowView.setTag(holder);
                }else{
                    rowView = inflater.inflate(R.layout.lable, null, true);
                    holder = new ViewHolder();
                    holder.lable = (TextView) rowView.findViewById(R.id.name);

                    rowView.setTag(holder);
                }


            }

        holder = (ViewHolder) rowView.getTag();


        if (holder.lable==null) {
            holder.name.setText(info[1]);
            holder.money.setText(info[2]);
            holder.rating.setRating(Float.valueOf("1"));
        }else{
            holder.lable.setText(names.get(position));
        }

        //}



        return rowView;
    }

【问题讨论】:

  • 使用 Logcat 查看确切的错误信息:adb logcat 或 Eclipse 中的 DDMS 透视图
  • 它说 nullPointerexeption @ holder.lable.setText(names.get(position));

标签: android listview layout


【解决方案1】:

由于您使用的是 Viewholder 模式并回收视图,因此最终会出现混乱。 这是因为您的列表中有两种不同类型的视图,当您获得转换视图时,它将是其中一种视图。

想象一个具有布局/视图 a 的数据集 A,对于 B b 也是如此

(-B- 表示尚未显示在屏幕上) 因此,如果您的初始列表是 Aa, Bb, Bb, Aa, -B- , -B- 并且您滚动以将数据 B 带入列表中。那么您将获得一个带有布局 a 或布局 b 的转换视图,因此没有办法可靠地使用转换视图。

我正在做一些搜索以找到一种方法来支持 ListView 中的不同视图,同时使用 convertView/viewHolder-pattern.. 到目前为止,我发现这个很有趣:https://github.com/commonsguy/cwac-merge#readme

您想要做的是覆盖 getItemViewType (position) 。 这是一个例子。你当然有你的 dataTypes 而不是 MoreResultsLoader 和 YPContact 。

@Override
public int getItemViewType(int position) {

    if (resultsList.get(position) instanceof MoreResultsLoader) {
        return VIEW_TYPE_MORE_RESULTS_LOADER;
    }
    if (resultsList.get(position) instanceof YPContact) {
        YPContact ypCon = (YPContact) resultsList.get(position);
        if(checkForGold(ypCon))
            return VIEW_TYPE_YPCONTACT_GOLD;
        else
            return VIEW_TYPE_YPCONTACT_REG;
    }
  }

然后在 getView 中,您需要检查您正在处理的视图类型并使用正确的 ViewHolder 类进行膨胀/填充。

public View getView(final int position, View convertView, ViewGroup parent) {

    View ourView = convertView;
    int itemViewType = getItemViewType(position);
    switch (itemViewType) {
    case VIEW_TYPE_MORE_RESULTS_LOADER:
        MoreResultsViewHolder moreResVH = null;
        if (ourView == null) {

            ourView = layoutInflator.inflate(R.layout.load_more_items,
                    null, true);
            moreResVH = new MoreResultsViewHolder(ourView);
            ourView.setTag(moreResVH);

        } else {
            moreResVH = (MoreResultsViewHolder) ourView.getTag();
        }
        if (moreResVH != null) {
            moreResVH.populate((MoreResultsLoader) resultsList
                    .get(position), context);
        }
        return ourView;
    case VIEW_TYPE_YPCONTACT_GOLD:
        ContactViewHolderGold contactVHGold = null;
        if (ourView == null) {

            ourView = layoutInflator.inflate(
                    R.layout.yp_search_result_list_item_gold, null, true);
            contactVHGold = new ContactViewHolderGold(ourView);
            ourView.setTag(contactVHGold);

        } else {
            contactVHGold = (ContactViewHolderGold) ourView.getTag();
        }
        if (contactVHGold != null) {
            final YPContact ypContact = (YPContact) resultsList
                    .get(position);
            contactVHGold.populate(ypContact, mCurrentLocation,
                    ypSearchResultsActivity);
            // moreResVH.populate(
            // (MoreResultsLoader)resultsList.get(position),context);
        }
        return ourView;

【讨论】:

    【解决方案2】:

    Android 在 ddms 透视图中有一个名为 logcat 的调试工具,您可以在其中找到日志。您将能够准确找出代码崩溃的行号。

    convertView 主要用于所有列表项统一时。因为它有助于回收视图。这里我们不确定回收的视图是 R.layout.employee 还是 R.layout.lable。这可能会导致问题。

    这又是猜测。 logcat 将帮助您缩小问题范围。

    【讨论】:

      【解决方案3】:

      看第一项"Cook"

      String[] names = new String[] {"Cook","2/Person/15/5","Cashier","2/Person/15/5"};
      

      你在做:

      String[] info = names.get(position).split("/");
      

      然后:

      holder.name.setText(info[1]);
      holder.money.setText(info[2]);
      

      我不必查看 logcat 来查看 ArrayIndexOutOfBoundsException

      【讨论】:

      • 哦,对不起,我在第一行添加了帮助人们理解代码。它应该是一个保存字符串的arrayadapter。
      • 好的,但你不是在检查数据,我的意思是 info[1]info[2]
      • split 可能返回长度为 0,1,2 的数组,... 在访问项目之前检查数组长度。
      • 但是logcat会澄清你有什么问题。
      • 崩溃问题已修复,但列表现在变得混乱。当我滚动标签布局时,有时会显示错误的字符串。像标签会显示“2/Person/15/5”而不是“Cook”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      相关资源
      最近更新 更多