How to attach an adapter in fragment? - kotlin

I use Kotlin in SDK 29.
I would like to make a recyclerView in my fragment. When I run the device, it doesn't crash, the fragment appear but not the Recycler View and I have the following error :
E/RecyclerView: No adapter attached; skipping layout
Here is my code :
Adapter
Import :
import android.content.Context
import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.givenaskv1.R
import kotlinx.android.synthetic.main.item_post.view.*
Code :
class PostsAdapter (val context: Context, val posts : List<Post>) :
RecyclerView.Adapter<PostsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.item_post, parent, false)
return ViewHolder(view)
}
override fun getItemCount() = posts.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(posts[position])
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(post: Post) {
itemView.tvUsername.text = post.user?.firstName
itemView.tvDescription.text = post.description
Glide.with(context).load(post.imageUrl).into(itemView.ivPost)
itemView.tvRelativeTime.text = DateUtils.getRelativeTimeSpanString(post.creationTimeMs)
}
}
}
Fragment
Import :
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.givenaskv1.R
import com.example.givenaskv1.models.Post
import com.example.givenaskv1.models.PostsAdapter
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import kotlinx.android.synthetic.main.fragment_flux.*
Code :
private const val TAG = "Flux"
#Suppress("UNREACHABLE_CODE")
class Flux : Fragment() {
private lateinit var firestoreDb : FirebaseFirestore
private lateinit var posts : MutableList<Post>
private lateinit var adapter: PostsAdapter
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_flux, container, false)
posts = mutableListOf()
adapter = PostsAdapter(requireContext(), posts)
rvPosts.adapter = adapter
rvPosts.layoutManager = LinearLayoutManager(requireContext())
firestoreDb = FirebaseFirestore.getInstance()
val postsReference = firestoreDb.collection("post")
// .limit() indique le nombre de post MAXIMIM a afficher en même temps, pour éviter le lagg
.limit(20)
// .orderBy() filtre selon le critère choisi (ici par ordre chonologique)
.orderBy("creation_time_ms", Query.Direction.DESCENDING)
postsReference.addSnapshotListener{ snapshot, exception ->
if (exception != null || snapshot == null) {
Log.e(TAG, "Exception when querying posts", exception)
return#addSnapshotListener
}
val postList = snapshot.toObjects(Post::class.java)
posts.clear()
posts.addAll(postList)
adapter.notifyDataSetChanged()
for (post in postList) {
Log.i(TAG, "Post ${post}")
}
}
}
Fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Flux.Flux">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvPosts"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical"
/>
</LinearLayout>
Can you please help me ? Thank you !

You should return view at the end of onCreateView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_flux, container, false)
posts = mutableListOf()
adapter = PostsAdapter(requireContext(), posts)
rvPosts = view.findViewById<RecyclerView>(R.id.rvPosts)
rvPosts.layoutManager = LinearLayoutManager(requireContext())
rvPosts.adapter = adapter
firestoreDb = FirebaseFirestore.getInstance()
val postsReference = firestoreDb.collection("post")
// .limit() indique le nombre de post MAXIMIM a afficher en même temps, pour éviter le lagg
.limit(20)
// .orderBy() filtre selon le critère choisi (ici par ordre chonologique)
.orderBy("creation_time_ms", Query.Direction.DESCENDING)
postsReference.addSnapshotListener{ snapshot, exception ->
if (exception != null || snapshot == null) {
Log.e(TAG, "Exception when querying posts", exception)
return#addSnapshotListener
}
val postList = snapshot.toObjects(Post::class.java)
posts.clear()
posts.addAll(postList)
adapter.notifyDataSetChanged()
for (post in postList) {
Log.i(TAG, "Post ${post}")
}
}
return view
}

Related

ERROR. java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter

I have this code for my layout with RecyclerView
package com.josue.snapshots
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.firebase.ui.database.FirebaseRecyclerAdapter
import com.firebase.ui.database.FirebaseRecyclerOptions
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.josueproyects.snapshots.databinding.FragmentHomeBinding
import com.josueproyects.snapshots.databinding.ItemSnapshotBinding
import com.josueproyects.snapshots.snapshot.Snapshot
class HomeFragment : Fragment() {
private lateinit var mBinding: FragmentHomeBinding
private lateinit var mFirebaseAdapter: FirebaseRecyclerAdapter<Snapshot,SnapshotHoler>
private lateinit var mLayoutManager: RecyclerView.LayoutManager
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mBinding = FragmentHomeBinding.inflate(inflater,container,false)
return mBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val query = FirebaseDatabase.getInstance().reference //es la raiz
.child("snapshot") //es la rama
val options = FirebaseRecyclerOptions.Builder<Snapshot>()
.setQuery(query,Snapshot::class.java).build()
mFirebaseAdapter = object : FirebaseRecyclerAdapter<Snapshot,SnapshotHoler>(options){
private lateinit var mContext: Context
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SnapshotHoler {
mContext = parent.context //declarar el contexto
val view = LayoutInflater.from(mContext)
.inflate(R.layout.item_snapshot,parent,false)
return SnapshotHoler(view)
}
override fun onBindViewHolder(holder: SnapshotHoler, position: Int, model: Snapshot) {
val snapshot = getItem(position)
with(holder){
setListener(snapshot)
with(binding){
tvTitle.text = snapshot.title
Glide.with(mContext)
.load(snapshot.photoUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.centerCrop()
.into(imgPhoto)
}
}
}
override fun onDataChanged() {
super.onDataChanged()
mBinding.progressBar.visibility = View.GONE
}
override fun onError(error: DatabaseError) {
super.onError(error)
Toast.makeText(mContext, error.message,Toast.LENGTH_LONG).show()
}
}
mLayoutManager = LinearLayoutManager(context) //el tipo de vista que se vera (sera de forma LinearLayout)
mBinding.recyclerView.apply {
setHasFixedSize(true)
layoutManager = mLayoutManager
adapter = mFirebaseAdapter
}
}
override fun onStart() {
super.onStart()
mFirebaseAdapter.startListening()
}
override fun onStop() {
super.onStop()
mFirebaseAdapter.stopListening()
}
//holder del snapshot (para el recycler view)
inner class SnapshotHoler(view: View) : RecyclerView.ViewHolder(view){
val binding = ItemSnapshotBinding.bind(view)
fun setListener(snapshot: Snapshot){
}
}
}
But it shows me this error:
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionSnapshotHoler{15a1686 position=1 id=-1, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached no parent} androidx.recyclerview.widget.RecyclerView{123fd4a VFED..... .......D 0,0-1080,1437 #7f080163 app:id/recyclerView}, adapter:com.josueproyects.snapshots.HomeFragment$onViewCreated$1#4bb94bb, layout:androidx.recyclerview.widget.LinearLayoutManager#ed17dd8, context:com.josue.snapshots.MainActivity#9d9a2fd
at androidx.recyclerview.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:6156)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6339)
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.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4255)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4010)
at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:2028)
at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:417)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:693)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
The project consists of uploading data to Firebase, when I enter the app everything goes well, but when I am in the Add frangment, I click an ImageButton to open the phone gallery, I select the photo and show it, but when show it in the layout I get the error, I know it has to do with the RecyclerView but... What do I do?.

RecyclerView doesn't appear on screen

