Unable To Load ImageView from External Storage RecyclerView - firebase

I am working on an Android app which has to load all QR created image from external storage to the fragment which contains a RecyclerView. All the work goes fine, but as I tried to load the image from the specific path from external storage directory, it fails to load and throws an exception..
I am stuck with this as I have given the path to it like
override fun onBindViewHolder(holder: ItemHolder, position: Int) {
val charItemcreate: CharItemsCreate = arrayList.get(position)
val path: String = Environment.getExternalStorageDirectory().toString() + "Maximus/QRCreated/"
val bitmap = BitmapFactory.decodeFile(path)
//holder.images = charItemcreate.imageload.toIcon()
}
Here is the Layout I Created For RecyclerView..
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constmain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints">
<ImageView
android:layout_width="#dimen/_62sdp"
android:layout_height="#dimen/_62sdp"
android:id="#+id/imgrecyclerviewcreate"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/txt_nametext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#id/imgrecyclerviewcreate"
android:text="#string/email"/>
<TextView
android:id="#+id/txt_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#id/imgrecyclerviewcreate"
app:layout_constraintTop_toBottomOf="#+id/txt_nametext"
android:text="#string/email"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The Adapter Class I have Created where i have Given the Images Folder path
class AdapterCreateHistory(var context: Context, var arrayList: ArrayList<CharItemsCreate>) :
RecyclerView.Adapter<AdapterCreateHistory.ItemHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
val viewHolder = LayoutInflater.from(parent.context)
.inflate(R.layout.createhistoryitem, parent, false)
return ItemHolder(viewHolder)
}
override fun getItemCount(): Int {
return arrayList.size
}
override fun onBindViewHolder(holder: ItemHolder, position: Int) {
val charItemcreate: CharItemsCreate = arrayList.get(position)
val path: String = Environment.getExternalStorageDirectory().toString() + "Maximus/QRCreated/"
val bitmap = BitmapFactory.decodeFile(path)
//holder.images = charItemcreate.imageload.toIcon()
}
class ItemHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var images = itemView.findViewById<ImageView>(R.id.imgrecyclerviewcreate)
}
Here is the Kotlin Model Class
class CharItemsCreate {
var imageload: Bitmap? = null
constructor(imageload: Bitmap) {
this.imageload = imageload
}
}
Here is the Main Fragment I am Working on. In Here I have Initialez the RecyclerView and the CharItemClass
class FragmentViewPagerScanHistory : Fragment() {
private var charItemcreate: ArrayList<CharItemsCreate>? = null
private var customAdaptercreate: AdapterCreateHistory? = null
private var gridLayoutManager: GridLayoutManager? = null
//val TYPE_SAVED = 15
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_view_pager_scan_history, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
gridLayoutManager = GridLayoutManager(context, 1, LinearLayoutManager.VERTICAL, false)
recyclerviewcreatehistory?.layoutManager = gridLayoutManager
recyclerviewcreatehistory?.setHasFixedSize(true)
charItemcreate = setImages()
customAdaptercreate = AdapterCreateHistory(this.context ?: return, charItemcreate!!)
recyclerViewfragment?.adapter = customAdaptercreate
}
private fun setImages(): ArrayList<CharItemsCreate>? {
return charItemcreate
}
I am Unable to Load Images into RecyclerView as I Am Getting Exception . I have Attached the Debugger With this It Also Give me the Null Values...
I have Also Given the Read Permission in the Manifest
Here is the Logcat After It Crashed

Hello you can use Glide or picasso library, that will handle exception in very appropriate way,
here is the implementation of Glide :-
implementation 'com.github.bumptech.glide:glide:4.11.0'
This is is the code block :-
Glide.with(context).load(yourpath).centerCrop().error(image that place while error occure).into(imageview);

Related

How to use onClick method of fragment inside recycleView and another fragments?

