Android: SeperatedList (Как получить эффект адресной книги?) - PullRequest
0 голосов
/ 09 января 2011

Привет всем,

У меня есть ListView, который содержит RadioGroup и кнопку в каждой строке. ListView работает хорошо. Теперь я хочу добавить заголовок в ListView, чтобы получить эффект, как адресная книга. Я финансирую Java класс из Интернета, который выглядит так:

package com.aiquan.android.wljs_ncre3_free;

import java.util.LinkedHashMap;
import java.util.Map;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;

public class SeparatedListAdapter extends BaseAdapter {

 public final Map<String, Adapter> sections = new LinkedHashMap<String, Adapter>();
 public final ArrayAdapter<String> headers;
 public final static int TYPE_SECTION_HEADER = 0;

 public SeparatedListAdapter(Context context) {
  headers = new ArrayAdapter<String>(context, R.layout.list_header);
 }

 public void addSection(String sectionHeader, Adapter sectionAdapter) {
  this.headers.add(sectionHeader);
  this.sections.put(sectionHeader, sectionAdapter);
 }

 public Object getItem(int position) {
  for (Object section : this.sections.keySet()) {
   Adapter adapter = sections.get(section);
   int size = adapter.getCount() + 1;

   // check if position inside this section
   if (position == 0)
    return section;
   if (position < size)
    return adapter.getItem(position - 1);

   // otherwise jump into next section
   position -= size;
  }
  return null;
 }

 public int getCount() {
  // total together all sections, plus one for each section header
  int total = 0;
  for (Adapter adapter : this.sections.values())
   total += adapter.getCount() + 1;
  return total;
 }

 public int getViewTypeCount() {
  // assume that headers count as one, then total all sections
  int total = 1;
  for (Adapter adapter : this.sections.values())
   total += adapter.getViewTypeCount();
  return total;
 }

 public int getItemViewType(int position) {
  int type = 1;
  for (Object section : this.sections.keySet()) {
   Adapter adapter = sections.get(section);
   int size = adapter.getCount() + 1;

   // check if position inside this section
   if (position == 0)
    return TYPE_SECTION_HEADER;
   if (position < size)
    return type + adapter.getItemViewType(position - 1);

   // otherwise jump into next section
   position -= size;
   type += adapter.getViewTypeCount();
  }
  return -1;
 }

 public boolean areAllItemsSelectable() {
  return false;
 }

 public boolean isEnabled(int position) {
  return (getItemViewType(position) != TYPE_SECTION_HEADER);
 }

// @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  int sectionnum = 0;
  for (Object section : this.sections.keySet()) {
   Adapter adapter = sections.get(section);
   int size = adapter.getCount() + 1;

   // check if position inside this section
   if (position == 0)
    return headers.getView(sectionnum, convertView, parent);
   if (position < size)
    return adapter.getView(position - 1, convertView, parent);

   // otherwise jump into next section
   position -= size;
   sectionnum++;
  }
  return null;
 }

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

Я пытаюсь использовать этот класс (без каких-либо изменений) для решения своей проблемы. Но я получил очень странный эффект: часть с RadioGroup и кнопками не отображается, а часть со строками отображается правильно! И я не получил сообщений об ошибках от Eclipse. Вот мой код:

   SeparatedListAdapter adapter = new SeparatedListAdapter(this); 

    adapter.addSection("Header 1", new ArrayAdapter<String>(this,  
            R.layout.list_item, new String[] { "First item", "Item two" })); 

    adapter.addSection("Header 2", new ExerciseAdapter(this,  
            R.layout.sc_for_exam, n_exercises));

    adapter.addSection("Header 3", new ArrayAdapter<String>(this,  
            R.layout.list_item, new String[] { "lala", "lolo" }));

   setListAdapter(adapter);

n_exercises - это ArrayList, который содержит элементы списка (каждый элемент списка содержит радиогруппу и кнопку). ExerciseAdapter происходит от ArrayAdapter.

Теперь я получил этот эффект: alt text

Кто-нибудь знает, что не так и как я могу решить эту проблему? Большое спасибо !!

Вот код ExerciseAdapter. Они в том же классе, что и код выше.

private class ExerciseAdapter extends ArrayAdapter<Exercise_SC> {

    public ExerciseAdapter(Context context, int textViewResourceId,
            ArrayList<Exercise_SC> exes) {
        super(context, textViewResourceId, exes);
    }

