Listview с двумя разными макетами

#android #listview #layout

#Android #listview #макет

Вопрос:

Приложение завершает работу после нескольких секунд прокрутки в listview.

  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;
    }
  

Комментарии:

1. Используйте Logcat, чтобы увидеть точное сообщение об ошибке: adb logcat или перспективу DDMS в eclipse

2. в нем говорилось, что nullPointerexeption @ holder.lable.setText(names.get (позиция));

Ответ №1:

Поскольку вы используете представления Viewholder-pattern и recycle, в итоге получается jumble. Это потому, что у вас в списке есть два разных вида представлений, и когда вы получаете convertview, это будет одно из этих представлений.

Представьте набор данных A с макетом / представлением a, и то же самое для B b

(-B- означает, что он еще не отображается на экране) Итак, если ваш первоначальный список Aa, Bb, Bb, Aa, -B-, -B- и вы прокручиваете, чтобы внести данные B в список.. Тогда вы получите convertview с макетом a или макетом b, таким образом, не имея возможности надежно использовать convertview.

Я провожу некоторый поиск, чтобы найти способ поддерживать разные представления в ListView и в то же время использовать шаблон convertView / ViewHolder.. Пока что я нахожу этот вариант интересным:https://github.com/commonsguy/cwac-merge#readme

Что вы хотите сделать, так это переопределить getItemViewType (позицию) . Вот пример. У вас, конечно, есть свои типы данных вместо 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 есть инструмент отладки logcat в перспективе ddms, где вы найдете журналы. Вы могли бы точно определить номер строки, в которой происходит сбой кода.

convertView в основном используется, когда все элементы списка одинаковы. Поскольку это помогает в переработке представлений. Здесь мы не уверены, является ли переработанный вид R.layout.employee или R.layout.ярлык. Это может быть причиной проблемы.

Опять же, это предположение. 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

Комментарии:

1. О, извините, я добавил в первую строку, чтобы помочь людям понять код. Это должен быть arrayadapter, который содержит строки.

2. Хорошо, но вы не проверяете данные, я имею в виду info[1] и info[2] .

3. split может возвращать массив длиной 0,1,2,… Проверьте длину массива перед доступом к элементам.

4. Но logcat уточнит, какая у вас проблема.

5. проблема с сбоем устранена, но теперь список становится беспорядочным. При прокрутке макета ярлыка иногда отображается неправильная строка. Подобная табличка отображала бы «2 / Person / 15 / 5» вместо «Cook».