I have made a simple app for taking notes, it works fine. When i scrolled up or down the screen, they are randomly expanded or shows previous screen states when scrolled as seen here screen1 (no scrolling) and screen2 (when scrolled)
Any help is very much appreciated.
My adapter code is below:
class NoteListAdapter : RecyclerView.Adapter<NoteListAdapter.ViewHolder>(), {
private var wordList: List<EnEntity> = arrayListOf()
private var filteredWordList: List<EnEntity> = arrayListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(
R.layout.note_list,
parent, false
)
return ViewHolder(view)
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(word: EnEntity) {
itemView.zk_entitle.text = word.titleWord
itemView.zk_custword.text = word.customWord
itemView.note_list_main.setOnClickListener {
val action = EnFragmentDirections.actionEnFragmentToNoteFragment(word)
itemView.findNavController().navigate(action)
}
//the eye icon
itemView.zk_eye.setOnClickListener {
if (itemView.zk_custword.isGone) {
itemView.zk_custword.visibility = View.VISIBLE
itemView.zk_eye.setColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP)
} else {
itemView.zk_custword.visibility = View.GONE
itemView.zk_eye.clearColorFilter()
}
}
if (word.isFavorite) {
itemView.zk_faved.visibility = View.VISIBLE
} else{
View.GONE
}
/** show heart icon*/
itemView.zk_faved.setOnClickListener {
if (itemView.zk_faved_deson.isGone) {
itemView.zk_faved_deson.visibility = View.VISIBLE
}
}
itemView.zk_faved.setOnLongClickListener {
val t = Toast.makeText(itemView.context, "Favorite", Toast.LENGTH_SHORT)
t.setGravity(Gravity.TOP, 0, 60)
t.show()
true
}
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//search
holder.bind(filteredWordList[position])
}
override fun getItemCount(): Int = filteredWordList.size
fun setAllWords(wordItems: List<EnEntity>) {
this.wordList = wordItems
this.filteredWordList = wordItems
notifyDataSetChanged()
}
}
Try applying setHasStableIds(true) to your adapter
like so:
class NoteListAdapter : RecyclerView.Adapter<NoteListAdapter.ViewHolder>(), {
init {
setHasStableIds(true)
}
Then add the following two functions inside your adapter class
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemViewType(position: Int): Int {
return position
}
Related
I implemented a simple RecyclerView example, with multiple items selection possibility, using the selection library.
Here's my code:
class MainActivity : AppCompatActivity() {
private var listOfItems = ArrayList<Item>()
private var selectionTracker: SelectionTracker<Long>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.rvMainRecyclerView)
for (i in 0..32) {
listOfItems.add(Item(i, "Item $i"))
}
val recyclerViewAdapter = RecyclerViewAdapter(listOfItems)
recyclerView.adapter = recyclerViewAdapter
selectionTracker = SelectionTracker.Builder<Long>(
"Itemselection",
recyclerView,
MyItemKeyProvider(recyclerView),
MyItemDetailsLookup(recyclerView),
StorageStrategy.createLongStorage()
).build()
selectionTracker?.addObserver(
object: SelectionTracker.SelectionObserver<Long>() {
override fun onSelectionChanged() {
super.onSelectionChanged()
val itemsSelected = selectionTracker?.selection?.size()
Log.d("MainActivity", "$itemsSelected items selected")
}
}
)
recyclerViewAdapter.tracker = selectionTracker
}
}
class RecyclerViewAdapter(
val dataSet: ArrayList\<Item\>
): RecyclerView.Adapter\<RecyclerViewAdapter.ViewHolder\>() {
var tracker: SelectionTracker<Long>? = null
init {
setHasStableIds(true)
}
inner class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
val textView: TextView
init {
textView = view.findViewById(R.id.tvRecyclerViewItemTitle)
}
fun getItemDetails(): ItemDetails<Long> {
return object : ItemDetails<Long>() {
override fun getPosition(): Int {
return adapterPosition
}
override fun getSelectionKey(): Long? {
return itemId
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater
.from(parent.context).inflate(R.layout.recycler_view_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = dataSet[position]
holder.textView.text = currentItem.value
holder.itemView.isActivated = tracker!!.isSelected(position.toLong())
}
override fun getItemCount(): Int {
return dataSet.size
}
override fun getItemId(position: Int): Long {
return dataSet[position].id.toLong()
}
}
I'm curious why the onSelectionChanged (in MainActivity selectionTracker?.addObserver...) is triggered several times while I hold an item to start selection mode?
To be more precise, this is the use case:
Nothing is selected,
Long click on any item => selection mode activated; the item is selected
Here, "1 items selected" is being printed out as long as I hold the first item.
I am currently working on a project in Kotlin and I'm having trouble working an image into a ViewHolder through Picasso and keep getting requests to create an extension function instead when troubleshoot. This is where the problem comes in
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val user = mUser[position]
holder.userNameTextView.text = user.getUsername()
holder.userFullNameTextView.text = user.getFullName()
Picasso.get().load(user.getImage())
.placeholder(R.drawable.ic_user_avatar_light)
.into(holder.userProfileImageView)
... with the rest of my adapter being this
class SearchAdapter(private var mContext: Context,
private var mUser: List<User>,
private var isFragment: Boolean = false) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() {
private var firebaseUser: FirebaseUser? = FirebaseAuth.getInstance().currentUser
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(mContext).inflate(R.layout.user_item_layout, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val user = mUser[position]
holder.userNameTextView.text = user.getUsername()
holder.userFullNameTextView.text = user.getFullName()
Picasso.get().load(user.getImage())
.placeholder(R.drawable.ic_user_avatar_light)
.into(holder.userProfileImageView)
user.getUid()?.let { checkWatchingStatus(it, holder.userWatchButton as Button) }
holder.itemView.setOnClickListener{
val pref = mContext.getSharedPreferences("PREFS", Context.MODE_PRIVATE).edit()
pref.putString("profileID", user.getUid())
pref.apply()
(mContext as FragmentActivity).supportFragmentManager.beginTransaction()
.replace(R.id.viewPager, ProfileFragment()).commit()
}
holder.userWatchButton.setOnClickListener{
if(holder.userWatchButton.text.toString() == "Watch"){
firebaseUser?.uid.let{ itl ->
user.getUid()?.let { it1 ->
FirebaseDatabase.getInstance().reference
.child("Watch").child(itl.toString())
.child("Watching").child(it1)
.setValue(true).addOnCompleteListener{ task ->
if (task.isSuccessful){
firebaseUser?.uid.let{ itl ->
FirebaseDatabase.getInstance().reference
.child("Watch").child(user.getUid()!!)
.child("Watchers").child(itl.toString())
.setValue(true).addOnCompleteListener{ task ->
if (task.isSuccessful){
}
}
}
}
}
}
}
} else {
firebaseUser?.uid.let{ itl ->
user.getUid()?.let { it1 ->
FirebaseDatabase.getInstance().reference
.child("Watch").child(itl.toString())
.child("Watching").child(it1)
.removeValue().addOnCompleteListener{ task ->
if (task.isSuccessful){
firebaseUser?.uid.let{ itl ->
FirebaseDatabase.getInstance().reference
.child("Watch").child(user.getUid()!!)
.child("Watchers").child(itl.toString())
.removeValue().addOnCompleteListener{ task ->
if (task.isSuccessful){
}
}
}
}
}
}
}
}
}
}
override fun getItemCount(): Int {
return mUser.size
}
class ViewHolder(#NonNull itemView: View) :RecyclerView.ViewHolder(itemView) {
var userNameTextView: TextView = itemView.findViewById(R.id.userName_search)
var userFullNameTextView: TextView = itemView.findViewById(R.id.userFullName_search)
var userProfileImageView: TextView = itemView.findViewById(R.id.userImage_search)
var userWatchButton: TextView = itemView.findViewById(R.id.watchButton_search)
}
private fun checkWatchingStatus(uid: String, userWatchButton: Button){
val watchingRef = firebaseUser?.uid.let{ itl ->
FirebaseDatabase.getInstance().reference
.child("Watch").child(itl.toString())
.child("Watching")
}
watchingRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
if (p0.child(uid).exists()) {
userWatchButton.text = "Watching"
} else {
userWatchButton.text = "Watch"
}
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
}
Can anyone help?
In your ViewHolder, you're declaring userProfileImageView as a TextView not as an ImageView, and passing that into Picasso's into() method, which accepts an ImageView as a parameter, that is why it is asking to create an extension function.
class ViewHolder(#NonNull itemView: View) :RecyclerView.ViewHolder(itemView) {
var userNameTextView: TextView = itemView.findViewById(R.id.userName_search)
var userFullNameTextView: TextView = itemView.findViewById(R.id.userFullName_search)
//declare userProfileImageView as an ImageView
var userProfileImageView: ImageView = itemView.findViewById(R.id.userImage_search)
var userWatchButton: TextView = itemView.findViewById(R.id.watchButton_search)
}
I am using kotlin language with android studio. I want to get the properties of the element I clicked in the RecyclerView.
Ben bu kod ile saderc id alabiliyorum
Ex: date
ListAdapter.kt
class ListAdapter(
private val context: Context
) : RecyclerView.Adapter<ListAdapter.ListViewHolder>() {
private var dataList = mutableListOf<Any>()
private lateinit var mListener: onItemClickListener
interface onItemClickListener {
fun onItemClick(position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener) {
mListener = listener
}
fun setListData(data: MutableList<Any>) {
dataList = data
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.item_row, parent, false)
return ListViewHolder(view)
}
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
val question: Questionio = dataList[position] as Questionio
holder.bindView(question)
}
override fun getItemCount(): Int {
return if (dataList.size > 0) {
dataList.size
} else {
return 0
}
}
inner class ListViewHolder(itemView: View, listener: onItemClickListener) :
RecyclerView.ViewHolder(itemView) {
fun bindView(questionio: Questionio) {
itemView.findViewById<TextView>(R.id.txt_policlinic).text = questionio.policlinic
itemView.findViewById<TextView>(R.id.txt_title).text = questionio.title
itemView.findViewById<TextView>(R.id.txt_description).text = questionio.description
itemView.findViewById<TextView>(R.id.txt_date).text = questionio.date
itemView.findViewById<TextView>(R.id.txt_time).text = questionio.time
}
init {
itemView.setOnClickListener {
listener.onItemClick(adapterPosition)
}
}
}
}
My code in onCreateView inside list fragment.Edit
ListFragment
recyclerView.layoutManager = LinearLayoutManager(requireContext())
recyclerView.adapter = adapter
observeData()
adapter.setOnItemClickListener(object : ListAdapter.onItemClickListener {
override fun onItemClick(position: Int) {
showShortToast(position.toString())
}
})
this function is also my observationData(),
I made new edits
private fun observeData() {
binding.shimmerViewContainer.startShimmer()
listViewModel.fetchQuestinData("questions",
requireContext())
.observe(viewLifecycleOwner, {
binding.shimmerViewContainer.startShimmer()
binding.shimmerViewContainer.hideShimmer()
binding.shimmerViewContainer.hide()
adapter.setListData(it)
adapter.notifyDataSetChanged()
})
}
You can pass highOrderFuction into the adapter then setonclickListener for any view you want. Like this:
class ListAdapter(
private val context: Context,
private val onItemClick:(questionio: Questionio)->Unit
) : RecyclerView.Adapter<ListAdapter.ListViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.item_row, parent, false)
return ListViewHolder(view,onItemClick)
}
...
inner class ListViewHolder(itemView: View,private val onItemClick:(questionio: Questionio)->Unit) : RecyclerView.ViewHolder(itemView) {
fun bindView(questionio: Questionio) {
//set on any view you want
itemView.findViewById<TextView>(R.id.root_view_id).
setOnClickListener{onItemClick(questionio)}
itemView.findViewById<TextView>(R.id.txt_policlinic).text =
questionio.policlinic
itemView.findViewById<TextView>(R.id.txt_title).text = questionio.title
itemView.findViewById<TextView>(R.id.txt_description).text =
questionio.description
itemView.findViewById<TextView>(R.id.txt_date).text = questionio.date
itemView.findViewById<TextView>(R.id.txt_time).text = questionio.time
}
}
}
So I tried to create multi views recyclerview in kotlin, but sadly it did not work.The recyclerview does not display on the screen. It worth to mention that I tried to set the orientation as vertical in my layout files, also added all the dependencies and things needed. Can anyone please help me with that?
My MainActivity.class
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
lateinit var adapter: NumbersAdapter
lateinit var recyclerView: RecyclerView
var list: List<Nums> = listOf(Nums(1,false))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
updateAll()
}
fun updateAll(){
binding.recyclerview.apply {
val layoutManager = LinearLayoutManager(this#MainActivity)
adapter = NumbersAdapter(list)
adapter = adapter
}}}
My Adapter
class NumbersAdapter(
var list: List<Nums>,
): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
class RedViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val name = itemView.findViewById<TextView>(R.id.red_number)
fun bindRed(number: Nums) {
name.text = number.nums.toString()
}
}
class OrangeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val name = itemView.findViewById<TextView>(R.id.orange_number)
fun bindOrange(number: Nums) {
name.text = number.nums.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if (viewType == 0) {
val redvView =
LayoutInflater.from(parent.context).inflate(R.layout.red_item, parent, false)
return RedViewHolder(redvView)
}
else {
val orangeView =
LayoutInflater.from(parent.context).inflate(R.layout.orange_item, parent, false)
return OrangeViewHolder(orangeView)
}
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if(getItemViewType(position)==0){
(holder as RedViewHolder).bindRed(list[position])
}
else{
(holder as OrangeViewHolder).bindOrange(list[position])
}
}
override fun getItemViewType(position: Int): Int {
checkItem()
if(list[position].flag)
return 0
return 1
}
fun checkItem(){
for (i in list.indices) {
for (k in i + 1 until list.size) {
if (list[i].nums + list[k].nums == 0) {
list[i].flag = true
list[k].flag = true
}}}}}
in MainActivity.class change code in updateAll() function
fun updateAll(){
binding.recyclerView.apply {
adapter = NumbersAdapter(list)
layoutManager = LinearLayoutManager(this#MainActivity)
}
}
I want to make Home screen like Instagram where video will play/pause on horizontal and vertical scrolling.
For that I am using fragment inside viewpager and viewpager inside recyclerview for achieving horizontal and vertical scrolling.
Issue is that for second item of recyclerview view of fragment is not created.
can anyone help me to achieve this functionality.
Thanks in advance.
Below is the adapter class of recyclerview.
class DashboardFeedsAdapterNew(
private val mContext: Context, var mList: ArrayList<PostListModel.PostListData>,
private val viewHolderClicks: ViewHolderClicks,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var mInflater: LayoutInflater =
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE) as LayoutInflater
var mActivePage = 0
private var isLoadingAdded = false
val LOADING_TYPE = 0
val POST_TYPE = 1
val STORY_TYPE = 2
fun getList(): ArrayList<PostListModel.PostListData> {
return mList
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
when (viewType) {
POST_TYPE -> {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.raw_feed, parent, false)
return PostViewHolder(v)
}
}
val v =
mInflater.inflate(R.layout.raw_feed, parent, false)
return PostViewHolder(
v
)
}
override fun getItemViewType(position: Int): Int {
if(position == mList.size -1 && isLoadingAdded) {
return LOADING_TYPE
} else {
/*if ((position + 1) % 5 == 0) {
return STORY_TYPE
}*/
return POST_TYPE
}
}
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int
) {
val model = mList[holder.adapterPosition]
if (holder is PostViewHolder) {
//post type
try {
if (model.files.isNotEmpty()) {
setupViewpager(holder, model)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
private fun setupViewpager(binding: PostViewHolder, model: PostListModel.PostListData) {
binding.vpAttachment.adapter = ViewPagerAdapter((activityContext() as AppCompatActivity).supportFragmentManager,model)
binding.vpAttachment.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
mActivePage = binding.vpAttachment.currentItem
}
override fun onPageSelected(position: Int) {
}
override fun onPageScrollStateChanged(state: Int) {}
})
}
inner class ViewPagerAdapter(fm: FragmentManager, val mData: PostListModel.PostListData) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT ) { //FragmentPagerAdapter
private val mFragmentList = java.util.ArrayList<Fragment>()
private val mFragmentTitleList = java.util.ArrayList<String>()
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
//added this metod to update fragment after edit post
override fun getItemPosition(`object`: Any): Int {
return POSITION_NONE
}
override fun getItem(position: Int): Fragment {
mData.files[position].position = position
return PostMediaPreviewPageFragment.newInstance(position,mData.id, mData.files[position])
}
override fun getCount(): Int {
return mData.files.size
}
override fun getPageTitle(position: Int): CharSequence? {
return mFragmentTitleList[position]
}
}
private fun activityContext(): Context {
val context = mContext
return context
}
override fun getItemCount(): Int {
return mList.size
}
inner class ViewMoreViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val progressBar: ProgressBar = itemView.findViewById(R.id.progressBar)
}
inner class PostViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imgAvatar: ImageView = itemView.findViewById(R.id.imgAvatar)
val tvUserName: TextView = itemView.findViewById(R.id.tvUserName)
val vpAttachment: ViewPager = itemView.findViewById(R.id.vpAttachment)
// val indicator: IndicatorView = itemView.findViewById(R.id.indicator)
val imgFeed: ImageView = itemView.findViewById(R.id.imgFeed)
val imgPlay: ImageView = itemView.findViewById(R.id.imgPlay)
val tvAttachmentCount: TextView = itemView.findViewById(R.id.tvAttachmentCount)
val tvFeedTitle: TextView = itemView.findViewById(R.id.tvFeedTitle)
val tvLocation: TextView = itemView.findViewById(R.id.tvLocation)
val tvViewCount: TextView = itemView.findViewById(R.id.tvViewCount)
val imgLike: ImageView = itemView.findViewById(R.id.imgLike)
val tvLikeCount: TextView = itemView.findViewById(R.id.tvLikeCount)
val lnComment: LinearLayout = itemView.findViewById(R.id.lnComment)
val tvCommentCount: TextView = itemView.findViewById(R.id.tvCommentCount)
val btnTakeAction: Button = itemView.findViewById(R.id.btnTakeAction)
}
inner class StoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val rvStory: RecyclerView = itemView.findViewById(R.id.rvStory)
val viewPager: ViewPager2 = itemView.findViewById(R.id.vpStory)
val indicator: CircleIndicator2 = itemView.findViewById(R.id.indicator)
}
interface ViewHolderClicks {
fun onUserClick(model: PostListModel.PostListData, position: Int)
fun onImageClick(model: PostListModel.PostListData, position: Int)
fun onLikeClick(model: PostListModel.PostListData, position: Int)
fun onLikeCountClick(model: PostListModel.PostListData, position: Int)
fun onCommentClick(model: PostListModel.PostListData, position: Int)
fun onTakeActionClick(model: PostListModel.PostListData, position: Int)
}
}