Как бы мне использовать другой макет строки в пользовательском CursorAdapter на основе данных курсора?

#android #listview #android-cursoradapter

#Android #listview #android-cursoradapter

Вопрос:

Справочная информация: Я пытаюсь внедрить систему обмена сообщениями в своем приложении, и я пишу пользовательский CursorAdapter для отображения сообщений в ListView окне чата. Я хочу использовать другой макет строки для входящих и исходящих сообщений (информация, которая сохраняется в строке SQLite в курсоре). В каждой строке есть одинаковые элементы с одинаковыми идентификаторами, но они расположены по-разному.

Проблема: В настоящее время я переопределил newView() и bindView() . Когда ListView сначала заполняется, он создает все View s идеально, проверяя каждую строку, чтобы увидеть, является ли она входящей или исходящей, и раздувает соответствующий XML-файл. Однако, когда я прокручиваю или в окно добавляется новое сообщение, адаптер повторно использует View s для неправильных строк. Я бы переопределил getView() , но это не передается Cursor в качестве параметра, поэтому у меня нет способа узнать, должна ли строка быть входящей или исходящей.

Я не ищу код, а скорее какое-нибудь предложение по элегантной реализации. Заранее спасибо!

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

1. Как долго вы ожидаете, что эти списки будут увеличиваться? Если они занимают более нескольких страниц, отказ от повторного использования просмотров может вызвать проблемы с прокруткой / производительностью.

2. Им нужно поддерживать довольно длинные списки сообщений, поэтому я определенно хотел бы переработать.

Ответ №1:

Вот два возможных решения:

(1) Используйте единый макет для всех элементов, который вы можете настроить при привязке для отображения по желанию. Самым простым способом было бы просто использовать корневой вид в виде FrameLayout, который содержит N дочерних элементов для каждого из разных состояний, и вы делаете одно из них видимым, а все остальные исчезают при привязке. Конечно, вы хотите позаботиться о том, чтобы это не привело к увеличению количества просмотров ваших элементов, которые они содержат.

(2) Реализовать Adapter.getItemViewType()http://developer.android.com/reference/android/widget/Adapter.html#getItemViewType (int), чтобы сообщить представлению списка о различных типах элементов, которые у вас есть, чтобы оно использовало правильный.

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

1. Хотя второй ответ немного расширяет предложение Боба, мне действительно нравится ваше первое предложение. Я думаю, что я собираюсь пойти по этому пути. Спасибо!

2. Для потомков я добился того, чего хотел, создав очень простой двухуровневый макет с 3 дочерними элементами в RelativeLayout . Затем я применяю другой RelativeLayout.LayoutParams к макету в bindView() .

Ответ №2:

Всего лишь несколько мыслей, лично я нахожу всю комбинацию ListView и CursorAdapter немного … ошибочной… раздутый — правильное слово? Было бы проще иметь комбинацию ScrollView / LinearLayout , которая просто добавит соответствующую TextView по запросу?

Но что касается вашего решения, поскольку пользователь, похоже, не может изменить порядок сообщений по мере их добавления, вы могли бы добавить ArrayList<String> поле в свой пользовательский CursorAdapter , которое будет отслеживать, являются ли сообщения входящими или исходящими. Что-то вроде:

 private ArrayList<String> cursorMonitor; //"incoming" and "outgoing" as your options.
  

… и затем внутри, где бы ListView ни заполнялся, просто используйте

 cursorMonitor.add(my_cursor.getString("outgoing_or_incoming"));
  

И затем в getView() вы можете переопределить его и использовать cursorMonitor , чтобы определить, какой макет вам нужно увеличить.