Skip to content

Instantly share code, notes, and snippets.

@benbaxter
Last active December 15, 2017 02:05
Show Gist options
  • Save benbaxter/6c9fbb568d05d8cb4b3829dbdb23e0cb to your computer and use it in GitHub Desktop.
Save benbaxter/6c9fbb568d05d8cb4b3829dbdb23e0cb to your computer and use it in GitHub Desktop.
Sample code to experiment using DiffCallback
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
package com.example.android.diffutilsample;
import android.support.v17.leanback.widget.ImageCardView
import android.support.v17.leanback.widget.Presenter
import android.support.v4.content.ContextCompat
import android.util.Log
import android.view.ViewGroup
import kotlin.properties.Delegates
private const val TAG = "DummyItemCardPresenter"
private const val CARD_WIDTH = 313
private const val CARD_HEIGHT = 88
/**
* A DummyItemCardPresenter is used to generate Views and bind Objects to them on demand.
* It contains an ImageCardView.
*/
class DummyItemCardPresenter : Presenter() {
private var sSelectedBackgroundColor: Int by Delegates.notNull()
private var sDefaultBackgroundColor: Int by Delegates.notNull()
override fun onCreateViewHolder(parent: ViewGroup): Presenter.ViewHolder {
Log.d(TAG, "onCreateViewHolder")
sDefaultBackgroundColor = ContextCompat.getColor(parent.context, R.color.default_background)
sSelectedBackgroundColor =
ContextCompat.getColor(parent.context, R.color.selected_background)
val cardView = object : ImageCardView(parent.context) {
override fun setSelected(selected: Boolean) {
updateCardBackgroundColor(this, selected)
super.setSelected(selected)
}
}
cardView.isFocusable = true
cardView.isFocusableInTouchMode = true
updateCardBackgroundColor(cardView, false)
return Presenter.ViewHolder(cardView)
}
override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, item: Any) {
Log.d(TAG, "onBindViewHolder")
val dummyItem = item as DummyItem
val cardView = viewHolder.view as ImageCardView
cardView.titleText = dummyItem.title
cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT)
}
override fun onUnbindViewHolder(viewHolder: Presenter.ViewHolder) {}
private fun updateCardBackgroundColor(view: ImageCardView, selected: Boolean) {
val color = if (selected) sSelectedBackgroundColor else sDefaultBackgroundColor
// Both background colors should be set because the view's background is temporarily visible
// during animations.
view.setBackgroundColor(color)
view.setInfoAreaBackgroundColor(color)
}
}
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
package com.example.android.diffutilsample
import android.graphics.Color
import android.os.Bundle
import android.support.v17.leanback.app.BrowseFragment
import android.support.v17.leanback.widget.ArrayObjectAdapter
import android.support.v17.leanback.widget.DiffCallback
import android.support.v17.leanback.widget.HeaderItem
import android.support.v17.leanback.widget.ListRow
import android.support.v17.leanback.widget.ListRowPresenter
import android.support.v17.leanback.widget.OnItemViewClickedListener
import android.support.v17.leanback.widget.Presenter
import android.support.v17.leanback.widget.Row
import android.support.v17.leanback.widget.RowPresenter
import android.support.v4.content.ContextCompat
import android.util.Log
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import java.util.*
private const val TAG = "MainFragment"
private const val GRID_ITEM_WIDTH = 200
private const val GRID_ITEM_HEIGHT = 200
/**
* Sample code to experiment with [DiffCallback]
*/
class MainFragment : BrowseFragment() {
private lateinit var rowsAdapter: ArrayObjectAdapter
private lateinit var itemsHeader: HeaderItem
private lateinit var gridHeader: HeaderItem
private lateinit var gridRowAdapter: ArrayObjectAdapter
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
Log.i(TAG, "onCreate")
title = getString(R.string.browse_title)
headersState = BrowseFragment.HEADERS_DISABLED
rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
itemsHeader = HeaderItem(1L, getString(R.string.items))
gridHeader = HeaderItem(2L, getString(R.string.options))
gridRowAdapter = ArrayObjectAdapter(GridItemPresenter()).apply {
add(getString(R.string.update_items))
}
loadRows()
onItemViewClickedListener = ItemViewClickedListener()
}
private fun loadRows() {
val itemAdapter = items().toArrayObjectAdapter(DummyItemCardPresenter())
with(rowsAdapter) {
add(ListRow(itemsHeader, itemAdapter))
add(ListRow(gridHeader, gridRowAdapter))
}
adapter = rowsAdapter
}
private fun updateItems() {
val diffCallback = object : DiffCallback<DummyItem>() {
override fun areItemsTheSame(oldItem: DummyItem, newItem: DummyItem): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: DummyItem, newItem: DummyItem): Boolean =
oldItem == newItem
}
val itemsAdapter = (rowsAdapter[0] as ListRow).adapter as ArrayObjectAdapter
itemsAdapter.setItems(randomItems(), diffCallback)
}
private inner class ItemViewClickedListener : OnItemViewClickedListener {
override fun onItemClicked(itemViewHolder: Presenter.ViewHolder, item: Any,
rowViewHolder: RowPresenter.ViewHolder, row: Row) {
if (item is DummyItem) {
Toast.makeText(activity, item.title, Toast.LENGTH_SHORT).show()
} else if (item is String) {
when (item) {
getString(R.string.update_items) -> updateItems()
else -> Toast.makeText(activity, item, Toast.LENGTH_SHORT).show()
}
}
}
}
private inner class GridItemPresenter : Presenter() {
override fun onCreateViewHolder(parent: ViewGroup): Presenter.ViewHolder {
val view = TextView(parent.context)
view.layoutParams = ViewGroup.LayoutParams(GRID_ITEM_WIDTH, GRID_ITEM_HEIGHT)
view.isFocusable = true
view.isFocusableInTouchMode = true
view.setBackgroundColor(ContextCompat.getColor(activity, R.color.default_background))
view.setTextColor(Color.WHITE)
view.gravity = Gravity.CENTER
return Presenter.ViewHolder(view)
}
override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, item: Any) {
(viewHolder.view as TextView).text = item as String
}
override fun onUnbindViewHolder(viewHolder: Presenter.ViewHolder) {}
}
}
data class DummyItem(val id: Long, val title: String)
fun items(): MutableList<DummyItem> =
LongRange(1, 10).map {
DummyItem(id = it, title = "Item $it")
}.toMutableList()
fun randomItems(): MutableList<DummyItem> {
val random = Random()
var range = random.nextInt(20)
while (range < 1) {
range = random.nextInt(20)
}
val size = random.nextInt(range) // There may potentially be an empty list
return LongRange(1, range.toLong())
.map {
DummyItem(id = it, title = "Item $it")
}
.shuffled()
.take(size)
.toMutableList()
}
operator fun <T> ArrayObjectAdapter.plusAssign(element: T) {
this.add(element)
}
inline fun <reified T> Collection<T>.toArrayObjectAdapter(presenter: Presenter): ArrayObjectAdapter {
val adapter = ArrayObjectAdapter(presenter)
return copyIntoArrayObjectAdapter(adapter)
}
fun <T> Collection<T>.copyIntoArrayObjectAdapter(adapter: ArrayObjectAdapter): ArrayObjectAdapter {
forEach { adapter += it }
return adapter
}
<resources>
<string name="app_name">DiffUtil Sample</string>
<string name="browse_title"><![CDATA[DiffUtil Sample]]></string>
<string name="items">Items</string>
<string name="update_items">Update items</string>
<string name="options">Options</string>
</resources>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment