How can I select all checkBoxes at once in kotlin? - android

I've got a recyclerView with checkBoxes and I want to select all of them at once by pressing a button
I've try this so far...
This is the Adapter -
class AdapterNfs (context: MainActivity, private val listener: OnItemClickListener) :
RecyclerView.Adapter<AdapterNfs.NfViewHolder>() {
private val context: Context
private var list = emptyList<ReceiverPayment>()
private var status: Boolean = false
init {
this.context = context
}
fun setAllChecked(isChecked: Boolean){
status = isChecked
Log.d("***log", status.toString())
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NfViewHolder {
val binding = ItemNotasFiscaisBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return NfViewHolder(binding)
}
override fun onBindViewHolder(holder: NfViewHolder, position: Int){
holder.binding.apply {
textNFnumber.text = list[position].id
textNFvalue.text = list[position].totalValue
nfStatus.text = list[position].paid.toString()
}
holder.binding.checkBoxNf.isChecked = status
}
override fun getItemCount() = list.size
inner class NfViewHolder(var binding: ItemNotasFiscaisBinding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener{
init{
binding.checkBoxNf.setOnClickListener(this)
}
override fun onClick(view: View?) {
val checkbox = view as CheckBox
val position : Int = adapterPosition
val data = list
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position, checkbox.isChecked, data)
}
}
}
fun setData(newList: List<ReceiverPayment>) {
val nfDiffUtil = DiffUtilGeneric(list, newList)
val nfResult = DiffUtil.calculateDiff(nfDiffUtil)
this.list = newList
nfResult.dispatchUpdatesTo(this)
}
interface OnItemClickListener {
fun onItemClick(
position: Int,
checked: Boolean,
data: List<ReceiverPayment>
)
}
}
and this is the Main -
class MainActivity() : AppCompatActivity(), AdapterNfs.OnItemClickListener {
private val myAdapter = AdapterNfs(this, this)
private lateinit var binding : ActivityMainBinding
private lateinit var mainViewModel: MainViewModel
private lateinit var recyclerView: RecyclerView
private var valueTotal = 00.00
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
mainViewModel = MainViewModel()
setupRecyclerView()
getAllNfs()
setContentView(binding.root)
binding.selectAllCheckBoxes.setOnClickListener {
setAllCheckBoxes(true)
}
}
override fun onItemClick(position: Int, checked: Boolean, data: List<ReceiverPayment>) {
val totalValueSelected = binding.totalValue
val nfSelected = data[position].totalValue.toString().toDouble()
if (checked) {
valueTotal += nfSelected
totalValueSelected.text = valueTotal.toString()
} else {
valueTotal -= nfSelected
totalValueSelected.text = valueTotal.toString()
}
}
private fun setupRecyclerView(){
recyclerView = binding.recyclerViewNfs
binding.recyclerViewNfs.layoutManager = LinearLayoutManager(this)
binding.recyclerViewNfs.itemAnimator = DefaultItemAnimator()
binding.recyclerViewNfs.addItemDecoration(
DividerItemDecoration(
this,
LinearLayoutManager.VERTICAL
)
)
binding.recyclerViewNfs.adapter = myAdapter
}
private fun getAllNfs(){
mainViewModel.allNfs.observe(this#MainActivity){response ->
response.let {
myAdapter.setData(it[0].receiverPayments as List<ReceiverPayment>)
}
}
}
private fun setAllCheckBoxes(isChecked: Boolean){
myAdapter.setAllChecked(isChecked)
}
}

In your adapter , call notifyDataSetChanged() after change the status
fun setAllChecked(isChecked: Boolean){
status = isChecked
Log.d("***log", status.toString())
notifyDataSetChanged()
}

Related

kotlin error recycler view with gridlayout type was mismatched

im facing errors in recyclerView here is //
data class categories(
val Name: String,
val Image:Int
)
here is model /////
object CategoriesModel {
fun getImages(): ArrayList<categories> {
val ImagesList = ArrayList<categories>()
val categoryFirst = categories(
"Memmals",R.drawable.memmals
)
ImagesList.add(categoryFirst)
val categorySecond = categories(
"Memmals",R.drawable.fish
)
ImagesList.add(categorySecond)
return ImagesList
}
}
//// adapter///
class CategoriesAdapter(private val itemList: ArrayList) :
RecyclerView.Adapter<CategoriesAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoriesAdapter.ViewHolder {
val view =LayoutInflater.from(parent.context)
.inflate(R.layout.memmals, parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: CategoriesAdapter.ViewHolder, position: Int) {
holder.bind(categories("Memmals",2))
}
override fun getItemCount(): Int {
return itemList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(category: categories) {
val textViewName = itemView.findViewById<TextView>(R.id.txtCategory)
textViewName.text = category.Name
val txtImage=itemView.findViewById<View>(R.id.image)
txtImage.id=category.Image
}
}
}
/////main activity///
class MainActivity : AppCompatActivity() {
private lateinit var mAdapter: CategoriesAdapter
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding= ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.recyclerView.setOnClickListener{
val intent=Intent(this,Level1::class.java)
startActivity(intent)
}
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = GridLayoutManager(this,2)
val itemList = ArrayList<CategoriesModel>()
// from here
itemList.add(categories("Memmals",R.drawable.memmals))
itemList.add(categories("Fishes",R.drawable.fish))
itemList.add(categories("Arthropods",R.drawable.dear))
itemList.add(categories("Yalk",R.drawable.yalk))
//to here errors are there
//Adapter setting
mAdapter = CategoriesAdapter(itemList)
recyclerView.adapter = mAdapter
}
}
/// here is the error///
MainActivity.kt: (34, 22): Type mismatch: inferred type is categories but CategoriesModel was expected
MainActivity.kt
val itemList = ArrayList<CategoriesModel>()
should be changed to
val itemList = ArrayList<categories>()
because you are using CategoriesModel object and expected is categories.

List is not updated after notifyDataSetChanged what should I do?