The list doesn't display on screen and it doesn't throw any error.
Am I doing something wrong connecting the adapter and layoutmanager?
Whenever I open the fragment it writes the following line: "W/RecyclerView: No adapter attached; skipping layout" and it doesn't change anything to the fragment.
This is the MainActivity.kt:
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomnavigation.BottomNavigationView
class MainActivity : AppCompatActivity() {
val addnewmoviefragment = AddNewMovieFragment()
val movielistfragment = MovieListFragment()
val moviedetailsfragment = MovieDetailsFragment()
private var layoutManager: RecyclerView.LayoutManager? = null
private var adapter: RecyclerView.Adapter<MovieListViewAdapter.ViewHolder>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
replaceFragment(movielistfragment)
val movies: MutableList<Movies> = initList()
layoutManager = LinearLayoutManager(this)
adapter = MovieListViewAdapter(this, movies)
val button = findViewById<BottomNavigationView>(R.id.bottom_navigation)
button.setOnNavigationItemSelectedListener {
when(it.itemId){
R.id.ic_movieadd -> replaceFragment(addnewmoviefragment)
R.id.ic_moviedetails -> replaceFragment(movielistfragment)
}
true
}
//val submitButton = findViewById<Button>(R.id.submitButton)
//val cancelButton = findViewById<Button>(R.id.cancelButton)
}
private fun replaceFragment(fragment: Fragment){
if(fragment!=null){
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, fragment)
transaction.commit()
}
}
private fun initList(): MutableList<Movies>{
return mutableListOf(
Movies(1, "Inception", "Very good movie!", "James Gun", Actors("Simeon")),
Movies(2, "Extracton", "Extracting!", "Christopher Nolan", Actors("Ivan"))
)
}
MovieListViewAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.EditText
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class MovieListViewAdapter(val context: Context, val allMovies: MutableList<Movies>):
RecyclerView.Adapter<MovieListViewAdapter.ViewHolder>(){
class ViewHolder(view: View): RecyclerView.ViewHolder(view){
val id: TextView
val name: TextView
val description: TextView
val producer: TextView
val actors: TextView
init{
id = view.findViewById(R.id.movieId)
name = view.findViewById(R.id.movieNameId)
description = view.findViewById(R.id.movieDescriptionId)
producer = view.findViewById(R.id.movieProducerId)
actors = view.findViewById(R.id.movieActorsId)
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_view_row, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentMovie: Movies = allMovies[position]
holder.id.text = currentMovie.id.toString()
holder.name.text = currentMovie.name
holder.description.text = currentMovie.description
holder.producer.text = currentMovie.producer
holder.actors.text = currentMovie.actors.toString()
}
override fun getItemCount(): Int {
return allMovies.size
}
}
MovieListFragment.kt
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MovieListFragment : Fragment() {
private var layoutManager: RecyclerView.LayoutManager? = null
private var adapter: RecyclerView.Adapter<MovieListViewAdapter.ViewHolder>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view: View = inflater.inflate(R.layout.fragment_movie_list, container, false)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Toast.makeText(context, "You are viewing the movie list!", Toast.LENGTH_SHORT).show()
}
}
Movies.kt
data class Movies(
val id: Int,
val name: String,
val description: String,
val producer: String,
val actors: Actors
) {
}
Actors.kt
data class Actors(
val name: String
){}
fragment_movie_list.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MovieListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/movieListId"
android:layout_width="389dp"
android:layout_height="589dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.246" />
</androidx.constraintlayout.widget.ConstraintLayout>
recycler_view_row.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/indexId"
android:layout_width="68dp"
android:layout_height="23dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.045"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.079" />
<TextView
android:id="#+id/nameId"
android:layout_width="68dp"
android:layout_height="21dp"
android:layout_marginBottom="620dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.046"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/descriptionId"
android:layout_width="68dp"
android:layout_height="19dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/nameId" />
<TextView
android:id="#+id/producerId"
android:layout_width="68dp"
android:layout_height="23dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/descriptionId" />
<TextView
android:id="#+id/actorsId"
android:layout_width="65dp"
android:layout_height="21dp"
android:layout_marginStart="16dp"
android:layout_marginTop="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/producerId" />
</androidx.constraintlayout.widget.ConstraintLayout>
From the code, I see that the adapter gets instantiated, but never attached to the recyclerView.
You are just missing the following line in the onViewCreated override in the fragment.
findViewById<RecyclerView>(R.id.movieListId).adapter = adapter
https://developer.android.com/guide/topics/ui/layout/recyclerview

Kotlin :Can't get the price of the item of RecyclerView on Fragment

