Как добавить разделители даты в представлении рециркулятора с помощью библиотеки подкачки? - PullRequest
0 голосов
/ 27 октября 2018

После долгих поисков я знаю, что это возможно с обычным адаптером, но я не знаю, как это сделать с помощью Paging Library. Мне не нужен код, просто ключ.

Пример

Ответы [ 5 ]

0 голосов
/ 22 мая 2019

Я был в том же месте, что и вы, и придумал это решение.

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

это мои конвертеры

class DateConverter {
    companion object {
        @JvmStatic
        val formatter = SimpleDateFormat("yyyyMMddHHmmss", Locale.ENGLISH)

        @TypeConverter
        @JvmStatic
        fun toDate(text: String): Date = formatter.parse(text)

        @TypeConverter
        @JvmStatic
        fun toText(date: Date): String = formatter.format(date)
    }
}

Некоторые начальные данные, хотя у меня есть список заголовков отчетов, которые я хочу показать, пролистать и иметь возможность фильтровать

Они представлены этим объектом:

data class ReportHeaderEntity(
@ColumnInfo(name = "id") override val id: UUID
, @ColumnInfo(name = "name") override val name: String
, @ColumnInfo(name = "description") override val description: String
, @ColumnInfo(name = "created") override val date: Date)

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

Я достиг этого, выполнивследующее:

Я создал новый запрос в комнате, как этот

 @Query(
    "SELECT id, name, description,created " +
            "FROM   (SELECT id, name, description, created, created AS sort " +
            "        FROM   reports " +
            "        WHERE  :filter = '' " +
            "                OR name LIKE '%' || :filter || '%' " +
            "                OR description LIKE '%' || :filter || '%' " +
            "        UNION " +
            "        SELECT '00000000-0000-0000-0000-000000000000' as id, Substr(created, 0, 9) as name, '' as description, Substr(created, 0, 9) || '000000' AS created, Substr(created, 0, 9) || '256060' AS sort " +
            "        FROM   reports " +
            "        WHERE  :filter = '' " +
            "                OR name LIKE '%' || :filter || '%' " +
            "                OR description LIKE '%' || :filter || '%' " +
            "        GROUP  BY Substr(created, 0, 9)) " +
            "ORDER  BY sort DESC ")

fun loadReportHeaders(filter: String = ""): DataSource.Factory<Int, ReportHeaderEntity>

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

, он также создаетфиктивная дата для сортировки (со временем 25:60:60, чтобы она всегда появлялась перед остальными отчетами)

Затем я объединяю это со своим списком, используя объединение, и сортирую их по фиктивной дате

Причина, по которой мне пришлось перейти с long на string, заключается в том, что гораздо проще создать фиктивные даты со строкой в ​​sql и отделить часть даты от всего времени даты

Выше приведен список, подобный следующему:

00000000-0000-0000-0000-000000000000    20190522        20190522000000
e3b8fbe5-b8ce-4353-b85d-8a1160f51bac    name 16769  description 93396   20190522141926
6779fbea-f840-4859-a9a1-b34b7e6520be    name 86082  description 21138   20190522141925
00000000-0000-0000-0000-000000000000    20190521        20190521000000
6efa201f-d618-4819-bae1-5a0e907ddcfb    name 9702   description 84139   20190521103247

В моем PagedListAdapter я изменил его на реализацию PagedListAdapter<ReportHeader, RecyclerView.ViewHolder> (не определенный видоискатель)

Добавлен в объект-компаньон:

companion object {
    private val EMPTY_ID = UUID(0L,0L)
    private const val LABEL = 0
    private const val HEADER = 1
}

и переопределить получить тип представления следующим образом:

override fun getItemViewType(position: Int): Int = if (getItem(position)?.id ?: EMPTY_ID == EMPTY_ID) LABEL else HEADER

Затем я создал два отдельных держателя вида:

class ReportHeaderViewHolder(val binding: ListItemReportBinding) : RecyclerView.ViewHolder(binding.root) 

class ReportLabelViewHolder(val binding: ListItemReportLabelBinding) : RecyclerView.ViewHolder(binding.root)

и реализовал другие переопределенные методы следующим образом:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val inflater = LayoutInflater.from(parent.context)
    return when (viewType) {
        HEADER -> ReportHeaderViewHolder(DataBindingUtil.inflate(inflater, R.layout.list_item_report, parent, false))
        else -> ReportLabelViewHolder(DataBindingUtil.inflate(inflater, R.layout.list_item_report_label, parent, false))
    }
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    val reportItem = getItem(position)
    when (getItemViewType(position)) {
        HEADER -> {
            (holder as ReportHeaderViewHolder).binding.apply {
                report = reportItem
                executePendingBindings()
            }
        }
        LABEL -> {
            (holder as ReportLabelViewHolder).binding.apply {
                date = reportItem?.name
                executePendingBindings()
            }
        }
    }
}

Я надеюсь, что это помогает и вдохновляет людей находить еще лучшие решения

0 голосов
/ 07 апреля 2019

Ответ Кискае превосходен, и для вашего случая вариант 2, вероятно, работает хорошо.

В моем случае я хотел иметь еще один элемент, которого нет в базе данных, например:

  • Показать все
  • Элемент 1
  • Элемент 2

Также необходимо было нажать на кнопку.Существует обычный способ переопределения getItemCount для возврата +1 и смещения позиций для других методов.

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

@Query("select '' as name, 0 as id " +
        "union " +
        "select name, id from user " +
        "order by 1 asc")
DataSource.Factory<Integer, User> getAllDataSource();

Это означает, что источник данных фактически возвращает другой элемент в начале, и нет необходимости корректировать позиции.В вашем адаптере вы можете проверить этот элемент и обработать его по-разному.

В вашем случае запрос должен быть другим, но я думаю, что это будет возможно.

0 голосов
/ 27 октября 2018

Как уже упоминалось здесь , библиотека подкачки работает с PagedListAdapter .И PagedListAdapter происходит от RecyclerView.Adapter, поэтому вы можете сделать это просто, как в Recyclerview ( пример ).В двух словах - вам нужно использовать разные типы представлений для заголовков даты и элементов контента.

0 голосов
/ 29 марта 2019

При связывании данных также передается в предыдущем элементе

  override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val item = getItem(position)
    val previousItem = if (position == 0) null else getItem(position - 1)
    holder.bind(item, previousItem)
  }

Затем каждое представление устанавливает заголовок, который становится видимым, только если предыдущий элемент не имеет такого же заголовка.

    val previousHeader =  previousItem?.name?.capitalize().first()
    val header = item?.name?.capitalize()?.first()
    view.cachedContactHeader.text = header
    view.cachedContactHeader.isVisible  = previousHeader != header
0 голосов
/ 27 октября 2018

Чтобы добавить разделители, у вас есть 2 варианта:

  1. На основе представления, вы явно включаете разделители как «элемент» в список и определяете новый тип представления для этих разделителей. Позволяет списку повторно использовать представления разделителей, но означает, что вам необходимо учитывать разделители при определении данных.
  2. На основе данных каждый элемент фактически имеет представление разделителя, но он отображается только для определенных элементов. Основываясь на некоторых критериях, вы показываете или скрываете это, в то время как привязываете держателя просмотра.

Для библиотеки подкачки доступен только вариант 2, поскольку он загружает данные только частично, а вставка разделителей становится намного сложнее. Вам просто нужно найти способ проверить, является ли элемент x днем ​​недели, отличным от элемента x-1, и показать / скрыть раздел даты в представлении в зависимости от результата.

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