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
}
}
Related
I thank you in advance for your help. I am not a professional developer. I'm a teacher. I'm looking to create an app that can time student performance. I want to start a general stopwatch and stop the stopwatch individually. But, I encounter a problem either I don't have a crash but I can't interact on the individual stop button or I have a crash of type "binding.btnStop make not null"
Can you tell me how I can interact between the adapter and the fragment to link the general and individual timers and to stop the individual timer?
Thank you in advance for your help
Here is my code:
EvalFragment.class
var mDisplay: Display? = null
var path: String? = null
val REQUEST_CODE = 1
var isPlay = false
var pauseOffSet :Long = 0
//Test chrono millisec
var isResume = false
private lateinit var handler: Handler
var tMilliSec = 0L
var tStart = 0L
var tBuff = 0L
var tUpdate = 0L
var sec: Int = 0
var min: Int = 0
var milliSec: Int = 0
//Pour accéder au fab
private var _binding: FragmentEvalBinding? = null
private val binding get() = _binding!!
private lateinit var mUserViewModel: UserViewModel
private lateinit var mUserEvalViewModel: UserEvalViewModel
private val args by navArgs<EvalFragmentArgs>()
private lateinit var btPlay: ImageButton
private lateinit var btnPause: ImageButton
private lateinit var btStop: ImageButton
private lateinit var chronomter: Chronometer
#RequiresApi(Build.VERSION_CODES.R)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentEvalBinding.inflate(inflater, container, false)
val view = binding.root
//Recyclerview pour afficher le custom row et les données
val adapter = EvalAdapter()
val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerview_time)
recyclerView?.adapter = adapter
recyclerView?.layoutManager = LinearLayoutManager(requireContext())
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
mUserEvalViewModel = ViewModelProvider(this).get(UserEvalViewModel::class.java)
chronomter = binding.chronometerGeneral
btPlay = binding.btStart
btStop = binding.btStop
btnPause = binding.btPause
handler = Handler()
btPlay.setOnClickListener {
if(!isResume){
tStart = SystemClock.uptimeMillis()
handler.postDelayed(runnable, 0)
chronomter.start()
binding.recyclerviewTime.chronometerIndividuel.start()
isResume = true
btStop.visibility = View.GONE
btPlay.setImageDrawable(resources.getDrawable(R.drawable.ic_pause))
} else {
tBuff += tMilliSec
handler.removeCallbacks(runnable)
chronomter.stop()
binding.recyclerviewTime.chronometerIndividuel.stop()
isResume = false
btStop.visibility = View.VISIBLE
btPlay.setImageDrawable(resources.getDrawable(R.drawable.ic_play))
}
}
btnPause.setOnClickListener {
pause()
}
btStop.setOnClickListener {
stop()
if(!isResume){
btPlay.setImageDrawable(resources.getDrawable(R.drawable.ic_play))
tMilliSec = 0L
tStart = 0L
tBuff = 0L
tUpdate = 0L
sec = 0
min = 0
milliSec = 0
chronomter.setText("00:00:00")
binding.recyclerviewTime.chronometerIndividuel.setText("00:00:00")
}
}
val userStart = args.currentUser.time
mUserEvalViewModel.readAllDataUserEval?.observe(viewLifecycleOwner, Observer { user ->
adapter.setDataEval(user)
})
val wm: WindowManager? =
activity?.getSystemService(Context.WINDOW_SERVICE) as WindowManager?
mDisplay = wm!!.defaultDisplay
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
requireActivity(),
arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
), REQUEST_CODE
)
} else {
Toast.makeText(
requireContext(),
"Veuillez accepter les permissions",
Toast.LENGTH_SHORT
).show()
}
// Add menu
setHasOptionsMenu(true)
return view
}
val runnable: Runnable = object : Runnable {
override fun run() {
tMilliSec = SystemClock.uptimeMillis() - tStart
tUpdate = tBuff + tMilliSec
sec = (tUpdate/1000).toInt()
min= sec/60
sec = sec%60
milliSec = (tUpdate%100).toInt()
chronomter.setText(String.format("%02d", min)+":"
+ String.format("%02d", sec)+":"+String.format("%02d", milliSec))
handler.postDelayed(this, 60)
}
}
private fun clicSound() {
val mediaPlayer: MediaPlayer = MediaPlayer.create(context, R.raw.positive_notification)
mediaPlayer.start()
}
private fun pause() {
if (isPlay){
chronomter.stop()
pauseOffSet = SystemClock.elapsedRealtime() - chronomter.base
isPlay = false
btnPause.setBackgroundResource(R.drawable.ic_play)
Toast.makeText(context,"Chronomètre: en Pause !!",Toast.LENGTH_SHORT).show()
}
else{
chronomter.base = SystemClock.elapsedRealtime() - pauseOffSet
chronomter.start()
btnPause.setBackgroundResource(R.drawable.ic_pause)
Toast.makeText(context,"Chronomètre : en route !!",Toast.LENGTH_SHORT).show()
isPlay = true
}
}
private fun play() {
chronomter.base = SystemClock.elapsedRealtime() - pauseOffSet
chronomter.start()
btPlay.setBackgroundResource(R.drawable.ic_stop)
Toast.makeText(context,"Chronomètre déclenché !!",Toast.LENGTH_SHORT).show()
isPlay =true
}
private fun stop() {
chronomter.base = SystemClock.elapsedRealtime()
pauseOffSet = 0
chronomter.stop()
btPlay.setBackgroundResource(R.drawable.ic_play)
Toast.makeText(context, "Chronomètre arrêté !!", Toast.LENGTH_SHORT).show()
isPlay = false
}
private fun reset(){
chronomter.base = SystemClock.elapsedRealtime() - pauseOffSet
chronomter.stop()
btnPause.visibility = View.INVISIBLE
btPlay.setBackgroundResource(R.drawable.ic_play)
Toast.makeText(context,"Chronomter is Start !!",Toast.LENGTH_SHORT).show()
isPlay = false
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PackageManager.PERMISSION_GRANTED && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(requireContext(), "Permission Autorisée", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(requireContext(), "Permission Refusée", Toast.LENGTH_SHORT).show()
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.delete_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.menu_delete) {
// deleteAllEvals()
}
return super.onOptionsItemSelected(item)
}
}```
My EvalAdapter.class:
```class EvalAdapter: RecyclerView.Adapter<EvalAdapter.MyViewHolder>() {
var evalList = emptyList<UserWithEval>()
private lateinit var mUserViewModel: UserViewModel
private lateinit var mEvalViewModel: EvalViewModel
private lateinit var mUserWithEvalViewModel: UserEvalViewModel
private lateinit var firstName: String
private lateinit var lastName: String
private var idUser: Int = 0
private var user_id_reference: Int = 0
private var gru_id_reference: Int = 0
private var timeInterDepart = 0
private lateinit var chronoInd : Chronometer
private lateinit var chronoGeneral : Chronometer
private lateinit var context: Context
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
context = parent.context
return MyViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.custom_time, parent, false)
)
}
override fun getItemCount(): Int {
return evalList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItemUser = evalList[position]
holder.itemView.findViewById<TextView>(R.id.firstName_txt).text = currentItemUser.firstName.uppercase()
holder.itemView.findViewById<TextView>(R.id.lastName_txt).text = currentItemUser.lastName.uppercase()
chronoInd = holder.itemView.findViewById(R.id.chronometerIndividuel)
holder.itemView.findViewById<Button>(R.id.bt_stop_individuel).setOnClickListener {
chronoInd.stop()
}
}
fun setDataEval(user: List<UserWithEval>){
this.evalList = user
notifyDataSetChanged()
}
}```
fragment_eval.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"
android:background="#drawable/gradient_background"
android:orientation="horizontal"
android:id="#+id/fragEval">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview_time"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/linearLayoutCompat"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_margin="30dp"
android:background="#drawable/bg_round"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Chronometer
android:id="#+id/chronometerGeneral"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:format="00:00:00"
android:textColor="#color/white"
android:textSize="40sp"
android:textStyle="bold" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<ImageButton
android:id="#+id/bt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/transparent_background"
android:src="#drawable/ic_play" />
<ImageButton
android:id="#+id/bt_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/transparent_background"
android:src="#drawable/ic_stop" />
<ImageButton
android:id="#+id/bt_pause"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/transparent_background"
android:src="#drawable/ic_pause" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<EditText
android:id="#+id/editTextTempsDepart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/custom_input_eval"
android:drawableLeft="#drawable/ic_chrono"
android:hint=" 15 "
android:inputType="number"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="#+id/linearLayoutCompat"
app:layout_constraintEnd_toStartOf="#+id/linearLayoutCompat"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/validTempsDepart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/validate"
android:layout_marginLeft="20dp"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/editTextTempsDepart"
app:layout_constraintStart_toEndOf="#+id/editTextTempsDepart"
app:layout_constraintTop_toTopOf="#+id/editTextTempsDepart" />
<TextView
android:id="#+id/tvTempsPremierDepart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/custom_input"
android:text="00 sec"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/linearLayoutCompat"
app:layout_constraintTop_toBottomOf="#+id/linearLayoutCompat" />
</androidx.constraintlayout.widget.ConstraintLayout>
custom_time.xml:
<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"
android:background="#drawable/gradient_background"
tools:context=".MainActivity">
//1ère ligne du chrono
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="#+id/bt_stop_individuel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:background="#drawable/shape_background"
android:text="#string/stop"
android:textColor="#color/white"
android:textSize="30sp"
android:textStyle="bold" />
<TextView
android:id="#+id/firstName_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="#string/firstName"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:id="#+id/lastName_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="#string/lastName"
android:textSize="25sp"
android:textStyle="bold" />
<Chronometer
android:id="#+id/chronometerIndividuel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:format="00:00:00"
android:text="00:00:00"
android:textSize="30sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
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
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);
THIS IS MY XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MakeComplaint.Category_Description"
android:background="#drawable/fragmentgradient_bg">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/heading_constraint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:layout_editor_absoluteX="17dp">
<ImageView
android:id="#+id/backToHistory"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingHorizontal="20dp"
android:layout_weight="2"
android:src="#drawable/ic_backarrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="#+id/location_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/location_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingHorizontal="20dp"
android:fontFamily="#font/pathway_gothic_one"
android:gravity="center"
android:textSize="40sp"
android:text="Further Details"
app:layout_constraintHorizontal_bias="0.35"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#+id/backToHistory"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.cardview.widget.CardView
android:id="#+id/details_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:elevation="#dimen/card_spacing"
app:cardUseCompatPadding="true"
app:layout_constraintTop_toBottomOf="#+id/heading_constraint"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:cardCornerRadius="#dimen/card_spacing"
>
<ScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/inner_constraint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/card_spacing">
<TextView
android:id="#+id/guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/pathway_gothic_one"
android:gravity="left"
android:text="Please enter any further details you would like to add:"
android:textSize="20sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/description_text_input"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:boxStrokeColor="#color/teal"
app:boxStrokeWidth="#dimen/card_spacing"
app:counterEnabled="true"
app:counterMaxLength="500"
android:hint="Additional Notes"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/guide"
app:prefixTextColor="#color/colorPrimaryDark"
android:outlineAmbientShadowColor="#color/teal"
android:outlineSpotShadowColor="#color/teal"
android:scrollbarAlwaysDrawHorizontalTrack="true"
app:layout_constraintBaseline_creator="#android:integer/config_longAnimTime"
>
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences|textMultiLine"
android:maxLength="500"
/>
</com.google.android.material.textfield.TextInputLayout>
<!--ImageView where image will be set-->
<ImageView
android:id="#+id/display_image"
android:scaleType="centerCrop"
android:layout_width="250dp"
android:layout_height="250dp"
android:adjustViewBounds="true"
app:layout_constraintTop_toBottomOf="#+id/description_text_input"
app:layout_constraintBottom_toTopOf="#+id/FAB_buttons"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/FAB_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/description_text_input"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginVertical="5dp">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:backgroundTint="#color/teal"
android:layout_marginHorizontal="#dimen/card_spacing"
android:src="#android:drawable/ic_menu_camera"
app:layout_constraintRight_toLeftOf="#+id/camera"
app:layout_constraintTop_toBottomOf="#+id/name_text_input"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/upload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:backgroundTint="#color/teal"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/name_text_input"
android:src="#android:drawable/ic_menu_gallery"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Make Complaint"
app:layout_constraintTop_toBottomOf="#+id/FAB_buttons"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:backgroundTint="#color/teal"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>```
**THIS IS MY KOTLIN FILE**
package com.example.atry.MakeComplaint
class Category_Description : Fragment() {
private val ALL_PERMISSIONS_RESULT = 107
private val IMAGE_RESULT = 200
private val REQUEST_IMAGE_CAPTURE = 12345
var mBitmap: Bitmap? = null
val permission = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val v = inflater.inflate(com.example.atry.R.layout.fragment_category__description, container, false)
val camera_FAB: View = v.findViewById(com.example.atry.R.id.camera)
val upload_FAB: View = v.findViewById(com.example.atry.R.id.upload)
val imageView = v.findViewById<ImageView>(com.example.atry.R.id.display_image)
upload_FAB.setOnClickListener {
pickImageFromGallery()
}
camera_FAB.setOnClickListener{
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val frag = this
/** Pass your fragment reference **/
frag.startActivityForResult(
intent,
REQUEST_IMAGE_CAPTURE
) // REQUEST_IMAGE_CAPTURE = 12345
}
fun hasPermissionInManifest(context: Context, permissionName: String): Boolean {
val packageName = context.packageName
try {
val packageInfo = context.packageManager
.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
val declaredPermisisons = packageInfo.requestedPermissions
if (declaredPermisisons != null && declaredPermisisons.size > 0) {
for (p in declaredPermisisons) {
if (p == permissionName) {
return true
}
}
}
} catch (e: PackageManager.NameNotFoundException) {
}
return false
}
v.backToHistory.setOnClickListener {
backFragment()
}
// Inflate the layout for this fragment
return v
}
private fun pickImageFromGallery() {
//Intent to pick image
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, IMAGE_PICK_CODE)
}
companion object {
//image pick code
private val IMAGE_PICK_CODE = 1000;
//Permission code
private val PERMISSION_CODE = 1001;
}
private fun backFragment() {
val manager = (context as AppCompatActivity).supportFragmentManager
manager.popBackStackImmediate()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && data !=null) {
if (requestCode == REQUEST_IMAGE_CAPTURE || requestCode== IMAGE_PICK_CODE) {
// Do something with imagePath
val extras = data.getExtras()
val photo = extras.get("data") as Bitmap
val imageView = view!!.findViewById<ImageView>(com.example.atry.R.id.display_image)
imageView.setImageBitmap(photo)
// CALL THIS METHOD TO GET THE URI FROM THE BITMAP
var selectedImage = activity.let { getImageUri( it!!,photo) }
val realPath = selectedImage.let { getRealPathFromURI(it) }
selectedImage = Uri.parse(realPath)
}
}
super.onActivityResult(requestCode, resultCode, data)
}
fun getImageUri(inContext: Context, inImage: Bitmap): Uri {
val bytes = ByteArrayOutputStream()
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes)
val path =
MediaStore.Images.Media.insertImage(inContext.contentResolver, inImage, "Title", null)
return Uri.parse(path)
}
fun getRealPathFromURI(contentUri: Uri): String {
var cursor: Cursor? = null
try {
val proj = arrayOf(MediaStore.Images.Media.DATA)
cursor = getActivity()?.getContentResolver()?.query(contentUri, proj, null, null, null)
val column_index = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor!!.moveToFirst()
return cursor!!.getString(column_index)
} finally {
if (cursor != null) {
cursor!!.close()
}
}
}
}```
For capturing the image everything works fine until the screen appears where I click on the tick to approve that the picture is okay...but then I am unable to view anything on the ImageView.
For the upload button when I am on the screen that allows me to select the picture ...when i click on it the app crashes and gives me the following error: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.os.Bundle.get(java.lang.String)' on a null object reference
I have searched the internet for days and couldn't find a proper solution to this. I would appreciate it if anyone could find me a solution to this.
URI of the selected image is not returned in Intent extras, but in the data of intent. You can get the selected image's URI as follows.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && data !=null) {
if (requestCode == REQUEST_IMAGE_CAPTURE || requestCode== IMAGE_PICK_CODE) {
// Get image URI From intent
var imageUri = data.data
// do something with the image URI
your_image_view.setImageURI(imageUri)
}
}
super.onActivityResult(requestCode, resultCode, data)
}
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
}