I am attempting to make a recyclerView on Fragment ,
The idea is to get the price of the Item ,when the item been selected ,
and multiply by the select amount from the popup menu also.
Like below :
The recyclerView model item : item_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="120dp"
android:gravity="center"
android:id="#+id/cardView"
android:layout_margin="10dp"
android:background="#40E0D0"
android:layout_height="200dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Price:"
android:textColor="#color/black"
android:textSize="18sp"/>
<TextView
android:id="#+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="100"
android:textColor="#color/black"
android:textSize="18sp"/>
</LinearLayout>
The model of the item : Product.kt :
package com.gearsrun.popmenuapplication
data class Product(var price : String)
private selectFuntion(itemPrice:Int){
}
ProductAdapter.kt
package com.gearsrun.popmenuapplication
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_layout.view.*
class ProductAdapter(private val productList:List<Product>,private val itemClick:(Int) -> Unit):RecyclerView.Adapter<ProductAdapter.ProductViewHolder>() {
private var selectedItemPosition :Int = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false)
return ProductViewHolder(itemView,itemClick)
}
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val currentItem = productList[position]
holder.price.text = currentItem.price.toString()
holder.itemView.setOnClickListener {
selectedItemPosition = position
notifyDataSetChanged()
}
if(selectedItemPosition == position){
holder.itemView.cardView.setBackgroundColor(Color.parseColor("#FAFAD2"))
}else{
holder.itemView.cardView.setBackgroundColor(Color.parseColor("#FFFFFF"))
}
}
override fun getItemCount() = productList.size
class ProductViewHolder(itemView: View, itemClick: (Int) -> Unit) :
RecyclerView.ViewHolder(itemView) {
val price : TextView = itemView.price
init {
itemView.setOnClickListener {
itemClick(price.text.toString().toInt()) //sortOf if you need String, change that on String in every declaration
}
}
}
}
Fragment.kt
package com.gearsrun.popmenuapplication.fragment
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.PopupMenu
import androidx.recyclerview.widget.LinearLayoutManager
import com.gearsrun.popmenuapplication.Product
import com.gearsrun.popmenuapplication.ProductAdapter
import com.gearsrun.popmenuapplication.R
import kotlinx.android.synthetic.main.fragment_home.*
class HomeFragment : Fragment(R.layout.fragment_home) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//init popup menu
val popupMenu = PopupMenu(
context,
selectedTv
)
//add menu items to popup menu
popupMenu.menu.add(Menu.NONE,0,0,"1")
popupMenu.menu.add(Menu.NONE,1,1,"2")
popupMenu.menu.add(Menu.NONE,2,2,"3")
popupMenu.menu.add(Menu.NONE,3,3,"4")
popupMenu.menu.add(Menu.NONE,4,4,"5")
//handle menu clicks
popupMenu.setOnMenuItemClickListener {menuItem ->
//get id of the item clicked
val id = menuItem.itemId
if(id==0){
selectedTv.text = "1"
}else if(id==1){
selectedTv.text = "2"
}else if(id==2){
selectedTv.text = "3"
}else if(id==3){
selectedTv.text = "4"
}else if(id==4){
selectedTv.text = "5"
}
true
}
//handle button click,show menu
selectedTv.setOnClickListener {
popupMenu.show()
}
//display recyclerview
val productList = generateProductList()
fun selectFuntion(itemPrice: Int){
Log.e("haha","You have click${itemPrice}")
}
var adapter = ProductAdapter(productList,::selectFuntion)
giftRecycleView.adapter = adapter
giftRecycleView.layoutManager = LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false)
}
private fun generateProductList():List<Product> {
val list = ArrayList<Product>()
list.add(Product(1))
list.add(Product(2))
list.add(Product(3))
return list
}
}
Can anyone help me modify my code ?
I will need that the item's value can be catch once click ,and multiply by the select amount ,in order to get the total price .
Thank you so much in advance !!
ProductAdapter.kt
add this:
class ProductAdapter(
private val productList:List<Product>,
private val itemClick: (Int) -> Unit
): RecyclerView.Adapter<ProductAdapter.ProductViewHolder>() {
delete this:
interface onItemClickListener {
fun onItemClick(position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener) {
mlistener = listener
}
replace this:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false)
return ProductViewHolder(itemView,itemClick)
}
replace this:
class ProductViewHolder(itemView: View, itemClick: (Int) -> Unit) :
RecyclerView.ViewHolder(itemView) {
val price : TextView = itemView.price
init {
itemView.setOnClickListener {
itemclick(price.text.toInt()) //sortOf if you need String, change that on String in every declaration
}
}
}
replace in fragment:
var adapter = ProductAdapter(productList, ::yourFunction)
giftRecycleView.adapter = adapter
add in fragment or ViewModel:
private yourFunction(itemPrice: Int) {
// do something with price
}
if you need to edit that price just make return type:
(Int) -> Int sort of :D
and in adapter
price.text = itemclick(price.text.toInt()).toString()

How can I attach an adapter to my fragment?

