issue with firebase and kotlin - android

For a long time I can not solve two problems, for some reason the elements in my RecyclerView are not displayed immediately but after interacting with something, for example when you click on the message field, the second problem is that when you send an image, it is once written to the database, but 3 times is displayed on screen, but if you go to the chat it is displayed once, with text messages no such problem
private fun listenMessage() {
database
.collection(KEY_COLLECTION_USERS)
.document(preferenceManager.getString(KEY_USER_ID)!!)
.collection(KEY_COLLECTION_CHAT)
.addSnapshotListener { value, error ->
if (error != null) {
return#addSnapshotListener
} else {
if (value == null) {
return#addSnapshotListener
} else {
for (documentChange in value.documentChanges) {
if (documentChange.type == DocumentChange.Type.ADDED) {
var doc = documentChange.document
if (doc.getString(KEY_MESSAGE_RECEIVER_ID) == receiverUser.uid) {
var text = doc.getString(KEY_MESSAGE).toString()
var id = doc.getString(KEY_MESSAGE_ID).toString()
var receiverId = doc.getString(KEY_MESSAGE_RECEIVER_ID).toString()
var date = doc.getDate(KEY_MESSAGE_DATE)!!
var isChecked = doc.getBoolean(KEY_MESSAGE_ISCHECKED)!!
var type = doc.getString(KEY_TYPE_MESSAGE).toString()
var message = Message(text, id, receiverId, date, isChecked, type)
messages.add(message)
}
}
}
val chatComparator =
Comparator { obj1: Message, obj2: Message -> obj1.date.compareTo(obj2.date) }
Collections.sort(messages, chatComparator)
var messages_test = ArrayList(messages)
userChatAdpater.updateList(messages_test)
if (messages.size != 0) {
mBinding.rvUserChat.smoothScrollToPosition(messages.size - 1)
}
}
}
}
database
.collection(KEY_COLLECTION_USERS)
.document(receiverUser.uid)
.collection(KEY_COLLECTION_CHAT)
.addSnapshotListener { value, error ->
if (error != null) {
return#addSnapshotListener
} else {
if (value == null) {
return#addSnapshotListener
} else {
for (documentChange in value.documentChanges) {
if (documentChange.type == DocumentChange.Type.ADDED) {
var doc = documentChange.document
if (doc.getString(KEY_MESSAGE_RECEIVER_ID) == preferenceManager.getString(
KEY_USER_ID
)
) {
var text = doc.getString(KEY_MESSAGE).toString()
var id = doc.getString(KEY_MESSAGE_ID).toString()
var receiverId = doc.getString(KEY_MESSAGE_RECEIVER_ID).toString()
var date = doc.getDate(KEY_MESSAGE_DATE)!!
var isChecked = doc.getBoolean(KEY_MESSAGE_ISCHECKED)!!
var type = doc.getString(KEY_TYPE_MESSAGE).toString()
var message = Message(text, id, receiverId, date, isChecked, type)
messages.add(message)
}
}
}
val chatComparator =
Comparator { obj1: Message, obj2: Message -> obj1.date.compareTo(obj2.date) }
Collections.sort(messages, chatComparator)
var messages_test = ArrayList(messages)
userChatAdpater.updateList(messages_test)
if (messages.size != 0) {
mBinding.rvUserChat.smoothScrollToPosition(messages.size - 1)
}
}
}
}
}
is a message listener
class UserChatAdapter( messages:List<Message>,receiverImage: String,senderId:String) :
RecyclerView.Adapter<UserChatAdapter.UserChatViewHolder>() {
var messages = messages
var receiverImage = receiverImage
var senderID = senderId
open class UserChatViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private fun getBitmapFromEncodedString(encodedImage:String): Bitmap {
val bytes = Base64.decode(encodedImage, Base64.DEFAULT)
return BitmapFactory.decodeByteArray(bytes,0,bytes.size)
}
private fun getReadableDateTime(date: Date): String {
return SimpleDateFormat("MMMM dd, yyyy - hh:mm a", Locale.getDefault()).format(date)
}
fun bind(type:Int, view:View, position: Int, messages: List<Message>, receiverImage: String){
if(type == SENT_TEXT){
SentTextMessageViewHolder(view).message.text = messages.get(position).message
SentTextMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
}else if( type == SENT_IMAGE){
SentImageMessageViewHolder(view).message.setImageURI(Uri.parse(messages.get(position).message))
SentImageMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
}else if(type == RECEIVED_TEXT){
ReceivedTextMessageViewHolder(view).message.text = messages.get(position).message
ReceivedTextMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
ReceivedTextMessageViewHolder(view).imageReceiver.setImageBitmap(getBitmapFromEncodedString(receiverImage))
}else if(type == RECEIVED_IMAGE){
ReceivedImageMessageViewHolder(view).message.setImageURI(Uri.parse(messages.get(position).message))
ReceivedImageMessageViewHolder(view).dateTime.text = getReadableDateTime(messages.get(position).date)
ReceivedImageMessageViewHolder(view).imageReceiver.setImageBitmap(getBitmapFromEncodedString(receiverImage))
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserChatViewHolder {
lateinit var viewHolder:UserChatViewHolder
if (viewType == SENT_TEXT) {
val layout = R.layout.item_container_sent_message
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = SentTextMessageViewHolder(view)
} else if(viewType == RECEIVED_TEXT) {
val layout = R.layout.item_container_received_message
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = ReceivedTextMessageViewHolder(view)
}else if(viewType == RECEIVED_IMAGE){
val layout = R.layout.item_container_received_message_image
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = ReceivedImageMessageViewHolder(view)
}else if(viewType == SENT_IMAGE){
val layout = R.layout.item_container_sent_message_image
val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
viewHolder = SentImageMessageViewHolder(view)
}
return viewHolder
}
override fun onBindViewHolder(holder: UserChatViewHolder, position: Int) {
holder.bind(holder.itemViewType,holder.itemView,position,messages,receiverImage)
}
override fun getItemCount(): Int {
return messages.size
}
fun updateList(newMessages: ArrayList<Message>){
val oldList = messages
val newList = newMessages
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(
UserChatDiffCallBack(oldList,newList)
)
messages = newMessages
diffResult.dispatchUpdatesTo(this)
}
override fun getItemViewType(position: Int): Int {
if(messages.get(position).type == MESSAGE_TYPE_IMAGE){
if (senderID == messages.get(position).receiverID) {
return RECEIVED_IMAGE
} else {
return SENT_IMAGE
}
}else{
if (senderID == messages.get(position).receiverID) {
return RECEIVED_TEXT
} else {
return SENT_TEXT
}
}
}
}
is an adapter for RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mGetContent = registerForActivityResult(ActivityResultContracts.GetContent(),
ActivityResultCallback {
val intent = Intent(APP_ACTIVITY, CropperAcrtivity::class.java)
intent.putExtra("DATA", it.toString())
startActivityForResult(intent, 101)
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == -1 && requestCode == 101) {
var result = data!!.getStringExtra("RESULT")
var resultUri: Uri = Uri.parse(result)
if (resultUri != null) {
sendMessageAsImage(resultUri)
}
}
}
private fun sendMessageAsImage(image: Uri) {
var text = image.toString()
var id = UUID.randomUUID().mostSignificantBits.toString()
val message = Message(text, id, receiverUser.uid, Date(), false, MESSAGE_TYPE_IMAGE)
database.collection(KEY_COLLECTION_USERS)
.whereEqualTo(KEY_UID,preferenceManager.getString(KEY_UID))
.get().addOnCompleteListener {
it.getResult().documents.get(0).reference.collection(KEY_COLLECTION_CHAT).add(message)
}
}

Related

updating storage with the use of io fotoapparat library | Kotlin

I make a mobile application using the "io fotoapparat" library and I want to create a document with a random id and in the document in the id field, add the document id, the photo we will take was updated in the firebase store and in the previously made about the same id in the receipt collection when taking a photo
link from which I took "io fotoapparat"
EDIT
add to firestore document
binding.button.setOnClickListener {
// Inflate the layout for this fragment
val biedronka = "biedronka"
val price = "20"
val img = " "
val identificator = " "
val from = biedronka
val value = price
val image = img
val idd = identificator
val db = Firebase.firestore
val data = hashMapOf(
"from" to from,
"value" to value,
"image" to image,
"id" to idd
)
db.collection("receipts")
.add(data)
.addOnSuccessListener { documentReference ->
Log.d(SCAN_DEBUG, "DocumentSnapshot written with ID: ${documentReference.id}")
db.collection("receipts")
.document(documentReference.id)
.update("id", documentReference.id)
.addOnSuccessListener {
}
}
.addOnFailureListener { e ->
Log.w(SCAN_DEBUG, "Error adding document", e)
}
}
2 add to storage and to document (doesnt work)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CAPTURE_IMAGE && resultCode == RESULT_OK) {
val uid = profileVm.user.value?.uid!!
val imageBitmap = data?.extras?.get("data") as Bitmap
val userImage = binding.userImg
val stream = ByteArrayOutputStream()
val result = imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
val byteArray = stream.toByteArray()
if (result) profileVm.uploadUserPhoto(byteArray, "$uid.jpg")
}
}
repository to 2
fun uploadReceiptPhoto(bytes: ByteArray) {
storage.getReference("receipts")
.child("${docId}.jpg")
.putBytes(bytes)
.addOnCompleteListener{
Log.d(REPO_DEBUG, "COMPLETE UPLOAD PHOTO")
}
.addOnSuccessListener {
getReceiptPhotoDownloadUrl(it.storage)
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
private fun getReceiptPhotoDownloadUrl(storage: StorageReference) {
storage.downloadUrl
.addOnSuccessListener {
updateReceiptPhoto(it.toString())
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
private fun updateReceiptPhoto(url: String) {
cloud.collection("receipts")
.document(docId)
.update("image", url)
.addOnSuccessListener {
Log.d(REPO_DEBUG, "UPDATE USER PHOTO")
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
THE REST OF THE CODE (camera code "io fotoapparat" and take pictures)
class ScanFragment : Fragment(), OnReceiptsItemAdd {
private var _binding: FragmentScanBinding? = null
private val binding get() = _binding!!
private val scanVm by viewModels<ScanViewModel>()
private val SCAN_DEBUG = "SCAN_DEBUG"
private var fotoapparat: Fotoapparat? = null
private var fotoapparatState: FotoapparatState? = null
private var cameraStatus: CameraState? = null
private var flashState: FlashState? = null
private val permissions = arrayOf(Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentScanBinding.inflate(inflater, container, false)
createFotoapparat()
cameraStatus = CameraState.BACK
flashState = FlashState.OFF
fotoapparatState = FotoapparatState.OFF
binding.fabSwitchCamera.setOnClickListener {
switchCamera()
}
binding.fabFlash.setOnClickListener {
changeFlashState()
}
return binding.root
}
private fun createFotoapparat(){
val cameraView = binding.cameraView
fotoapparat = Fotoapparat(
context = requireContext(),
view = cameraView,
scaleType = ScaleType.CenterCrop,
lensPosition = back(),
logger = loggers(
logcat()
),
cameraErrorCallback = { error ->
println("Recorder errors: $error")
}
)
}
private fun changeFlashState() {
fotoapparat?.updateConfiguration(
CameraConfiguration(
flashMode = if(flashState == FlashState.TORCH) off() else torch()
)
)
flashState = if(flashState == FlashState.TORCH) FlashState.OFF
else FlashState.TORCH
}
private fun switchCamera() {
fotoapparat?.switchTo(
lensPosition = if (cameraStatus == CameraState.BACK) front() else back(),
cameraConfiguration = CameraConfiguration()
)
cameraStatus = if(cameraStatus == CameraState.BACK) CameraState.FRONT
else CameraState.BACK
}
private fun takePhoto() {
if (hasNoPermissions()) {
requestPermission()
}else{
fotoapparat
?.takePicture()
?.toBitmap()
}
}
override fun onStart() {
super.onStart()
if (hasNoPermissions()) {
requestPermission()
}else{
fotoapparat?.start()
fotoapparatState = FotoapparatState.ON
}
}
private fun hasNoPermissions(): Boolean{
return ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
}
private fun requestPermission(){
ActivityCompat.requestPermissions(requireActivity(), permissions,0)
}
override fun onStop() {
super.onStop()
fotoapparat?.stop()
FotoapparatState.OFF
}
}
enum class CameraState{
FRONT, BACK
}
enum class FlashState{
TORCH, OFF
}
enum class FotoapparatState{
ON, OFF
}

Nested Recyclerview makes scroll laggy

I am using recyclerview with multi view type and using nested recyclerviews:
But its scrolling very slow. I also handled the child recyclerviews scroll position in onViewRecycled function:
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
super.onViewRecycled(holder)
//save horizontal scroll state
val key = getSectionID(holder.layoutPosition)
if (holder is HomeSectionsViewHolder) {
scrollStates[key] =
holder
.itemView
.findViewById<RecyclerView>(R.id.itemsList)
.layoutManager?.onSaveInstanceState()
}
}
And in the onBindViewHolder
val state = scrollStates[key]
if (state != null) {
itemBinding.itemsList.layoutManager?.onRestoreInstanceState(state)
} else {
itemBinding.itemsList.layoutManager?.scrollToPosition(0)
}
I also tried:
binding.rvHome.recycledViewPool.setMaxRecycledViews(0, 0);
I am using ListAdapter with DiffUtils. I also tried to set adapter to child recyclerviews in the onCreateViewHolder and submit the list from onBindViewHolder and also tried setting adapter from onBindViewHolder. But in all cases main recycler view recycling the views and lagging. I dont want to disable the recycling of the recyclerview.
Can anyone suggest me what i am doing wrong here.
Code:
class MainAdapter(
private val context: Context,
private val currentLocale: String,
private val currentCountry: String,
private val homeRepository: HomeRepository
) :
ListAdapter<Section, RecyclerView.ViewHolder>(Companion) {
var selectedCondition: List<Int?>? = emptyList()
var selectedBrand: MutableList<Int?>? = arrayListOf()
private var carousalListBinded: Boolean = false
private var carousalList: List<CarouselItem>? = null
private var banners: List<Banner>? = null
private var carousel: ImageCarousel? = null
private var COVIDMsg: String? = null
private var COVIDMsgColor: String? = null
private var tvCovidMessage: TextView? = null
private var categoryAdapter = CategoryAdapter(context)
companion object : DiffUtil.ItemCallback<Section>() {
override fun areItemsTheSame(oldItem: Section, newItem: Section): Boolean =
oldItem == newItem
override fun areContentsTheSame(oldItem: Section, newItem: Section): Boolean =
oldItem == newItem
const val VIEW_TYPE_CATEGORY = 0
const val VIEW_TYPE_ITEM_SECTION = 1
const val VIEW_TYPE_BRAND = 2
const val VIEW_TYPE_IMAGE = 3
const val VIEW_TYPE_ADVANCE_IMAGE = 4
const val VIEW_TYPE_ADVANCE_CATEGORY = 5
const val VIEW_TYPE_BANNER = 6
const val VIEW_TYPE_HOME_BOTTOM_SECTION = 7
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) {
VIEW_TYPE_CATEGORY -> {
val categoryViewHolder = CategoryViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_categories_item,
parent,
false
)
)
categoryViewHolder.initRecView()
return categoryViewHolder
}
VIEW_TYPE_ITEM_SECTION -> {
val homeSectionsViewHolder = HomeSectionsViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_item_section,
parent,
false
)
)
homeSectionsViewHolder.initRecView()
return homeSectionsViewHolder
}
VIEW_TYPE_BRAND -> {
val brandsViewHolder = BrandsViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_brands_item,
parent,
false
)
)
brandsViewHolder.initRecView()
return brandsViewHolder
}
VIEW_TYPE_IMAGE -> {
val imagesViewHolder = ImagesViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_brands_item,
parent,
false
)
)
imagesViewHolder.initRecView()
return imagesViewHolder
}
VIEW_TYPE_ADVANCE_IMAGE -> {
val advanceImagesViewHolder = AdvanceImagesViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_brands_item,
parent,
false
)
)
advanceImagesViewHolder.initRecView()
return advanceImagesViewHolder
}
VIEW_TYPE_ADVANCE_CATEGORY -> {
val categorySectionViewHolder = CategorySectionViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_item_section,
parent,
false
)
)
categorySectionViewHolder.initRecView()
return categorySectionViewHolder
}
VIEW_TYPE_BANNER -> {
val binding: HomeBannerItemBinding = DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_banner_item,
parent,
false
)
binding.carousel.post {
val numberItemsInColumn = 1
val collectionViewWidth = getWidth(context)
val widthPerCell = collectionViewWidth / numberItemsInColumn
val widthPerItem = widthPerCell
val cellHeight = getCellHeight(widthPerItem)
binding.carousel.layoutParams.width = widthPerItem
binding.carousel.layoutParams.height = cellHeight
binding.carousel.requestLayout()
}
return HomeBannerViewHolder(
binding
)
}
VIEW_TYPE_HOME_BOTTOM_SECTION -> {
return HomeBottomLayViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_screen_bottom_layout,
parent,
false
)
)
}
else -> {
val categoryViewHolder = CategoryViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.home_categories_item,
parent,
false
)
)
categoryViewHolder.initRecView()
return categoryViewHolder
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (getItemViewType(position)) {
VIEW_TYPE_CATEGORY -> {
(holder as CategoryViewHolder).bind(position)
}
VIEW_TYPE_ITEM_SECTION -> {
(holder as HomeSectionsViewHolder).bind(position)
}
VIEW_TYPE_BRAND -> {
(holder as BrandsViewHolder).bind(position)
}
//
VIEW_TYPE_IMAGE -> {
(holder as ImagesViewHolder).bind(position)
}
//
VIEW_TYPE_ADVANCE_IMAGE -> {
(holder as AdvanceImagesViewHolder).bind(position)
}
VIEW_TYPE_ADVANCE_CATEGORY -> {
(holder as CategorySectionViewHolder).bind(position)
}
VIEW_TYPE_BANNER -> {
// (holder as HomeBannerViewHolder).setIsRecyclable(false)
(holder as HomeBannerViewHolder).bind()
}
VIEW_TYPE_HOME_BOTTOM_SECTION -> {
(holder as HomeBottomLayViewHolder)
}
}
// holder.itemView.setFadeAnimation()
}
override fun getItemViewType(position: Int): Int {
return when (currentList[position].sectionType) {
SectionType.items -> {
VIEW_TYPE_ITEM_SECTION
}
SectionType.brands -> {
VIEW_TYPE_BRAND
}
SectionType.images -> {
VIEW_TYPE_IMAGE
}
SectionType.advanceimages -> {
VIEW_TYPE_ADVANCE_IMAGE
}
SectionType.category -> {
VIEW_TYPE_ADVANCE_CATEGORY
}
SectionType.banners -> {
VIEW_TYPE_BANNER
}
SectionType.homeCategories -> {
VIEW_TYPE_CATEGORY
}
SectionType.homeBottomView -> {
VIEW_TYPE_HOME_BOTTOM_SECTION
}
else -> {
VIEW_TYPE_CATEGORY
}
}
}
inner class CategoryViewHolder(private val itemBinding: HomeCategoriesItemBinding) :
RecyclerView.ViewHolder(
itemBinding.root
) {
fun initRecView() {
itemBinding.rvCategoryItem.adapter = categoryAdapter
}
fun bind(position: Int) {
// val newItem = (currentList[position] as CategorySection).items
// categoryAdapter.submitList(newItem)
}
}
inner class HomeSectionsViewHolder(private val itemBinding: HomeItemSectionBinding) :
RecyclerView.ViewHolder(
itemBinding.root
) {
private var sectionsAdapter = ItemSectionsAdapter(context)
fun initRecView() {
itemBinding.itemsList.adapter = sectionsAdapter
}
fun bind(position: Int) {
val section = getItem(position)
itemBinding.section = section
itemBinding.executePendingBindings()
sectionsAdapter.submitList(null)
val newItem = (currentList[position] as ItemSection).items
sectionsAdapter.submitList(newItem)
// val state = scrollStates[key]
// if (state != null) {
// itemBinding.rvProducts.layoutManager?.onRestoreInstanceState(state)
// } else {
// itemBinding.rvProducts.layoutManager?.scrollToPosition(0)
// }
}
}
inner class BrandsViewHolder(private val itemBinding: HomeBrandsItemBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
private val brandsAdapter = BrandsAdapter()
fun initRecView() {
itemBinding.itemsList.adapter = brandsAdapter
}
fun bind(position: Int) {
itemBinding.sectionBtnViewAll.visibility = View.INVISIBLE
val section = getItem(position)
itemBinding.section = section
itemBinding.executePendingBindings()
brandsAdapter.submitList((currentList[position] as BrandSection).items)
}
}
inner class ImagesViewHolder(private val itemBinding: HomeBrandsItemBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
private val imagesAdapter = ImagesAdapter(context)
val layoutManager = GridLayoutManager(context, 3)
fun initRecView() {
itemBinding.itemsList.let {
it.layoutManager = layoutManager
it.setHasFixedSize(true)
it.adapter = imagesAdapter
}
}
fun bind(position: Int) {
val numberOfColumns = getNumberOfColumns((currentList[position] as ImageSection).items)
itemBinding.itemsList.layoutManager = GridLayoutManager(context, numberOfColumns)
// layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
// override fun getSpanSize(position: Int): Int {
// return numberOfColumns
// }
// }
itemBinding.sectionBtnViewAll.visibility = View.INVISIBLE
val section = getItem(position)
itemBinding.section = section
itemBinding.executePendingBindings()
imagesAdapter.submitList((currentList[position] as ImageSection).items)
}
}
inner class AdvanceImagesViewHolder(private val itemBinding: HomeBrandsItemBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
private var imagesAdapter = AdvanceImagesAdapter(context, null, null)
fun initRecView() {
itemBinding.itemsList.let {
// val layoutManager = GridLayoutManager(context, getNumberOfColumns((currentList[position] as AdvanceImageSection).items))
val layoutManager = GridLayoutManager(context, 3)
it.layoutManager = layoutManager
it.setHasFixedSize(true)
it.adapter = imagesAdapter
}
}
fun bind(position: Int) {
val layoutManager = GridLayoutManager(
context,
getNumberOfColumns((currentList[position] as AdvanceImageSection).items)
)
itemBinding.itemsList.layoutManager = layoutManager
val section = getItem(position)
// var imagesAdapter = AdvanceImagesAdapter(context, section.columns, section.aspectRatio)
//
// itemBinding.itemsList.adapter = imagesAdapter
// val imagesAdapter = AdvanceImagesAdapter(section,context)
itemBinding.sectionBtnViewAll.visibility = View.INVISIBLE
itemBinding.section = section
itemBinding.executePendingBindings()
imagesAdapter.submitList((currentList[position] as AdvanceImageSection).items)
//
//
//
}
}
inner class CategorySectionViewHolder(private val itemBinding: HomeItemSectionBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
private val categoryAdapter = HomeCategorySectionAdapter(context)
fun initRecView() {
itemBinding.itemsList.let {
val linearLayoutManager = LinearLayoutManager(
context,
LinearLayoutManager.HORIZONTAL,
false
)
it.layoutManager = linearLayoutManager
// it.setHasFixedSize(true)
it.adapter = categoryAdapter
}
}
fun bind(position: Int) {
// (currentList[position] as CategorySection)
val section = getItem(position)
itemBinding.section = section
itemBinding.executePendingBindings()
if (categoryAdapter.itemCount <= 0) {
itemBinding.pb.show()
GlobalScope.launch(Dispatchers.Main) {
val items = async(Dispatchers.IO) {
homeRepository.getSolarSearch(
getSolarSearchRequest(section)
)
}
when (items.await()) {
is Resource.Success -> {
itemBinding.pb.hide()
categoryAdapter.submitList((items.await() as Resource.Success<SolarSearchResponse>).value.items)
}
is Resource.Failure -> {
itemBinding.pb.hide()
}
is Resource.Loading -> {
}
}
}
}
// itemBinding.sectionBtnViewAll.setOnClickListener {
// homeSectionListener.onCatSectionViewAllClicked(section.categoryID.toString(),section)
// }
}
private fun getSolarSearchRequest(section: Section): SolarSearchRequest {
val result = section.categoryID!! % 100
if (result == 0) {
return SolarSearchRequest(
0,
null,
null,
25,
"popularity",
arrayListOf(section.categoryID),
emptyList<Int>(),
selectedCondition,
selectedBrand,
"1",
"15000"
)
// putIntegerArrayListExtra(CATEGORY_ID, arrayListOf(id))
} else {
// putIntegerArrayListExtra(SUB_CAT_ID, arrayListOf(id))
return SolarSearchRequest(
OFFSET,
null,
null,
PAGE_SIZE_LIMIT,
"popularity",
emptyList<Int>(),
arrayListOf(section.categoryID),
selectedCondition,
selectedBrand,
"1",
"15000"
)
}
}
}
inner class HomeBannerViewHolder(private val itemBinding: HomeBannerItemBinding) :
RecyclerView.ViewHolder(itemBinding.root) {
// private val handler: Handler? = null
// private val delay = 5000 //milliseconds
// private var page = 0
fun bind() {
// if (carousalListBinded) {
// return
// }
itemBinding.carousel.start()
carousalList?.let {
itemBinding.carousel.addData(it)
}
if (COVIDMsg.isNullOrEmpty()) {
itemBinding.covidMessage.visibility = View.GONE
} else {
itemBinding.covidMessage.visibility = View.VISIBLE
}
itemBinding.covidMessage.text = COVIDMsg
if (COVIDMsgColor != null) {
(itemBinding.covidMessage.background as GradientDrawable).setColor(
Color.parseColor(
COVIDMsgColor
)
)
} else {
(itemBinding.covidMessage.background as GradientDrawable).setColor(
context.getColor(
R.color.colorAccent
)
)
}
carousel = itemBinding.carousel
tvCovidMessage = itemBinding.covidMessage
if (carousalList != null) {
carousalListBinded = true
}
}
fun openNewTabWindow(urls: String, context: Context) {
val uris = Uri.parse(urls)
val intents = Intent(Intent.ACTION_VIEW, uris)
val b = Bundle()
b.putBoolean("new_window", true)
intents.putExtras(b)
context.startActivity(intents)
}
}
inner class HomeBottomLayViewHolder(private val itemBinding: HomeScreenBottomLayoutBinding) :
RecyclerView.ViewHolder(
itemBinding.root
) {
}
fun getNumberOfColumns(items: List<Image>): Int {
var numberItemsInColumn: Int = 3
if ((items.size) % 3 == 0) {
numberItemsInColumn = 3
} else if ((items.size) % 2 == 0) {
numberItemsInColumn = 2
} else if (items.size == 1) {
numberItemsInColumn = 1
} else {
numberItemsInColumn = 3
}
return numberItemsInColumn
}
#RequiresApi(Build.VERSION_CODES.M)
fun setBanners(
carousalList: List<CarouselItem>?,
bannersList: List<Banner>?,
COVIDMsg: String?,
COVIDMsgColor: String?
) {
this.carousalList = carousalList
this.banners = bannersList
this.COVIDMsg = COVIDMsg
this.COVIDMsgColor = COVIDMsgColor
carousalList?.let { carousel?.addData(it) }
if (COVIDMsg.isNullOrEmpty()) {
tvCovidMessage?.visibility = View.GONE
} else {
tvCovidMessage?.visibility = View.VISIBLE
}
tvCovidMessage?.text = COVIDMsg
if (COVIDMsgColor != null && tvCovidMessage != null) {
(tvCovidMessage?.background as GradientDrawable).setColor(Color.parseColor(COVIDMsgColor))
} else {
if (tvCovidMessage != null) {
(tvCovidMessage?.background as GradientDrawable).setColor(context.getColor(R.color.colorAccent))
}
}
}
fun getWidth(context: Context): Int {
var width: Int = 0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val displayMetrics = DisplayMetrics()
val display: Display? = context.display
display!!.getRealMetrics(displayMetrics)
return displayMetrics.widthPixels
} else {
val displayMetrics = DisplayMetrics()
(context as Activity).windowManager.defaultDisplay.getMetrics(displayMetrics)
width = displayMetrics.widthPixels
return width
}
}
fun getCellHeight(width: Int): Int {
var height = width
val ratio = 0.37
val height1 = height * ratio
height = height1.roundToInt()
return height
}
fun setCategories(categoriesList: List<Category>?) {
categoryAdapter.submitList(categoriesList)
}
}

LongClickListerner Not Responding (Kotlin/RecyclerView

I have implemented a onClicklistener in my recycleview which works but the onLongClickListener is not responding? I have added the code in the Adapter, which is being called from a fragment. The onClickListener works well. Whn I click onLongClick -> it needs to display an AlertDialog, but in this case on running the app, there are no errors and no longclick too. This is in Kotlin, what am I doing wrong - any thoughts please?
class UserMsgAdapter(
mContext: Context,
userMsgList: List<MessageList>,
mUsers: List<Users>,
isChatCheck: Boolean
): RecyclerView.Adapter<UserMsgAdapter.ViewHolder?>()
{
private val mContext: Context
private val userMsgList: List<MessageList>
private val mUsers:List<Users>
private var isChatCheck: Boolean
init{
this.mUsers = mUsers
this.userMsgList = userMsgList
this.mContext = mContext
this.isChatCheck = isChatCheck
}
var lastMsg: String = ""
var timeMsg: Long = 0
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val view: View = LayoutInflater.from(mContext).inflate(
R.layout.user_search_item_layout,
viewGroup,
false
)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val message: MessageList? = userMsgList[position]
//Accessing the receiverId from the ChatList
val receiverId = message!!.getId()
val ref = FirebaseDatabase.getInstance().reference.child("Users").child(receiverId!!)
ref.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
val user = p0.getValue(Users::class.java)
holder.userNameText.text = user!!.getUserName()
Picasso.get().load(user.getProfile())
.placeholder(R.drawable.ic_baseline_whatshot_24).fit().centerCrop().into(
holder.profileImageView
)
//Showcasing Last Message
if (isChatCheck) {
retrieveLastMessage(
user.getUID(),
holder.lastMessagetxt,
holder.timestamptxt,
holder.new_message_count
)
} else {
holder.lastMessagetxt.visibility = View.GONE
}
//Calling the Message Activity
holder.itemView.setOnClickListener {
val intent = Intent(mContext, MessageActivity::class.java)
intent.putExtra("visit_id", user.getUID())
mContext.startActivity(intent)
}
//Menu on Search Fragment
holder.itemView.setOnLongClickListener {
val options = arrayOf<CharSequence>(
"Delete Chat",
"Visit Profile"
)
val builder: AlertDialog.Builder = AlertDialog.Builder(mContext)
builder.setTitle("What would you like to do?")
builder.setItems(options, DialogInterface.OnClickListener { _, which ->
if (which == 0) {
val intent = Intent(mContext, MessageActivity::class.java)
intent.putExtra("visit_id", user.getUID())
mContext.startActivity(intent)
}
if (which == 1) {
val intent = Intent(mContext, VisitUserProfile::class.java)
intent.putExtra("visit_id", user.getUID())
mContext.startActivity(intent)
}
})
builder.show()
true
}
}
override fun onCancelled(error: DatabaseError) {
}
})
}
override fun getItemCount(): Int {
return userMsgList.size
}
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
{
var userNameText: TextView = itemView.findViewById(R.id.username)
var profileImageView: ShapeableImageView = itemView.findViewById(R.id.profile_image)
var lastMessagetxt: TextView = itemView.findViewById(R.id.last_message)
var timestamptxt: TextView = itemView.findViewById(R.id.time_stamp)
var new_message_count: TextView = itemView.findViewById(R.id.new_message_count)
}
//print last message and timestamp
private fun retrieveLastMessage(
messageUserId: String?, lastMessagetxt: TextView,
timestamptxt: TextView, new_message_count: TextView,
)
{
lastMsg = "defaultMsg"
timeMsg = 0
var countUnreadMessages = 0
val firebaseUser = FirebaseAuth.getInstance().currentUser
val reference = FirebaseDatabase.getInstance().reference.child("Chats")
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
for (dataSnapshot in p0.children) {
val message: Message? = dataSnapshot.getValue(Message::class.java)
if (firebaseUser != null && message != null) {
if (message.getReceiver() == firebaseUser.uid && message.getSender() == messageUserId ||
message.getReceiver() == messageUserId && message.getSender() == firebaseUser.uid
) {
lastMsg = message.getMessage()!!
timeMsg = message.getTimestamp()!!
}
if (message.getReceiver() == firebaseUser.uid && message.getSender() == messageUserId && !message.isIsSeen()) {
countUnreadMessages += 1
}
}
}
when (lastMsg) {
"defaultMsg" -> lastMessagetxt.text = ""
"Shared an image with you." -> lastMessagetxt.text = "Shared an image"
else -> lastMessagetxt.text = lastMsg
}
//Display count of unread messages
if (countUnreadMessages != 0) {
new_message_count.text = countUnreadMessages.toString()
new_message_count.setBackgroundResource(R.drawable.new_chat_bg)
} else {
new_message_count.setBackgroundResource(0)
new_message_count.text = ""
}
countUnreadMessages = 0
//Display formatted date and time
val time = dateFormatter(timeMsg)
when (time) {
"01-01-1970" -> timestamptxt.text = ""
else -> timestamptxt.text = time
}
}
override fun onCancelled(error: DatabaseError) {
}
})
}
}

