Kotlin way of building RecyclerView Adapter 🧩. You do not have to write RecyclerView Adapters again and again and suffer from handling of different view types. Kiel will help you.

Overview

build Download Android Arsenal GitHub license GitHub issues GitHub stars

Kiel

Kiel is a RecyclerView.Adapter with a minimalistic and convenient Kotlin DSL which provides utility on top of Android's normal RecyclerView.Adapter.

kiel_icon

Most of the time:

  • We found ourselves repeating same boilerplate code for RecyclerView.Adapter.
  • We have difficulty in handling RecyclerView.Adapter when there are many viewTypes.

But now, Kiel may help us to get rid of these problems. You may read the detailed story in this blog post.

Usage:

Basic Usage:

adapterOf
 val recyclerViewAdapter = adapterOf<Text> {
                register(
                    layoutResource = R.layout.adapter_message_text_item,
                    viewHolder = ::TextMessageViewHolder,
                    onViewHolderCreated = { vh->
                       //you may handle your on click listener
                       vh.itemView.setOnClickListener {

                       }
                    },
                    onBindViewHolder = { vh, _, it ->
                        vh.messageText.text = it.text
                        vh.sentAt.text = it.sentAt
                    }
                )
     }

 recyclerView.adapter = recyclerViewAdapter
pagingDataAdapterOf
 val pagingDataAdapterOf = pagingDataAdapterOf<Text> {
                register(
                    layoutResource = R.layout.adapter_message_text_item,
                    viewHolder = ::TextMessageViewHolder,
                    onViewHolderCreated = { vh->
                       //you may handle your on click listener
                       vh.itemView.setOnClickListener {

                       }
                    },
                    onBindViewHolder = { vh, _, it ->
                        vh.messageText.text = it.text
                        vh.sentAt.text = it.sentAt
                    }
                )
     }

 recyclerView.adapter = recyclerViewAdapter

Different View Types:

You may register different ViewHolders to your adapters.

              register(
                    layoutResource = R.layout.adapter_message_text_item,
                    viewHolder = ::TextMessageViewHolder,
                    onBindViewHolder = { vh, _, it ->
                        vh.messageText.text = it.text
                        vh.sentAt.text = it.sentAt
                    }
                )

                register(
                    layoutResource = R.layout.adapter_message_image_item,
                    viewHolder = ::ImageMessageViewHolder,
                    onBindViewHolder = { vh, _, item ->
                        vh.messageText.text = item.text
                        vh.sentAt.text = item.sentAt

                        Glide.with(vh.messageImage)
                            .load(item.imageUrl)
                            .into(vh.messageImage)
                    }
                )

Handling Events:

As ViewHolder instance is accessible in:

  • onViewHolderCreated
  • onBindViewHolder
  • onBindViewHolderWithPayload

You can handle the events in the same way how you did it before.

 val recyclerViewAdapter = adapterOf<Text> {
                register(
                    layoutResource = R.layout.adapter_message_text_it,
                    viewHolder = ::TextMessageViewHolder,
                    onViewHolderCreated = { vh->
                       vh.itemView.setOnClickListener {

                       }
                       vh.messageText.addTextChangedListener{text ->

                       }
                    },
                    onBindViewHolder = { vh, _, it ->
                        vh.messageText.text = it.text
                        vh.sentAt.text = it.sentAt
                    }
                )
 }

recyclerView.adapter = recyclerViewAdapter

View Binding:

As ViewHolder instance is accessible in:

  • onViewHolderCreated
  • onBindViewHolder
  • onBindViewHolderWithPayload

You may define your ViewBinding in your ViewHolder class and you can easily reach it:

class TextMessageViewHolder(view: View) : RecyclerViewHolder<Text>(view) {
    val binding = AdapterTextItemBinding.bind(view)
}

