Фильтр ListView .. Изображения, не следующие за фильтром - PullRequest
2 голосов
/ 26 июля 2011

Я создал пользовательский адаптер для своего списка, который раздувает пользовательский вид и позволяет пользователю фильтровать список.

Это все работает нормально, но проблема в том, что значки, которые я поместил вэлементы списка не соответствуют отфильтрованным данным.

Пример

No Filtering Correctly Filtering names but not icons

Обратите внимание, что значки не меняют положение, ноИмена фильтруются правильно.

Вот мой пользовательский адаптер, который выполняет настраиваемый просмотр списка

Я использую Mono, поэтому он написан на C #, но, надеюсь, вы, ребята, Javaбыть в состоянии сказать, что я делаю здесь также ...

/// <summary>
/// ArrayAdapter to handle displaying student with risk indicator
/// </summary>
private class StudentListAdapter : ArrayAdapter<Student>
{
    private IList<Student> items;
    private Context outer_context;

    public StudentListAdapter(Context context, int resource, int textViewResourceId, IList<Student> items)
        : base(context, resource, textViewResourceId, items)
    {
        this.items = items;
        this.outer_context = context;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        LayoutInflater vi = (LayoutInflater)outer_context.GetSystemService(Context.LayoutInflaterService);
        View tmpView = vi.Inflate(Resource.Layout.ItemStudent, null);

        // call base.GetView that uses Object.ToString() to keep sorting intact
        View v = base.GetView(position, tmpView, parent);

        Student s = items[position];
        if (s != null)
        {
            // determine correct risk image
            ImageView listRisk = v.FindViewById<ImageView>(Resource.Id.listRisk);
            if (s.R != null)
            {
                switch ((int)s.R.Value)
                {
                    case 1:
                        listRisk.SetImageResource(Resource.Drawable.risk_green);
                        break;
                    case 0:
                        listRisk.SetImageResource(Resource.Drawable.risk_yellow);
                        break;
                    case -1:
                        listRisk.SetImageResource(Resource.Drawable.risk_red);
                        break;
                    case -2:
                        listRisk.SetImageResource(Resource.Drawable.risk_red2);
                        break;
                    default:
                        listRisk.SetImageResource(Resource.Drawable.risk_gray);
                        break;
                }
            }
            else
            {
                listRisk.SetImageResource(Resource.Drawable.risk_gray);
            }
        }

        return v;
    }
}

ОБНОВЛЕНИЕ

После некоторых остановок и осмотра, я 'мы обнаружили, что при фильтрации списка он перестраивает весь список перед фильтрацией

Например, когда письмо вводится в поле фильтрации, первый студент (s), который проходит через процесс GetView (), является Heath, Ackerson, который является первым студентом в списке, даже если фильтр не соответствует ему.

Итак, похоже, что фильтрация выполняется ПОСЛЕ запуска GetView, оставляя изображения на месте ... Все еще не уверены, как это исправить ..

* ПОЛНОЕ РЕШЕНИЕ *

http://jondavidjohn.com/blog/2011/08/android-custom-listview-filtering

Ответы [ 4 ]

2 голосов
/ 30 июля 2011

Я бы сделал следующее: Поместите EditText и ListView в ваш макет.Используйте BaseAdapter вместо ArrayAdapter.На самом деле это то же самое, но я не вызываю base.getView ():

private class StudentListAdapter : BaseAdapter
{
    private IList<Student> items;
    private Context outer_context;

