Q1
I make some recyclerview with cardview I want to click some position and change bg current position to black and another position to green in the adapter
Q2
I want to change something specific position in the adapter
class RecyclerAdapterBrand(private var imageList: List<Int>) :
RecyclerView.Adapter<RecyclerAdapterBrand.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.imgViewBrand)
val cardView: CardView = itemView.findViewById(R.id.cardViewBrand)
init {
// Set Recycler Click
itemView.setOnClickListener { v: View ->
val positionClick: Int = (adapterPosition + 1)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(
R.layout.recy_brand_layout,
parent,
false
)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.post {
holder.imageView.setImageResource(imageList[position])
}
}
override fun getItemCount(): Int {
return imageList.size
}
You can change the background of the clicked item easily.You have to create a variable called selectedposition and assigned to -1. Whenever you click the item you have to set the clicked position value to selectedPosition.And call notifyDataSetChanged() method on recyclerview's item ClickListener method. Then in OnBindViewHolder() method you have to check if the position & selected position are same, set the background color to green.otherwise set the background color to black.
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var selectedPosition=-1
val imageView: ImageView = itemView.findViewById(R.id.imgViewBrand)
val cardView: CardView = itemView.findViewById(R.id.cardViewBrand)
init {
// Set Recycler Click
itemView.setOnClickListener { v: View ->
selectedPosition=(adapterPosition + 1)
val positionClick: Int = (adapterPosition + 1)
notifyDataSetChanged()
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(
R.layout.recy_brand_layout,
parent,
false
)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
if(selectedPosition==position){
holder.itemView.setBackground(#green color)
}else{
holder.itemView.post {
holder.imageView.setImageResource(#black color)
}
}
}
override fun getItemCount(): Int {
return imageList.size
}
I have included those lines in your adapter class.I hope it will solve your problem.
Related
Initially load 3 items from list after click on view all button load remaining all data to same page in kotlin.
To show 3 items I added limit to show data in adapter class in getItemCount mathod. So now I am able to see only 3 items from list. But not able to do like ad all data on same page on click view all button.
Here is how I have solved the issue.
class MyAdapter(private val maxItems: Int = 3) : RecyclerView.Adapter<MyViewHolder>() {
private val items = mutableListOf<String>()
fun setData(data: List<String>) {
items.clear()
items.addAll(data)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return min(items.size, maxItems)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(items[position])
}
fun updateMaxItems(max: Int) {
maxItems = max
notifyDataSetChanged()
}
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val textView = itemView.findViewById<TextView>(R.id.item_text)
fun bind(text: String) {
textView.text = text
}
}
In your Activity/Fragment where you set up the RecyclerView, create a button "View All" and set its onClickListener
val viewAllButton = findViewById<Button>(R.id.viewAllButton)
viewAllButton.setOnClickListener {
//update the adapter's maxItems to show all items
adapter.maxItems = Int.MAX_VALUE
adapter.notifyDataSetChanged()
}
I have a recyclerView populated by the val microphones: MutableList<Microphone>. There's a button in the row layout to remove that item from the list, which I've managed to get functioning, but the animation is going wrong. It looks like when the recyclerView updates, it removes the last item in the list, then the correct item, and then the whole list below the removed item animates to the correct state.
Here's the relevant bits of the recyclerView adapter:
class RecyclerViewAdapter(
val microphones: MutableList<Microphone>
): RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val cellForRow = LayoutInflater.from(parent.context).inflate(R.layout.favorites_row, parent, false)
return ViewHolder(cellForRow)
}
override fun getItemCount(): Int {
return microphones.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val microphone = microphones[position]
holder.bind(microphone)
holder.favoritesButton.setOnClickListener {
microphones.remove(microphone)
notifyItemRemoved(position)
}
}
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val modelText = view.findViewById<TextView>(R.id.model_textView)
val brandText = view.findViewById<TextView>(R.id.brand_textView)
val favoritesButton = view.findViewById<ImageButton>(R.id.btnFavorite)
fun bind(
microphone: Microphone,
) {
modelText.text = microphone.model
brandText.text = microphone.brand
}
}
}
Here's a screen recording of the issue:
https://imgur.com/a/pJt3KwH
When I delete an item in recyclerview and then I add a new item, the items I deleted appear again on my Android app. I used the init in my Adapter to call the setonClickLister. I think that I need to call this code in my Activity but how will ı do ? I use the kotlin and how can ı fix it ? I shared my adapter code below to see clearly, thanx
class NoteAdapter(private var titleText: ArrayList<String>, private var imageButton: ArrayList<String>, private var noteText: ArrayList<String>) : RecyclerView.Adapter<NoteAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val itemTitle : TextView = itemView.findViewById(R.id.recyclerTitleText)
val itemImage : ImageView = itemView.findViewById(R.id.recyclerImage)
val itemDelete : ImageView = itemView.findViewById(R.id.delete)
init {
itemView.setOnClickListener { v: View ->
// Toast.makeText(itemView.context,"You clicked on item # ${position + 1}", Toast.LENGTH_SHORT).show()
val intent = Intent(itemView.context, PastNotesActivity::class.java)
intent.putExtra("oldTitle", titleText[position])
intent.putExtra("oldNote", noteText[position])
intent.putExtra("oldImage", imageButton[position])
itemView.context.startActivity(intent)
}
itemDelete.setOnClickListener { v: View ->
titleText.removeAt(position)
imageButton.removeAt(position)
notifyItemRemoved(position)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.recycler_row, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemTitle.text = titleText[position]
Picasso.get().load(imageButton[position]).resize(150,150).into(holder.itemImage)
}
override fun getItemCount(): Int {
return titleText.size
}
}
by the way, ı tried this code, but it does not work
notifyItemRemoved(position)
notifyItemRangeChanged(position, titletext.size)
I have some suggests:
-You shouldn't use inner ViewHolder like that.
-And clarify your activity, adapter and viewholder.
-Create your own Listener or a callback function to handle the action from the viewholder.
-Create your data class/map/... to manage or store your data, shouldn't use like that.
Put button click inside onBindViewHolder:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemTitle.text = titleText[position]
Picasso.get().load(imageButton[position]).resize(150,150).into(holder.itemImage)
val itemDelete : ImageView = itemView.findViewById(R.id.delete)
itemDelete.setOnClickListener { v: View ->
titleText.removeAt(position)
imageButton.removeAt(position)
notifyItemRemoved(position)
}
}
I'm new to Android development (and Kotlin).
I'm trying to implement a RecyclerView (which works fine) and when I click on a specific row it opens a new activity (Intent).
However, whenever I've press/click on one of the rows, I'm only able to get the value "-1" returned.
I've tried a number of different approaches (you should see the number of tabs in my browser).
This seems like it should be a fairly straightforward occurrence for something as common as a RecyclerView, but for whatever reason I'm unable to get it working.
Here is my RecyclerView Adapter file:
class PNHLePlayerAdapter (val players : ArrayList<PNHLePlayer>, val context: Context) : RecyclerView.Adapter<ViewHolder>() {
var onItemClick: ((Int)->Unit) = {}
// Gets the number of items in the list
override fun getItemCount(): Int {
return players.size
}
// Inflates the item views
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemView = LayoutInflater.from(context).inflate(
R.layout.pnhle_list_item,
parent,
false
)
val viewHolder = ViewHolder(itemView)
itemView.setOnClickListener {
onItemClick(viewHolder.adapterPosition)
}
return ViewHolder(itemView)
}
// Binds each item in the ArrayList to a view
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.tvPlayerName?.text = players[position].Name
holder.tvPlayerRank?.text = position.toString()
holder.tvPNHLe?.text = players[position].PNHLe.toString()
holder.tvTeam?.text = players[position].Team
holder.ivLeague?.setImageResource(leagueImageID)
}
}
class ViewHolder (view: View) : RecyclerView.ViewHolder(view) {
val linLayout = view.hor1LinearLayout
val ivTeam = view.teamImageView
val tvPlayerName = view.playerNameTextView
val tvPlayerRank = view.rankNumTextView
val tvPNHLe = view.pnhleTextView
val tvTeam = view.teamTextView
val ivLeague = view.leagueImageView
}
As you can see, there is a class property "onItemClick" which uses a lambda as the click callback.
I setOnClickListener in the onCreateViewHolder method after the view is inflated.
Next, in my Activity I add the list to my Adapter and set the call back.
However, every time I 'Toast' the position it is displayed as '-1'.
val adapter = PNHLePlayerAdapter(list, this)
adapter.onItemClick = { position ->
Toast.makeText(this, position.toString(),Toast.LENGTH_SHORT).show()
var intent = Intent(this, PlayerCardActivity::class.java)
//startActivity(intent)
}
rv_player_list.adapter = adapter
Perhaps I'm not thinking about this properly, but shouldn't the position represent the row number of the item out of the RecyclerView???
Ideally, I need to use the position so that I can obtain the correct item from the 'list' (ArrayList) so that I can pass information to my next Activity using the Intent
I found the issue.
Change this line in onCreateViewHolder:
return ViewHolder(itemView)
to this one:
return viewHolder
I would reorganize the adapter like this:
class PNHLePlayerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<Adapter.ViewHolder>() {
interface AdapterListener {
fun onItemSelected(position: Int?)
}
var players: List<Player> = listOf()
set(value) {
field = value
this.notifyDataSetChanged()
}
var listener: AdapterListener? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_car_selector, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(position)
}
override fun getItemCount(): Int {
return brands.size
}
inner class ViewHolder(view: View): androidx.recyclerview.widget.RecyclerView.ViewHolder(view) {
private var position: Int? = null
private val baseView: LinearLayout? = view.findViewById(R.id.baseView) as LinearLayout?
...
init {
baseView?.setOnClickListener {
listener?.onManufacturerSelected(position)
}
}
fun bind(position: Int) {
this.position = position
...
}
}
}
And from your activity/fragment set the listener as adapter.listener = this, and implement the onItemSelected(position: Int?)
override fun onItemSelected(position: Int?) {
...
}
I'm trying to make 2 view holder one will be at position 0 always which will be a header view for selecting image, another for displaying the model,
I can do it for normal recyclerview adapter but in firestore recycler adapter i can't do it,
what I try it increase the item count by 1 but I got
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
This is my adapter class code:
val TYPE_SELECT_IMAGE = 0
val TYPE_ITEMS = 1
class UsersImageAdapter(options: FirestoreRecyclerOptions<UserImage>)
: FirestoreRecyclerAdapter<UserImage, RecyclerView.ViewHolder>(options) , AnkoLogger{
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, model: UserImage) {
when(holder){
is SelectImageViewHolder -> {
holder.bindModel()
}
is UserImageViewHolder -> {
holder.bindImages(model)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
TYPE_SELECT_IMAGE -> {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_add_image, parent, false)
SelectImageViewHolder(view)
}
TYPE_ITEMS -> {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_image,parent,false)
UserImageViewHolder(view)
}
else -> throw RuntimeException()
}
}
override fun getItemViewType(position: Int): Int {
return if (isPositionHeader(position)) {
TYPE_SELECT_IMAGE
} else {
TYPE_ITEMS
}
}
fun isPositionHeader(position: Int): Boolean {
return position == 0
}
override fun getItemCount(): Int {
return super.getItemCount() + 1
}
}
and this is two view holder one for header view another for displaying model
class SelectImageViewHolder(val view: View) : RecyclerView.ViewHolder(view) , AnkoLogger{
fun bindModel() {
view.setOnClickListener {
info {
"clicked !"
}
}
}
}
class UserImageViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bindImages(userImage: UserImage) {
val imageView = view.findViewById<ImageView>(R.id.image_user_post)
Glide.with(view.context).load(userImage.imageUrl).into(imageView)
}
}
my goal is to keep the SelectImageViewHolder in position 0 always
FirebaseUI maintainer here. onBindViewHolder(RecyclerView.ViewHolder, Int, Model) makes a getItem(position) call internally to seamlessly populate your model. Since you're manually injecting an item, the RecyclerView is going to think there are items in the database and will blow up as you saw. To fix that, you'll want to override the native onBindViewHolder(RecyclerView.ViewHolder, Int) method without calling super:
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder) {
is SelectImageViewHolder -> holder.bindModel()
is UserImageViewHolder -> {
// Manually get the model item
holder.bindImages(getItem(position - 1))
}
}
}