In my application I want create custom calendar with RecyclerView
.
I write below codes but when show days into recyclerview adapter show me force close error!
My Adapter codes:
class DaysAdapter constructor(val context: Context, private val items: MutableList<DayEntity>) :
RecyclerView.Adapter<DaysAdapter.ViewHolder>() {
private val TYPE_HEADER = 0
private val TYPE_DAY = 1
private var firstDayDayOfWeek = 0
private var totalDays = 0
init {
firstDayDayOfWeek = items[0].dayOfWeek
totalDays = items.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return ViewHolder(inflater.inflate(R.layout.item_day_new, parent, false))
}
override fun getItemCount() = 7 * 7
override fun getItemViewType(position: Int): Int {
return if (isPositionHeader(position)) {
TYPE_HEADER
} else {
TYPE_DAY
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//New position
var newPosition = position
newPosition = 6 - (newPosition % 7) * 2
if (totalDays < position - 6 - firstDayDayOfWeek) {
return
}
//Day
if (!isPositionHeader(newPosition)) {
if (newPosition - 7 - firstDayDayOfWeek >= 0) {
holder.dayTxt.text = items[newPosition - 7 - items[0].dayOfWeek].num
//Holiday
if (items[newPosition - 7 - firstDayDayOfWeek].isHoliday) {
holder.dayTxt.setTextColor(ContextCompat.getColor(context, R.color.red))
} else {
holder.dayTxt.setTextColor(ContextCompat.getColor(context, R.color.black))
}
}
} else {
//Header
holder.dayTxt.text = Constants.FIRST_CHAR_OF_DAYS_OF_WEEK_NAME[newPosition]
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val dayTxt = itemView.findViewById(R.id.dayTxt) as TextView
@SuppressLint("SetTextI18n")
fun bind() {
}
}
private fun isPositionHeader(position: Int) = position < 7
}
Error Message in Logcat:
java.lang.IndexOutOfBoundsException: Index: 34, Size: 30
at java.util.ArrayList.get(ArrayList.java:437)
at myapp.mycharts.calendar_my.utils.pages.month.DaysAdapter.onBindViewHolder(DaysAdapter.kt:53)
at myapp.mycharts.calendar_my.utils.pages.month.DaysAdapter.onBindViewHolder(DaysAdapter.kt:15)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7254)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6296)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2330)
at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:572)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3686)
at android.view.View.measure(View.java:23169)
Show error for this line:
holder.dayTxt.text = items[newPosition - 7 - items[0].dayOfWeek].num
My Fragment codes for fill days entity:
class CalendarMonthFragment : Fragment() {
private lateinit var binding: FragmentCalendarMonthBinding
private val utils by lazy { UtilsKotlin.getInstance(requireContext()) }
private var monthOffset = 0
private lateinit var persianDate: PersianDate
private val daysAdapter by lazy { DaysAdapter(requireContext(), daysList) }
private val daysList = mutableListOf<DayEntity>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentCalendarMonthBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//Utils
utils.let { utils ->
//Persian date
persianDate = utils.today
//Init days
arguments?.let {
monthOffset = it.getInt(Constants.OFFSET_ARGUMENT)
daysList.addAll(utils.getDays(monthOffset).toMutableList())
}
}
//Days recyclerview
daysAdapter.notifyDataSetChanged()
//InitViews
binding.apply {
//Recyclerview
daysRecyclerview.apply {
layoutManager = GridLayoutManager(requireContext(), 7)
adapter = daysAdapter
}
}
}
}
How can I fix it and show data into recyclerview ?
CodePudding user response:
You need to add a check for preventing crash for this line holder.dayTxt.text = items[newPosition - 7 - items[0].dayOfWeek].num
val position = newPosition - 7 - items[0].dayOfWeek
if(position != -1 && position < items.size) {
holder.dayText.text = items[position].num
}
try above code...
CodePudding user response:
IndexOutOfBounds says, that in items there's no element with such position number.
At first check if "items" consists any elements,
if yes then check if items[0] exists.
if yes then you can get result number from
val resultPos = newPosition - 7 - items[0].dayOfWeek
and the check if items.size > resultPos
if yes then you can get this element.
I hope it can help you.