I have the custom view (post_skeleton_manage) and imageView with onclick parameter in it.
The structure is: MainActivity > MainFragment > ManageFragment > RecycleView > ManageBlockFragment > ImageView
Adapter creates some of my custom views:
class ManageAdapter(private val names: List<String>) : RecyclerView
.Adapter<ManageAdapter.MyViewHolder>() {
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val label: TextView = itemView.findViewById(R.id.label)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.post_skeleton_manage, parent, false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.label.text = names[position]
}
override fun getItemCount() = names.size
}
In post_skeleton_manage i have this one:
...
<ImageView
android:onClick="ActiveAdminPanel"
android:id="#+id/settings"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="6dp"
app:layout_constraintEnd_toEndOf="#+id/bottom"
app:layout_constraintTop_toTopOf="#+id/bottom"
app:srcCompat="#drawable/settings_svgrepo_com" />
...
When User clicks to the imageView I wanna navigate to another Fragment. Here is the code of the MainActivity:
public fun activeAdminPanel(view: View){
Navigation.findNavController(this, R.id.nav_graph_pages).navigate(R.id.action_Pages_Manage_to_Admin)
}
In ManageBlockFragment I also have these ones:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.settings.setOnClickListener {
println("admin panel")
findNavController().navigate(R.id.action_Pages_Manage_to_Admin)
}
}
public fun activeAdminPanel(view: View){
findNavController().navigate(R.id.action_Pages_Manage_to_Admin)
}
When i run app and ... and click to imageView, Android Studio shows this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.sutk, PID: 14414
java.lang.IllegalStateException: Could not find method ActiveAdminPanel(View) in a parent or ancestor Context for android:onClick attribute defined on view class androidx.appcompat.widget.AppCompatImageView with id 'settings'
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:479)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:437)
at android.view.View.performClick(View.java:7506)
at android.view.View.performClickInternal(View.java:7483)
at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
at android.view.View$PerformClick.run(View.java:29341)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7872)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Please, help
I need to make my "button" works. Help me, please <3

Populate a RecyclerView in a bottom nav fragment from firebase realtime database

I want to populate a recycler view with a realtime firebase database query. The recycler´s fragment is on a bottom nav (the second destiny). The layout:
<TextView
android:id="#+id/tv_id_owner_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_menu_owner"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_id_owner_menu"
app:layout_constraintVertical_bias="1.0" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/btn_add_item_menu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginBottom="24dp"
android:contentDescription="#string/add_item"
android:src="#drawable/ic_add_item"
app:layout_constraintBottom_toBottomOf="#+id/rv_menu_owner"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
In my gradle:
implementation 'com.google.firebase:firebase-database:19.7.0'
implementation 'com.firebaseui:firebase-ui-database:2.3.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
kapt "androidx.lifecycle:lifecycle-compiler:2.3.1"
// ViewModel Kotlin support
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
//Koin
implementation "org.koin:koin-android:2.0.1"
implementation "org.koin:koin-androidx-viewmodel:2.0.1"
//Navigation
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
The code in fragment:
class MenuOwnerFragment : Fragment() {
private var _binding: FragmentMenuOwnerBinding? = null
private val binding get() = _binding!!
private val firebaseOwnerViewModel: FirebaseOwnerViewModel by inject()
lateinit var ownersMenuDb: DatabaseReference
private lateinit var menuRecyclerView: RecyclerView
private lateinit var firebaseRecyclerAdapter: FirebaseRecyclerAdapter<MenuOwner, MenusViewHolder>
private val coroutineScope = CoroutineScope(Dispatchers.Main)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
_binding = FragmentMenuOwnerBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
firebaseOwnerViewModel.currentOwnerLD.observe(viewLifecycleOwner, Observer {
binding.tvIdOwnerMenu.text = it.id
})
val ownerId = binding.tvIdOwnerMenu.text.toString()
menuRecyclerView = view.findViewById(R.id.rv_menu_owner)
menuRecyclerView.layoutManager = LinearLayoutManager(requireContext())
loadFirebaseData(ownerId)
binding.btnAddItemMenu.setOnClickListener { view ->
findNavController().navigate(R.id.action_navigation_menu_owner_to_itemMenuFragment)
}
}
private fun loadFirebaseData(ownerId: String) {
ownersMenuDb = FirebaseDatabase.getInstance().getReference("Menus").child(ownerId)
firebaseRecyclerAdapter = object : FirebaseRecyclerAdapter<MenuOwner, MenusViewHolder>(
MenuOwner::class.java,
R.layout.menu_row,
MenusViewHolder::class.java,
ownersMenuDb
) {
override fun populateViewHolder(viewHolder: MenusViewHolder?, model: MenuOwner?, p2: Int) {
viewHolder?.binding?.itemName?.text = model?.itemName
viewHolder?.binding?.itemDescription?.text = model?.itemDescription
viewHolder?.binding?.itemPrice?.text = model?.itemPrice.toString()
Glide.with(requireContext()).load(model?.itemPhoto).into(viewHolder!!.binding.itemImage)
}
}
menuRecyclerView.adapter = firebaseRecyclerAdapter
}
class MenusViewHolder(mview: View) : RecyclerView.ViewHolder(mview) {
val binding = MenuRowBinding.bind(mview)
}
}
It works and compiles and if I put .child("a value from my firestore child") instead of .child(ownerId), the result it´s what I expect.
With .child(ownerId), the textView shows the right value in the app, but the recycler shows "null". Debuger said "val ownerId = binding.tvIdOwnerMenu.text.toString()" is "". I don´t know what I´m missing because this way:
firebaseOwnerViewModel.currentOwnerLD.observe(viewLifecycleOwner, Observer {
binding.tvIdOwnerMenu.text = it.id
})
of passing parameters works fine for me in other fragments/activities. I´d try with sinthetics (instead of view binding), findViewById, coroutines (to delay loadFirebaseData(ownerId)), all the compile ways with/without parameter ownerId, the code onCreateView, onViewCreated, the FIFA, the UEFA... It´s my first post, sorry if I´m not clear. Any suggestion? Thanks in advance