I am fetching JSON data from API and passing it in recycler view but if I want to fetch new data and display it in recycler view then I have to clear the list and then add new data in that list and notify the adapter that the data is changed but it is not updated what should I do?
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var recipeViewModel: RecipeViewModel
private lateinit var mainBinding: ActivityMainBinding
private lateinit var recipeAdapter: RecipeAdapter
private lateinit var recipeItemList: ArrayList<Hit>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(mainBinding.root)
recipeViewModel =
ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory
.getInstance(application)
)[RecipeViewModel::class.java]
recipeItemList = arrayListOf()
mainBinding.recyclerView.layoutManager = LinearLayoutManager(this)
mainBinding.recyclerView.hasFixedSize()
recipeAdapter = RecipeAdapter(this)
mainBinding.recyclerView.adapter = recipeAdapter
recipeViewModel.recipeLiveData.observe(this, Observer { recipeItems ->
recipeItemList.addAll(recipeItems.hits)
recipeAdapter.updateRecipes(recipeItemList)
Log.d("RESPONSE", recipeItems.toString())
Log.d("List size", recipeAdapter.itemCount.toString())
})
searchRecipeName()
}
private fun searchRecipeName() {
mainBinding.searchRecipeFabBtn.setOnClickListener {
val view = layoutInflater.inflate(R.layout.recipe_search_layout, null)
val searchRecipeET = view.findViewById<EditText>(R.id.searchRecipeET)
val searchRecipeBtn = view.findViewById<Button>(R.id.searchRecipeBtn)
val bottomSheetDialog = BottomSheetDialog(this)
bottomSheetDialog.apply {
this.setContentView(view)
this.show()
}
searchRecipeBtn.setOnClickListener {
val recipeName = searchRecipeET.text.toString()
searchRecipeName(recipeName, searchRecipeET, bottomSheetDialog)
}
}
}
private fun searchRecipeName(
recipeName: String,
searchRecipeET: EditText,
bottomSheetDialog: BottomSheetDialog
) {
if (recipeName.isEmpty()) {
searchRecipeET.error = "Please enter recipe name"
} else {
recipeViewModel.getRecipes(recipeName)
bottomSheetDialog.dismiss()
}
}
}
RecipeAdapter.kt
class RecipeAdapter(val context: Context) : RecyclerView.Adapter<RecipeAdapter.RecipeViewHolder>() {
private val recipesList: ArrayList<Hit> = arrayListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeViewHolder {
val layoutInflater = LayoutInflater.from(context)
val view = layoutInflater.inflate(R.layout.recipe_items_layout, null, false)
return RecipeViewHolder(view)
}
override fun onBindViewHolder(holder: RecipeViewHolder, position: Int) {
val currentItem = recipesList[position]
holder.recipeImageView.load(currentItem.recipe.image)
holder.recipeNameText.text = currentItem.recipe.label
}
override fun getItemCount(): Int {
return recipesList.size
}
class RecipeViewHolder(itemView: View) :RecyclerView.ViewHolder(itemView) {
val recipeImageView: ImageView = itemView.findViewById(R.id.recipeImageView)
val recipeNameText: TextView = itemView.findViewById(R.id.recipeNameText)
}
fun updateRecipes(newRecipesList: ArrayList<Hit>){
recipesList.clear()
Log.d("RECIPE SIZE", "${recipesList.size}")
recipesList.addAll(newRecipesList)
notifyDataSetChanged()
}
}
This may be helpful.
Be careful of this :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(mainBinding.root)
recipeViewModel =
ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory
.getInstance(application)
)[RecipeViewModel::class.java]
recipeItemList = arrayListOf()
mainBinding.recyclerView.layoutManager = LinearLayoutManager(this)
mainBinding.recyclerView.hasFixedSize()
recipeAdapter = RecipeAdapter(this)
mainBinding.recyclerView.adapter = recipeAdapter
recipeViewModel.recipeLiveData.observe(this, Observer { recipeItems ->
// You're adding items here but never clear the list
// list will be bigger every time you'll be notified
// recipeItemList.addAll(recipeItems.hits
// recipeAdapter.updateRecipes(recipeItemList)
// Do this instead
recipeItemList = recipeItems.hits
recipeAdapter.updateRecipes(recipeItemList)
Log.d("RESPONSE", recipeItems.toString())
Log.d("List size", recipeAdapter.itemCount.toString())
})
searchRecipeName()
}
Also, here: It's a little better to do this (https://stackoverflow.com/a/10298038/4221943)
fun updateRecipes(newRecipesList: ArrayList<Hit>){
recipesList = newRecipesList
Log.d("RECIPE SIZE", "${recipesList.size}")
notifyDataSetChanged()
}
BTW it will always be more efficient to use the more specific change events if you can. Rely on notifyDataSetChanged() as a last resort. It is also good practice to use notifyItemInserted(mItems.size() - 1) for "easier" solution.
You could convert the RecyclerView.Adapter into a ListAdapter:
class RecipeAdapter(val context: Context) : ListAdapter<Hit, RecipeAdapter.RecipeViewHolder>(RecipeDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeViewHolder {
val layoutInflater = LayoutInflater.from(context)
val view = layoutInflater.inflate(R.layout.recipe_items_layout, null, false)
return RecipeViewHolder(view)
}
override fun onBindViewHolder(holder: RecipeViewHolder, position: Int) {
val currentItem = getItem(position)
holder.recipeImageView.load(currentItem.recipe.image)
holder.recipeNameText.text = currentItem.recipe.label
}
class RecipeViewHolder(itemView: View) :RecyclerView.ViewHolder(itemView) {
val recipeImageView: ImageView = itemView.findViewById(R.id.recipeImageView)
val recipeNameText: TextView = itemView.findViewById(R.id.recipeNameText)
}
}
class RecipeDiffCallback : DiffUtil.ItemCallback<Hit>() {
// Change this condition based on the attribute of `Hit` that will change
override fun areItemsTheSame(oldItem: Hit, newItem: Hit): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Hit, newItem: Hit): Boolean = oldItem == newItem
}
Then update its content with the submitList method.
Every item not satisfying the RecipeDiffCallback conditions will be automatically updated:
recipeViewModel.recipeLiveData.observe(this, Observer { recipeItems ->
recipeAdapter.submitList(recipeItems.hits)
})

How to implement serch in recycler view for firestore data?