I use Kotlin in SDK 29.
I would like to make a recyclerView in my fragment. When I run the device, it doesn't crash, the fragment appear but not the Recycler View and I have the following error :
E/RecyclerView: No adapter attached; skipping layout
Here is my code :
Adapter
Import :
import android.content.Context
import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.givenaskv1.R
import kotlinx.android.synthetic.main.item_post.view.*
Code :
class PostsAdapter (val context: Context, val posts : List<Post>) :
RecyclerView.Adapter<PostsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.item_post, parent, false)
return ViewHolder(view)
}
override fun getItemCount() = posts.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(posts[position])
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(post: Post) {
itemView.tvUsername.text = post.user?.firstName
itemView.tvDescription.text = post.description
Glide.with(context).load(post.imageUrl).into(itemView.ivPost)
itemView.tvRelativeTime.text = DateUtils.getRelativeTimeSpanString(post.creationTimeMs)
}
}
}
Fragment
Import :
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.Navigation
import com.example.givenaskv1.R
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.fragment_page_profil.*
Code :
class FragmentPageProfil : BottomSheetDialogFragment(), OnMapReadyCallback {
private lateinit var googleMap: GoogleMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
readFireStoreData()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_page_profil, container, false)
readFireStoreData()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btnProfilOption.setOnClickListener {
val action = FragmentPageProfilDirections.actionFragmentPageProfil2ToProfilOption()
Navigation.findNavController(it).navigate(action)
}
retourBtnprofil.setOnClickListener {
val action = FragmentPageProfilDirections.actionFragmentPageProfil2ToNotificationFragment()
Navigation.findNavController(it).navigate(action)
}
btnCalendar.setOnClickListener {
val action = FragmentPageProfilDirections.actionFragmentPageProfil2ToFragmentCalendrier()
Navigation.findNavController(it).navigate(action)
}
mapProfil.onCreate(savedInstanceState)
mapProfil.onResume()
mapProfil.getMapAsync(this)
}
override fun onMapReady(map: GoogleMap?) {
map?.let {
googleMap = it
}
}
fun readFireStoreData() {
val db = FirebaseFirestore.getInstance()
db.collection("users")
.get()
.addOnCompleteListener {
val result: StringBuffer = StringBuffer()
if(it.isSuccessful) {
for(document in it.result!!) {
result.append(document.data.getValue("firstName")).append(" ")
}
nomUtilisateur.setText(result)
}
}
}
}
Fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Flux.Flux">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvPosts"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Can you please help me ?
Thank you !
You forgot to add layoutManager and orientation that's it
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvPosts"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical" />
And You can also fix this function as after return the function doesn't call ever
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
readFireStoreData()
return inflater.inflate(R.layout.fragment_page_profil, container, false)
}
E/RecyclerView: No adapter attached; skipping layout error could be happened when adapter has no data.
Move readFireStoreData() function to before return inflater code
like as below.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
readFireStoreData()
return inflater.inflate(R.layout.fragment_page_profil, container, false)
}