Filter In Expandable ReyclerView in Kotlin

I am am trying to put filter in expandable recylerview but not able to achieve:
Please find the code below:
class adapter1(internal var context: Context, internal var mData: MutableList<faqBody?>,val
fragmentInterface: FragmentInterface) : RecyclerView.Adapter<adapter1.myViewHolder>()
,Filterable {
internal var mfilter: NewFilter
var orginallist: MutableList<faqBody?> = ArrayList()
override fun getFilter(): Filter {
return mfilter
}
init {
mfilter = NewFilter(this#adapter1)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): adapter1.myViewHolder {
val view =
LayoutInflater.from(context).inflate(R.layout.recyclerview_adapter12, parent, false)
return myViewHolder(view)
}
override fun onBindViewHolder(holder: adapter1.myViewHolder, position: Int) {
val countryDataItem = mData[position]
val intMaxNoOfChild = 0
holder.country.text = countryDataItem!!.menuText
val noOfChildTextViews = holder.linearLayout_childItems.childCount
val noOfChild = countryDataItem.childItem.size
for (index in 0 until noOfChildTextViews) {
val currentTextView =
holder.linearLayout_childItems.getChildAt(index) as TextView
currentTextView.visibility = View.VISIBLE
}
if (noOfChild < noOfChildTextViews) {
for (index in noOfChild until noOfChildTextViews) {
val currentTextView =
holder.linearLayout_childItems.getChildAt(index) as TextView
currentTextView.visibility = View.GONE
}
}
for (textViewIndex in 0 until noOfChild) {
val currentTextView =
holder.linearLayout_childItems.getChildAt(textViewIndex) as TextView
currentTextView.setText(countryDataItem.childItem[textViewIndex].menuText)
}
}
override fun getItemCount(): Int {
return mData.size
}
inner class myViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
View.OnClickListener {
internal var country: TextView
val linearLayout_childItems: LinearLayout
init {
country = itemView.findViewById(R.id.country)
linearLayout_childItems = itemView.findViewById(R.id.ll_child_items)
linearLayout_childItems.visibility = View.GONE
var intMaxNoOfChild = 0
for (index in mData.indices) {
val intMaxSizeTemp = mData[index]!!.childItem.size
if (intMaxSizeTemp > intMaxNoOfChild) intMaxNoOfChild = intMaxSizeTemp
}
for (indexView in 0 until intMaxNoOfChild) {
val textView = TextView(context)
textView.id = indexView
textView.setPadding(5, 20, 0, 20)
// textView.background = ContextCompat.getDrawable(context, R.drawable.background_sub_module_text)
val layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
textView.setOnClickListener(this)
linearLayout_childItems.addView(textView, layoutParams)
}
country.setOnClickListener(this)
}
override fun onClick(view: View) {
if (view.getId() == R.id.country) {
if (linearLayout_childItems.visibility == View.VISIBLE) {
linearLayout_childItems.visibility = View.GONE
} else {
linearLayout_childItems.visibility = View.VISIBLE
}
} else {
val textViewClicked = view as TextView
Toast.makeText(
context, "" + textViewClicked.text.toString(), Toast.LENGTH_SHORT
).show()
fragmentInterface.onClick(textViewClicked.text.toString())
}
}
}
inner class NewFilter(var mAdapter: adapter1) : Filter() {
override fun performFiltering(charSequence: CharSequence): FilterResults {
orginallist.clear()
orginallist.addAll(mData)
val results = FilterResults()
if (charSequence.length == 0) {
mData.addAll(orginallist)
} else {
val filterPattern = charSequence.toString().toLowerCase().trim { it <= ' ' }
for (i in 0..orginallist.size) {
val newList: ArrayList<childItem> = ArrayList<childItem>()
for (childmenu in orginallist[i]!!.childItem) {
if (childmenu.menuText.toLowerCase().contains(filterPattern)) {
newList.add(childmenu)
}
}
val faqBody = faqBody(menuText = orginallist[i]!!.menuText, childItem = newList)
mData.add(faqBody)
}
}
results.values = mData
results.count = mData.size
return results
}
override fun publishResults(charSequence: CharSequence, filterResults: FilterResults) {
mAdapter.notifyDataSetChanged()
}
}
}
Can anyone help on the above.
mData is the list of faqBody that contains chilitems of the same.
faqbody (
menutext: String
childItem : List<childItem>
)
chilitem(
menutext: String
)

RecyclerView not updating View

I have a recycler view. For the first time, it loads all the data and the view is shown perfect. But when the data is added dynamically, pull to refresh, I add it to the list of data and call notifyDataSetChanged. It increases the count of the list and the list is updated with the latest data but the view is not updating with the latest data added to the list. onBindViewHolder has the updated listView size and the listView has all the valid data within it.
override fun onBindViewHolder(holder: HistoryListAdapter.ViewHolder?, position: Int) {
info("onBindViewHolder =>"+listAssets.size)
info("onBindViewHolder itemCount =>"+itemCount)
info("onBindViewHolder position =>"+position)
val notesButton = holder?.notesButton
val notesView = holder?.notesTextView
val dateTime = listAssets[position].date
val location = listAssets[position].location
val sessionId = listAssets[position].id
holder?.sessionID = sessionId
holder?.portraitImageView?.setImageDrawable(listAssets[position].image)
holder?.titleTextView?.text = DateTimeFormatter.getFormattedDate(context, dateTime)
val timeString = DateTimeFormatter.getFormattedTime(context, dateTime)
if (location.length != 0) {
holder?.subtitleTextView?.text = "$timeString # $location"
} else {
holder?.subtitleTextView?.text = "$timeString"
}
val data = listAssets[position].data
for (actionData in data) {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val parent = inflater.inflate(R.layout.history_card_action, null)
val icon = parent?.findViewById(R.id.historyActionIcon) as ImageView
val title = parent?.findViewById(R.id.historyActionTitle) as TextView
val subtitle = parent?.findViewById(R.id.historyActionSubtitle) as TextView
var iconDrawable: Drawable? = null
when(actionData.type) {
ActionType.HEART -> {
iconDrawable = ContextCompat.getDrawable(context, R.drawable.heart)
}
ActionType.LUNGS -> {
iconDrawable = ContextCompat.getDrawable(context, R.drawable.lungs)
}
ActionType.TEMPERATURE -> {
iconDrawable = ContextCompat.getDrawable(context, R.drawable.temperature)
}
}
icon.setImageDrawable(iconDrawable)
val titleString = actionData.title
titleString?.let {
title.text = titleString
}
val subtitleString = actionData.subtitle
subtitleString?.let {
subtitle.text = subtitleString
}
holder?.actionContainer?.addView(parent)
}
val notes = listAssets[position].notes
notesView?.text = notes
if (notes.length == 0) {
notesButton?.layoutParams?.width = 0
} else {
notesButton?.layoutParams?.width = toggleButtonWidth
}
if (expandedNotes.contains(sessionId)) {
notesView?.expandWithoutAnimation()
} else {
notesView?.collapseWithoutAnimation()
}
notesButton?.onClick {
notesView?.toggleExpansion()
}
}
data class ListAssets(val id: String,
val date: Date,
val location: String,
val notes: String,
val image: Drawable,
val data: ArrayList<ListData>)
data class ListData(val type: ActionType,
val title: String?,
val subtitle: String?)
override fun onViewRecycled(holder: HistoryListAdapter.ViewHolder?) {
super.onViewRecycled(holder)
if (holder != null) {
holder.actionContainer.removeAllViews()
val notesTextView = holder.notesTextView
if (notesTextView != null) {
if (notesTextView.expandedState) {
val sessionID = holder.sessionID
sessionID?.let {
val sessionSearch = expandedNotes.firstOrNull {
it.contentEquals(sessionID)
}
if (sessionSearch == null) {
expandedNotes.add(sessionID)
}
}
} else {
val sessionID = holder.sessionID
sessionID?.let {
val sessionSearch = expandedNotes.firstOrNull {
it.contentEquals(sessionID)
}
if (sessionSearch != null) {
expandedNotes.remove(sessionSearch)
}
}
}
}
}
}
ActionView is Enum.
Kindly please let me know if I am doing anything wrong.

Categories

Resources