val recyclerViewAdapter = adapterOf<Text> {
                register(
                    layoutResource = R.layout.adapter_message_text_it,
                    viewHolder = ::TextMessageViewHolder,
                    onViewHolderCreated = { vh->
                       vh.binding.
                    },
                    onBindViewHolder = { vh, _, it ->
                       vh.binding.messageText.text = it.text
                       vh.binding.sentAt.text = it.sentAt
                    }
                )
 }

DiffUtil:

val recyclerViewAdapter = adapterOf<MessageViewState> {
                diff(
                    areContentsTheSame = { old, new -> old == new },
                    areItemsTheSame = { old, new -> old.message.id == new.message.id },
                    getChangePayload = { oldItem, newItem ->
                        val diffBundle = Bundle()

                        if (oldItem.selectionState != newItem.selectionState) {
                            diffBundle.putParcelable(
                                TextMessageViewHolder.KEY_SELECTION,
                                newItem.selectionState
                            )
                        }

                        if (diffBundle.isEmpty) null else diffBundle
                    }
                )
                register (
                    layoutResource = R.layout.adapter_message_text_item,
                    viewHolder = ::TextMessageViewHolder,
                    onBindViewHolder = { vh, _, it ->
                        vh.messageText.text = it.message.text
                        vh.sentAt.text = it.message.sentAt
                    }
                )

Download

implementation 'me.ibrahimyilmaz:kiel:latestVersion'

latestVersion = Download

License

Copyright 2020 Ibrahim Yilmaz

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • [question] Use setHasFixedSize list will not be displayed

    [question] Use setHasFixedSize list will not be displayed

    @ibrahimyilmaz If the RecyclerView layout uses wrap_content instead of match_parent and setHasFixedSize = true, the list will not be displayed.

    activity_country_indonesia.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/app_bar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
        </com.google.android.material.appbar.AppBarLayout>
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" / "wrap_content"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            tools:listitem="@layout/item_task_detail" />
    
    </LinearLayout>
    

    CountryIndonesiaActivity.kt

    class CountryIndonesiaActivity : BaseActivity() {
        private val viewModel by viewModel<CountryIndonesiaViewModel>()
        private lateinit var binding: ActivityCountryIndonesiaBinding
        private val viewAdapter by lazy { createAdapter(::onItemClicked) }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityCountryIndonesiaBinding.inflate(layoutInflater)
            setContentView(binding.root)
            setupActionBarWithBackButton(binding.toolbar)
            initView()
    
            viewModel.loadData()
        }
    
        private fun initView() {
            with(binding.recyclerView) {
                adapter = viewAdapter
                setHasFixedSize(true)
            }
        }
    
        override fun observeChange() {
            observe(viewModel.items, ::onDataLoaded)
            observe(viewModel.toastMessage, ::showSnackbarMessage)
        }
    
        private fun onDataLoaded(items: List<BaseViewItem>) {
            viewAdapter.submitList(items)
        }
    
    
        private fun onItemClicked(viewItem: BaseViewItem, view: View) {
            when (viewItem) {
                is DailyItem -> {
    
                }
                is TextItem -> {
                    DailyGraphActivity.startActivity(this)
                }
            }
        }
    
        companion object {
            @JvmStatic
            fun startActivity(context: Context?) =
                context?.startActivity(Intent(context, CountryIndonesiaActivity::class.java))
        }
    }
    

    This question can be through kotlin-mvvm-covid19 project test.

    Q&A 
    opened by tcqq 23
  • Add

    Add "import" information in README

    Hi, I just tried out your library and I have to say: Awesome! I WILL use it in my projects from now on.

    But it seems like adapterOf does not get imported automatically, so I had to search for the import in the sample app. Maybe you should add the note to the README that you need the import import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter.Companion.adapterOf like in the Download section.

    Greetings!

    documentation enhancement kiel 
    opened by cyb3rko 5
  • [kiel] : Support HasStableId in adapterOf

    [kiel] : Support HasStableId in adapterOf

    In order to set hasStableId, we may pass lambda or interface to RecyclerViewAdapter to override getItemId.

    When it is passed, RecyclerViewAdapter use it, When it is not passed, RecyclerViewAdapter default super.getItemId()

    Aim is to make it composable also:

    syntax would be:

    val adapter =adapterOf<Type>{
             itemId{ t.getId() }
             ....
    }
    
    
    documentation good first issue up-for-grabs 
    opened by ibrahimyilmaz 5
  • [kiel] Drop Jetifier

    [kiel] Drop Jetifier

    FEATURE REQUEST

    Hi! Thank you for making Kiel! I've played with it for some time now and I want to use it in our project but this issue is we are trying to reduce build time by dropping jetifier.

    We found out by dropping jetifier we can reduce a significant amount of build time. thank you!

    Describe the solution you'd like

    I've forked your project and dropped jetifier, test it and it works! I just disabled the app module because of some conflicts. Anyway it's working fine in my test project.

     implementation 'com.github.raquezha:kiel:1.2.1-beta'
    

    Describe alternatives you've considered

    I hope you consider this feature request

    Additional context

    1. Adam Bennet's Article about droping jetifier: https://adambennett.dev/2020/08/disabling-jetifier/
    2. Can I Drop Jetifier Repo: https://github.com/plnice/can-i-drop-jetifier
    enhancement kiel 
    opened by raquezha 4
  • [Kiel] Support for nested recyclerview

    [Kiel] Support for nested recyclerview

    Hi @ibrahimyilmaz, There is a common case that we will have a child list of items as a row of recyclerview just like Google Play did. Is there any solution for this case in Kiel?

    opened by rainboy93 4
  • [kiel] Support for load more functions

    [kiel] Support for load more functions

    Hi there, RecyclerView usually have to handle a large amount of data, I think it really need to add support for load more functions. What do you think?

    opened by rainboy93 4
  • [kiel] Create alternative methods for register , where layoutResource is passed as a value, and then wrapped into a function type.

    [kiel] Create alternative methods for register , where layoutResource is passed as a value, and then wrapped into a function type.

    Create alternative methods for register , where layoutResource is passed as a value, and then wrapped into a function type.

    This

    register(
        type = Text::class.java
        layoutResource = { R.layout.adapter_message_text_item }
        viewHolder = { ::TextMessageViewHolder }
        onViewHolderBound = { vh, _, it ->
            vh.messageText.text = it.text
            vh.sentAt.text = it.sentAt
        }
    )
    

    would become this: Kotlin

    register(
        type = Text::class.java
        layoutResource = R.layout.adapter_message_text_item
        viewHolder = { ::TextMessageViewHolder }
        onViewHolderBound = { vh, _, it ->
            vh.messageText.text = it.text
            vh.sentAt.text = it.sentAt
        }
    )
    

    With:

    fun register(layoutResourceProvider: () -> Int) {
        // use layoutResourceProvider
    }
    
    fun register(layoutResource: Int) = register(
        layoutResourceProvider = { layoutResource }
    )
    
    enhancement good first issue 
    opened by ibrahimyilmaz 4
  • `listAdapterOf` DSL implementation

    `listAdapterOf` DSL implementation

    Proposed Changes/Issues Fixed

    listAdapterOf DSL introduced. example syntax:

    
    val adapter =listAdapterOf<Any> {
                itemDiffUtil { RecyclerViewItemCallback() }
                register { 
                    type {  }
                    viewHolder {  }
                    layoutResource {  }
                    onViewHolderBound { vh, i, it ->  }
                    onViewHolderCreated<> { vh, i, it ->  }
                    onViewHolderBoundWithPayload { vh, i, it, list ->  }<> { vh, i, it ->  }
                }
            }
    

    Example:

    General

    • [x] Change/Fix added to CHANGELOG.md
    • [x] Issue Link https://github.com/ibrahimyilmaz/kiel/issues/29
    • [ ] Current Sample was changed/ new sample is introcuded

    Testing

    • [x] Unit-Tests implemented
    • [x] Monkey-Test done
    • [x] Does your submission pass ./gradlew check?
    opened by ibrahimyilmaz 2
  • Artifact Maven Central Upload

    Artifact Maven Central Upload

    General

    • [x] Change/Fix added to CHANGELOG.md
    • [x] Issue Link https://github.com/ibrahimyilmaz/kiel/issues/72
    • [ ] Current Sample was changed/ new sample is introcuded

    Testing

    • [ ] Unit-Tests implemented
    • [x] Monkey-Test done
    • [x] Does your submission pass ./gradlew check?
    opened by ibrahimyilmaz 1
  • MavenCentral upload task added to pipeline.

    MavenCentral upload task added to pipeline.

    General

    • [ ] Change/Fix added to CHANGELOG.md
    • [ ] Issue Link
    • [ ] Current Sample was changed/ new sample is introcuded

    Testing

    • [ ] Unit-Tests implemented
    • [ ] Monkey-Test done
    • [ ] Does your submission pass ./gradlew check?
    opened by ibrahimyilmaz 0
  • Remove jcenter from kiel

    Remove jcenter from kiel

    Proposed Changes/Issues Fixed

    Before publishing kiel to Maven Central, jcenter should be removed.

    General

    • [x] Change/Fix added to CHANGELOG.md
    • [x] Issue Link https://github.com/ibrahimyilmaz/kiel/issues/72

    Testing

    • [x] Monkey-Test done
    • [x] Does your submission pass ./gradlew check?
    opened by ibrahimyilmaz 0
  • how to define viewTypes with conditions

    how to define viewTypes with conditions

    now we can register viewTypes but README has no way to determine which viewType is created at spefici position i.e how to make views has two types Head, Sub

    • Head with odd positions
    • Sub with even positions
    Q&A 
    opened by MahmoudMabrok 5
  • Composable Diff improvements

    Composable Diff improvements

    https://github.com/ibrahimyilmaz/kiel/pull/40 added syntax to define Diff callback for whole adapter. But you still have no ability to define diff callback for register blocks separately.

    There is example of how it may look like:

    adapterOf<Animal> {
        register(
            layoutResource = R.layout.item_cat,
            viewHolder = ::CatHolder,
            diff = diff(
                areItemsTheSame = { cat1, cat2 -> cat1.name == cat2.name }
            )
        )
    
        register(
            layoutResource = R.layout.item_dog,
            viewHolder = ::DogHolder,
            diff = diff(
                areItemsTheSame = { dog1, dog2 -> dog1.bark == dog2.bark }
            )
        )
    }
    

    This builder under the hood should create single DiffUtil.Callback with multiple "delegates": one for Cat, one for Dog. Then, when DiffUtil.Callback methods are called, that Callback must pick appropriate "delegate" and call it

    enhancement help wanted good first issue reddit up-for-grabs 
    opened by terekhovyes 0