    public StudentListAdapter(Context context, IList<Student> items)
    {
        this.items = items;
        this.outer_context = context;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        LayoutInflater vi = (LayoutInflater)outer_context.GetSystemService(Context.LayoutInflaterService);
        View v = vi.Inflate(Resource.Layout.ItemStudent, null);

        Student s = items[position];

        v.FindViewById<TextView>(R.id.text_view_id).setText(s.Name);

        // determine correct risk image
        ImageView listRisk = v.FindViewById<ImageView>(Resource.Id.listRisk);
        if (s.R != null)
        {
            switch ((int)s.R.Value)
            {
                case 1:
                    listRisk.SetImageResource(Resource.Drawable.risk_green);
                    break;
                case 0:
                    listRisk.SetImageResource(Resource.Drawable.risk_yellow);
                    break;
                case -1:
                    listRisk.SetImageResource(Resource.Drawable.risk_red);
                    break;
                case -2:
                    listRisk.SetImageResource(Resource.Drawable.risk_red2);
                    break;
                default:
                    listRisk.SetImageResource(Resource.Drawable.risk_gray);
                    break;
            }
        }
        else
        {
            listRisk.SetImageResource(Resource.Drawable.risk_gray);
        }

        return v;
    }

    void displayNewData(IList<Student> new_items)
    {
        items=new_items;
        notifyDatasetChanged();
    }
}

Поэтому, когда текст фильтра изменяется, вам просто нужно поместить новые данные в адаптер, используя метод displayNewData ():

public class StudentsActivity extends Activity {

    public override void onCreate(Bundle savedInstanceState) 
    {
        ...
        filterEditText.addTextChangedListener(filterTextWatcher);
    }

    private TextWatcher filterTextWatcher = new TextWatcher() 
    {

        public void afterTextChanged(Editable s) {}
        public void beforeTextChanged(CharSequence s, int start, int count,int after) {}

        public void onTextChanged(CharSequence filter, int start, int before, int count) 
        {
            IList<Student> items = getStudentsFiltered(filter);
            adapter.displayNewData(items);
        }
    };

    //getStudentsFiltered() method may look like that:
    getStudentsFiltered(String filter)
    {
        IList<Student> students_filtered=new List<Students>();
        foreach(Student student in students)
        if(student.Name.Contains(filter))
                students_filtered.Add(student);
        return students_filtered;
    }
}

Я почти уверен, что этот подход будет работать нормально.Не стесняйтесь задавать любые вопросы.
Я не скомпилировал код, поэтому возможны незначительные ошибки.

0 голосов
/ 29 июля 2011

Проверьте tmpView и v. У меня нет материала Mono, поэтому я не могу взглянуть на реализацию ArrayAdapter <>.

Я видел проблему, возникающую из-за того, что мое представление добавлялось вродитель, прежде чем я сделаю мои вещи населения.Реализации по умолчанию GetView () добавят представление к родителю и вернут родителя, а не вновь завышенное представление.Выполнение findViewById () для родителя всегда возвращало один и тот же ImageView (возможно, первый в списке) вместо ImageView в моем недавно раздутом представлении.

Если это так, не передавайте родительский элемент в базу.GetView (), вместо этого передайте null.Добавьте ваш недавно завышенный вид к родителю в конце реализации GetView ().

0 голосов
/ 29 июля 2011

Одна вещь, которую я заметил (при кодировании на Java, а не Mono), это то, что если вы попытаетесь сделать что-то вроде этого:

imageView.setImageResource(R.myResourceID1);
imageView.setImageResource(R.myResourceID2);

Отображаемое изображение всегда будет myResourceID1. Чтобы обойти это, кто-то, с кем я работаю, предложил использовать этот код, когда вы хотите установить уже установленный ресурс imageView. Итак:

imageView.setImageResource(R.myResourceID1);
imageView.setImageResource(0);  //supposedly invalidates the image resource
imageView.setImageResource(R.myResourceID2);

Хотя после прочтения вашего обновления кажется, что если вы фильтруете после установки imageViews в методе getView (), это может быть не вашей проблемой. Мысль, которой я поделюсь, поскольку установка уже используемого ресурса imageView во 2-й раз через getView () звучит как проблема, которую я описал выше.

0 голосов
/ 26 июля 2011

Попробуйте создать экземпляр ImageView listRisk = v.FindViewById<ImageView>(Resource.Id.listRisk), а затем установить ресурсы в каждом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...