I want to implement search in my recyclerview. The data I am retrieving is from firebase (firestore). When I click on the search icon and type any text, my application crashes and I am not able to figure out what could be the reason. Can anyone tell me what is wrong with my code?
class ActivityStudentList : AppCompatActivity() {
private lateinit var studentRecyclerView: RecyclerView
private lateinit var recyclerViewAdapter: RecyclerViewAdapter
private val db = FirebaseFirestore.getInstance()
private lateinit var studentArrayList: ArrayList<StudentRecyclerViewDataClass>
private lateinit var editStudentFab: ExtendedFloatingActionButton
private lateinit var addStudentFab: ExtendedFloatingActionButton
private lateinit var removeStudentFab: ExtendedFloatingActionButton
private lateinit var tempArrayList: ArrayList<StudentRecyclerViewDataClass>
private lateinit var newArrayList: ArrayList<StudentRecyclerViewDataClass>
private var clicked = false
private lateinit var obstructor: RelativeLayout
private val fromBottom: Animation by lazy { AnimationUtils.loadAnimation(this,R.anim.from_bottom_anim) }
private val toBottom: Animation by lazy { AnimationUtils.loadAnimation(this,R.anim.to_bottom_anim) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_student_list)
supportActionBar?.setDisplayHomeAsUpEnabled(false)
actionBar?.setDisplayShowTitleEnabled(false)
supportActionBar?.setDisplayShowTitleEnabled(false)
editStudentFab = findViewById(R.id.editStudentFab)
addStudentFab = findViewById(R.id.addStudentFab)
removeStudentFab = findViewById(R.id.removeStudentFab)
obstructor = findViewById(R.id.obstructor)
studentRecyclerView = findViewById(R.id.studentRecyclerView)
studentRecyclerView.layoutManager = LinearLayoutManager(this)
studentRecyclerView.setHasFixedSize(true)
studentArrayList = arrayListOf<StudentRecyclerViewDataClass>()
recyclerViewAdapter = RecyclerViewAdapter(studentArrayList)
studentRecyclerView.adapter = recyclerViewAdapter
studentRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(studentRecyclerView: RecyclerView, dx: Int, dy: Int) {
if (dy > 0) editStudentFab.hide() else if (dy < 0) editStudentFab.show()
}
})
getStudentData()
editStudentFab.setOnClickListener {
onEditButtonClicked()
}
addStudentFab.setOnClickListener {
startActivity(Intent(this,ActivityAddStudent::class.java))
}
removeStudentFab.setOnClickListener {
startActivity(Intent(this,ActivityAddStudent::class.java))
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.student_recycler_view_search, menu)
val search = menu?.findItem(R.id.student_recycler_view_search)
val searchView = search?.actionView as? SearchView
searchView?.isSubmitButtonEnabled = true
searchView?.setOnQueryTextListener(object: SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
TODO("Not yet implemented")
}
#SuppressLint("NotifyDataSetChanged")
override fun onQueryTextChange(newText: String?): Boolean {
tempArrayList.clear()
val searchText = newText!!.toLowerCase(Locale.getDefault())
if(searchText.isNotEmpty()){
newArrayList.forEach{
if(it.Name!!.toLowerCase(Locale.getDefault()).contains(searchText)){
tempArrayList.add(it)
}
}
studentRecyclerView.adapter!!.notifyDataSetChanged()
}else{
tempArrayList.clear()
tempArrayList.addAll(newArrayList)
studentRecyclerView.adapter!!.notifyDataSetChanged()
}
return false
}
})
return super.onCreateOptionsMenu(menu)
}
private fun onEditButtonClicked() {
setVisibility(clicked)
setAnimation(clicked)
clicked = !clicked
}
#SuppressLint("SetTextI18n")
private fun setAnimation(clicked: Boolean) {
obstructor = findViewById(R.id.obstructor)
addStudentFab = findViewById(R.id.addStudentFab)
removeStudentFab = findViewById(R.id.removeStudentFab)
editStudentFab = findViewById(R.id.editStudentFab)
if(!clicked){
obstructor.visibility = View.VISIBLE
editStudentFab.text = "Close"
editStudentFab.setIconResource(R.drawable.ic_outline_close_24)
addStudentFab.startAnimation(fromBottom)
removeStudentFab.startAnimation(fromBottom)
}else{
obstructor.visibility = View.INVISIBLE
editStudentFab.text = "Edit List"
editStudentFab.setIconResource(R.drawable.ic_outline_edit_24)
addStudentFab.startAnimation(toBottom)
removeStudentFab.startAnimation(toBottom)
}
}
private fun setVisibility(clicked: Boolean) {
addStudentFab = findViewById(R.id.addStudentFab)
removeStudentFab = findViewById(R.id.removeStudentFab)
if(!clicked){
addStudentFab.visibility = View.VISIBLE
removeStudentFab.visibility = View.VISIBLE
}else{
addStudentFab.visibility = View.INVISIBLE
removeStudentFab.visibility = View.INVISIBLE
}
}
private fun getStudentData() {
db.collection("StudentInfo").addSnapshotListener(object: EventListener<QuerySnapshot>{
#SuppressLint("NotifyDataSetChanged")
override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
if(error != null){
Log.e("Firestore Error",error.message.toString())
return
}
for(dc : DocumentChange in value?.documentChanges!!){
if(dc.type == DocumentChange.Type.ADDED){
studentArrayList.add(dc.document.toObject(StudentRecyclerViewDataClass::class.java))
}
}
recyclerViewAdapter.notifyDataSetChanged()
}
})
}
}
RecyclerView Adapter code:
class RecyclerViewAdapter(private var studentList : ArrayList<StudentRecyclerViewDataClass>) : RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.recycler_view_student_list_item,parent,false)
return RecyclerViewHolder(itemView)
}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
val currentItem = studentList[position]
holder.name.text = currentItem.Name
holder.SRN.text = currentItem.SRN
holder.phone.text = currentItem.Phone
holder.age.text = currentItem.Age
}
override fun getItemCount(): Int {
return studentList.size
}
class RecyclerViewHolder(itemView : View ) : RecyclerView.ViewHolder(itemView){
val name : TextView = itemView.findViewById(R.id.tv_name)
val SRN : TextView = itemView.findViewById(R.id.tv_srn)
val phone : TextView = itemView.findViewById(R.id.tv_phone)
val age : TextView = itemView.findViewById(R.id.tv_age)
}
}