Kotlin RecyclerView how select first list item after activity load? tried (code below) failed :(

I can select 1st item in RecyclerView (working code below, click on "email" FAB button - boom! 1st selected)
However I cannot get 1st RecyclerView click in code when app starts,
I looked for override fun onViewCreated() but nothing like it for activity,
where can I call selectFirstOnList() after activity & recyclerview fully rendered?
what event fires on activity fully rendered/loaded?
or is my noob kotlin way of thinking flawed? its 99.9% working :(
Thanks in advance for any help :)
SOLUTIUON (code edited to bottom of this post will replace code in ItemListActivity.kt)
postdelay select first (you can see from original code I'd already tried something like this!) PHEW! hope this helps someone :)
ItemListActivity.kt
package ie.dpsystems.asm.list
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import ie.dpsystems.asm.R
import ie.dpsystems.asm.data.Orientation
import ie.dpsystems.asm.data.State
import ie.dpsystems.asm.data.State.Companion.trackLog
import ie.dpsystems.asm.detail.ItemDetailActivity
import ie.dpsystems.asm.detail.ItemDetailFragment
import kotlinx.android.synthetic.main.activity_item_list.*
import kotlinx.android.synthetic.main.item_list_content.view.*
import kotlinx.android.synthetic.main.item_list.*
import android.os.Handler
class ItemListActivity : AppCompatActivity() {
private var twoPane: Boolean = false
private var showToastEvents: Boolean = true
private fun uiIsTwoPane():Boolean{
try{
if (item_detail_container != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-w900dp).
// If this view is present, then the
// activity should be in two-pane mode.
return true
}
}catch(e:Exception)
{
Toast.makeText(this,"E: ${e.toString()}",Toast.LENGTH_SHORT).show()
}
return false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
trackLog(this,"onCreate()")
setContentView(R.layout.activity_item_list)
twoPane = uiIsTwoPane()
setSupportActionBar(toolbar)
toolbar.title = title
fab.setOnClickListener { view -> onListFabClick(view) }
setupRecyclerView(recycleview_list)
refreshUI()
}
private fun setupRecyclerView(recyclerView: RecyclerView) {
trackLog(this,"setupRecyclerView()")
State.dataRows = ListContent.ITEMS
recyclerView.adapter = SimpleItemRecyclerViewAdapter(
this,
twoPane,
this
)
var recycleViewUI = recycleview_list
postAndNotifyAdapter(Handler(), recycleViewUI)
}
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
trackLog(this,"onConfigurationChanged()")
}
override fun onStart() {
super.onStart()
trackLog(this,"onStart()")
}
override fun onResume() {
super.onResume()
trackLog(this,"onResume() A")
checkOrientationChange()
refreshUI()
trackLog(this,"onResume() B")
}
private fun checkOrientationChange() {
trackLog(this,"checkOrientationChange()")
if (State.lastOrientation != null) {
val thisOrientation = if (twoPane) Orientation.landscape else Orientation.portrate
if (thisOrientation != State.lastOrientation) {
putDetailFragmentOnDetailFragmentHolder()
}
}
}
private fun putDetailFragmentOnDetailFragmentHolder() {
trackLog(this,"putDetailFragmentOnDetailFragmentHolder()")
if(item_detail_container!=null){
val fragment = ItemDetailFragment() //val fragment = ItemDetailFragment().apply {arguments = Bundle().apply {putInt("SOME UNIQUE TAG", selectedItemUniqueID)}}
val container = item_detail_container
container.removeAllViewsInLayout()
supportFragmentManager.beginTransaction().replace(R.id.item_detail_container, fragment).commit()
}
}
override fun onPause() {
super.onPause()
trackLog(this,"onPause()")
}
override fun onStop() {
super.onStop()
trackLog(this,"onStop()")
}
class SimpleItemRecyclerViewAdapter( private val parentActivity: ItemListActivity
,private val twoPane: Boolean
,private val context: Context //private val context = parentActivity.applicationContext
) : RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder>() {
override fun getItemCount(): Int {
return State.dataRows.size
}
override fun onBindViewHolder(recyclerViewRow: ViewHolder, position: Int) {
trackLog(context, "onBindViewHolder()")
val dataThisRow = State.dataRows[position]
dataThisRow.listRowIndex = position
setDataToRecyclerRow(recyclerViewRow, dataThisRow)
recyclerViewRow.itemView.setOnClickListener {
onListItemClick(dataThisRow.uniqueID)
}
if (dataThisRow.uniqueID == State.selectedListItemUniqueId) {
recyclerViewRow.idRow.setBackgroundColor(Color.parseColor("#009688"))
} else {
recyclerViewRow.idRow.setBackgroundColor(Color.WHITE)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
trackLog(context, "onCreateViewHolder()")
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_list_content, parent, false)
return ViewHolder(view, 1)
}
override fun onViewAttachedToWindow(holder: ViewHolder) {
super.onViewAttachedToWindow(holder)
trackLog(context, "onViewAttachedToWindow()")
}
inner class ViewHolder(itemView: View, position: Int) : RecyclerView.ViewHolder(itemView) {
val idView: TextView = itemView.id_text
val contentView: TextView = itemView.content
val idRow = itemView.id_row_linear_layout
}
private fun setDataToRecyclerRow(recyclerViewRow: ViewHolder, data: ListContent.ListItem) {
trackLog(context, "setDataToRecyclerRow(id: ${data.id})")
recyclerViewRow.idView.text = data.id
recyclerViewRow.contentView.text = data.itemTitle
recyclerViewRow.itemView.tag = data
}
private fun onListItemClick(selectedItemUniqueID: Int) {
trackLog(context, "onListItemClick($selectedItemUniqueID)")
State.selectedListItemUniqueId = selectedItemUniqueID
if (twoPane) {
State.lastOrientation = Orientation.landscape
putDetailFragmentOnDetailActivity()
} else {
State.lastOrientation = Orientation.portrate
launchDetailActivity()
}
notifyDataSetChanged()
}
private fun launchDetailActivity() {
trackLog(context, "launchDetailActivity()")
val intent = Intent(
context,
ItemDetailActivity::class.java
) //val intent = Intent(context, ItemDetailActivity::class.java).apply {putExtra(ItemDetailFragment.ARG_ITEM_ID, selectedItemUniqueID)}
context.startActivity(intent)
}
private fun putDetailFragmentOnDetailActivity() {
trackLog(context, "putDetailFragmentOnDetailFragmentHolder()")
val fragment =
ItemDetailFragment() //val fragment = ItemDetailFragment().apply {arguments = Bundle().apply {putInt("SOME UNIQUE TAG", selectedItemUniqueID)}}
val container = parentActivity.item_detail_container
container.removeAllViewsInLayout()
parentActivity.supportFragmentManager.beginTransaction()
.replace(R.id.item_detail_container, fragment).commit()
}
}
private fun onListFabClick(view: View) {
trackLog(this, "onListFabClick()")
selectFirstOnList()
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
private fun refreshUI() {
trackLog(this, "refreshUI()")
var recycleViewUI = recycleview_list
if (State.selectedListItemUniqueId == null) {
selectFirstOnList()
} else {
val selectedListItem: ListContent.ListItem? =
State.findDataRowByUniqueId(State.selectedListItemUniqueId)
if (selectedListItem == null) {
selectFirstOnList()
recycleViewUI.findViewHolderForAdapterPosition(0)?.itemView?.performClick()
} else {
recycleViewUI.getLayoutManager()
?.scrollToPosition(selectedListItem.listRowIndex)
}
}
}
private fun selectFirstOnList() {
trackLog(this, "selectFirstOnList()")
if (twoPane) {
var recycleViewUI = recycleview_list
//recycleViewUI.getLayoutManager()?.scrollToPosition(0)
recycleViewUI.findViewHolderForAdapterPosition(0)?.itemView?.performClick()
}
}
protected fun postAndNotifyAdapter(handler: Handler, recyclerView: RecyclerView) {
trackLog(this, "postAndNotifyAdapter()")
/*
handler.post(Runnable {
if (!recyclerView.isComputingLayout) {
// This will call first item by calling "performClick()" of view.
(recyclerView.findViewHolderForLayoutPosition(0) as RecyclerView.ViewHolder).itemView.performClick()
} else {
postAndNotifyAdapter(handler, recyclerView) //, adapter
}
})
*/
}
}
class State (hold selected on screen rotation/activity changes)
import android.content.Context
import android.util.Log
import android.widget.Toast
import ie.dpsystems.asm.list.ListContent
import java.util.ArrayList
enum class Orientation { portrate, landscape }
class State {
companion object {
public var selectedListItemUniqueId:Int? = null
public var dataRows: MutableList<ListContent.ListItem> = ArrayList()
public var lastOrientation:Orientation? = null
public fun findDataRowByUniqueId(uniqueID:Int?):ListContent.ListItem?{
if(uniqueID==null) return null
return State.dataRows.find { it.uniqueID == uniqueID}
}
public fun trackLog(context: Context, text:String){
//Toast.makeText(context,text, Toast.LENGTH_LONG).show()
Log.d("track",text)
}
}
}
src/main/res/layout-w900dp/item_list.xml (2 pane for tablet)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle"
tools:context=".list.ItemListActivity">
<!--
This layout is a two-pane layout for list / detail
-->
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/recycleview_list"
android:name="ie.dpsystems.asm.ItemListFragment"
android:layout_width="#dimen/item_width"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context="ie.dpsystems.asm.list.ItemListActivity"
tools:listitem="#layout/item_list_content" />
<FrameLayout
android:id="#+id/item_detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
item_list_content.xml (RecyclerView per row layout)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/id_row_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/id_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem" />
</LinearLayout>
object ListContent (to put fake data into list during development)
import java.util.ArrayList
import java.util.HashMap
/**
* Helper class for providing sample itemTitle for user interfaces created by
* Android template wizards.
*
* TODO: Replace all uses of this class before publishing your app.
*/
object ListContent {
/**
* An array of sample (dummy) items.
*/
val ITEMS: MutableList<ListItem> = ArrayList()
/**
* A map of sample (dummy) items, by ID.
*/
val ITEM_MAP: MutableMap<String, ListItem> = HashMap()
private val COUNT = 25
init {
// Add some sample items.
for (i in 1..COUNT) {
addItem(fakeGetRecordFromSqlite(i))
}
}
private fun addItem(item: ListItem) {
ITEMS.add(item)
ITEM_MAP.put(item.id, item)
}
private fun fakeGetRecordFromSqlite(position: Int): ListItem {
return ListItem(position, -1, position.toString(), "Item " + position, fakeGetRecordCollectionFromSqlite(position))
}
private fun fakeGetRecordCollectionFromSqlite(position: Int): String {
val builder = StringBuilder()
builder.append("Details about Item: ").append(position)
for (i in 0..position - 1) {
builder.append("\nMore details information here.")
}
return builder.toString()
}
/**
* A dummy item representing a piece of itemTitle.
*/
data class ListItem(val uniqueID:Int, var listRowIndex:Int, val id: String, val itemTitle: String, val details: String) {
override fun toString(): String = itemTitle
}
}
class ItemDetailFragment (display details in detail fragment)
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import ie.dpsystems.asm.R
import ie.dpsystems.asm.data.State
import ie.dpsystems.asm.list.ListContent
import kotlinx.android.synthetic.main.activity_item_detail.*
import kotlinx.android.synthetic.main.item_detail.view.*
/**
* A fragment representing a single Item detail screen.
* This fragment is either contained in a [ItemListActivity]
* in two-pane mode (on tablets) or a [ItemDetailActivity]
* on handsets.
*/
class ItemDetailFragment : Fragment() {
/**
* The dummy itemTitle this fragment is presenting.
*/
private var item: ListContent.ListItem? = null
private var selectedItemUniqueID:Int? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//arguments?.let { if (it.containsKey(ARG_ITEM_ID)) {val uniqueID = it.getInt(ARG_ITEM_ID)}}
item = State.findDataRowByUniqueId(State.selectedListItemUniqueId)
activity?.toolbar_layout?.title = item?.itemTitle
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(R.layout.item_detail, container, false)
item?.let {rootView.item_detail.text = it.details}
return rootView
}
}
class ItemDetailActivity (for single pane screen size devices)
import android.content.Intent
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NavUtils
import android.view.MenuItem
import android.view.View
import ie.dpsystems.asm.list.ItemListActivity
import ie.dpsystems.asm.R
import kotlinx.android.synthetic.main.activity_item_detail.*
import kotlinx.android.synthetic.main.activity_item_detail.fab
/**
* An activity representing a single Item detail screen. This
* activity is only used on narrow width devices. On tablet-size devices,
* item details are presented side-by-side with a list of items
* in a [ItemListActivity].
*/
class ItemDetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_item_detail)
setSupportActionBar(detail_toolbar)
fab.setOnClickListener { view -> onListFabClick(view) }
supportActionBar?.setDisplayHomeAsUpEnabled(true) // Show the Up button in the action bar.
putDetailFragmentOnDetailActivity(savedInstanceState)
}
private fun putDetailFragmentOnDetailActivity(savedInstanceState: Bundle?){ // Create the detail fragment and add it to the activity using a fragment transaction.
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
// (e.g. when rotating the screen from portrait to landscape).
// In this case, the fragment will automatically be re-added
// to its container so we don't need to manually add it.
// For more information, see the Fragments API guide at:
// http://developer.android.com/guide/components/fragments.html
if (savedInstanceState == null) {
val fragment = ItemDetailFragment() //val fragment = ItemDetailFragment().apply {arguments = Bundle().apply {putString("SOME UNIQUE TAG",intent.getStringExtra("SOME UNIQUE TAG"))}}
supportFragmentManager.beginTransaction().add(R.id.item_detail_container, fragment).commit()
}
}
private fun onListFabClick(view: View?) {
if(view!=null) Snackbar.make(view, "Replace with your own detail action", Snackbar.LENGTH_LONG).setAction("Action", null).show()
}
override fun onOptionsItemSelected(item: MenuItem) =
when (item.itemId) {
android.R.id.home -> {
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
NavUtils.navigateUpTo(this, Intent(this, ItemListActivity::class.java))
true
}
else -> super.onOptionsItemSelected(item)
}
}
SOLUTIUON
postdelay select first (you can see from original code I'd already tried something like this!) PHEW! hope this helps someone :)
protected fun postAndNotifyAdapter(handler: Handler, recyclerView: RecyclerView) {
trackLog(this, "postAndNotifyAdapter() ${State.selectedListItemUniqueId}")
if (twoPane && State.selectedListItemUniqueId==null) {
Handler().postDelayed({
if (!recyclerView.isComputingLayout) {
trackLog(this, "postAndNotifyAdapter() !recyclerView.isComputingLayout ${State.selectedListItemUniqueId}")
selectFirstOnList()
} else {
postAndNotifyAdapter(handler, recyclerView) //, adapter
}
}, 1000)
}
}
I've edited my original post above to be complete with answer!
I recommend you use an interface to notify when recyclerview is done rendering it's items.
How to know when the RecyclerView has finished laying down the items?