#android #kotlin #android-recyclerview #android-custom-view #android-binding-adapter
Вопрос:
Может ли кто-нибудь помочь мне использовать пользовательское представление (AAChartCore-Kotlin, ChartView) в режиме повторного просмотра (отображение данных некоторых сеансов speedcubing) с помощью адаптера привязки?
Я попытался добавить представление диаграммы в список элементов RecyclerView и реализовать для него привязывающий адаптер, в котором я вызываю aa_drawChartWithChartModel (…), который должен отображать данные на диаграмме, передавая ему модель диаграммы элемента, но я понятия не имею, правильно ли это.
На данный момент кажется, что диаграмма загружена в представление, но она невидима.
list_item_session.xml
<!-- ... -->
</LinearLayout>
<!-- ... -->
</HorizontalScrollView>
<!-- ... -->
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- ... -->
<com.github.aachartmodel.aainfographics.aachartcreator.AAChartView
android:id="@ id/sessionChart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_big"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@ id/sessionEndDateTime"
app:layout_constraintTop_toTopOf="parent"
app:sessionChartView="@{session}">
</com.github.aachartmodel.aainfographics.aachartcreator.AAChartView>
</androidx.constraintlayout.widget.ConstraintLayout>
</HorizontalScrollView>
</LinearLayout>
SessionAdapter.kt
class SessionAdapter(private val clickListener: SessionListener) : ListAdapter<DataItem, RecyclerView.ViewHolder>(SessionsDiffCallback()) {
/* PROPERTIES */
// Coroutines
private val adapterScope = CoroutineScope(Dispatchers.Default)
/* COMPANION OBJECT */
companion object
{
private const val ITEM_VIEW_TYPE_PADDING = 0
private const val ITEM_VIEW_TYPE_SESSION = 1
}
/* ADAPTER METHODS */
fun submitListWithPadding(list: List<Session>?) {
adapterScope.launch {
val items = when(list) {
null -> listOf(DataItem.PaddingItem)
else -> list.map { DataItem.SessionItem(it) } listOf(DataItem.PaddingItem)
}
withContext(Dispatchers.Main) {
submitList(items)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType) {
ITEM_VIEW_TYPE_PADDING -> TextViewHolder.from(parent)
ITEM_VIEW_TYPE_SESSION -> ViewHolder.from(parent)
else -> throw ClassCastException("Unknown viewType $viewType")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder) {
is ViewHolder -> {
val sessionItem = getItem(position) as DataItem.SessionItem
holder.bind(clickListener, sessionItem.session)
}
}
}
override fun getItemViewType(position: Int): Int {
return when(getItem(position)) {
is DataItem.PaddingItem -> ITEM_VIEW_TYPE_PADDING
is DataItem.SessionItem -> ITEM_VIEW_TYPE_SESSION
}
}
/* VIEW HOLDER FOR SESSION ITEMS */
class ViewHolder private constructor(val binding: ListItemSessionBinding) : RecyclerView.ViewHolder(binding.root)
{
fun bind(clickListener: SessionListener, item: Session) {
binding.session = item
binding.clickListener = clickListener
binding.executePendingBindings()
}
companion object {
fun from(parent: ViewGroup): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ListItemSessionBinding.inflate(layoutInflater, parent, false)
return ViewHolder(binding)
}
}
}
/* TEXT VIEW HOLDER FOR PADDING ITEM */
class TextViewHolder(view: View) : RecyclerView.ViewHolder(view)
{
companion object
{
fun from(parent: ViewGroup): TextViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.list_item_padding, parent, false)
return TextViewHolder(view)
}
}
}
}
Связывающие адаптеры.кт
/* ... */
@BindingAdapter("sessionChartView")
fun AAChartView.setSessionChartView(item: Session?) {
item?.let {
aa_drawChartWithChartModel(it.chartModel)
}
}
DataItem.kt
sealed class DataItem
{
abstract val id: Long
data class SessionItem(val session: Session) : DataItem()
{
override val id = session.id
}
object PaddingItem : DataItem()
{
override val id = Long.MIN_VALUE
}
}
Сеансы обратного вызова.kt
class SessionsDiffCallback : DiffUtil.ItemCallback<DataItem>()
{
override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
return oldItem == newItem
}
}
Ответ №1:
Вы должны установить представление в качестве аргумента и вызвать его методы в своем адаптере привязки.
@BindingAdapter("sessionChartView")
@JvmStatic
fun setSessionChartView(view: AAChartView, item: Session?) {
item?.let {
view.aa_drawChartWithChartModel(it.chartModel)
}
}
Комментарии:
1. Я попытался скопировать код, который вы опубликовали, но, похоже, это ничего не меняет.
2. В
AAChartModel
документации написано, чтоaa_drawChartWithChartModel
метод вызывается только в первый раз после создания объекта экземпляра AAChartView. Так может быть, когда вашBindingAdapter
первый звонокlist
пуст. И после этогоaa_drawChartWithChartModel
метод не работает. Попробуйте использоватьaa_onlyRefreshTheChartDataWithChartModelSeries
илиaa_refreshChartWholeContentWithChartModel
методы для перерисовки диаграмм.