← Назад к вопросам

Как реализовать разделитель в RecyclerView?

1.3 Junior🔥 131 комментариев
#Android компоненты#UI и вёрстка

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация разделителей в RecyclerView

В Android есть несколько подходов к добавлению разделителей между элементами RecyclerView. Выбор метода зависит от требований к дизайну, производительности и сложности разделителя.

1. ItemDecoration - Наиболее правильный подход

Стандартный способ — использование класса ItemDecoration, который позволяет рисовать разделители между и вокруг элементов. Создаем собственный декор:

class DividerItemDecoration(
    private val dividerHeight: Int,
    private val dividerColor: Int = Color.GRAY
) : RecyclerView.ItemDecoration() {

    private val paint = Paint().apply {
        color = dividerColor
        style = Paint.Style.FILL
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        
        val position = parent.getChildAdapterPosition(view)
        val itemCount = parent.adapter?.itemCount ?: 0
        
        // Не добавляем отступ после последнего элемента
        if (position < itemCount - 1) {
            outRect.bottom = dividerHeight
        }
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        
        for (i in 0 until parent.childCount - 1) {
            val child = parent.getChildAt(i)
            val params = child.layoutParams as RecyclerView.LayoutParams
            
            val top = child.bottom + params.bottomMargin
            val bottom = top + dividerHeight
            
            c.drawRect(
                child.left.toFloat(),
                top.toFloat(),
                child.right.toFloat(),
                bottom.toFloat(),
                paint
            )
        }
    }
}

Использование:

val divider = DividerItemDecoration(
    dividerHeight = 2.dpToPx(), // dpToPx() - расширение для конвертации dp в пиксели
    dividerColor = ContextCompat.getColor(context, R.color.divider)
)
recyclerView.addItemDecoration(divider)

2. Готовое решение от AndroidX

AndroidX предоставляет готовый DividerItemDecoration (хотя он deprecated в новых версиях):

// Устаревший, но простой способ
val divider = DividerItemDecoration(context, LinearLayoutManager.VERTICAL)
divider.setDrawable(ContextCompat.getDrawable(context, R.drawable.divider))
recyclerView.addItemDecoration(divider)

3. Разделитель как часть макета элемента

Можно добавить разделитель непосредственно в layout элемента списка:

<!-- item_layout.xml -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    
    <!-- Контент элемента -->
    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    
    <!-- Разделитель -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/divider"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"/>
</LinearLayout>

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

4. Условное отображение в адаптере

Управляем видимостью разделителя в onBindViewHolder:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    // ... привязка данных
    
    // Показываем разделитель для всех элементов кроме последнего
    holder.divider.visibility = if (position < items.size - 1) {
        View.VISIBLE
    } else {
        View.GONE
    }
}

5. Сложные кастомные разделители

Для нестандартных разделителей (с градиентом, иконками, разными отступами):

class CustomDividerDecoration : RecyclerView.ItemDecoration() {
    
    override fun getItemOffsets(outRect: Rect, view: View, 
                               parent: RecyclerView, state: RecyclerView.State) {
        val position = parent.getChildAdapterPosition(view)
        val viewType = parent.adapter?.getItemViewType(position)
        
        // Разные отступы для разных типов элементов
        when (viewType) {
            TYPE_HEADER -> outRect.set(0, 0, 0, 16.dpToPx())
            TYPE_ITEM -> outRect.set(16.dpToPx(), 0, 16.dpToPx(), 8.dpToPx())
        }
    }
    
    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        // Рисуем сложные разделители с градиентами
        val gradient = LinearGradient(...)
        val paint = Paint().apply { shader = gradient }
        // ... отрисовка
    }
}

Критерии выбора подхода

  1. ItemDecoration — лучший выбор для большинства случаев:

    • ✅ Не влияет на механизм переиспользования ViewHolder
    • ✅ Разделение ответственности (отдельно от адаптера)
    • ✅ Высокая производительность при правильной реализации
  2. Разделитель в layout — подходит для простых случаев:

    • ✅ Максимальная простота
    • ❌ Сложности с условным отображением
    • ❌ Нарушает принцип единственной ответственности
  3. Готовые решения — для быстрого прототипирования:

    • ✅ Быстрое внедрение
    • ❌ Ограниченная кастомизация

Производительность и оптимизация

  • Избегайте создания объектов в методах onDraw — создавайте Paint, Drawable и другие объекты в конструкторе
  • Используйте кэширование расчетов для сложных разделителей
  • Для GridLayoutManager потребуется более сложная логика в getItemOffsets, учитывающая spanCount
  • Учитывайте состояние RecyclerView — анимированные добавления/удаления элементов

Практический пример с Material Components

Для современных приложений с Material Design 3:

recyclerView.addItemDecoration(
    MaterialDividerItemDecoration(recyclerView, LinearLayoutManager.VERTICAL).apply {
        setDividerColorResource(context, R.color.outline_variant)
        isLastItemDecorated = false // Важно для последнего элемента
    }
)

Рекомендация: Для большинства production-приложений используйте кастомный ItemDecoration, так как это дает полный контроль над отрисовкой, производительностью и анимациями, сохраняя архитектурную чистоту решения.