how to fix this thing in Recycler View in Kotlin Android

I am trying to display notes in my recycler view. the note body is like this:
Note Title in one text view
Note Content in the other text view below the title
So, this will get displayed in one Item and then the next note in the next item. But the issue is that,
one item is containing the note title, and the other one is containing its content.
Here is my NotesAdapter Class:
class NotesAdapter(private var noteView: ArrayList<String>):
RecyclerView.Adapter<NotesAdapter.MyViewHolder>() {
inner class MyViewHolder(noteView: View) : RecyclerView.ViewHolder(noteView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val noteView : View =LayoutInflater.from(parent.context).inflate(R.layout.note_card,parent,false)
return MyViewHolder(noteView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
//Set data here
holder.itemView.apply {
note_title_TV.text = noteView[position]
note_content_TV.text = noteView[position]
}
}
override fun getItemCount(): Int {
return noteView.size
}
}
My Main Activity Class (This class contains my firebase code too, as I am reading data from there and storing that into a list) :
class HomeActivity : AppCompatActivity() {
var nList = ArrayList<String>();
private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: RecyclerView.Adapter<*>
private lateinit var viewManager: RecyclerView.LayoutManager
val rootReference = Firebase.database.reference //app root in firebase database
val currentUser = FirebaseAuth.getInstance().currentUser
val uid = currentUser?.uid.toString()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
//Show user's name in welcome message
//get the name of user from firebase
val nameFromFirebase: FirebaseDatabase = FirebaseDatabase.getInstance()
var nameReference = rootReference.child("users").child(uid).child("name")
nameReference.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val result = snapshot.value
tv_User_Name.text = result.toString()
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
btn_createNote.setOnClickListener {
Intent(this, AddNoteActivity::class.java).also {
startActivity(it)
}
}
//Read notes from database
readNotesFromFirebaseDatabase()
//Updating Layout to display notes in RecyclerView
recyclerView = findViewById<RecyclerView>(R.id.rv_displayNotesInRecyclerView)
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager=LinearLayoutManager(this)
//RecyclerView Adapter being passed the notes list
val adapter = NotesAdapter(nList)
rv_displayNotesInRecyclerView.adapter = adapter
}
fun readNotesFromFirebaseDatabase(){
val noteReference = rootReference.child("users").child(uid).child("Notes")
noteReference.addValueEventListener(object:ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
val noteContent = snapshot.child("noteContent").getValue(String::class.java)
val noteTitle = snapshot.child("noteTitle").getValue(String::class.java)
//Add Notes to the ArrayList of Notes
nList.add(noteTitle.toString())
nList.add(noteContent.toString())
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
}
}
Note_item XML Layout File:
<?xml version="1.0" encoding="UTF-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/prompt_cardview"
android:layout_width="390dp"
android:layout_height="89dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:minHeight="120dp"
app:cardCornerRadius="15dp"
app:cardElevation="3dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="384dp"
android:layout_height="match_parent"
android:minHeight="120dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/note_title_TV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:fontFamily="#font/lato"
android:lineHeight="22dp"
android:text="Title"
android:textAlignment="gravity"
android:textColor="#4F4B4B"
android:textSize="18sp"
android:textStyle="bold"
android:paddingLeft="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.037"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/note_content_TV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginStart="12dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="8dp"
android:fontFamily="#font/lato"
android:paddingLeft="5dp"
android:lineHeight="14dp"
android:singleLine="false"
android:text="#string/some_comments_are_here_to_stay_you_know"
android:textAlignment="center"
android:textColor=" #877B7B"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/note_title_TV"
app:layout_constraintVertical_bias="0.0" />
<ImageButton
android:id="#+id/btn_edit"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="#drawable/round_button_edit"
android:src="#drawable/icon_btn_edit"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btn_delete"
app:layout_constraintHorizontal_bias="0.972"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/note_content_TV"
app:layout_constraintVertical_bias="1.0" />
<ImageButton
android:id="#+id/btn_delete"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="#drawable/round_button_delete"
android:src="#drawable/icon_btn_delete"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.983"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/note_content_TV"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I Also have made a Note Class (if it may be of any assistance) :
class Note (val noteContent:String , val noteTitle: String) {
}
This is my Firebase Database Note Entry, 1:https://i.stack.imgur.com/bixCW.png
Now, I am getting this output, 2: https://i.stack.imgur.com/VV7l7.png
P.S I know there are some posts regarding this like this one: How to create Multiple View Type in Recycler View but they are in Java and I am getting stuck while converting that here.
Try this:
Create a model class with 2 variables
class Notes{
val title: String = ""
val content: String = ""
}
after that creates an array list using that model class instead of String which looks like this:
val list: MutableList<Notes> = Notes()
val nots : Notes = Notes()
notes.title = "test"
notes.content = "Good Work!"
list.add(notes)
Once your list is created pass that list to adapter and you are good to go
class NotesAdapter(private var list: ArrayList<Note>):
RecyclerView.Adapter<NotesAdapter.MyViewHolder>() {
inner class MyViewHolder(noteView: View) : RecyclerView.ViewHolder(noteView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val noteView : View = LayoutInflater.from(parent.context).inflate(R.layout.note_card,parent,false)
return MyViewHolder(noteView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.itemView.apply {
note_title_TV.text = list[position].title
note_content_TV.text = list[position].content
}
}
override fun getItemCount(): Int {
return list.size
}
}
The problem is solved.
Change the ArrayList from String to Note
And in the Main Activity Class, edited this block of code:
//Add Notes to the ArrayList of Notes
var note : Note
note.noteContent = noteTitle.toString()
note.noteTitle = noteTitle.toString()
In the NotesAdapter Class (Posting the complete correct code):
class NotesAdapter(private var noteView: ArrayList<Note>):
RecyclerView.Adapter<NotesAdapter.MyViewHolder>() {
inner class MyViewHolder(noteView: View) : RecyclerView.ViewHolder(noteView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val noteView : View = LayoutInflater.from(parent.context).inflate(R.layout.note_card,parent,false)
return MyViewHolder(noteView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
//Set data here
holder.itemView.apply {
note_title_TV.text = noteView[position].noteContent
note_content_TV.text = noteView[position].noteTitle
}
}
override fun getItemCount(): Int {
return noteView.size
}
}

ListView ID called on null? (Kotlin)

I'm new to Kotlin and im trying to build a HomePage where there is a BottomNavigation with 3 Fragment pages but in 1 of the pages I set a ListView and whenever I call the ID it gives the following errer(Caused by: java.lang.IllegalStateException: categoryListView must not be null)
Here is how Im calling it in my HomePage which is where the content appears:
class HomePage : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
lateinit var adapter : CategoryAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home_page)
adapter = CategoryAdapter(this, DataService.categories)
categoryListView.adapter = adapter
navView.setNavigationItemSelectedListener(this)
bottomNavigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
replaceFragment(HomeFragment())
}
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when(item.itemId) {
R.id.Bottom_Nav_Home -> {
println("Home pressed")
replaceFragment(HomeFragment())
return#OnNavigationItemSelectedListener true
}
R.id.Bottom_Nav_Notifs -> {
println("Notification pressed")
replaceFragment(NotifsFragment())
return#OnNavigationItemSelectedListener true
}
R.id.Bottom_Nav_List -> {
println("List pressed")
replaceFragment(ListFragment())
return#OnNavigationItemSelectedListener true
}
}
false
}
private fun replaceFragment(fragment: Fragment) {
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.NavPageFragment, fragment)
fragmentTransaction.commit()
}
}
am I doing it correct? or am I supposed to call the categoryListView elsewhere? because I tried in my ListFragment which is where my activity code is and it gave a context error
here is how the Fragment activity looks:
<?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:id="#+id/Bottom_List"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.ListFragment">
<ListView
android:id="#+id/categoryListView"
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
You are trying to get the categoryListView resolved inside the activity but it is (as far as I understand) part of the fragment. This simply does not work.
The CategoryAdapter and the ListView should be used inside your HomeFragment class and this will work then.
So move this code into your fragment:
adapter = CategoryAdapter(this, DataService.categories)
categoryListView.adapter = adapter
Update
I would move it into the onViewCreated() method. There you can simply rely on the fact that there is a view available with a context.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
adapter = CategoryAdapter(view.context, DataService.categories)
categoryListView.adapter = adapter // categoryListView will be not null here
}

