Skip to content

Commit

Permalink
Updated sample app to match README sample
Browse files Browse the repository at this point in the history
* Updated sample app to match README sample

* Reduces gif resolution

* Added crash warning to readme

* Fixed indentation

* Explained crash
  • Loading branch information
marcin-adamczewski authored Mar 12, 2021
1 parent 0782487 commit 2f6972b
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 74 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ fun `when 2 of 4 registered students are attendees then student items correctly
viewModel.adapterItems.subscribe(adapter)
```

## Known issues
There is an issue in androidx.recyclerview version <= 1.1.0. If you use such version then you have to override
`LayoutManager.supportsPredictiveItemAnimations` and return false to avoid crash that may happen during list animation.
```kotlin
layoutManager = object : LinearLayoutManager(context, RecyclerView.VERTICAL, false) {
override fun supportsPredictiveItemAnimations(): Boolean {
return false
}
}
}
```

### More

Expand Down
3 changes: 2 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 29
Expand All @@ -24,7 +25,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.cardview:cardview:1.0.0"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.2.0-beta02'
implementation 'com.google.android.material:material:1.2.1'
implementation project(":universal-adapter")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,64 +17,96 @@ package com.jacekmarchwicki.changesdetector.example

import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.jacekmarchwicki.universaladapter.DefaultAdapterItem
import com.jacekmarchwicki.universaladapter.LayoutViewHolderManager
import com.jacekmarchwicki.universaladapter.UniversalAdapter
import com.jacekmarchwicki.universaladapter.ViewHolderManager.BaseViewHolder
import com.jacekmarchwicki.universaladapter.*
import kotlinx.android.synthetic.main.item_header.view.*
import kotlinx.android.synthetic.main.item_song.view.*
import kotlinx.android.synthetic.main.main_activity.*

