Last active
December 15, 2017 02:05
-
-
Save benbaxter/6c9fbb568d05d8cb4b3829dbdb23e0cb to your computer and use it in GitHub Desktop.
Sample code to experiment using DiffCallback
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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