    public View getView(final int position, View convertView,
            ViewGroup parent) {
        View row = convertView;
        SC_ViewWrapper wrapper;
        RadioGroup rg;

        if (row == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            if (ChooseMode_Act.modeInfo.equalsIgnoreCase("Training")) {
                row = vi.inflate(R.layout.sc_for_training, parent, false);
            } else {
                row = vi.inflate(R.layout.sc_for_exam, parent, false);
            }
            wrapper = new SC_ViewWrapper(row);
            row.setTag(wrapper);
            rg = wrapper.getRadioGroup();

            RadioGroup.OnCheckedChangeListener l = new RadioGroup.OnCheckedChangeListener() {
                // @Override
                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    Integer myPosition = (Integer) group.getTag();
                    Exercise_SC eRow = getExerciseRow(myPosition);
                    eRow.setCheckedRB(checkedId);
                    switch (checkedId) {
                    case R.id.RB_A:
                        n_exercises.get(myPosition).setCustomerAnswer("A");
                        break;
                    case R.id.RB_B:
                        n_exercises.get(myPosition).setCustomerAnswer("B");
                        break;
                    case R.id.RB_C:
                        n_exercises.get(myPosition).setCustomerAnswer("C");
                        break;
                    case R.id.RB_D:
                        n_exercises.get(myPosition).setCustomerAnswer("D");
                        break;
                    default:
                        n_exercises.get(myPosition).setCustomerAnswer("");
                    }
                }
            };
            rg.setOnCheckedChangeListener(l);
        } else {
            wrapper = (SC_ViewWrapper) row.getTag();
            rg = wrapper.getRadioGroup();
        }
        Exercise_SC myExe = getExerciseRow(position);
        int size = ChooseMode_Act.size;
        wrapper.getTi().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
        wrapper.getTVExer().setText(myExe.getExerciseText());
        wrapper.getTVExer().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);

        wrapper.getA().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
        wrapper.getTVA().setText(myExe.getAnswerA());
        wrapper.getTVA().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);

        wrapper.getB().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
        wrapper.getTVB().setText(myExe.getAnswerB());
        wrapper.getTVB().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);

        wrapper.getC().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
        wrapper.getTVC().setText(myExe.getAnswerC());
        wrapper.getTVC().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);

        wrapper.getD().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
        wrapper.getTVD().setText(myExe.getAnswerD());
        wrapper.getTVD().setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
        wrapper.getImageView().setImageResource(myExe.getImageSrc());

        if (ChooseMode_Act.modeInfo.equalsIgnoreCase("Training")) {
            wrapper.getButton().setOnClickListener(new OnClickListener() {
                // @Override
                public void onClick(View v) {
                    Toast toast = Toast.makeText(
                            getApplicationContext(),
                            "题-"
                                    + (position + 1)
                                    + ": "
                                    + n_exercises.get(position)
                                            .getCorrectAnswer(),
                            Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
                    toast.show();
                }
            });
        }
        rg.setTag(new Integer(position));
        rg.check(myExe.getCheckedRB());
        return row;
    }
}

Ответы [ 2 ]

0 голосов
/ 10 января 2012

Попробуйте:

public int getViewTypeCount() {
    // assume that headers count as one, then total all sections
    //int total = 1;
    //int total = 0;
    int total = headers.getCount() + 1;
    for (Adapter adapter : this.sections.values())
        //total += adapter.getViewTypeCount();
        total += (adapter.getCount() + 10);
    return total;
}

Не знаю почему, но у меня это сработало.Я прочитал совет от другого вопроса, что getItemViewType() не может быть больше, чем getViewTypeCount().

0 голосов
/ 09 января 2011

ИМО SeparatedListAdapter.getView(...) выглядит подозрительно. Поставьте логи на него (или отладку), чтобы изучить, как он работает и что он возвращает. Похоже, он никогда не возвращает View из ExerciseAdapter.

ОБНОВЛЕНИЕ : подумав еще раз, я понял, что он вызывает ExerciseAdapter для View. Поэтому, вероятно, сосредоточьтесь на том, что ExerciseAdapter.getView(...) возвращает вызов из контекста SeparatedListAdapter.getView(...). Также не могли бы вы опубликовать код ExerciseAdapter?

...