该应用程序的底部导航有两个选项卡,一个用于任务,一个用于注释。
我从一开始就没有错误,因为它通过查找任务开始。但是当我按“笔记”标签时,它崩溃了。
已从主列表的位置减去1,因为我在顶部(阵列中的第1个位置)添加了一个按钮,认为这可以纠正它。
BaseRecyclerAdapter类
abstract class BaseRecyclerAdapter<T>(
protected val masterList: MutableList<T> = mutableListOf()
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun getItemCount(): Int = masterList.size + 1
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is TaskAdapter.AddButtonViewHolder) {
holder.onBind(Unit)
} else {
(holder as BaseViewHolder<T>).onBind(masterList[position - 1])
}
}
override fun getItemViewType(position: Int): Int =
if (position == 0) {
TYPE_ADD_BUTTON
} else {
TYPE_INFO
}
abstract class BaseViewHolder<E>(val view: View) : RecyclerView.ViewHolder(view) {
abstract fun onBind(data: E)
}
abstract class AddButtonViewHolder(view: View) : BaseViewHolder<Unit>(view)
companion object {
const val TYPE_ADD_BUTTON = 0
const val TYPE_INFO = 1
}
}
NotesAdapter
class NoteAdapter(notesList: MutableList<Note> = mutableListOf()) : BaseRecyclerAdapter<Note>(notesList) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
if(viewType == TYPE_ADD_BUTTON){
AddButtonViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.view_add_button, parent, false))
} else {
NoteViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_note, parent, false))
}
override fun getItemViewType(position: Int): Int =
if(position == 0){
TYPE_ADD_BUTTON
}else {
TYPE_INFO
}
override fun getItemCount(): Int = masterList.size + 1
class NoteViewHolder(view: View) :BaseViewHolder<Note>(view){
override fun onBind(data: Note) {
(view as NoteView).initView(data)
}
}
class AddButtonViewHolder(view: View): BaseRecyclerAdapter.AddButtonViewHolder(view){
override fun onBind(data: Unit) {
view.buttonText.text = view.context.getText(R.string.add_button_note)
}
}
}
NoteListFragment
class NotesListFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_notes_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerViewNote.layoutManager = LinearLayoutManager(context)
val adapter = NoteAdapter(mutableListOf(
Note("Ben Mohammad", null),
Note("Joesph and and Maria", null)
))
recyclerViewNote.adapter = adapter
}
companion object {
fun newInstance() = NotesListFragment()
}
}
NoteView
class NoteView @JvmOverloads constructor (context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 1) :
ConstraintLayout(context, attrs, defStyleAttr){
fun initView(note: Note){
description.text = note.description
}
}
我使用的是嵌套的自定义视图,这就是我要尝试的方法。...显然是试图使它保持非常的OOP风格...
class TaskAdapter(
tasksList: MutableList<Task> = mutableListOf()
) : BaseRecyclerAdapter<Task>(tasksList) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
if (viewType == TYPE_INFO) {
TaskViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_task, parent, false))
} else {
AddButtonViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.view_add_button, parent, false))
}
class TaskViewHolder(view: View) : BaseViewHolder<Task>(view) {
override fun onBind(data: Task) {
(view as TaskView).initView(data)
}
}
class AddButtonViewHolder(view: View) : BaseRecyclerAdapter.AddButtonViewHolder(view) {
override fun onBind(data: Unit) {
view.buttonText.text = view.context.getText(R.string.add_button_task)
}
}
}
TasksListfragment
class TasksListFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_tasks_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = LinearLayoutManager(context)
val adapter = TaskAdapter(
mutableListOf(
Task(
"Testing one!!",
mutableListOf(
Todo("Test 1!!"),
Todo("Test 2!!", true)
)
),
Task("Testing two!!")
)
)
recyclerView.adapter = adapter
}
companion object {
fun newInstance() = TasksListFragment()
}
}
TaskView
class TaskView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 1) :
ConstraintLayout(context, attrs, defStyleAttr) {
lateinit var task: Task
fun initView(task: Task) {
this.task = task
titleView.text = task.title
task.todos.forEach {
todo ->
val todoView =
(LayoutInflater.from(context).inflate(R.layout.view_todo, todoContainer, false) as TodoView).apply {
initView(todo) {
if (isTaskcomplete()) {
createstrikeThrough()
} else {
removeStrikeThrough()
}
}
}
todoContainer.addView(todoView)
}
}
fun isTaskcomplete(): Boolean = task.todos.filter { !it.isComplete }.isEmpty()
private fun createstrikeThrough() {
titleView.apply {
paintFlags = paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
}
}
private fun removeStrikeThrough() {
titleView.apply {
paintFlags = paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
}
}
}
有关其他课程,请all code is pushed to GitHub。
答案 0 :(得分:-1)
问题在这里:
if (holder is TaskAdapter.AddButtonViewHolder) { // <--- problematic line holder.onBind(Unit) } else { (holder as BaseViewHolder<T>).onBind(masterList[position - 1]) }
您有BaseRecyclerAdapter
的两个不同子类:TaskAdapter
和NotesAdapter
。当您的0
的位置NotesAdapter
被调用时,if (holder is ...)
检查将失败,因为类型为NotesAdapter.AddButtonViewHolder
。
这将导致执行陷入else
情况,并且您的masterList[position - 1]
逻辑将最终查询索引-1
。
要解决此问题,请使用视图类型,而不要使用is
检查子类。基础RecyclerView.ViewHolder
类具有一个getItemViewType()
方法,该方法将从适配器返回的任何内容返回给您。由于视图类型逻辑是在基本适配器类中定义的,因此无论使用哪种具体实现类型,都将是相同的。
if (holder.itemViewType == TYPE_ADD_BUTTON) {
(holder as AddButtonViewHolder).onBind(Unit)
} else {
(holder as BaseViewHolder<T>).onBind(masterList[position - 1])
}