Owner
ibrahim yilmaz
ibrahim yilmaz
An adapter which could be used to achieve a parallax effect on RecyclerView.

android-parallax-recycleview Integration Step 1. Add the JitPack repository to your build file repositories { maven { url "https://jitpack

Pedro Oliveira 1.6k Nov 17, 2022
*** WARNING: This library is no longer maintained *** An easy way to add a simple 'swipe-and-do-something' behavior to your `RecyclerView` items. Just like in Gmail or Inbox apps.

SwipeToAction An easy way to add a simple 'swipe-and-do-something' behavior to your RecyclerView items. Just like in Gmail or Inbox apps. Integration

Victor Calvello 223 Nov 16, 2022
Android library providing simple way to control divider items (ItemDecoration) of RecyclerView

RecyclerView-FlexibleDivider Android library providing simple way to control divider items of RecyclerView Release Note [Release Note] (https://github

Yoshihito Ikeda 2.4k Dec 18, 2022
Android library to display a ListView whose cells are not rigid but flabby and react to ListView scroll.

FlabbyListView This library is not maintained anymore and there will be no further releases Android library to display a ListView which cells are not

JPARDOGO 762 Nov 23, 2022
Android library to achieve in an easy way, the behaviour of the home page in the Expedia app, with a pair of auto-scroll circular parallax ListViews.

ListBuddies This library is not maintained anymore and there will be no further releases Android library of a pair of auto-scroll circular parallax Li

JPARDOGO 970 Dec 29, 2022
A very easy-to-use and non-intrusive implement of Swipe to dismiss for RecyclerView.

RecyclerViewSwipeDismiss A very easy-to-use and non-intrusive implement of Swipe to dismiss for RecyclerView. Preview How to use Add these lines to yo

xcodebuild 431 Nov 23, 2022
RecyclerView extension library which provides advanced features. (ex. Google's Inbox app like swiping, Play Music app like drag and drop sorting)

Advanced RecyclerView This RecyclerView extension library provides Google's Inbox app like swiping, Play Music app like drag-and-drop sorting and expa

Haruki Hasegawa 5.2k Dec 23, 2022
Pumped up RecyclerView

##Description This is an attempt to make RecyclerView easier to use. Features built in: ProgressBar while adapter hasn't been set EmptyView if adapter

Anton Malinskiy 2.6k Jan 5, 2023
. Android library that integrate sticky section headers in your RecyclerView

recyclerview-stickyheaders Recyclerview-stickyheaders is an Android library that makes it easy to integrate section headers in your RecyclerView. Thes

null 968 Nov 10, 2022
An Android Animation library which easily add itemanimator to RecyclerView items.

RecyclerView Animators RecyclerView Animators is an Android library that allows developers to easily create RecyclerView with animations. Please feel

Daichi Furiya 11.2k Jan 5, 2023
A Fast Scroller for the RecyclerView world!

RecyclerViewFastScroller The RecyclerViewFastScroller is a widget that can be added to a layout and connected to a RecyclerView for fast scrolling. Th

Daniel Smith 1.1k Dec 19, 2022
ItemDecoration for RecyclerView using LinearLayoutManager for Android

RecyclerItemDecoration RecyclerItemDecoration allows you to draw divider between items in recyclerview with multiple ViewType without considering item

magiepooh 328 Dec 27, 2022
[UNMAINTAINED] Sticky Headers decorator for Android's RecyclerView

This project is no longer being maintained sticky-headers-recyclerview This decorator allows you to easily create section headers for RecyclerViews us

timehop 3.7k Dec 31, 2022
A drag-and-drop scrolling grid view for Android

DraggableGridView¶ ↑ a drag-and-drop scrolling grid view for Android Including in your project¶ ↑ To start using DraggableGridView: Place libs/Draggab

Tom Quinn 565 Dec 27, 2022
An Android staggered grid view which supports multiple columns with rows of varying sizes.

AndroidStaggeredGrid ##Notice - Deprecated - 09-2015 This library has been deprecated. We will no longer be shipping any updates or approving communit

Etsy, Inc. 4.8k Dec 29, 2022
👇 Easy Google Photos style multi-selection for RecyclerViews, powered by Kotlin and AndroidX.

Drag Select Recycler View This library allows you to implement Google Photos style multi-selection in your apps! You start by long pressing an item in

Aidan Follestad 1.9k Dec 7, 2022
A modified version of Android's experimental StaggeredGridView. Includes own OnItemClickListener and OnItemLongClickListener, selector, and fixed position restore.

StaggeredGridView Introduction This is a modified version of Android's experimental StaggeredGridView. The StaggeredGridView allows the user to create

Maurycy Wojtowicz 1.7k Nov 28, 2022
An Android custom ListView and ScrollView with pull to zoom-in.

PullZoomView An Android custom ListView and ScrollView with pull to zoom-in. Features Set ZoomView enable Add HeaderView Custom ZoomView Parallax or N

Frank-Zhu 2.3k Dec 26, 2022
Android ListView that mimics a GridView with asymmetric items. Supports items with row span and column span

AsymmetricGridView An Android custom ListView that implements multiple columns and variable sized elements. Please note that this is currently in a pr

Felipe Lima 1.8k Jan 7, 2023