How to sort encrypted ArrayList and show this in a RecyclerView

My target is to sort in alphabetical order data from an ArrayList with encrypted data and put correct order into a RecyclerView.
I'm able to show decrypted data into RecyclerView, but in the same order witch I use to add item into the ArrayList (see code in adapter).
I tried to sort with sortby{}without success (see code in activity). The result is an partial order and onItemClick not return correct position.
My activity that extend adapter:
class HomeActivity : AppCompatActivity(),DocumentAdapter.OnItemClickListener {
companion object{
lateinit var dbHandler: DBHandler
}
private var documentslist = ArrayList<PassItem>()
private lateinit var adapter : RecyclerView.Adapter<*>
private lateinit var rv : RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
dbHandler = DBHandler(this, null, null,1)
viewDocuments()
val fab = findViewById<FloatingActionButton>(R.id.fabAdd)
fab.setOnClickListener {
val i = Intent(this, AddDocument :: class.java)
startActivity(i)
}
}
#SuppressLint("WrongConstant")
private fun viewDocuments(){
documentslist = dbHandler.getDocuments(this)
//documentslist.sortBy { it.PassItemApp.toString() } ---> this sort encrypted data then not in alphabetic order and onItemClick return uncorrect position
adapter = DocumentAdapter(this,documentslist,this)
rv = findViewById(R.id.recyclerView)
rv.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL,false)
rv.adapter = adapter
}
override fun onItemClick(position: Int) {
val intent = Intent(this#HomeActivity,DocActivity::class.java)
intent.putExtra("clickedPosition", position)
startActivity(intent)
}
override fun onResume() {
viewDocuments()
super.onResume()
}
and my adapter:
class DocumentAdapter(val mCtx: Context, private val documents: ArrayList<PassItem>, val listener: OnItemClickListener) : RecyclerView.Adapter<DocumentAdapter.ViewHolder>(){
interface OnItemClickListener{
fun onItemClick(position : Int)
}
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView), View.OnClickListener{
val txtDocApp : TextView = itemView.findViewById(R.id.txtDocApp)
init {
itemView.setOnClickListener(this)
}
override fun onClick(v: View?) {
val position : Int = adapterPosition
if (position != RecyclerView.NO_POSITION){
listener.onItemClick(position)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DocumentAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.item_pass_layout,parent,false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val document : PassItem = documents[position]
//Decryption of item showed in Recyclerview
val initialisationVector = document.PassItemIvApp
val bytesIV = Base64.decode(initialisationVector, Base64.NO_WRAP)
val oisIV = ObjectInputStream(ByteArrayInputStream(bytesIV))
val initializationVectorIV = oisIV.readObject() as ByteArray
val encryptedText = document.PassItemApp
val bytesText = Base64.decode(encryptedText, Base64.NO_WRAP)
val oisText = ObjectInputStream(ByteArrayInputStream(bytesText))
val textByteArray = oisText.readObject() as ByteArray
val key = document.PassItemKeyApp
val keyText = Base64.decode(key, Base64.NO_WRAP)
val oisKey = ObjectInputStream(ByteArrayInputStream(keyText))
val keyToDecrypt = oisKey.readObject() as SecretKey
val aesDecrypt = Decrypted(keyToDecrypt,initializationVectorIV)
val decryptedByteArray = aesDecrypt.decrypt(textByteArray)
val textAfterDecryption = decryptedByteArray.toString(charset("UTF_8"))
//Data in Recyclerview
holder.txtDocApp.text = textAfterDecryption
}
override fun getItemCount(): Int {
return documents.size
}
}

show progressbar in recyclerview's onBindViewHolder

I want to show progressBar from activity (in SubitemAdapter.kt) when elements in recyclerView are being loaded (about 150 to populate) but now this progressBar not shows at all. Here is my code:
CurrencyListFragment.kt
class CurrencyListFragment : Fragment(), MainContract.View {
companion object {
private val TAG = CurrencyListFragment::class.qualifiedName
}
private val restModel: RestModel = RestModel()
private val handler: Handler = Handler(Looper.getMainLooper())
private lateinit var mainPresenter: MainPresenter
private lateinit var itemAdapter: ItemAdapter
private lateinit var _layoutManager: LinearLayoutManager
private lateinit var onChangeFragment: OnChangeFragment
private lateinit var currentDate: String
private var isLoading: Boolean = false
private var apiResponseList: MutableList<ApiResponse> = arrayListOf()
private var listSize: Int = 0
override fun onAttach(context: Context) {
super.onAttach(context)
try {
if (activity is OnChangeFragment) onChangeFragment = activity as OnChangeFragment
} catch (error: ClassCastException) {
error.message?.let { Log.e(TAG, it) }
}
}
// #formatter:off
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.currency_list_fragment, container, false)
}
// #formatter:on
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_layoutManager = LinearLayoutManager(activity)
mainPresenter = MainPresenter(this, restModel, SharedPreferencesModel(activity as Activity))
currentDate = mainPresenter.convertCurrentDate()
if (mainPresenter.checkIfSuchDateExistsinSp(currentDate)) {
Log.i(TAG, "Date $currentDate already exists in SharedPreferences")
mainPresenter.processDateWithoutMakingACall(currentDate)
} else {
mainPresenter.makeACall(currentDate)
Log.i(TAG, "Date $currentDate does not exist in SharedPreferences. Retrofit call made")
}
mainPresenter.saveNumberOfMinusDaysIntoSp(0)
addScrollerListener()
}
override fun showProgressBarOnLoadingCurrencies() {
progress_bar.visibility = View.VISIBLE
}
override fun hideProgressBarOnFinishedLoadingCurrencies() {
progress_bar.visibility = View.GONE
}
override fun setRecyclerViewStateToLoading() {
if (apiResponseList.size > 0) {
apiResponseList.add(ApiResponse("", "", listOf(Currency("", 0f)), true))
itemAdapter.notifyItemInserted(apiResponseList.size - 1)
}
}
override fun removeRecyclerViewStetOfLoading() {
if (apiResponseList.size > 1) {
apiResponseList.removeAt(apiResponseList.size - 1)
listSize = apiResponseList.size
itemAdapter.notifyItemRemoved(listSize)
}
isLoading = false
}
override fun getApiResponseList(): List<ApiResponse> {
return apiResponseList
}
override fun showLogAboutExistingDateInSp(date: String) {
Log.i(TAG, "Date $date already exists in SharedPreferences (new element)")
}
override fun showLogAboutNotExistingDateInSp(date: String) {
Log.i(TAG, "Date $date does not exist in SharedPreferences. Retrofit call made (new element)")
}
override fun assignResponseToRecyclerview(apiResponse: ApiResponse?) {
rv_item.apply {
layoutManager = _layoutManager
apiResponseList.add(apiResponse!!)
itemAdapter = activity?.let { ItemAdapter(apiResponseList, it) }!!
adapter = itemAdapter
}
}
private fun addScrollerListener() {
rv_item.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(rvItem: RecyclerView, newState: Int) {
super.onScrollStateChanged(rvItem, newState)
mainPresenter.processRvitemOnScroll(isLoading, rvItem, newState)
}
})
}
private fun loadMore() {
setRecyclerViewStateToLoading()
var numberOfDays = mainPresenter.getNumberOfMinusDays()
numberOfDays++
mainPresenter.saveNumberOfMinusDaysIntoSp(numberOfDays)
val dateMinusXDays = mainPresenter.currentDateMinusXDaysToStr(numberOfDays)
val nextLimit = listSize + 1
for (i in listSize until nextLimit) {
if (mainPresenter.checkIfSuchDateExistsinSp(dateMinusXDays)) {
Log.i(TAG, "Date $dateMinusXDays already exists in SharedPreferences (new element)")
handler.postDelayed({
mainPresenter.processDateWithoutMakingACall(dateMinusXDays)
}, 2000)
} else {
Log.i(TAG, "Date $dateMinusXDays does not exist in SharedPreferences. Retrofit call made (new element)")
mainPresenter.makeACall(dateMinusXDays)
}
}
itemAdapter.notifyDataSetChanged()
}
override fun notifyChangedItemAdapter() {
itemAdapter.notifyDataSetChanged()
}
override fun onDestroy() {
super.onDestroy()
restModel.cancelJob()
}
}
ItemAdapter.kt
class ItemAdapter(private var items: MutableList<ApiResponse>, private val activity: Activity) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
private const val VIEW_TYPE_DATA = 0
private const val VIEW_TYPE_PROGRESS = 1
}
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): RecyclerView.ViewHolder {
return when (p1) {
VIEW_TYPE_DATA -> {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
DataViewHolder(view, activity)
}
VIEW_TYPE_PROGRESS -> {
val view = LayoutInflater.from(parent.context).inflate(R.layout.progress_bar_layout, parent, false)
ProgressViewHolder(view)
}
else -> throw IllegalArgumentException("Different View type")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is DataViewHolder)
holder.bind(items[position])
}
override fun getItemCount() = items.size
override fun getItemViewType(position: Int): Int {
val viewtype = items[position]
return when (viewtype.isLoading) {//if data is load, returns PROGRESSBAR viewtype.
true -> VIEW_TYPE_PROGRESS
false -> VIEW_TYPE_DATA
}
}
class DataViewHolder(view: View, activity: Activity) : RecyclerView.ViewHolder(view) {
private var isRvSubitemVisible = false
private val tvDate = view.tv_date
private val rvSubitem = view.rv_subitem
private val activity = activity
fun bind(apiResponse: ApiResponse) {
tvDate.text = String.format(itemView.context.getString(R.string.day_x), apiResponse.date)
tvDate.setOnClickListener {
if (isRvSubitemVisible) {
rvSubitem.visibility = View.GONE
isRvSubitemVisible = false
} else {
rvSubitem.visibility = View.VISIBLE
isRvSubitemVisible = true
}
}
rvSubitem.apply {
layoutManager = LinearLayoutManager(itemView.context)
adapter = SubitemAdapter(apiResponse.rates, apiResponse.date, activity)
}
}
}
inner class ProgressViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
SubitemAdapter.kt
class SubitemAdapter(private val subitems: List<Currency>, private val day: String, private val activity: Activity) : RecyclerView.Adapter<SubitemAdapter.SubitemViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): SubitemViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.subitem, parent, false)
return SubitemViewHolder(view, day, activity)
}
override fun onBindViewHolder(holder: SubitemViewHolder, position: Int) {
if(position < subitems.size - 1) {
activity.progress_bar.visibility = View.VISIBLE
}
else
activity.progress_bar.visibility = View.GONE
holder.bind(subitems[position], position)
}
override fun getItemCount() = subitems.size
class SubitemViewHolder(view: View, day: String, activity: Activity) : RecyclerView.ViewHolder(view) {
private val subitemRootView = view.subitem_root
private val tvCurrencyName = view.tv_currency_name
private val tvCurrencyValue = view.tv_currency_value
private val day = day
private val activity = activity
fun bind(currency: Currency, position: Int) {
subitemRootView.setOnClickListener { v ->
activity as OnChangeFragment
activity.changeFragment(SpecificCurrencyFragment(), ChangeFragmentData(hashMapOf(currency.currencyName to currency.currencyValue.toString()), day))
}
tvCurrencyName.text = currency.currencyName
tvCurrencyValue.text = currency.currencyValue.toString()
}
}
}
Here is I think everything to help me. But if you need something else more just aks.
Any help will bve really appreciated. Thank you in advance!
You are already passing a List<Currency> which are the items to be loaded inside your recyclerview. You should not be checking this inside onBindViewHolder since you already have those items when you passed them as an argument to the recyclerview adapter
Instead, when you are passing the List<Currency> to your adapter, you must update the progressbar at that time from activity itself. You can edit your question and add code for your Activity if this didn't help you, I'll try to answer you :)

Categories

Resources