class MainActivity : AppCompatActivity() {
class MainActivity : AppCompatActivity(), MainPresenter.MainView {

private val presenter = MainPresenter()
private val presenter = MainPresenter(this)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
val recyclerView = (findViewById<View>(R.id.main_activity_recycler) as RecyclerView).apply {
layoutManager = LinearLayoutManager(this@MainActivity, LinearLayoutManager.VERTICAL, false).apply {
val recyclerView = main_activity_recycler.apply {
layoutManager = object : LinearLayoutManager(this@MainActivity, RecyclerView.VERTICAL, false) {
// If you use androidx.recyclerview version <= 1.1.0 then you have to override this method
// as there is a bug that may cause a crash when the list animates
/* override fun supportsPredictiveItemAnimations(): Boolean {
return false
}*/
}.apply {
recycleChildrenOnDetach = true
}

}

val adapter = UniversalAdapter(listOf(DataViewHolder(), HeaderViewHolder()))
val adapter = UniversalAdapter(listOf(
SongViewHolder(ImageLoader()), HeaderViewHolder(), FooterViewHolder())
)
recyclerView.adapter = adapter

findViewById<View>(R.id.main_activity_fab)
.setOnClickListener { adapter.submitList(presenter.getItems()) }
main_activity_fab.setOnClickListener { adapter.submitList(presenter.getItems()) }
}
}

data class DataItem(val id: Long, val name: String, val color: Int) : DefaultAdapterItem() {
override val itemId: Any = id
override fun onSongClicked(id: String) {
Toast.makeText(this, "Song $id clicked", Toast.LENGTH_SHORT).show()
}
}

class DataViewHolder : LayoutViewHolderManager<DataItem>(
R.layout.data_item, DataItem::class, { ViewHolder(it) }
// Data models
data class HeaderItem(val text: String, val songsCount: Int, override val itemId: Any = text) : DefaultAdapterItem()

data class SongItem(
val id: String,
val title: String,
val imageUrl: String,
override val itemId: Any = id,
val onSongClick: (id: String) -> Unit
) : DefaultAdapterItem()

data class FooterItem(override val itemId: Any = BaseAdapterItem.NO_ID) : DefaultAdapterItem()

// View Holders
class HeaderViewHolder : LayoutViewHolderManager<HeaderItem>(
R.layout.item_header, HeaderItem::class, { HeaderViewHolder(it) }
) {
class ViewHolder(itemView: View) : BaseViewHolder<DataItem>(itemView) {
override fun bind(item: DataItem) {
itemView.findViewById<TextView>(R.id.data_item_text).apply {
text = item.name
setOnClickListener { println("Click: $item") }
}
itemView.findViewById<CardView>(R.id.data_item_cardview)
.setCardBackgroundColor(item.color)
class HeaderViewHolder(itemView: View) : ViewHolderManager.BaseViewHolder<HeaderItem>(itemView) {
override fun bind(item: HeaderItem) {
itemView.item_header_tv.text = "${item.text} (songs count: ${item.songsCount})"
}
}
}

data class HeaderItem(val text: String, override val itemId: Any = text) : DefaultAdapterItem()

class HeaderViewHolder : LayoutViewHolderManager<HeaderItem>(
R.layout.item_header, HeaderItem::class, { HeaderViewHolder(it) }
class SongViewHolder(private val imageLoader: ImageLoader) : LayoutViewHolderManager<SongItem>(
R.layout.item_song, SongItem::class, { ViewHolder(it, imageLoader) }
) {
class HeaderViewHolder(itemView: View) : BaseViewHolder<HeaderItem>(itemView) {
override fun bind(item: HeaderItem) {
itemView.findViewById<TextView>(R.id.item_header_tv).text = item.text
class ViewHolder(itemView: View, private val imageLoader: ImageLoader) : ViewHolderManager.BaseViewHolder<SongItem>(itemView) {
override fun bind(item: SongItem) {
itemView.item_song_title.text = item.title
itemView.setOnClickListener { item.onSongClick(item.id) }
imageLoader.load(item.imageUrl).into(itemView.item_song_card)
}
}
}

class FooterViewHolder : LayoutViewHolderManager<FooterItem>(
R.layout.item_footer, FooterItem::class, { ViewHolder(it) }
) {
class ViewHolder(itemView: View) : ViewHolderManager.BaseViewHolder<FooterItem>(itemView) {
override fun bind(item: FooterItem) {}
}
}

class ImageLoader {
fun load(url: String): ImageLoader {
return this
}

fun into(view: View) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,38 @@

package com.jacekmarchwicki.changesdetector.example

import android.graphics.Color
import com.jacekmarchwicki.universaladapter.BaseAdapterItem
import java.util.*
import kotlin.math.min
import kotlin.random.Random

class MainPresenter {
class MainPresenter(private val view: MainView) {

interface MainView {
fun onSongClicked(id: String)
}

fun getItems(): List<BaseAdapterItem> {
val random = Random()
var hue = 0f
val itemsCount = randomBetween(random, 10, 30)
val items = mutableListOf<BaseAdapterItem>()
for (i in 0 until itemsCount) {
hue += 0.12345f
if (!randomWithGaussianBoolean(random, 2.0)) {
continue
val albumsCount = Random.nextInt(2, 4)
return mutableListOf<BaseAdapterItem>().apply {
repeat(albumsCount) { index ->
val songs = getSongsForAlbum()
add(HeaderItem("Album $index", songsCount = songs.size, itemId = index))
addAll(songs)
}
val realHue = hue % 1.0f
val color = Color.HSVToColor(255, floatArrayOf(realHue * 360, 1f, 0.5f))
val name = if (randomWithGaussianBoolean(random, 2.0)) "item$i" else "item$i - changed"
items.add(DataItem(i.toLong(), name, color))
}
val swapStart = randomBetween(random, 0, items.size - 2)
val swapEnd = min(items.size - 1, swapStart + 2)
Collections.swap(items, swapStart, swapEnd)

items.add(0, HeaderItem("Header 0"))
val secondPosition = itemsCount / 3
items.add(secondPosition, HeaderItem("Header $secondPosition"))
val thirdPosition = itemsCount / 2
items.add(thirdPosition, HeaderItem("Header $thirdPosition"))

return items.toList()
add(FooterItem())
}.toList()
}

private fun randomWithGaussianBoolean(random: Random, proablity: Double): Boolean {
return Math.abs(random.nextGaussian()) < proablity
private fun getSongsForAlbum(): List<BaseAdapterItem> {
val songsCount = Random.nextInt(1, 4)
return mutableListOf<BaseAdapterItem>().apply {
repeat(songsCount) { index ->
add(SongItem(index.toString(), "Song $index",
itemId = index, onSongClick = ::onSongClick, imageUrl = "url"))
}
}.toList()
}

private fun randomBetween(random: Random, start: Int, end: Int): Int {
return random.nextInt(end - start) + start
private fun onSongClick(id: String) {
view.onSongClicked(id)
}
}
10 changes: 10 additions & 0 deletions app/src/main/res/layout/item_footer.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="6dp"
android:background="#FADDE7"
android:gravity="center"
android:text="FOOTER"
app:fontFamily="sans-serif-medium" />
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,25 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp">
android:background="?selectableItemBackground">

<androidx.cardview.widget.CardView
android:id="@+id/data_item_cardview"
android:id="@+id/item_song_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#f00"
app:cardUseCompatPadding="true"
app:cardCornerRadius="4dp"
app:cardElevation="4dp">


<TextView
android:id="@+id/data_item_text"
android:id="@+id/item_song_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"
android:textColor="#c1000000"
android:textSize="16sp"
tools:text="ASdfasdf asdfasdf aklsdfj ">

</TextView>
tools:text="ASdfasdf asdfasdf aklsdfj "/>

</androidx.cardview.widget.CardView>
</FrameLayout>
1 change: 1 addition & 0 deletions app/src/main/res/layout/main_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="@drawable/ic_switch_arrows_white_24dp"
app:useCompatPadding="true"
app:elevation="4dp"
app:fabSize="normal" />
</FrameLayout>
Binary file modified data/screencast.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2f6972b

Please sign in to comment.