how to replace a fragment in kotlin from a onclicklistener inside a recyclerview

How can I replace the fragment when i click on an item inside a recyclerView
I've tried inside onClickListener of adapter
childFragmentManager
.beginTransaction()
.replace(R.id.framefragment2, Fragment2())
.commit()
with no succes it returns me
java.lang.IllegalArgumentException: No view found for id 0x7f0a0137 (com.test.justaapp:id/framefragment1) for fragment Fragmetnone{1ebd5fc #0 id=0x7f0a0137}
Here is mi xml of 1st fragment already inflated
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/framefragment1"
android:layout_width="match_parent"
android:layout_height="match_parent">
and the second frame layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C0C0C0">
<FrameLayout
android:id="#+id/framefragment2"
android:layout_width="match_parent"
android:layout_height="match_parent">
I've been searching for hours and can't get it to work, any ideas? maybe I'm mimssing something very simple, any help would be apreciated Greets.
You can implement an interface on your ViewHolder, then you pass an implementation of this interface to your adapter from your activity. In your adapter your pass the implementation when you create the CustomViewHolder instance (create method).
In your activity/fragment:
private val adapter = YourAdapter(object: CustomViewHolder.Listener {
fun onClick() {
// change the fragment here with the fragment manager of your activity/fragment.
}
})
In your adapter:
class YourAdapter(private val listener: CustomViewHolder.Listener): RecyclerView.Adapter {
...
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return CustomViewHolder(
LayoutInflater.from(context).inflate(R.layout.view_layout, parent, false),
listener
)
}
}
ViewHolder implementation:
class CustomViewHolder(view: View, private val listener: Listener): ViewHolder(view) {
...
interface Listener {
fun onClick()
}
fun onCreate(parent: View, listener: Listener): CustomViewHolder {
// inflate the view and return an instance of CustomViewHolder
}
fun onBind() {
button.setOnClickListener {
listener.onClick()
}
}
}
I didn't test this code but the logic is here. You just need to adapt it to your project.

Resources