I'm hoping to update a Boolean value of data that I have in the list. If checkbox is checked I would like the value to be true, but if the checkbox is unchecked, I would like it to change the value to false, and vice versa.
On clicking the checkbox, I would like it to change the value of 'favourite' in my db to either true or false, depending on whether the checkbox is checked or not. I am unsure how to update this value with a checkbox. Please help! My code is as follows:
Adapter:
package org.wit.hikingtrails.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.Picasso
import org.wit.hikingtrails.databinding.CardHikeBinding
import org.wit.hikingtrails.main.MainApp
import org.wit.hikingtrails.models.HikeModel
import timber.log.Timber.i
interface HikeListener {
fun onHikeClick(hike: HikeModel)
}
class HikeAdapter constructor(private var hikes: List<HikeModel>,
private val listener: HikeListener) :
RecyclerView.Adapter<HikeAdapter.MainHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainHolder {
val binding = CardHikeBinding
.inflate(LayoutInflater.from(parent.context), parent, false)
return MainHolder(binding)
}
override fun onBindViewHolder(holder: MainHolder, position: Int) {
val hike = hikes[holder.adapterPosition]
holder.bind(hike, listener)
}
override fun getItemCount(): Int = hikes.size
class MainHolder(private val binding : CardHikeBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(hike: HikeModel, listener: HikeListener) {
binding.hikeName.text = hike.name
binding.description.text = hike.description
binding.favourite.isChecked = hike.favourite
binding.favourite.setOnClickListener {
hike.favourite = binding.favourite.isChecked
listener.onHikeClick(hike)
}
if (hike.image != ""){
Picasso.get()
.load(hike.image)
.resize(200, 200)
.into(binding.imageIcon)
}
binding.root.setOnClickListener { listener.onHikeClick(hike) }
}
}
}
Presenter:
package org.wit.hikingtrails.views.hikeList
import android.content.Intent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.google.firebase.auth.FirebaseAuth
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.wit.hikingtrails.main.MainApp
import org.wit.hikingtrails.models.HikeModel
import org.wit.hikingtrails.views.BasePresenter
import org.wit.hikingtrails.views.BaseView
import org.wit.hikingtrails.views.VIEW
import org.wit.hikingtrails.views.hike.HikeView
import org.wit.hikingtrails.views.map.HikeMapView
import org.wit.hikingtrails.views.signIn.SignInView
class HikeListPresenter(view: BaseView) : BasePresenter(view) {
var hike = HikeModel()
private lateinit var refreshIntentLauncher : ActivityResultLauncher<Intent>
private lateinit var editIntentLauncher : ActivityResultLauncher<Intent>
init {
registerEditCallback()
registerRefreshCallback()
}
suspend fun getHikes() = app.hikes.findAll()
fun doAddHike() {
val launcherIntent = Intent(view, HikeView::class.java)
editIntentLauncher.launch(launcherIntent)
}
fun doEditHike(hike: HikeModel) {
val launcherIntent = Intent(view, HikeView::class.java)
launcherIntent.putExtra("hike_edit", hike)
editIntentLauncher.launch(launcherIntent)
}
fun doShowHikesMap() {
val launcherIntent = Intent(view, HikeMapView::class.java)
editIntentLauncher.launch(launcherIntent)
}
fun doLogout() {
FirebaseAuth.getInstance().signOut()
val launcherIntent = Intent(view, SignInView::class.java)
editIntentLauncher.launch(launcherIntent)
}
private fun registerRefreshCallback() {
refreshIntentLauncher =
view!!.registerForActivityResult(ActivityResultContracts.StartActivityForResult())
{
GlobalScope.launch(Dispatchers.Main){
getHikes()
}
}
}
private fun registerEditCallback() {
editIntentLauncher =
view!!.registerForActivityResult(ActivityResultContracts.StartActivityForResult())
{ }
}
}
View:
package org.wit.hikingtrails.views.hikeList
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import org.wit.hikingtrails.R
import org.wit.hikingtrails.adapters.HikeAdapter
import org.wit.hikingtrails.adapters.HikeListener
//import org.wit.hikingtrails.databinding.ActivityHikeListBinding
import org.wit.hikingtrails.main.MainApp
import org.wit.hikingtrails.models.HikeModel
import android.content.Intent
import android.view.*
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.wit.hikingtrails.databinding.ActivityHikeListBinding
import org.wit.hikingtrails.views.BaseView
import timber.log.Timber
class HikeListView : BaseView(), HikeListener {
lateinit var app: MainApp
lateinit var binding: ActivityHikeListBinding
lateinit var presenter: HikeListPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHikeListBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.toolbar.title = title
setSupportActionBar(binding.toolbar)
presenter = HikeListPresenter(this)
val layoutManager = LinearLayoutManager(this)
binding.recyclerView.layoutManager = layoutManager
updateRecyclerView()
}
// override fun showHikes(hikes: List<HikeModel>) {
// recyclerView.adapter = HikeAdapter(hikes, this)
// recyclerView.adapter?.notifyDataSetChanged()
// }
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onResume() {
//update the view
super.onResume()
updateRecyclerView()
binding.recyclerView.adapter?.notifyDataSetChanged()
Timber.i("recyclerView onResume")
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item?.itemId) {
R.id.item_add -> presenter.doAddHike()
R.id.item_map -> presenter.doShowHikesMap()
R.id.logout -> presenter.doLogout()
}
return super.onOptionsItemSelected(item)
}
override fun onHikeClick(hike: HikeModel) {
presenter.doEditHike(hike)
}
private fun updateRecyclerView(){
GlobalScope.launch(Dispatchers.Main){
binding.recyclerView.adapter =
HikeAdapter(presenter.getHikes(), this#HikeListView)
}
}
}
Related
I am simply trying to setup the ClickListener for changing the user name. Google's tutorials emphasize fragments, which I will do later. Based on what I've seen in other examples and the Android documentation, I thought I had the View Binding set up properly. I don't have enough information to understand why I see a list of copies of the activity screen inside the RecyclerView.
UserListAdapter.kt
package com.neillbarrett.debitsandcredits
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
val inAdapter: String = "In UserListAdapter "
class UserListAdapter(private val userSelect: (UsersTable?) -> Unit) :
ListAdapter<UsersTable, UserListAdapter.UserViewHolder>(UsersComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserListAdapter.UserViewHolder {
Log.w(inAdapter,"OnCreateViewHolder started")
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder.create(parent)
}
class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(usersTable: UsersTable?, userSelect: (UsersTable?) -> Unit) {
Log.w(inAdapter,"UserViewHolder started")
itemView.setOnClickListener { View.OnClickListener {
/* if (View.) { }*/
val nameSelected = userSelect(usersTable)
//userSelect(usersTable)
//need to assign the result of the clicklistener to the editText
//binding.etEditName.setText(R.layout.activity_list_of_users.toString())
}}
}
companion object {
fun create(parent: ViewGroup) : UserViewHolder {
Log.w(inAdapter,"Companion object 'Create' function started")
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder(view)
}
}
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
Log.w(inAdapter,"OnBindViewHolder started")
val current = getItem(position)
holder.bind(current, userSelect)
}
class UsersComparator : DiffUtil.ItemCallback<UsersTable>() {
override fun areItemsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
Log.w(inAdapter,"areItemsTheSame function started")
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
Log.w(inAdapter,"areContentsTheSame function started")
return oldItem.userName == newItem.userName
}
}
}
ManageUsers.kt
package com.neillbarrett.debitsandcredits
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.CreditsAndDebitsApp
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
class ManageUsers : AppCompatActivity() {
lateinit var binding: ActivityManageUsersBinding
lateinit var recyclerView: RecyclerView
lateinit var editTextAddUser: EditText
lateinit var editTextChangeUser: EditText
lateinit var newUser: String
var userSelect: ((UsersTable?) -> Unit) = {}
var position: Long = 0
val inWhichActivity: String = "In ManageUsers"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityManageUsersBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//setContentView(R.layout.activity_manage_users)
Log.w(inWhichActivity, "Setting up userViewModel & repository")
val userViewModel: UserViewModel by viewModels {
UserViewModelFactory((application as CreditsAndDebitsApp).repository)
}
recyclerView = findViewById(R.id.rec_view_userList)
editTextAddUser = findViewById(R.id.et_AddUser)
editTextChangeUser = findViewById(R.id.et_Edit_Name)
val adapter = UserListAdapter(userSelect)
binding.recViewUserList.adapter = adapter
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
userViewModel.allUsers.observe(this, Observer() {user ->
Log.w(inWhichActivity,"Starting Observer")
user?.let { adapter.submitList(it) }
Log.w(inWhichActivity, "Started Observer")
})
val btnAddUser = findViewById<Button>(R.id.btn_AddUser)
btnAddUser.setOnClickListener {
Log.w(inWhichActivity,"Started btnAddUser.setOnClickListener")
if (TextUtils.isEmpty(editTextAddUser.text)) {
Toast.makeText(this, "User name cannot be empty", Toast.LENGTH_SHORT).show()
} else {
newUser = editTextAddUser.text.toString()
// Log.w("Add user button", "Username put into newUser")
userViewModel.insertUser(UsersTable(0, newUser))
// Toast.makeText(this, "Username added to table", Toast.LENGTH_SHORT).show()
// Log.w("Add user button", "Username added to table")
}
}
val btnChangeUser = findViewById<Button>(R.id.btn_ChangeUserName)
btnChangeUser.setOnClickListener {
Log.w(inWhichActivity,"Started btnChangeUser.setOnClickListener")
Toast.makeText(this, "Selected position is ${recyclerView.getChildAdapterPosition(it)}", Toast.LENGTH_SHORT).show()
/* if (recyclerView.getChildAdapterPosition(it) == -1) {
Toast.makeText(this, "Select a name.", Toast.LENGTH_SHORT).show()
} else {
if (editTextChangeUser.text.toString() == recyclerView.adapter.toString()) {
Toast.makeText(this, "Name has not been changed.", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Name would have been changed.", Toast.LENGTH_SHORT).show()
val rvItemRecId: Long
rvItemRecId = adapter.getItemId(position.toInt())
userViewModel.updateUser(UsersTable(rvItemRecId.toInt(), adapter.toString()))
}
}*/
}
}
}
UserViewModel.kt
package com.neillbarrett.debitsandcredits
import android.util.Log
import androidx.lifecycle.*
import com.neillbarrett.debitsandcredits.database.UsersTable
import kotlinx.coroutines.launch
import java.lang.IllegalArgumentException
val inViewModel: String = "In UserViewModel "
class UserViewModel(private val repository: UserRepository) : ViewModel() {
// Using LiveData and caching what allWords returns has several benefits:
// - We can put an observer on the data (instead of polling for changes) and only update the
// the UI when the data actually changes.
// - Repository is completely separated from the UI through the ViewModel.
val allUsers: LiveData<List<UsersTable>> = repository.allUsers.asLiveData()
/**
* Launching a new coroutine to insert the data in a non-blocking way
*/
fun insertUser(user: UsersTable) = viewModelScope.launch {
repository.insertUser(user)
Log.w(inViewModel,"insertUser called")
//repository.insertUser(usersTable = List<UsersTable>())
//repository.insertUser(UsersTable(0, userName = user.userName))
}
fun updateUser(user: UsersTable) = viewModelScope.launch {
repository.updateUser(user)
Log.w(inViewModel, "updateUser called")
}
fun deleteUser(user: UsersTable) = viewModelScope.launch {
repository.deleteUser(user)
Log.w(inViewModel, "deteUser called")
}
}
class UserViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory{
override fun <T : ViewModel> create(modelClass: Class<T>): T {
Log.w(inViewModel,"UserViewModelFactory called")
if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
#Suppress("UNCHECKED_CAST")
return UserViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
The app must show all product but show only last (number 6). when i launch app, work, but return this error : E/RecyclerView: No adapter attached; skipping layout. I'm beginner in android language and searching online i didn't find nothing.
the app was composed from mainActivity and CartActivity
output
this is realtime DB
this is main code
package com.example.tpsi_maccagnola
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.GridLayoutManager
import com.example.tpsi_maccagnola.events.UpdateCarrello
import com.example.tpsi_maccagnola.listener.cartlistener
import com.example.tpsi_maccagnola.listener.foodListener
import com.example.tpsi_maccagnola.modelli.Carrello
import com.example.tpsi_maccagnola.modelli.Food
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import kotlinx.android.synthetic.main.activity_main.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class MainActivity : AppCompatActivity(), foodListener, cartlistener {
lateinit var foodListener: foodListener
lateinit var cartlistener1: cartlistener
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
}
override fun onStop() {
super.onStop()
if (EventBus.getDefault().hasSubscriberForEvent(UpdateCarrello::class.java))
EventBus.getDefault().removeStickyEvent(UpdateCarrello::class.java)
EventBus.getDefault().unregister(this)
}
#Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onUpdateCart(event: UpdateCarrello) {
counCartDB()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
caricaDB()
counCartDB()
}
private fun counCartDB() {
val cartmodels: MutableList<Carrello> = ArrayList()
FirebaseDatabase.getInstance()
.getReference("carrello")
.child("UNIQUE_USER_ID")
.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (cartsnapshot in snapshot.children) {
val cartmodel = cartsnapshot.getValue(Carrello::class.java)
cartmodel!!.key = cartsnapshot.key
cartmodels.add(cartmodel)
}
cartlistener1.onCartSuccess(cartmodels)
}
override fun onCancelled(error: DatabaseError) {
cartlistener1.onCartFailed(error.message)
}
})
}
private fun caricaDB() {
val foods: MutableList<Food> = ArrayList()
FirebaseDatabase.getInstance()
.getReference("Food").addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()) {
for (FoodSnapshot in snapshot.children) {
val foodModel = FoodSnapshot.getValue(Food::class.java)
foodModel!!.key = FoodSnapshot.key
foods.add(foodModel)
}
foodListener.onloadsuccess(foods)
} else {
foodListener.onloadfailed("non esiste")
}
}
override fun onCancelled(error: DatabaseError) {
foodListener.onloadfailed(error.message)
}
})
}
private fun init() {
foodListener = this
cartlistener1 = this
val gridLayoutManager = GridLayoutManager(this, 2)
food_recycler.layoutManager = gridLayoutManager
food_recycler.addItemDecoration(decoration())
btnCart.setOnClickListener{ startActivity(Intent(this,CartActivity::class.java))}
}
override fun onloadsuccess(foodModelList: List<Food>?) {
val adapter = FoodAdapter(this, foodModelList!!, cartlistener1)
food_recycler.adapter = adapter
}
override fun onloadfailed(message: String?) {
Snackbar.make(layoutprincipale, message!!, Snackbar.LENGTH_LONG).show()
}
override fun onCartSuccess(carrelloList: List<Carrello>) {
var cartTot = 0
for (cartlist in carrelloList!!) {
cartTot += cartlist!!.quantita
/*badge!!.setNumber(cartTot)*/
}
}
override fun onCartFailed(message: String?) {
Snackbar.make(layoutprincipale, message!!, Snackbar.LENGTH_LONG).show()
}
}
this is adapter
package com.example.tpsi_maccagnola
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.tpsi_maccagnola.events.UpdateCarrello
import com.example.tpsi_maccagnola.listener.RecyclerListener
import com.example.tpsi_maccagnola.listener.cartlistener
import com.example.tpsi_maccagnola.modelli.Carrello
import com.example.tpsi_maccagnola.modelli.Food
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import org.greenrobot.eventbus.EventBus
class FoodAdapter(
private val context: Context,
private val list: List<Food>,
private val cartlistener1: cartlistener
) : RecyclerView.Adapter<FoodAdapter.FoodHolder>() {
class FoodHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var imageView: ImageView?= null
var txtName: TextView?= null
var txtprice: TextView?= null
private var clickListener: RecyclerListener? = null
fun setClickListener (clickListener: RecyclerListener){
this.clickListener = clickListener;
}
init {
imageView = itemView.findViewById(R.id.imageView) as ImageView;
txtName = itemView.findViewById(R.id.txtName) as TextView;
txtprice = itemView.findViewById(R.id.txtprice) as TextView;
itemView.setOnClickListener(this)
}
override fun onClick(p0: View?) {
clickListener!!.onclcickProdotto(p0,adapterPosition )
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoodHolder {
return FoodHolder(LayoutInflater.from(context).inflate(R.layout.layout_food,parent,false))
}
override fun onBindViewHolder(holder: FoodHolder, position: Int) {
Glide.with(context).load(list[position].image).into(holder.imageView!!)
holder.txtName!!.text =StringBuilder().append(list[position].name)
holder.txtprice!!.text =StringBuilder("€").append(list[position].price)
holder.setClickListener(object: RecyclerListener{
override fun onclcickProdotto(view: View?, position: Int) {
aggiungiCarrello(list[position])
}
} )
}
private fun aggiungiCarrello(food: Food) {
val utenteCart = FirebaseDatabase.getInstance().getReference("Cart").child("UNIQUE_USER_ID")
utenteCart.child(Food.key!!).addListenerForSingleValueEvent(object :ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
if(snapshot.exists()){ //se è gia presente aggiorno
val cartmodel = snapshot.getValue(Carrello::class.java)
val updatecart: MutableMap<String,Any> = HashMap()
cartmodel!!.quantita = cartmodel!!.quantita+1
updatecart["quantita"] = cartmodel!!.quantita
updatecart["totale"] =cartmodel!!.quantita * cartmodel.price!!.toFloat()
utenteCart.child(food.key!!)
.updateChildren(updatecart)
.addOnSuccessListener {
EventBus.getDefault().postSticky(UpdateCarrello())
cartlistener1.onCartFailed("aggiunto correttamente")
}.addOnFailureListener{e -> cartlistener1.onCartFailed(e.message)
}
}else{
val carrello1 = Carrello
carrello1.key = food.key
carrello1.name = food.name
carrello1.image = food.image
carrello1.price = food.price
carrello1.quantita = 1
carrello1.totale = food.price!!.toFloat()
utenteCart.child(food.key!!)
.setValue(carrello1)
.addOnSuccessListener {
EventBus.getDefault().postSticky(UpdateCarrello())
cartlistener1.onCartFailed("aggiunto correttamente")
}.addOnFailureListener{e -> cartlistener1.onCartFailed(e.message)
}
}
}
override fun onCancelled(error: DatabaseError) {
cartlistener1.onCartFailed(error.message)
}
})
}
override fun getItemCount(): Int {
return list.size
}
}
I am making a quiz app. My main activity has blocks. Each block has a date written over it. the date act as title while fetching information from firebase. These blocks are working perfectly fine, (fetching questions).I also have a floating action button, on clicking displays a calender and we can select date from there and access quiz for that particular day, but it is not working .
Home screen : home screen
Interface while accessing question from block : image
Interface while accessing through floating action bar :image
Main Activity:
package com.example.quiz.activities
import android.annotation.SuppressLint
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.recyclerview.widget.GridLayoutManager
import com.example.quiz.R
import com.example.quiz.adapters.QuizAdapter
import com.example.quiz.databinding.ActivityMainBinding
import com.example.quiz.models.Quiz
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.FirebaseFirestore
import java.text.SimpleDateFormat
import java.util.*
class MainActivity() : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
lateinit var adapter: QuizAdapter
private var quizList = mutableListOf<Quiz>()
lateinit var firestore : FirebaseFirestore
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setUpViews()
}
fun setUpViews(){
setUpFirestore()
setUpDrawerLayout()
setUpRecyclerView()
setUpDatePicker()
}
#SuppressLint("SimpleDateFormat")
private fun setUpDatePicker() {
// val btnDatePicker = binding.btnDatePicker
binding.btnDatePicker.setOnClickListener{
val datePicker = MaterialDatePicker.Builder.datePicker().build()
datePicker.show(supportFragmentManager,"DatePicker")
datePicker.addOnPositiveButtonClickListener {
Log.d("DATEPICKER",datePicker.headerText)
val dateFormatter = SimpleDateFormat("dd-mm-yyyy")
val date = dateFormatter.format(Date(it))
val intent = Intent(this,QuestionActivity::class.java)
intent.putExtra("DATE",date)
startActivity(intent)
}
datePicker.addOnNegativeButtonClickListener {
Log.d("DATEPICKER",datePicker.headerText)
}
datePicker.addOnCancelListener {
Log.d("DATEPICKER","Date Picker was cancelled")
}
}
}
private fun setUpFirestore() {
firestore = FirebaseFirestore.getInstance()
val collectionReference = firestore.collection("quizzes")
collectionReference.addSnapshotListener{ value, error ->
if(value == null || error != null){
Toast.makeText(this,"Error fetching data",Toast.LENGTH_SHORT).show()
return#addSnapshotListener
}
Log.d("DATA", value.toObjects(Quiz::class.java).toString())
quizList.clear()
quizList.addAll(value.toObjects(Quiz::class.java))
adapter.notifyDataSetChanged()
}
}
private fun setUpRecyclerView(){
val quizRecyclerView = binding.quizRecyclerView
adapter = QuizAdapter(this,quizList)
quizRecyclerView.layoutManager = GridLayoutManager(this,2)
quizRecyclerView.adapter = adapter
}
private fun setUpDrawerLayout(){
val appBar = binding.appBar
val mainDrawer = binding.mainDrawer
val navigationView = binding.navigationView
setSupportActionBar(appBar)
actionBarDrawerToggle = ActionBarDrawerToggle(this,mainDrawer,
R.string.app_name,
R.string.app_name
)
actionBarDrawerToggle.syncState()
navigationView.setNavigationItemSelectedListener {
val intent = Intent(this,ProfileActivity::class.java)
startActivity(intent)
mainDrawer.closeDrawers()
true
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (actionBarDrawerToggle.onOptionsItemSelected(item)){
return true
}
return super.onOptionsItemSelected(item)
}
}
Quiz adapter
package com.example.quiz.adapters
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.RecyclerView
import com.example.quiz.R
import com.example.quiz.activities.QuestionActivity
import com.example.quiz.models.Quiz
import com.example.quiz.utils.ColorPicker
import com.example.quiz.utils.IconPicker
class QuizAdapter(val context: Context, val quizzes: List<Quiz>) :
RecyclerView.Adapter<QuizAdapter.QuizViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuizViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.quiz_item,parent,false)
return QuizViewHolder(view)
}
override fun onBindViewHolder(holder: QuizViewHolder, position: Int) {
holder.textViewTitle.text = quizzes[position].title
holder.cardContainer.setCardBackgroundColor(Color.parseColor(ColorPicker.getColor()))
holder.iconView.setImageResource(IconPicker.getIcon())
holder.itemView.setOnClickListener{
Toast.makeText(context,quizzes[position].title,Toast.LENGTH_SHORT).show()
val intent = Intent(context , QuestionActivity::class.java)
intent.putExtra("DATE",quizzes[position].title)
context.startActivity(intent)
}
}
override fun getItemCount(): Int {
return quizzes.size
}
inner class QuizViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textViewTitle: TextView = itemView.findViewById(R.id.quizTitle)
var iconView: ImageView = itemView.findViewById(R.id.quizIcon)
var cardContainer: CardView = itemView.findViewById(R.id.cardContainer)
}
}
Question Activity
package com.example.quiz.activities
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.Toast
import androidx.core.view.allViews
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.quiz.R
import com.example.quiz.adapters.OptionAdapter
import com.example.quiz.databinding.ActivityQuestionBinding
import com.example.quiz.models.Question
import com.google.firebase.firestore.FirebaseFirestore
import com.example.quiz.models.Quiz
import com.google.gson.Gson
class QuestionActivity : AppCompatActivity() {
var quizzes : MutableList<Quiz>? = null
var questions : MutableMap<String,Question>? = null
var index = 1
lateinit var firestore : FirebaseFirestore
private lateinit var binding: ActivityQuestionBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityQuestionBinding.inflate(layoutInflater)
setContentView(binding.root)
setUpFireStore()
setUpEventListener()
}
private fun setUpEventListener() {
val btnPrevious = binding.btnPrevious
val btnSubmit = binding.btnSubmit
val btnNext = binding.btnNext
btnPrevious.setOnClickListener{
index--
bindViews()
}
btnNext.setOnClickListener{
index++
bindViews()
}
btnSubmit.setOnClickListener{
Log.d("FINAL QUIZ",questions.toString())
val intent = Intent(this,ResultActivity::class.java)
val json = Gson().toJson(quizzes!![0])
intent.putExtra("QUIZ",json)
startActivity(intent)
}
}
private fun setUpFireStore() {
val firestore = FirebaseFirestore.getInstance()
var date = intent.getStringExtra("DATE")
if (date!= null){
firestore.collection("quizzes").whereEqualTo("title",date)
.get()
.addOnSuccessListener {
if (it != null && !it.isEmpty){
Log.d("DATA",it.toObjects(Quiz::class.java).toString())
quizzes = it.toObjects(Quiz::class.java)
questions = quizzes!![0].questions
bindViews()
}
else{
Toast.makeText(this,"Error Fetching data",Toast.LENGTH_SHORT).show()
}
}
}
}
private fun bindViews() {
val btnPrevious = binding.btnPrevious
val btnSubmit = binding.btnSubmit
val btnNext = binding.btnNext
val description = binding.description
val optionList = binding.optionList
btnPrevious.visibility = View.GONE
btnSubmit.visibility = View.GONE
btnNext.visibility = View.GONE
if (index == 1) {
btnNext.visibility = View.VISIBLE
}
else if(index == questions!!.size){
btnSubmit.visibility = View.VISIBLE
btnPrevious.visibility = View.VISIBLE
}
else{
btnNext.visibility = View.VISIBLE
btnPrevious.visibility = View.VISIBLE
}
val question = questions!!["question$index"]
question?.let {
description.text = it.description
val optionAdapter = OptionAdapter(this,it)
optionList.layoutManager = LinearLayoutManager(this)
optionList.adapter = optionAdapter
optionList.setHasFixedSize(true)
}
}
}
No logcat error is shown but this error is shown in run section : E/RecyclerView: No adapter attached; skipping layout
so after uploading my image from gallery my app works fine, but when i try to close and open my app again, on debug console it throws this error java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{ce75251 30290:eu.tuto.youtubeproject/u0a447} (pid=30290, uid=10447) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs here is my code
MainActivity.kt
package eu.tuto.youtubeproject
import android.annotation.SuppressLint
import android.app.Dialog
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.os.Environment.getExternalStorageDirectory
import android.util.Log
import android.view.View
import android.widget.*
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.net.toUri
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import eu.tuto.youtubeproject.ViewModels.SplashScreenViewModel
import eu.tuto.youtubeproject.data.ListData
import eu.tuto.youtubeproject.ViewModels.VideoViewModel
import eu.tuto.youtubeproject.fragments.*
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.popup.view.*
import org.w3c.dom.Text
class MainActivity : AppCompatActivity() {
private var dialogView: View? = null
private lateinit var mUserViewModel: VideoViewModel
private val mSplashScreenViewModel: SplashScreenViewModel by viewModels()
private val getPreviewImage = //get image from gallery
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri != null) {
dialogView?.findViewById<TextView>(R.id.imageUriHolder)?.text = uri.toString() //URI holder doesn't work
dialogView?.findViewById<ImageView>(R.id.imageChange)?.setImageURI(uri) // set imageURI as Thumbnail
} else {
Log.e("MainActivity", "URI not present")
}
}
private val getPreviewVideo =//get video from gallery
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri != null) {
dialogView?.findViewById<TextView>(R.id.videoUriHolder)?.text = uri.toString() //videoURI holder doesn't work
dialogView?.findViewById<VideoView>(R.id.videoChange)?.setVideoURI(uri) // set videoURi as video
} else {
Log.e("MainActivity", "URI not present")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
installSplashScreen().apply {
setKeepOnScreenCondition {
mSplashScreenViewModel.isLoading.value
}
}
setContentView(R.layout.activity_main)
supportActionBar?.hide()
bottomNavigationView.background = null
bottomNavigationView.menu.findItem(R.id.placeholder).isEnabled = false
replaceFragment(HomeFragment()) //base fragment
popupAddButton.setOnClickListener {
showDialog()
}
bottomNavigationView.setOnItemSelectedListener { // navigation bar
when (it.itemId) {
R.id.home -> replaceFragment(HomeFragment())
R.id.player -> replaceFragment(PlayerFragment())
R.id.profile -> replaceFragment(ProfileFragment())
R.id.settings -> replaceFragment(SettingsFragment())
}
true
}
}
private fun replaceFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, fragment)
transaction.commit()
}
#SuppressLint("InflateParams", "CutPasteId")
private fun showDialog() { //this is for popupWindow
dialogView = layoutInflater.inflate(R.layout.popup, null)
mUserViewModel = ViewModelProvider(this)[VideoViewModel::class.java]
val dialog = Dialog(this)
val titleEditText = dialogView?.findViewById<EditText>(R.id.titleEdit) //popUp edit field title
val descEditText = dialogView?.findViewById<EditText>(R.id.description) //popUp edit field description
dialogView?.addImage?.setOnClickListener { //opens gallery where you can pick image
getPreviewImage.launch("image/*")
}
dialogView?.addVideo?.setOnClickListener { //opens gallery where you can pick video
getPreviewVideo.launch("video/*")
}
dialogView?.addButton?.setOnClickListener {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
if (titleEditText?.text?.isEmpty() == true || descEditText?.text?.isEmpty() == true) {
Toast.makeText(applicationContext, "add required data", Toast.LENGTH_LONG).show()
} else {
//all variables bellow add specific data to database
val addTitleToDatabase = titleEditText?.text.toString()
val addDescToDatabase = descEditText?.text.toString()
val addImageToDatabase = dialogView?.findViewById<TextView>(R.id.imageUriHolder)?.text.toString()
val addVideoToDatabase = dialogView?.findViewById<TextView>(R.id.videoUriHolder)?.text.toString()
val video = ListData(
0,
addTitleToDatabase,
addDescToDatabase,
addImageToDatabase,
addVideoToDatabase
)
mUserViewModel.addUser(video)
Toast.makeText(applicationContext, "Successfully added!", Toast.LENGTH_SHORT).show()
}
}
dialog.setContentView(dialogView!!)
dialog.show()
}
}
RecyclerAdapter.kt
package eu.tuto.youtubeproject
import android.app.VoiceInteractor
import android.content.Intent
import android.content.Intent.ACTION_OPEN_DOCUMENT
import android.net.Uri
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.app.ActivityCompat.startActivityForResult
import androidx.core.net.toUri
import androidx.recyclerview.widget.RecyclerView
import eu.tuto.youtubeproject.databinding.CardLayoutBinding
import eu.tuto.youtubeproject.data.ListData
import androidx.recyclerview.widget.DiffUtil
import kotlinx.android.synthetic.main.card_layout.view.*
const val PICK_FILE = 1
class RecyclerAdapter: RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>() {
private var oldList = emptyList<ListData>()
inner class MyViewHolder(binding: CardLayoutBinding): RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(CardLayoutBinding.inflate(LayoutInflater.from(parent.context), parent,false))
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = oldList[position]
holder.itemView.tv_id.text = currentItem.id.toString()
holder.itemView.tv_title.text = currentItem.title
holder.itemView.tv_description.text = currentItem.description
holder.itemView.tv_thumbnail.setImageURI(currentItem.image.toUri())
holder.itemView.tv_Video.setVideoURI(currentItem.Video.toUri())
}
override fun getItemCount(): Int {
return oldList.size
}
fun setData(newList: List<ListData>){
val diffUtil = eu.tuto.youtubeproject.data.DiffUtil(oldList, newList)
val diffResults = DiffUtil.calculateDiff(diffUtil)
oldList = newList
diffResults.dispatchUpdatesTo(this)
}
}
I want to write a hashmap into my firebase using the click listener which I have implemented in the fragment which acts only if one of the items is selected. but I get an error that I haven't got anytime before.
The logcat shows:
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.get(ArrayList.java:437)
at com.reazon.foodrunner.adapter.MenuRecyclerAdapter$MenuViewHolder$bind$1$1.onDataChange(MenuRecyclerAdapter.kt:104)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
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)
this is my adapter :
package com.reazon.foodrunner.adapter
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import com.reazon.foodrunner.R
import com.reazon.foodrunner.fragment.CartFragment
import com.reazon.foodrunner.model.MenuItem
class MenuRecyclerAdapter(
val context: Context,
private val btnProceedToCart: Button,
private val proceedToCartPassed: RelativeLayout,
private val menuList: List<MenuItem>,
private val listener: ContentListener
) : RecyclerView.Adapter<MenuRecyclerAdapter.MenuViewHolder>() {
private var goToCart: Int = 0
private var itemSelected: Int = 0
private var itemNumber: Int = 0
private var itemSelectedId = arrayListOf<String>()
private var itemSelectedName = arrayListOf<String>()
lateinit var proceedToCartLayout: RelativeLayout
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MenuViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.recycler_menu_single_row, parent, false)
return MenuViewHolder(view)
}
override fun getItemCount(): Int {
return menuList.size
}
override fun onBindViewHolder(holder: MenuViewHolder, position: Int) {
val menuItemItem = menuList[position]
holder.menuItemName.text = menuItemItem.item.toString()
proceedToCartLayout = proceedToCartPassed
btnProceedToCart.setOnClickListener {
Toast.makeText(context, "Proceeding To Cart", Toast.LENGTH_SHORT).show()
}
holder.btnMenuItem.setOnClickListener {
if (holder.btnMenuItem.text.toString() == "Remove") {
itemSelected--
holder.btnMenuItem.text = "ADD"
itemSelectedId.remove(holder.btnMenuItem.toString())
itemSelectedName.remove(holder.menuItemName.toString())
holder.btnMenuItem.setBackgroundResource(R.drawable.btn_menu_add_background)
} else {
itemSelected++
holder.btnMenuItem.text = "Remove"
itemSelectedId.add(holder.btnMenuItem.toString())
itemSelectedName.add(holder.menuItemName.toString())
holder.btnMenuItem.setBackgroundResource(R.drawable.btn_menu_remove_background)
}
if (itemSelected > 0) {
proceedToCartLayout.visibility = View.VISIBLE
} else {
proceedToCartLayout.visibility = View.INVISIBLE
}
print("$goToCart")
holder.btnMenuItem.tag = menuItemItem.id
itemNumber = position + 1
Log.d("Restaurant", "" + holder.menuItemName.text)
}
holder.btnMenuItem.tag = menuItemItem.id.toString() + ""
holder.bind(itemSelectedId, itemSelectedName, btnProceedToCart, listener)
}
class MenuViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(menuSelectedId: List<String>, menuList: List<String>, btnProceedToCart: Button, listener: ContentListener) {
btnProceedToCart.setOnClickListener {
val mReference = FirebaseDatabase.getInstance().reference.child("Orders")
.child(FirebaseAuth.getInstance().currentUser!!.uid)
mReference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val orderHashMap = HashMap<String, Any>()
for (item in 1..menuList.size) {
orderHashMap["id"] = menuSelectedId[item]
orderHashMap["item"] = menuList[item]
orderHashMap["cost"] = 200
orderHashMap["placed"] = true
}
mReference.updateChildren(orderHashMap)
}
override fun onCancelled(error: DatabaseError) {
Log.d("MenuRecyclerAdapter", error.message)
}
})
listener.openCart()
}
}
val menuItemName: TextView = view.findViewById(R.id.menuItemName)
val btnMenuItem: Button = view.findViewById(R.id.btnMenuAdd)
}
interface ContentListener {
fun openCart()
}
}
this is my menu fragment:
package com.reazon.foodrunner.fragment
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.RelativeLayout
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.database.*
import com.reazon.foodrunner.R
import com.reazon.foodrunner.adapter.MenuRecyclerAdapter
import com.reazon.foodrunner.model.MenuItem
import com.reazon.foodrunner.model.Restaurant
import kotlinx.android.synthetic.main.fragment_menu.*
import kotlinx.android.synthetic.main.recycler_home_single_row.*
import kotlinx.android.synthetic.main.recycler_menu_single_row.*
class MenuFragment : Fragment(),MenuRecyclerAdapter.ContentListener{
private var menuRecyclerAdapter: MenuRecyclerAdapter? = null
private lateinit var menuReference: DatabaseReference
private var recyclerMenu: RecyclerView? = null
internal var menuItemList: MutableList<MenuItem> = ArrayList()
private var layoutManager: RecyclerView.LayoutManager? = null
private lateinit var proceedToCartLayout:RelativeLayout
private lateinit var btnProceedToCart: Button
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_menu, container, false)
menuReference = FirebaseDatabase.getInstance().reference.child("Menu")
recyclerMenu = view.findViewById(R.id.recyclerMenu)
btnProceedToCart = view.findViewById(R.id.btnGoToCart)
proceedToCartLayout = view.findViewById(R.id.rlProceedToCart)
// val restaurant = (Restaurant::class.java)
layoutManager = LinearLayoutManager(activity)
recyclerMenu!!.layoutManager = layoutManager
retrieveMenu()
return view
}
private fun retrieveMenu() {
menuItemList.clear()
menuReference.addValueEventListener(object : ValueEventListener {
override fun onCancelled(error: DatabaseError) {
Log.d("ERROR", "" + error.message)
}
override fun onDataChange(snapshot: DataSnapshot) {
for (p0 in snapshot.children) {
val menu = p0.getValue(MenuItem::class.java)
menuRecyclerAdapter = MenuRecyclerAdapter(context!!, btnProceedToCart, proceedToCartLayout,menuItemList,this#MenuFragment)//,this#MenuFragment)
recyclerMenu!!.adapter = menuRecyclerAdapter
if (menu != null) {
menuItemList.add(menu)
}
}
}
})
}
fun onBackPressed() {
when (this.fragmentManager?.findFragmentById(R.id.frame)) {
!is HomeFragment -> openHome()
}
}
private fun openHome() {
val transaction = fragmentManager?.beginTransaction()
transaction?.replace(R.id.frame, HomeFragment())
transaction?.commit()
}
override fun openCart() {
val transaction = fragmentManager?.beginTransaction()
transaction?.replace(R.id.frame, CartFragment())
transaction?.commit()
}
}
although I haven't made the cart fragment and recycler properly, this is my cart fragment:
package com.reazon.foodrunner.fragment
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
import com.reazon.foodrunner.R
import com.reazon.foodrunner.activity.FinishActivity
import com.reazon.foodrunner.adapter.CartRecyclerAdapter
import com.reazon.foodrunner.model.Order
import kotlinx.android.synthetic.main.fragment_cart.*
class CartFragment : Fragment() {
lateinit var btnCheckout:Button
private var recyclerCart:RecyclerView? = null
private var recyclerAdapter:CartRecyclerAdapter? = null
private var layoutManager:RecyclerView.LayoutManager? = null
private var orderList:MutableList<Order> = ArrayList()
private var cartDatabaseReference:DatabaseReference? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_cart, container, false)
btnCheckout = view.findViewById(R.id.btnCheckout)
val firebaseUid = FirebaseAuth.getInstance().currentUser!!.uid
cartDatabaseReference = FirebaseDatabase.getInstance().reference.child("Orders").child(firebaseUid)
layoutManager =LinearLayoutManager(activity)
recyclerCart = view.findViewById(R.id.recyclerCart)
recyclerCart!!.layoutManager = layoutManager
btnCheckout.setOnClickListener {
val intent = Intent(activity, FinishActivity::class.java )
startActivity(intent)
}
return view
}
}
Cart adapter:
package com.reazon.foodrunner.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.reazon.foodrunner.R
import com.reazon.foodrunner.model.Order
import kotlinx.android.synthetic.*
import kotlinx.android.synthetic.main.recycler_cart_single_row.view.*
import java.util.function.ToDoubleBiFunction
class CartRecyclerAdapter(
val context: Context,
private val orderList:List<Order>
):RecyclerView.Adapter<CartRecyclerAdapter.CartViewHolder>() {
class CartViewHolder(view: View):RecyclerView.ViewHolder(view){
val txtItemName:TextView = view.findViewById(R.id.txtItemNameCart)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CartViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_cart_single_row,parent,false)
return CartViewHolder(view)
}
override fun onBindViewHolder(holder: CartViewHolder, position: Int) {
val order = orderList[position]
holder.txtItemName.text = order.item
}
override fun getItemCount(): Int {
return orderList.size
}
}
I am unable to understand what to do here to simply upload the hash map of orders and retrieve them.
it was a simple error as I was using the index (indices) in the wrong manner as it should have been
for (item in menuList.indices) {
orderHashMap["id"] = menuSelectedId[item]
orderHashMap["item"] = menuList[item]
orderHashMap["cost"] = 200
orderHashMap["placed"] = true
}
and the list got the correct index of each element thereafter, and hashmap was written to firebase.