I made selectDelete button on the main activity instead of RecyclerView.
When I click that button, I want to delete the items which are checked.
There is an error that checks the RecyclerView item checkbox and unchecks the item when scrolling.
Activity
class CartViewActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefreshListener {
private val tag = this::class.java.simpleName
lateinit var adapter: CartItemRecyclerAdapter
var itemList: MutableList<CartItemDataVo> = arrayListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_cart_view)
selectDelete.setOnClickListener {
if (checkBox.isChecked) {
*adapter.removeItems()*
}
}
swipeRefreshLo.setOnRefreshListener(this)
itemList.add(CartItemDataVo("item1", 1, 16800, "cart_doll", false))
itemList.add(CartItemDataVo("item2", 1, 16800, "cart_cup", false))
itemList.add(CartItemDataVo("item3", 1, 30000, "cart_perfume", false))
itemList.add(CartItemDataVo("item4", 1, 16800, "cart_fan", false))
adapter = CartItemRecyclerAdapter(this, this, itemList)
recycler_view.adapter = adapter
recycler_view.layoutManager =
androidx.recyclerview.widget.LinearLayoutManager(applicationContext)
}
override fun onRefresh() {
swipeRefreshLo.isRefreshing = false
}
}
Adapter:
class CartItemDataVo(
title: String,
itemNumber: Int,
pointValue: Int,
imageView: String,
CheckBox: Boolean
) {
var title: String = title
var itemNumber: Int = itemNumber
var pointValue: Int = pointValue
var image: String = imageView
var isChecked: Boolean = CheckBox
}
class CartItemRecyclerAdapter(
val context: Context,
private var activity: Activity,
private var dataList: MutableList<CartItemDataVo>
) : RecyclerView.Adapter<CartItemRecyclerAdapter.Holder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(context).inflate(R.layout.cart_item_list, parent, false)
return Holder(view)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
holder?.bind(dataList[position], context)
}
override fun getItemCount(): Int = dataList.size
*#SuppressLint("NewApi")
fun removeItems() {
dataList.removeIf { it.isChecked }
notifyDataSetChanged()
}*
fun toggleItems() {
for (item: CartItemDataVo in dataList) {
var state = item.isChecked
item.isChecked = state.not()
}
notifyDataSetChanged()
}
inner class Holder(itemView: View?) : RecyclerView.ViewHolder(itemView!!) {
var titleText = itemView?.findViewById(R.id.titleText) as TextView
var temNumerTextt = itemView?.findViewById(R.id.textViewItemNumer) as TextView
var pointValueText = itemView?.findViewById(R.id.pointValueText) as TextView
var imageView = itemView?.findViewById(R.id.imageView) as ImageView
var checkBox = itemView?.findViewById(R.id.checkBox) as CheckBox
fun bind(data: CartItemDataVo, context: Context) {
if (data.image != "") {
val resourceId =
context.resources.getIdentifier(data.image, "drawable", context.packageName)
imageView?.setImageResource(resourceId)
} else {
imageView.setImageResource(R.mipmap.ic_launcher)
}
titleText?.text = data.title
temNumerTextt?.text = data.itemNumber.toString()
pointValueText?.text = data.pointValue.toString() + "P"
if (data.isChecked) {
checkBox.buttonDrawable =
checkBox.context.getDrawable(R.drawable.check_box_active_cs)
val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
layout.visibility = View.VISIBLE
} else {
checkBox.buttonDrawable = checkBox.context.getDrawable(R.drawable.check_box_no)
val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
layout.visibility = View.GONE
}
checkBox?.setOnClickListener {
if (checkBox.isChecked == data.isChecked) {
checkBox.buttonDrawable = it.context.getDrawable(R.drawable.check_box_active_cs)
val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
layout.visibility = View.VISIBLE
} else {
checkBox.buttonDrawable = it.context.getDrawable(R.drawable.check_box_no)
val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
layout.visibility = View.GONE
}
}
}
}
}
First of all, replace
var itemList: MutableList<CartItemDataVo> = arrayListOf()
with
val itemList: MutableList<CartItemDataVo> = arrayListOf()
You don't want mutable property, which is also mutable collection at the same time. This is very bad practice.
Same situation in adapter
private var dataList : MutableList<CartItemDataVo>
replace with
private val dataList : MutableList<CartItemDataVo>
Then remove private var activity : Activity from your adapter's constructor. Don't put any references to Activity or Fragment in adapter!
Adapter should be only responsible for displaying list.
If in any case, you need communication between Activity or Fragment and adapter, use interface instead. This is not ViewHolder responsibility to hold reference to parent layout and manipulate it!
val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
All lines like below should be removed from ViewHolder. If you need set something which belongs to Activity, based on action on list, use interface.
Finally, in adapter add method which will remove checked items from it:
fun removeItems() {
itemList.removeIf { it.isChecked }
notifyDataSetChanged()
}
Add the following line right after checkBox?.setOnClickListener { (as first line in listener)
data.isChecked = !data.isChecked
And replace
selectDelete.setOnClickListener {
if(checkBox.isChecked){
}
}
with
selectDelete.setOnClickListener {
if(checkBox.isChecked){
adapter?.removeItems()
}
}
Bonus:
read about data class, and use it for CartItemDataVo (don't use CheckBox in constructor),
updateData method can be optimized using DiffUtil for RecyclerView,
it can be improved by modifying data in Activity, not in adapter, so responsible would be moved to better place,
read about SOLID principles,
read about MVVM and MVP design patterns.
Related
**Hello everyone. I am new in android development. I am using room database and I set data in recyclerView. Now I am trying to Do when I click any recyclerview item then I need to go another activity.Anyone Please help me. **
MainActivity RecyclerView Adding code
private fun setUpListOfDataIntoRecyclerView(registerList:ArrayList<registerEntity>,
registerDao: registerDao){
if(registerList.isNotEmpty()){
var itemAdapter = MainAdapter(registerList)
binding?.rvHappyPlaceList?.layoutManager = LinearLayoutManager(this)
binding?.rvHappyPlaceList?.adapter = itemAdapter
binding?.rvHappyPlaceList?.visibility = View.VISIBLE
binding?.noRecordText?.visibility = View.GONE
}else{
binding?.rvHappyPlaceList?.visibility = View.GONE
binding?.noRecordText?.visibility = View.VISIBLE
}
}
MainAdapter
class MainAdapter(val items: ArrayList<registerEntity>):
RecyclerView.Adapter<MainAdapter.MainHolder>() {
//step 2
private var onClickListener: AdapterView.OnItemClickListener? = null
inner class MainHolder(var binding: ItemHappyPlaceBinding): RecyclerView.
ViewHolder(binding.root) {
val llTitle = binding.tvTitle
val llDescription = binding.tvDescription
var llImage = binding.ivPlaceImage
}
fun setOnClickListener(onClickListener: View.OnContextClickListener){
this.onClickListener = onClickListener
}
override fun onBindViewHolder(holder: MainHolder, position: Int) {
val item = items[position]
holder.llTitle.text = item.title
holder.llDescription.text = item.description
holder.llImage.setImageURI(Uri.parse(item.image))
}
I recommend you replace:
private var onClickListener: AdapterView.OnItemClickListener? = null
with this:
var onItemClick: (() -> Unit)? = null
You can also delete the fun setOnClickListener(..){}
And add in your MainHolder the binding.root.setOnClickListener{} like:
inner class MainHolder(var binding: ItemHappyPlaceBinding): RecyclerView.ViewHolder(binding.root) {
init {
binding.root.setOnClickListener {
onItemClick?.invoke()
}
}
val llTitle = binding.tvTitle
val llDescription = binding.tvDescription
var llImage = binding.ivPlaceImage
}
Or if you prefer u can also add the onItemClick?.invoke() in the onBindViewHolder like:
holder.itemView.setOnClickListener {
onItemClick?.invoke()
}
And then in your activity, in fun setUpListOfDataIntoRecyclerView add:
var itemAdapter = MainAdapter(registerList)
itemAdapter.onItemClick = this::goToActivity()
And also add the goToActivity fun like:
fun goToActivity(){
// launch the activity
}
Trying to get a button to open another activity in android studio using kotlin. I am user a recycles view to do so. I have view card and want to edit the data in the card so I am user onClick to get the page to respond but that does seem to work I tried researching it but nothing come up that I can make sense of. Here is the code.
Thank you for all your help I appreciate it
This is the adapter class:
```class EventAdapter(var mListener: onItemClickListener, var context: Context, val items: ArrayList<EventModelk>):
RecyclerView.Adapter<EventAdapter.ViewHolder>() {
interface onItemClickListener {
fun onItemClick(position: Int)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemview = LayoutInflater.from(context).inflate(
R.layout.eventitems,
parent,
false,
)
return ViewHolder(itemview, mListener)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position]
holder.setEmail.text = item.eEmail
holder.setNotes.text = item.nNotes
holder.setData.text = item.dDate
holder.setTime.text = item.tTime
if (item.repeat == 1) {
holder.setReap.isChecked = true
// holder.setReap.text = item.repeat.toString()
}
if (position % 2 == 0) {
holder.main.setBackgroundColor(
ContextCompat.getColor(
context,
R.color.colorLightGray
)
)
} else {
holder.main.setBackgroundColor(ContextCompat.getColor(context, R.color.colorWhite))
}
holder.pushimg.setOnClickListener {
if (context is UpdateDataInfo) {
(context as UpdateDataInfo).updateEvent(item)
}
}
// interface onItemClickListener{
// fun onItemClick(position: Int)
}
override fun getItemCount(): Int {
return items.size
}
class ViewHolder(view: View,onItemClickListener: onItemClickListener): RecyclerView.ViewHolder(view),onItemClickListener {
val main: CardView = view.IIMain
val setData: TextView = view.set_date
val setTime: TextView = view.set_time
val setEmail: TextView = view.Tv_email
val setNotes: TextView = view.set_note
val setReap: CheckBox =view.is_repeat
val pushimg: ImageView = view.img_edit
val onItemClickListener = onItemClickListener
override fun onItemClick(position: Int) {
onItemClickListener.onItemClick(absoluteAdapterPosition)
}
}
}```
This is my code for getting the click to go to another activity:
class CurrentSch : AppCompatActivity(), EventAdapter.onItemClickListener {
//private var change =imageView2?.isClickable
var STORAGE_LOCAL =true
val eventlist = ArrayList<EventModelk>()
#RequiresApi(Build.VERSION_CODES.N)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.currentsch)
btnNewApp2.setOnClickListener {
val intent = Intent(this, NewPlan::class.java)
startActivity(intent)
}
seeAllEventInPlan()
}
//private var change =imageView2?.isClickable
private fun getEventist(): ArrayList<EventModelk>{
val eventdatabase = EventDatabasek(this)
return eventdatabase.veiwEvent()
}
fun seeAllEventInPlan() = if(getEventist().size >0){
ryc_eventLists.visibility = View.VISIBLE
viewnotview.visibility = View.GONE
ryc_eventLists.layoutManager = LinearLayoutManager(this)
val eventAdapter = EventAdapter(this,this, getEventist())
ryc_eventLists.adapter = eventAdapter
}else{
ryc_eventLists.visibility = View.GONE
viewnotview.visibility = View.VISIBLE
}
override fun onItemClick(position: Int) {
val item = eventlist[position]
img_edit.setOnClickListener {
val intent = Intent(this, UpdateDataInfo::class.java)
intent.putExtra("Events", position)
startActivity(intent)
}
}
}
Inside the onBindViewHolder function, simply call mListener.onItemClick(position) for example if you wanted to open another Activity on click of setData, then you can write below code in onBindViewHolder
holder.setData.setOnClickListener { mListener.onItemClick(position) }
according to your above code , you have made callbacks where you calling thee adapter you will get callback there and you will open a activity there .. .. but you can simple open your new activity from adapter like this ..
holder.itemView.setOnClickListener(View.OnClickListener {
val intent = Intent (context,SomeActivity::class.java)
context.startactivity(intent)
})
I'm retrieving a list of items from the firebase database and displaying them using RecyclerView in my android app. The problem is when I'm retrieving more than 9 items and updating some data in the 1st item (while running) as you can see in the image below the 10th item also got affected and vice-versa same with 2nd and 11th item and so on.
Like when I'm adding and fixing the quantity of the 1st item , the same happens with the 10th item (the 10th item also get added with the same quantity as of 1st item).
MenuFragment.kt
class MenuFragment : Fragment() {
private var dishList: MutableList<DishModel> = mutableListOf()
private lateinit var myRef: DatabaseReference
lateinit var list: RecyclerView
lateinit var proceedToCartLayout: RelativeLayout
lateinit var addToCartBtn: Button
private var selectedCategory = ""
companion object {
fun newInstance(): Fragment {
return MenuFragment()
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_menu, container, false)
//retrieve id
val bundle = this.arguments
selectedCategory = bundle!!.getString("CATEGORY_ID")!!
list = view.findViewById(R.id.recyclerMenu)
myRef = FirebaseDatabase.getInstance().getReference("Category")
proceedToCartLayout = view.findViewById(R.id.ProceedToCart)
addToCartBtn = view.findViewById(R.id.btn_cart)
return view
}
override fun onResume() {
if (ConnectionManager().checkConnectivity(activity as Context)) {
fetchMenu()
} else {
val alterDialog = androidx.appcompat.app.AlertDialog.Builder(activity as
Context)
alterDialog.setTitle("No Internet")
alterDialog.setMessage("Connect to internet to continue")
alterDialog.setIcon(R.drawable.nointernet)
alterDialog.setPositiveButton("Open Settings") { _, _ ->
val settingsIntent = Intent(Settings.ACTION_SETTINGS)//open wifi settings
startActivity(settingsIntent)
}
alterDialog.setNegativeButton("Exit") { _, _ ->
ActivityCompat.finishAffinity(activity as Activity)
}
alterDialog.setCancelable(false)
alterDialog.create()
alterDialog.show()
}
super.onResume()
}
private fun fetchMenu() {
myRef.child(selectedCategory).addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
Toast.makeText(context, "$p0", Toast.LENGTH_SHORT).show()
}
override fun onDataChange(p0: DataSnapshot) {
if (p0.exists()) {
dishList.clear()
for (i in p0.children) {
val plan = i.getValue(DishModel::class.java)
dishList.add(plan!!)
}
val adapter = MenuAdapter(
context!!,
R.layout.menu_list_item,
dishList,
proceedToCartLayout,
addToCartBtn, selectedCategory
)
list.adapter = adapter
}
}
})
}
}
MenuAdapter.kt
class MenuAdapter(
private val ctx: Context,
private val layoutResId: Int,
private val dishList:
List<DishModel>,
private val proceedToCartPassed: RelativeLayout,
private val buttonProceedToCart: Button,
private val categoryName: String
) : RecyclerView.Adapter<MenuAdapter.MyViewHolder>() {
private lateinit var proceedToCart: RelativeLayout
private var itemSelectedCount: Int = 0
private var itemsSelectedId = arrayListOf<String>()
private var itemList = arrayListOf<DishModel>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MenuAdapter.MyViewHolder {
val layoutInflater: LayoutInflater = LayoutInflater.from(ctx)
val view: View = layoutInflater.inflate(layoutResId, null)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MenuAdapter.MyViewHolder, position: Int) {
var btnClick = false
var no = 0
val range = 1..5
val dish = dishList[position]
holder.dishName.text = dish.dishName
holder.dishPrice.text = "Rs " + dish.cost + " /-"
Picasso.get().load(dish.image).error(R.drawable.defaultdish).into(holder.dishImage)
holder.increaseBtn.setOnClickListener {
if (btnClick) {
no += 1
if (no in range) {
holder.quantity.text = no.toString()
dish.qty = no
}
}
}
holder.decreaseBtn.setOnClickListener {
if (btnClick) {
no -= 1
if (no in range) {
holder.quantity.text = no.toString()
dish.qty = no
}
}
}
proceedToCart = proceedToCartPassed
buttonProceedToCart.setOnClickListener {
val intent = Intent(ctx, CartActivity::class.java)
intent.putExtra(
"categoryId",
categoryName
)
intent.putExtra(
"selectedItemsId",
itemsSelectedId
)
intent.putExtra("itemList", itemList)
ctx.startActivity(intent)
}
holder.buttonAddToCart.setOnClickListener {
if (holder.buttonAddToCart.text.toString() == "Remove") {
itemSelectedCount--//unselected
itemsSelectedId.remove(holder.buttonAddToCart.tag.toString())
itemList.remove(dish)
holder.buttonAddToCart.text = "Add"
holder.buttonAddToCart.setBackgroundResource(R.drawable.rounded_corners)
btnClick = false
no = 0
dish.qty = no
holder.quantity.text = no.toString()
} else {
itemSelectedCount++//selected
itemsSelectedId.add(holder.buttonAddToCart.tag.toString())
itemList.add(dish)
holder.buttonAddToCart.text = "Remove"
holder.buttonAddToCart.setBackgroundResource(R.drawable.rounded_corners_yellow)
btnClick = true
no = 1
dish.qty = no
holder.quantity.text = no.toString()
}
if (itemSelectedCount > 0) {
proceedToCart.visibility = View.VISIBLE
} else {
proceedToCart.visibility = View.GONE
}
}
holder.buttonAddToCart.tag = dishList.indexOf(dish) + 1
}
override fun getItemCount(): Int {
return dishList.size
}
inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val dishName: TextView = view.findViewById(R.id.txtDishName)
val dishPrice: TextView = view.findViewById(R.id.txtDishPrice)
val dishImage: ImageView = view.findViewById(R.id.dishImage)
val buttonAddToCart: Button = view.findViewById(R.id.add_dish)
val increaseBtn: Button = view.findViewById(R.id.increase)
val decreaseBtn: Button = view.findViewById(R.id.decrease)
val quantity: TextView = view.findViewById(R.id.quantity)
}
}
Please Add
holder.quantity.text = dish.qty.toString() after or before as you wish Picasso.get().load(dish.image).error(R.drawable.defaultdish).into(holder.dishImage)
Something like below.
Picasso.get().load(dish.image).error(R.drawable.defaultdish).into(holder.dishImage)
holder.quantity.text = dish.qty.toString()
holder.increaseBtn.setOnClickListener
Because I can see you are not setting holder.quantity.text thinking your recyclerview item view have the default as 0 but as you know in recyclerview the views are been reused and when they. are been reused the default value is not 0 for that but the value last view which is going to be reused, which in your case is every 10th item.
The golden rule if you are working with recylerview and thinking of using default value of any view from the XML view itself, so you will be surprised when you start scrolling you will notice that that is not the case and the default value is something other than that.
Always set the default value in onBind so next time the view been reused it takes the default value you want
if you are having an if condition to update something do write it's else as well because the same caching will make you wonder why your items are behaving differently.
Important point, make sure your setting default value in 1st point is outside any clicklistener or any view listener you set up because we have to make sure the setter gets executed every time the onBind is getting called
I have my fair share of experience working with checkbox, edittext , radio button etc in items and giving me surprising result on scrolling hence I always make sure to follow the above points when working with recylerviews.
I added the below code in my adapter (override getItemViewType) and it worked !
override fun getItemViewType(position: Int): Int {
return position
}
I'm successfully passing data from MainActivity to my recyclerView via adapter, and my view with items is rendering correctly. However, I need to change one member of my item object on click (status), and i wrote a method for that (updateStatus), and it works great, it changes the value and save it to database.
But i cannot refresh my recyclerView, so it could render changed Status attribute. I need to go back on my phone, reenter, and then it renders it correctly. I have tried everything, from notifyDataSetChanged to restarting adapter, no luck. There is something missing and I can't find what.
Here is my MainActivity class
class MainActivity : AppCompatActivity() {
private var posiljkaDAO: PosiljkaDAO? = null
private var dostavnaKnjizicaDAO: DostavnaKnjizicaDAO? = null
private var allItems: ArrayList<DostavnaKnjizicaModel> = arrayListOf()
var adapter = RecycleViewAdapter(allItems)
private var eSifraPosiljke: EditText? = null
#RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_listview)
//get logo
supportActionBar!!.setDisplayShowHomeEnabled(true)
supportActionBar!!.setLogo(R.drawable.logo_bp)
supportActionBar!!.setDisplayUseLogoEnabled(true)
dostavnaKnjizicaDAO = DostavnaKnjizicaDAO(this)
dostavnaKnjizicaDAO?.closeDB()
getAllItems(this)
//connecting adapter and recyclerView
adapter = RecycleViewAdapter(allItems)
recycleView.adapter = adapter
recycleView.layoutManager = LinearLayoutManager(this)
recycleView.setHasFixedSize(true)
eSifraPosiljke = findViewById<EditText>(R.id.eSifraPosiljke)
posiljkaDAO = PosiljkaDAO(this)
}
//method that gets all items from database
private fun getAllItems(context: Context) {
var dostavenFromLOcal = dostavnaKnjizicaDAO?.getAllLocalDostavneKnjizice(context)
if (dostavenFromLOcal != null) {
allItems = dostavenFromLOcal
}
}
//method that changes status of an item
fun changeStatus(context: Context, IdDostavne: Int, statusDostavne: Int) {
dostavnaKnjizicaDAO = DostavnaKnjizicaDAO(context)
dostavnaKnjizicaDAO?.changeStatus(IdDostavne, statusDostavne)
getAllItems(context)
adapter.notifyDataSetChanged()
}
}
and my Adapter class
class RecycleViewAdapter(var dostavneKnjiziceBP: ArrayList<DostavnaKnjizicaModel>)
: RecyclerView.Adapter<RecycleViewAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view){
val nazivPrimaoca: TextView = view.txtNazivPrimaoca
val brojPosiljke: TextView = view.txtBrojPosiljke
val statusDostave: TextView = view.txtStatusDostave
val imgMore: ImageView = view.img_more
val context: Context = view.context
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.urucenje_posiljke_layout, parent, false)
return ViewHolder(layoutView)
}
override fun getItemCount() = dostavneKnjiziceBP.size
#RequiresApi(Build.VERSION_CODES.KITKAT)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//New variable to get all modeliPosiljakaBP and their position
var dosKnjizica = dostavneKnjiziceBP[position]
val mainActivity = MainActivity()
//Sending data to layout for display in specific field
if (dosKnjizica.naziv_primaoca != null) {
holder.brojPosiljke.text = "${dosKnjizica.id_dostavna_knjizica}, "
holder.nazivPrimaoca.text = "${dosKnjizica.naziv_primaoca}"
if (dosKnjizica.naziv_primaoca!!.length > 25) {
holder.nazivPrimaoca.text = "${dosKnjizica.naziv_primaoca!!.subSequence(0, 25)}..."
}
} else {
holder.brojPosiljke.text = "${dosKnjizica.id_dostavna_knjizica}"
holder.nazivPrimaoca.text = ""
}
holder.statusDostave.text = "${dosKnjizica.status_dostave_naziv}"
when (dosKnjizica.status_dostave) {
StatusDostaveEnum.Neurucena.value -> {
holder.statusDostave.setTextColor(Color.RED)
}
StatusDostaveEnum.Uruceno.value, StatusDostaveEnum.ZaRejon.value, StatusDostaveEnum.Nadoslano.value, StatusDostaveEnum.Izgubljeno.value -> {
holder.statusDostave.setTextColor(Color.GREEN)
}
StatusDostaveEnum.Obavjesteno.value, StatusDostaveEnum.ZaNarednuDostavu.value -> {
holder.statusDostave.setTextColor(Color.BLUE)
}
StatusDostaveEnum.Retour.value -> {
holder.statusDostave.setTextColor(Color.parseColor("#dda0dd"))
}
}
//Calling menu menu_pregled_drugih_vrsta_posiljke to display menu options on click on three dots
holder.imgMore.setOnClickListener {
val popupMenu = PopupMenu(holder.context, it, Gravity.START)
popupMenu.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.uruci -> {
//calling new activity from second item in dropdown menu
holder.imgMore.context.startActivity(
Intent(holder.imgMore.context, MainActivityInfo::class.java).putExtra(
"Id", dosKnjizica.id_dostavna_knjizica.toString()
)
)
true
}
//here i am calling my changeStatus method from MainActivity
R.id.obavjesti -> {
mainActivity.changeStatus(holder.context, dosKnjizica.id_dostavna_knjizica!!, StatusDostaveEnum.Uruceno.value)
Toast.makeText(holder.context, "obavjesti", Toast.LENGTH_SHORT).show()
true
}
R.id.vrati -> {
Toast.makeText(holder.context, "vrati", Toast.LENGTH_SHORT).show()
true
}
else -> false
}
}
popupMenu.inflate(R.menu.menu_urucenje_posiljke)
popupMenu.show()
}
}
}
Your adapter doesn't have the updated data. Initially, you fetch all data from the database and create an adapter with it: adapter = RecycleViewAdapter(allItems). Afterwards, you are updating the database, calling getAllItems(Context) but you don't pass the data to the adapter.
Add the line adapter.dostavneKnjiziceBP = allItems to the changeStatus method like this:
//method that changes status of an item
fun changeStatus(context: Context, IdDostavne: Int, statusDostavne: Int) {
dostavnaKnjizicaDAO = DostavnaKnjizicaDAO(context)
dostavnaKnjizicaDAO?.changeStatus(IdDostavne, statusDostavne)
getAllItems(context)
adapter.dostavneKnjiziceBP = allItems
adapter.notifyDataSetChanged()
}
Save dostavneKnjiziceBP as a private var inside the adapter and create functions for assigning and updating that ArrayList from within the adapter, using notifyDataSetChanged() everytime a change is done.
class RecycleViewAdapter internal constructor(
context: Context
) : RecyclerView.Adapter<RecycleViewAdapter.ViewHolder>() {
private var items = ArrayList<DostavnaKnjizicaModel>()
// ...
internal fun setItems(items: ArrayList<DostavnaKnjizicaModel>) {
this.items = items
notifyDataSetChanged()
}
override fun getItemCount() = this.items.size
}
Also, try using adapter.notifyItemChanged(updateIndex); if you know the index of the updated item.
I want to create an android app with Kotlin. In this app, i use swagger also to get all the web service in a file.
I want to create an interface, the description is as follows:
A RecyclerView horizontal that contains all the list of categories
comes from a web service apiMobileProductCategoriesGetAllPost.
after that, when i click on a which category, a RecyclerView(Grid)
appear that contains all the product by category id.
I want to know how can i get the category id when i click on item,and how to use it in the activity
The following the RecyclerView category adapter:
class CategoryAdapter(private val categories: Array<ProductCategoryData>) :
RecyclerView.Adapter<CategoryAdapter.ViewHolder>(), View.OnClickListener {
private var onItemClickListener: OnItemClickListener? = null
override fun onClick(v: View?) {
if (v != null) {
onItemClickListener?.onItemClick(v, ProductCategoryData())
}
}
fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
this.onItemClickListener = onItemClickListener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.category_item, parent, false)
view.setOnClickListener(this)
return ViewHolder(view)
}
override fun getItemCount() = categories.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val itemCategory: ProductCategoryData = categories[position]
holder.categoryId.text = itemCategory.id.toString()
println(holder.categoryId.text)
println(itemCategory.name?.get("En").toString())
holder.categoryName.text = itemCategory.name?.get("En").toString()
println(itemCategory.id)
if (itemCategory.logo != null) {
Picasso.get()
.load("..../T/${itemCategory.logo}")
.into(holder.categoryImage, object : com.squareup.picasso.Callback {
override fun onError(e: Exception?) {
holder.categoryImage.setImageResource(R.drawable.homecraftdefault)
}
override fun onSuccess() {
Picasso.get().load("....T/${itemCategory.logo}")
.into(holder.categoryImage)
}
})
holder.itemView.setOnClickListener {
onItemClickListener?.onItemClick(holder.itemView,itemCategory)
}
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
val categoryName: TextView = itemView.categoryName
val categoryImage: ImageView = itemView.categoryImage
val categoryId: TextView = itemView.categoryId
override fun onClick(v: View?) {
if (v != null) {
onItemClickListener?.onItemClick(v, ProductCategoryData())
}
}
}
interface OnItemClickListener {
fun onItemClick(view : View, viewModel:ProductCategoryData)
}
}
The following code is relative to the activity:
class CategoryByProduct : AppCompatActivity(), CategoryAdapter.OnItemClickListener {
override fun onItemClick(view: View, viewModel: ProductCategoryData) {
var params = "CategoryProductID";"5cc057458c4d9823743736d2"
println(viewModel.id)
val products = mobileApi!!.apiMobileProductsGetAllPost(params, 0, 50, "", "")
recyclerViewProductByCategory.apply {
recyclerViewProductByCategory.layoutManager = GridLayoutManager(this#CategoryByProduct, 2)
recyclerViewProductByCategory.adapter = ProductAdapter(products)
} }
var mobileApi: MobileApi? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.list_product_by_category)
mobileApi = MobileApi()
val params = HashMap<String, String>()
GlobalScope.launch(Dispatchers.IO) {
val categories = mobileApi!!.apiMobileProductCategoriesGetAllPost(params, 0, 50, "", "")
withContext(Dispatchers.Main) {
recyclerViewCategories.apply {
recyclerViewCategories.layoutManager =
LinearLayoutManager(this#CategoryByProduct, OrientationHelper.HORIZONTAL, false)
recyclerViewCategories.adapter = CategoryAdapter(categories)
}
}
}
}
}
First of all , never put your onclick in onBindViewHolder That's not a good practice, after that i think you need to get the ID of the category i will give you simple example in all of the Adapter Class
class NewsAdapter (val context: Context, private val arrayList: ArrayList <NewsModel>):
RecyclerView.Adapter <NewsAdapter.Holder> () {
companion object {
// val TAG: String = OperationAdapter::class.java.simpleName
}
override fun onCreateViewHolder (parent: ViewGroup, viewType: Int): Holder {
return Holder (LayoutInflater.from (parent.context ).inflate (R.layout.newslist , parent, false))
}
override fun getItemCount (): Int = arrayList. size
override fun onBindViewHolder (holder: Holder, position: Int) {
val mynews = arrayList[position]
holder.setData(mynews , position)
}
inner class Holder (itemView: View): RecyclerView.ViewHolder (itemView) {
private var currentnews: NewsModel? = null
private var currentPosition: Int = 0
init {
//The click listener
itemView.newscardview.setOnClickListener {
//do it here
Toast.makeText(this,currentnews!!.id,Toast.LENGTH_SHORT).show()
}
//the end of the init
}
//getting data from model and bind it into View
fun setData(news: NewsModel?, position: Int) {
news?.let {
itemView.newsid.text = news.id
itemView.newstitle.text = news.title
itemView.body.text = news.body
itemView.txtdate.text = news.ndate
}
this.currentnews = news
this.currentPosition = position
}
}
}
In this example you will get the news ID when you click newscardview, i hope to understand it
In your Activity
put this code in onCreate
//set up the recycleview
mRecyclerView.setHasFixedSize (true)
mRecyclerView. layoutManager = LinearLayoutManager(this)
mRecyclerView is my RecycleView
also call your Adapter class in anywhere you want
//adapter
val adapter = NewsAdapter (this,arrayList)
adapter.notifyDataSetChanged()
mRecyclerView.adapter = adapter
you get the position of the category inside a viewholder by calling adapterPosition and with this you can get the category from your list you provide to your adapter in the constructor (categories[adapterPosition])
In your case it is very simple.Try these:-
holder.tv_broadcast_title.text=broadList[position].name
where broadlist is my array list created in the adapter itself.In this list the json data is getting stored from api.
internal var broadList = ArrayList<Model>()
and .name is the name of key to fetch name from json data.
holder.categoryName.text = itemCategory.name?.get("En").toString()
in your case do something like this:-
itemCategory[position].name
To get data from adapter to activity, you can make an interface in the adapter or globally and from the activity you can pass that interface in adapter's constructor and use that to get data. I am giving you an example.
interface ProductCategoryListner {
fun getProductCategory(viewModel:ProductCategoryData)
}
Not in adapter's constructor add this interface.
class CategoryAdapter(private val categories: Array<ProductCategoryData>,private val productCategoryListner: ProductCategoryListner):
RecyclerView.Adapter<CategoryAdapter.ViewHolder>(), View.OnClickListener {
Now you can use this to pass data in the activity when you click on view.
productCategoryListner.getProductCategory(categories[adapterPosition])