I'm trying to use a RecyclerView to show an array of values in CardViews in a specific order i.e. "Title A" & "Subtitle A" in 1 CardView; "Title B" & "Subtitle B" in another. Is there a way to obtain the values from the arrays in my fragment without having to create a new verbose class, or do I have to use a data class to achieve this?
Fragment class
class MyFragment : androidx.fragment.app.Fragment() {
private lateinit var mRecyclerView: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_rv, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
val v = view
mRecyclerView = v!!.findViewById<RecyclerView>(R.id.my_recyclerview)
mRecyclerView.layoutManager = LinearLayoutManager(activity)
val myList = mutableListOf(
RVAdapterTConnections.ITEM_A,
RVAdapterTConnections.ITEM_B,
RVAdapterTConnections.ITEM_B
)
val titlesList = mutableListOf(
"Title A",
"Title B"
)
val subtitlesList = mutableListOf(
"Subtitle A",
"Subtitle B"
)
val mAdapter = MyRVAdapter(myList, titlesList)
mRecyclerView.adapter = mAdapter
super.onActivityCreated(savedInstanceState)
}
}
Adapter class
internal class MyRVAdapter(private val listViewType: List<Int>, private val myList: List<CharSequence>) : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {
companion object {
const val ITEM_A = 1
const val ITEM_B = 2
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
ITEM_A -> ViewHolderItemA(inflater.inflate(R.layout.layout_item_a, parent, false))
else -> ViewHolderItemB(inflater.inflate(R.layout.layout_item_b, parent, false))
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val viewType = listViewType[position]
when (viewType) {
ITEM_A -> {
val viewHolderA = holder as ViewHolderItemA
viewHolderA.textView.text = "Lorem Ipsum"
}
ITEM_B -> {
val viewHolderB = holder as ViewHolderItemB
viewHolderB.ivExpandCollapse.setImageDrawable(ContextCompat.getDrawable(holder.ivExpandCollapse.context, R.drawable.ic_keyboard_arrow_down))
viewHolderB.tvTitle.text = titlesList[position]
viewHolderB.tvSubtitle.text = subtitlesList[position]
}
else -> {
val viewHolderA = holder as ViewHolderItemA
viewHolderA.textView.text = "Lorem Ipsum"
}
}
}
override fun getItemCount(): Int = listViewType.size
override fun getItemViewType(position: Int): Int = listViewType[position]
open inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
inner class ViewHolderItemA(itemView: View) : ViewHolder(itemView) {
val textView: TextView = itemView.findViewById(R.id.my_custom_tv)
}
inner class ViewHolderItemB(itemView: View) : ViewHolder(itemView) {
val tvTitle: TextView = itemView.findViewById(R.id.tv_title)
val tvSubtitle: TextView = itemView.findViewById(R.id.tv_subtitle)
}
}
Data class
data class MyItem (val title: String, val subtitle: String)
the view-type ordinary can be derived from the data model, most commonly from some type of groupId. these titlesList and subtitlesList need to be replaced; use BaseAdapter to populate the RecyclerView.Adapter. for example (it loads string resources, where SpinnerItem is a simple data model):
abstract class BaseArrayAdapter : BaseAdapter {
private var mItems: ArrayList<SpinnerItem>? = null
private var layoutInflater: LayoutInflater? = null
internal constructor(#NonNull context: Context) {
this.layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
}
internal constructor(#NonNull context: Context, #NonNull #ArrayRes arrayKeys: Int, #NonNull #ArrayRes arrayValues: Int) {
this.layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
this.setItems(context, arrayKeys, arrayValues)
}
#NonNull
#Override
override fun getItem(position: Int): SpinnerItem {
return this.mItems!!.get(position)
}
#Override
override fun getItemId(position: Int): Long {
return this.mItems!!.get(position).id!!
}
#NonNull
#Override
override fun getView(position: Int, #Nullable view: View?, #NonNull parent: ViewGroup): View {
var convertView = view
if (convertView == null) {
convertView = this.layoutInflater!!.inflate(R.layout.support_simple_spinner_dropdown_item, parent, false)
}
convertView!!.setTag(this.mItems!!.get(position))
val textView: TextView = convertView.findViewById(android.R.id.text1)
textView.text = this.mItems!![position].name
textView.setAllCaps(true)
return convertView
}
private fun clearItems() {
if (this.mItems != null) {
this.mItems!!.clear()
} else {
this.mItems = ArrayList()
}
}
internal fun setItems(#NonNull context: Context, #NonNull #ArrayRes arrayKeys: Int, #NonNull #ArrayRes arrayValues: Int) {
this.clearItems()
val res = context.getResources()
val keys = res.getStringArray(arrayKeys)
val values = res.getStringArray(arrayValues)
for (i in keys.indices) {
this.mItems!!.add(i, SpinnerItem((i + 1).toLong(), keys[i], values[i]))
}
}
override fun getCount(): Int {
return this.mItems!!.size
}
}
some sub-class of the abstract class:
class SomeAdapter(#NonNull context: Context) : BaseArrayAdapter(context) {
init {
this.setItems(context, R.array.some_keys, R.array.some_values)
}
}
and then in the RecyclerView.Adapter:
init {
this.setItems(new SomeAdapter(context));
}
Related
i have defined a val in my fragment like so
private var selectionMode: Boolean = false
and a property to change it
fun enableSelectionMode() {
selectionMode = true
}
and i passed both to Adapter and want to call enableSelectionMode after clicking on each recycler item but nothing happen
here is my fragment:
class PostsFragment : Fragment() {
private val model: PostsViewModel by activityViewModels()
private var selectionMode: Boolean = false
fun enableSelectionMode() {
selectionMode = true
}
private lateinit var recyclerView: RecyclerView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_posts, container, false)
recyclerView = view.findViewById(R.id.posts_recycler)
recyclerView.layoutManager = LinearLayoutManager(view.context)
model.posts.observe(viewLifecycleOwner, { items ->
recyclerView.adapter = PostsAdapter(items, model, selectionMode,
::enableSelectionMode)
})
return view
}
}
and my adapter
class PostsAdapter(
private val posts: List<Post>,
private val model: PostsViewModel,
private val selectionMode: Boolean,
private val enableIt: () -> Unit
) :
RecyclerView.Adapter<PostsAdapter.ViewHolder>() {
companion object {
private const val TYPE_FROM = 0
private const val TYPE_TO = 1
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var postContent: TextView = itemView.findViewById(R.id.post_content)
var selectPostCheckBox: ImageView = itemView.findViewById(R.id.post_select_checkbox)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(
if (viewType == TYPE_TO) R.layout.to_post else R.layout.from_post,
parent,
false
)
return ViewHolder(view)
}
#SuppressLint("CheckResult")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.selectPostCheckBox.visibility = if (selectionMode) View.VISIBLE else View.GONE
holder.postContent.text = selectionMode.toString()
holder.selectPostCheckBox.setImageResource(R.drawable.cursor_color)
holder.itemView.setOnClickListener() {
enableIt()
notifyDataSetChanged()
}
}
override fun getItemCount() = posts.size
override fun getItemViewType(position: Int): Int {
return posts[position].selfPost
}
}
I'm building quiz app and all the time I have trouble with notifying RecyclerView about updated item.
DiffUtil didn't work for me, anyway - I can use adapter.notifyItemChanged() but after this call my TabLayout jumps to start of it's width.
I have set onClickListener to my floatingButton to be sure that it's notifyItemChanged() issue.
Am I doing something wrong?
Fragment
class TestFragment : Fragment() {
private lateinit var viewModel: TestViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding: FragmentTestBinding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_test,
container,
false
)
val args = TestFragmentArgs.fromBundle(requireArguments())
val viewModelFactory = TestViewModelFactory(args.course)
viewModel = ViewModelProvider(this, viewModelFactory).get(TestViewModel::class.java)
binding.viewModel = viewModel
binding.lifecycleOwner = viewLifecycleOwner
val adapter = PagerAdapter(ClickListener { questionDatabase: QuestionDatabase, string: String ->
val questionUpdated = questionDatabase.apply { answer = string }
viewModel.updateAnswer(questionDatabase, questionUpdated)
})
binding.viewPager.adapter = adapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab: TabLayout.Tab, i: Int ->
tab.text = (i + 1).toString()
}.attach()
viewModel.pytania.observe(viewLifecycleOwner, Observer {
adapter.differ.submitList(it)
})
viewModel.score.observe(viewLifecycleOwner, Observer {
if (it != null) {
findNavController().navigate(
TestFragmentDirections.actionTestFragmentToScoreFragment(it)
)
viewModel.score.value = null
}
})
binding.bttnFinish.setOnClickListener {
adapter.notifyItemChanged(binding.viewPager.currentItem)
}
return binding.root
}
}
ViewModel
class TestViewModel(
test: String
): ViewModel() {
private val _pytania = MutableLiveData<List<QuestionDatabase>>()
val pytania: LiveData<List<QuestionDatabase>>
get() = _pytania
val score = MutableLiveData<Int?>()
init {
val listOfQuestions = mutableListOf<QuestionDatabase>()
for (x in 1..15) {
listOfQuestions.add(
QuestionDatabase(
question = "Question $x",
answerA = "AnswerA",
answerB = "AnswerB",
answerC = "AnswerC",
answerD = "AnswerD",
correctAnswer = "AnswerD",
image = 0,
questionNumber = 0
)
)
}
_pytania.value = listOfQuestions.toList()
}
fun updateAnswer(questionDatabase: QuestionDatabase, questionUpdated: QuestionDatabase) {
_pytania.value = _pytania.value?.replace(questionDatabase, questionUpdated)
}
}
ViewPagerAdapter
class PagerAdapter(
private val clickListener: ClickListener
) : RecyclerView.Adapter<ViewHolder>() {
private val differCallBack = object : DiffUtil.ItemCallback<QuestionDatabase>() {
override fun areItemsTheSame(oldItem: QuestionDatabase, newItem: QuestionDatabase): Boolean {
return oldItem.question == newItem.question
}
override fun areContentsTheSame(oldItem: QuestionDatabase, newItem: QuestionDatabase): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, differCallBack)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(differ.currentList[position], clickListener)
}
override fun getItemCount(): Int {
return differ.currentList.size
}
}
class ViewHolder private constructor(val binding: VpItemQuestionBinding): RecyclerView.ViewHolder(
binding.root
) {
fun bind(
question: QuestionDatabase,
clickListener: ClickListener
) {
binding.question = question
binding.onClickListener = clickListener
binding.executePendingBindings()
}
companion object {
fun from(parent: ViewGroup): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = VpItemQuestionBinding.inflate(layoutInflater, parent, false)
return ViewHolder(binding)
}
}
}
class ClickListener(val clickListener: (QuestionDatabase, string: String) -> Unit) {
fun onClick(question: QuestionDatabase, string: String) = clickListener(question, string)
}
Before notifyItemChanged()
After notifyItemChanged()
For a school project, I made a custom arrayadapter with a context, resources and items attribute. Today I received feedback from my teacher and he wants me to find a solution where I don't have a Context attribute because he doesnt like that I always need to specify the context.
This is my code:
class TalentListAdapter(
var mCtx: Context,
var resources: Int,
var items: MutableList<Talent>
) : ArrayAdapter<Talent>(mCtx, resources, items) {
lateinit var mItem: Talent
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val layoutInflater: LayoutInflater = LayoutInflater.from(mCtx)
val view: View = layoutInflater.inflate(resources, null)
mItem = items[position]
//set name of talent
val talentTextView: TextView = view.findViewById(R.id.talentName)
talentTextView.text = mItem.toString()
return view
}
}
He wants to get rid of the mCtx: Context attribute, but I don't find a solution for it. Any suggestions?
The adapter is created like this atm:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val listView: ListView = binding.talentList
// set custom adapter for talent_list
val adapter = TalentListAdapter(view.context, R.layout.talentlayout, binding.talentViewModel?.getTalents()?.value as MutableList<Talent>)
listView.adapter = adapter
}
Can you try this
class YourAdapter() : RecyclerView.Adapter<YourAdapter.ViewHolder>() {
inner class ViewHolder(val view: View) : RecyclerView.ViewHolder(view)
var Data: List<YourResponse> = emptyList()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(
R.layout.your_layout, parent, false
)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return Data.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val getYourModel = Data[position]
val Binding = holder.view
Binding.yourTextView.apply{
text = getYourModel.yourField
}
.....
}
}
and pass Data from your Fragment or Activity (my example uses Retrofit2)
private var theList: List<YourResponse> = emptyList()
private val theAdapter =yourAdapter()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
onUpdateData()
}
private fun onUpdateData() {
...
override fun onResponse(call: Call<YourResponse>, response: Response<YourResponse>) {
val body = response.body()?.results
if (response.isSuccessful && body != null) {
onUpdateDataSuccess(body)
} else {
// Something
}
}
...
}
private fun onUpdateDataSuccess(data: List<YourResponse>) {
theList = data
theAdapter.Data = data
}
...
You only need context while inflating so you should use parent.context instead of explicit context.
Parent.Context represent the Activity/Fragment where this recycler view is implemented.
I'm writing code to use multiple viewtype. But also I have to do inflate TextView.
I wanna inflate holder.participant using loop.
The raw data of participant is "AAA#BBB#CCC". using split method, I wanna inflate TextView.
what should I do for this? what I wanna say is how to inflate TextView or other views, not multiple viewtype.
class ScheduleAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
lateinit var view : View
lateinit var itemList: ArrayList<ScheduleItem>
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val context = parent.context
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
if(viewType == HEADER_TYPE){
view = inflater.inflate(R.layout.schedule_header,parent,false)
return HeaderViewHolder(view)
}
else if(viewType == ITEM_TYPE){
view = inflater.inflate(R.layout.schedule_item,parent,false)
return ItemViewHolder(view)
}else{
return HeaderViewHolder(view)
}
}
override fun getItemCount(): Int = itemList.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if(holder is HeaderViewHolder){
holder.startDay.text = itemList.get(position).startDay
}else if(holder is ItemViewHolder){
holder.time.text = itemList.get(position).startTime+"~"+itemList.get(position).endTime
holder.title.text = itemList.get(position).title
holder.participant.text = itemList.get(position).participant
holder.title.text = itemList.get(position).title
}
}
inner class HeaderViewHolder internal constructor(itemView: View) :
RecyclerView.ViewHolder(itemView) {
internal var startDay: TextView
init {
startDay = itemView.findViewById(R.id.startDay)
}
}
inner class ItemViewHolder internal constructor(itemView: View) :
RecyclerView.ViewHolder(itemView) {
internal var time: TextView
internal var title: TextView
internal var participant: TextView
internal var place: TextView
init {
time = itemView.findViewById(R.id.time)
title = itemView.findViewById(R.id.title)
participant = itemView.findViewById(R.id.participant)
place = itemView.findViewById(R.id.place)
}
}
fun addItems(items : ArrayList<ScheduleItem>){
items.addAll(items)
}
}
I did some corrections to your code. Maybe will help you
class ScheduleAdapter : RecyclerView.Adapter<ScheduleAdapter.BaseViewHolder>() {
private val itemsList = mutableListOf<ScheduleItem>()
override fun getItemCount(): Int = itemList.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
return when (viewType) {
HEADER_TYPE -> HeaderViewHolder.create(parent)
ITEM_TYPE -> ItemViewHolder.create(parent)
// TEXT_TYPE -> TextItemHolder.create(parent)
}
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
holder.bind(itemsList.get(position))
}
fun addItems(items: Collection<ScheduleItem>) {
itemsList.addAll(items)
notifyDataSetChanged()
}
fun clear() {
itemsList.clear()
notifyDataSetChanged()
}
abstract internal class BaseViewHolder
internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bind(item: ScheduleItem);
}
internal class HeaderViewHolder
internal constructor(itemView: View): BaseViewHolder(itemView) {
internal var startDay: TextView
init {
// initialize here your views
}
override fun bind(item: ScheduleItem) {
startDay.text = item.startDay
}
companion object {
#JvmStatic
fun create(container: ViewGroup): HeaderViewHolder {
val inflater = LayoutInflater.from(container.context)
return HeaderViewHolder(
inflater.inlate(R.layout.schedule_header), container, false
)
}
}
}
internal class ItemViewHolder
internal constructor(itemView: View): BaseViewHolder(itemView) {
internal var time: TextView
internal var title: TextView
internal var participant: TextView
internal var place: TextView
init {
// initialize here your views
}
override fun bind(item: ScheduleItem) {
time.text = item.startTime+"~"+item.endTime
title.text = item.title
participant.text = item.participant
title.text = item.title
}
companion object {
#JvmStatic
fun create(container: ViewGroup): ItemViewHolder {
val inflater = LayoutInflater.from(container.context)
return ItemViewHolder(
inflater.inlate(R.layout.schedule_item), container, false
)
}
}
}
internal class TextItemHolder
internal constructor(val textView: TextView): BaseViewHolder(textView) {
override fun bind(item: ScheduleItem) {
textView.text = "Set your values here"
}
companion object {
#JvmStatic
fun create(container: ViewGroup): TextItemHolder {
val textView = TextView(container.context)
textView.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
return TextItemHolder(textView)
}
}
}
}
P.S: I didn't test this code on my machine. There might be some syntax errors :)
I'm trying to get my RecyclerView adapter to obtain values from an Array in my fragment but for some reason is doesn't work and I get this error (I think I have gotten lost somewhere):
lateinit property dataTitles has not been initialized
What's the correct way to obtain the data in this scenario?
Fragment class
class MyFragment : androidx.fragment.app.Fragment() {
private lateinit var mRecyclerView: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_rv, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
val v = view
val dataTitles: ArrayList<String> = ArrayList()
val dataSubtitles: ArrayList<String> = ArrayList()
mRecyclerView = v!!.findViewById<RecyclerView>(R.id.my_recyclerview)
// Set the linear layout manager
mRecyclerView.layoutManager = LinearLayoutManager(activity)
// create the adapter
val mAdapter = MyRVAdapter()
// init data
dataTitles.add(getString(R.string.addition))
dataTitles.add(getString(R.string.subtraction))
dataTitles.add(getString(R.string.multiplication))
dataTitles.add(getString(R.string.division))
dataSubtitles.add(getString(R.string.addition_information))
dataSubtitles.add(getString(R.string.subtraction_information))
dataSubtitles.add(getString(R.string.multiplication_information))
dataSubtitles.add(getString(R.string.division_information))
// Set the adapter
mRecyclerView.adapter = mAdapter
super.onActivityCreated(savedInstanceState)
}
}
Adapter class
class MyRVAdapter(private val dataTitles: Array<String>, private val dataSubtitles: Array<String>): RecyclerView.Adapter<MyRVAdapter.MyViewHolder>() {
private val typeItem = 1
private val typeHeader = 2
private val typeGrid = 3
private val primeNumbers = arrayOf("2", "3", "5", "7", "11", "13",
"17", "19", "23")
private lateinit var adapterGV: MyAdapter
override fun onCreateViewHolder(parent: ViewGroup, type: Int): MyRVAdapter.MyViewHolder {
return when (type) {
typeHeader -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_header, parent))
typeItem -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_item, parent))
typeGrid -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_gv, parent))
else -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_item, parent))
}
}
override fun onBindViewHolder(viewHolder: MyRVAdapter.MyViewHolder, position: Int) {
val llGV = viewHolder.itemView.findViewById<LinearLayout>(R.id.ll_gv)
val llTV = viewHolder.itemView.findViewById<LinearLayout>(R.id.ll_tv)
val mGridView = viewHolder.itemView.findViewById<GridView>(R.id.my_gv)
when (getItemViewType(position)) {
typeHeader -> {
val tValueE = TypedValue()
// test
llTV.context.theme.resolveAttribute(R.attr.imgUnfoldMore, tValueE, true)
val tValueC = TypedValue()
// test
llTV.context.theme.resolveAttribute(R.attr.imgUnfoldLess, tValueC, true)
}
typeGrid -> {
val titleG = viewHolder.itemView.findViewById<TextView>(R.id.tv_gv_A)
titleG.setText(R.string.prime_numbers)
//
val cardViewGV = viewHolder.itemView.findViewById<CardView>(R.id.cv_gv)
val mLinearLayoutGV = viewHolder.itemView.findViewById<LinearLayout>(R.id.cardview_gv_titlerow
mGridViewA.isEnabled = false
mGridViewA.isVerticalScrollBarEnabled = false
// adapterGV = MyAdapter(activity!!.applicationContext, 0)
mGridViewA.adapter = adapterGV
for (ldnBusesRoute in ldnBusesRoutes) {
adapterGV.addAdapterItem(AdapterItem(ldnBusesRoute))
}
typeItem -> {
// get the current item
val itemA = dataTitles[position - 2]
val itemB = dataSubtitles[position - 2]
//
val txtTitle = viewHolder.itemView.findViewById<TextView>(R.id.tv_title)
txtTitle.text = itemA
val txtSubtitle = viewHolder.itemView.findViewById<TextView>(R.id.tv_subtitle)
txtSubtitle.text = itemB
}
}
}
private fun inflateHelper(resId: Int, parent: ViewGroup): View {
return LayoutInflater.from(parent.context).inflate(resId, parent, false)
}
// inner class for view holder to use,
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
// Adapter for GridView
private inner class MyAdapter internal constructor(context: Context, textviewid: Int) : ArrayAdapter<AdapterItem>(context, textviewid) {
private val items = ArrayList<AdapterItem>()
internal fun addAdapterItem(item: AdapterItem) {
items.add(item)
}
override fun getCount(): Int {
return items.size
}
override fun getItem(position: Int): AdapterItem? {
return items[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val rowView: View = when (convertView) {
null -> LayoutInflater.from(parent.context).inflate(R.layout.gridview_item, parent, false)
// activity!!.layoutInflater.inflate(R.layout.gridview_item, parent, false)
else -> convertView
}
val tv = rowView.findViewById(R.id.item_gridview) as TextView
tv.text = items[position].first
return rowView
}
}
internal inner class AdapterItem // add more items
(var first: String)
override fun getItemCount(): Int {
return dataTitles.size + 2
}
override fun getItemViewType(position: Int): Int {
return when (position) {
0 -> typeHeader
1 -> typeGrid
else -> typeItem
}
}
}
Well, the error is pretty straightforward: you're not initializing dataTitles. When you label a variable with lateinit, Kotlin expects you to initialize it later. It's a way to avoid having to declare the variable as nullable.
To initialize it, you can do something like:
private val mutableList = mutableListOf<String>()
And you're doing the same with dataSubtitles.