I have a fragment where I'm processing data from xml source, and everything is working fine, but the thing is when I refresh my layout by detaching and then attaching my fragment, the ui keeps blinking until all data is processed, I checked my code many time but I feel lost and I couldn't find anything
This is how i'm processing my xml source data
fun getData(){
val url = URL("www.xmldatasource.com")
val factory = XmlPullParserFactory.newInstance()
factory.isNamespaceAware = false
val xpp = factory.newPullParser()
xpp.setInput(GetInputStream(url), "utf-8")
var insideItem = false
var eventType = xpp.eventType
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.name.equals("item", ignoreCase = true)) {
insideItem = true
} else if (xpp.name.equals("title", ignoreCase = true)) {
if (insideItem) {
title = xpp.nextText()
}
} else if (xpp.name.equals("pubDate", ignoreCase = true)) {
if (insideItem) {
val subbedDate = xpp.nextText()
publishDate = subbedDate.substring(0, 25)
}
} else if (xpp.name.equals("guid", ignoreCase = true)) {
if (insideItem) {
link = xpp.nextText()
}
} else if (xpp.name.equals("description", ignoreCase = true)) {
if (insideItem) {
val newsDescription = xpp.nextText()
if (newsDescription.contains("src") && newsDescription.contains("jpg")) {
imageUrl = newsDescription.substring(
newsDescription.indexOf("src=") + 5,
newsDescription.indexOf("jpg") + 3
)
}
if (newsDescription.contains("<BR>") && newsDescription.contains("</p>")) {
description =
newsDescription.substring(
newsDescription.indexOf("<BR>") + 4,
newsDescription.indexOf("</p>")
)
}
}
}
} else if (eventType == XmlPullParser.END_TAG && xpp.name.equals("item", ignoreCase =
true)) {
insideItem = false
imageUrl?.let {
//TODO : Getting Image Url And Convert it to Bitmap
val urlImg = URL(it)
val httpURLConnection = urlImg.openConnection() as HttpURLConnection
httpURLConnection.connect()
val inputStream = httpURLConnection.inputStream
val bitmap = BitmapFactory.decodeStream(inputStream)
CoroutineScope(Dispatchers.Main).launch{
xmlList?.clear()
val model = NewsModel(bitmap, title, description, publishDate!!, link!!)
xmlList?.add(model)
leagueViewModel.insertNews(model)
binding.newsrcycler.adapter = LeagueNewsAdapter(requireContext(), xmlList!!)
customType(requireActivity(), "left-to-right")
}
})
}
}
}
eventType = xpp.next()
}
}
Thsi is how i'm refreshing my fragment
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.refresh -> {
if(Constants.checkConnectivity(requireContext())){
requireActivity().supportFragmentManager.beginTransaction().detach(this).attach(this).commit()
} else {
requireContext().ShowToast(requireContext(),"Please Check Your Internet..")
}
}
}
return true
}
This is the layout containing all views of my adapter
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="listener"
type="taki.eddine.premier.league.pro.uilisteners.RssListener" />
<variable
name="newsModel"
type="taki.eddine.premier.league.pro.models.NewsModel" />
</data>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="16dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="?attr/selectableItemBackground"
android:onClick="#{() -> listener.RssArticle(newsModel)}">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_margin="8dp"
android:layout_marginTop="5dp"
app:layout_constraintBottom_toTopOf="#+id/guideline7"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:rssimg="#{newsModel.newsBanner}"/>
<TextView
android:id="#+id/newstitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:fontFamily="#font/andada"
android:maxLines="2"
android:text="#{newsModel.newsTitle}"
android:textColor="#android:color/black"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="#+id/guideline14"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/guideline7"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/newsdescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:fontFamily="#font/adamina"
android:maxLines="3"
android:text="#{newsModel.newsDescription}"
android:textColor="#android:color/black"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="#+id/guideline15"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/guideline14"
app:layout_constraintVertical_bias="0.0" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="11dp"
android:layout_marginStart="8dp"
android:src="#drawable/ic_baseline_date_range_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/guideline22"
app:layout_constraintHorizontal_bias="0.842"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/guideline15" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginEnd="16dp"
android:fontFamily="#font/andada"
android:textStyle="bold"
android:textSize="11sp"
android:textColor="#android:color/holo_blue_dark"
android:layout_marginTop="15dp"
android:text="#{newsModel.newsDate}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/guideline22"
app:layout_constraintTop_toTopOf="#+id/guideline15" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>
This is my fragment layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/newsprogress"
android:visibility="visible"
android:layout_gravity="center"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/newsrcycler"
android:scrollbars="vertical"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
You seem to be setting the RecyclerView adapter multiple times in the while loop. This will keep refreshing the RecyclerView.
You shouldn't be replacing the entire adapter, as the data changes. The data should be kept inside the adapter, and it should be updated inside the adapter.
How I got to this conclusion:
getData() contains a while() loop.
In this while loop, in the last branch you call CoroutineScope(Dispatchers.Main).launch {}
In this launch {} you call binding.newsrcycler.adapter = LeagueNewsAdapter().
Related
I wanna make a logout feature for my app, here's my SettingsActivity:
class SettingsActivity : BaseActivity(), View.OnClickListener {
private lateinit var binding: ActivitySettingsBinding
private lateinit var mUserDetails: User
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
supportActionBar?.hide()
#Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.insetsController?.hide(WindowInsets.Type.statusBars())
}
else {
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
}
binding.toolbarUserProfileActivity.setNavigationIcon(R.drawable.ic_baseline_arrow_back_ios_24)
binding.toolbarUserProfileActivity.setNavigationOnClickListener {
val intent = Intent(this#SettingsActivity, DashboardActivity::class.java)
startActivity(intent)
finish()
}
disableEditProfile()
binding.btnLogout.setOnClickListener(this)
binding.tvEdit.setOnClickListener(this)
}
private fun getUserDetails(){
showProgressDialog(resources.getString(R.string.please_wait))
FireStoreClass().getUsersDetails(this)
}
fun loadUserDetailsSuccess(user: User){
mUserDetails = user
hideProgresDialog()
GlideLoader(this#SettingsActivity).loadUserPicture(user.image, binding.tvUserImageSetting)
binding.etFirstNameSetting.setText(user.firstName)
binding.etLastNameSetting.setText(user.lastName)
binding.etEmailSetting.setText(user.email)
if (mUserDetails.mobile != 0L){
binding.etMobileNumberSetting.setText(mUserDetails.mobile.toString())
}
binding.etAddressSetting.setText(user.address)
binding.etPosCodeSetting.setText(mUserDetails.codepos.toString())
if (user.gender == Constants.MALE){
binding.btnGenderMale.isChecked
}else{
binding.btnGenderFemale.isChecked
}
}
override fun onResume() {
super.onResume()
getUserDetails()
}
private fun disableEditProfile(){
binding.tvUserImageSetting.isEnabled = false
binding.etFirstNameSetting.isEnabled = false
binding.etLastNameSetting.isEnabled = false
binding.etEmailSetting.isEnabled = false
binding.etMobileNumberSetting.isEnabled = false
binding.etAddressSetting.isEnabled = false
binding.etPosCodeSetting.isEnabled = false
binding.rgGender.isEnabled = false
}
override fun onClick(v: View?) {
if (v != null){
when(v.id){
R.id.tv_edit -> {
val intent = Intent(this#SettingsActivity, UserProfileActivity::class.java)
intent.putExtra(Constants.EXTRA_USER_DETAILS, mUserDetails)
startActivity(intent)
}
R.id.btn_logout -> {
FirebaseAuth.getInstance().signOut()
Intent(this#SettingsActivity, LoginActivity::class.java).also {
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}
}
}
}
}
fun sellerLoggedInSuccess(seller: Seller){
//hide progress bar
hideProgresDialog()
//userType 0 = admin...... userType 1 = user..... userType 2 = seller
if (seller.userType == 2){
if (seller.profileComplete == 0){
//jika profile user belum complete arahkan user ke activity SellerProfileActivity
val intent = Intent(this#SettingsActivity, SellerProfileActivity::class.java)
intent.putExtra(Constants.EXTRA_SELLER_DETAILS, seller)
startActivity(intent)
}else{
//jika profile seller sudah complete langsung arahkan ke SellerActivity
val intent = Intent(this#SettingsActivity, SellerActivity::class.java)
intent.putExtra(Constants.EXTRA_SELLER_DETAILS, seller)
startActivity(intent)
}
}else{
hideProgresDialog()
showErrorSnackBar(R.string.msg_login_seller_unsuccess.toString(), true)
finish()
}
}
}
this is my setting_activity layout :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.user.SettingsActivity">
<FrameLayout
android:id="#+id/fl_header_bg"
android:layout_width="match_parent"
android:layout_height="#dimen/header_image_height"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/iv_header_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="#string/content_description"
android:scaleType="fitXY"
android:src="#drawable/auth_screens_background"/>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar_user_profile_activity"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/tv_tittle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingStart="-25dp"
android:paddingEnd="0dp"
android:text="#string/tittle_setting"
android:textColor="#color/white"
android:textSize="#dimen/toolbar_title_text_size"
android:textStyle="bold"/>
</androidx.appcompat.widget.Toolbar>
</FrameLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/fl_header_bg">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:id="#+id/fl_user_image"
android:layout_width="#dimen/profile_user_image_size"
android:layout_height="#dimen/profile_user_image_size"
android:layout_marginTop="#dimen/profile_user_image_marginTop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/tv_user_image_setting"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/profile_user_photo_margin"
android:background="#color/colorLightGrey"
android:scaleType="centerCrop"
android:src="#drawable/ic_user_placeholder"
android:contentDescription="#string/profile_picture" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/user_image_background"/>
</FrameLayout>
<com.adit.bangkit.plagroid.utils.MSPTextView
android:id="#+id/tv_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/lbl_edit"
android:textAlignment="viewEnd"
android:textColor="#color/secondary_text"
android:textSize="#dimen/setting_edit_label_textSize"
android:textStyle="bold"
android:layout_margin="16dp"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:paddingStart="#dimen/setting_edit_label_marginStartEnd"
android:paddingBottom="#dimen/setting_edit_label_marginTopBottom"
android:paddingEnd="#dimen/setting_edit_label_marginStartEnd"
android:paddingTop="#dimen/setting_edit_label_marginTopBottom"
app:layout_constraintTop_toBottomOf="#+id/fl_user_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#+id/til_first_name"/>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til_first_name"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="#string/hint_first_name"
android:textColorHint="#color/secondary_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_edit">
<com.adit.bangkit.plagroid.utils.MSPEditText
android:id="#+id/et_first_name_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:padding="#dimen/et_padding"
android:textColor="#color/primary_text"
android:textSize="#dimen/et_textSize"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til_last_name"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="#string/hint_last_name"
android:textColorHint="#color/secondary_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/til_first_name">
<com.adit.bangkit.plagroid.utils.MSPEditText
android:id="#+id/et_last_name_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:padding="#dimen/et_padding"
android:textColor="#color/primary_text"
android:textSize="#dimen/et_textSize"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til_email_reg"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="#string/er_hint_email_id"
android:textColorHint="#color/secondary_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/til_last_name">
<com.adit.bangkit.plagroid.utils.MSPEditText
android:id="#+id/et_email_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:padding="#dimen/et_padding"
android:textColor="#color/primary_text"
android:textSize="#dimen/et_textSize"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til_password_reg"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="#string/et_hint_mobile_number"
android:textColorHint="#color/secondary_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/til_email_reg">
<com.adit.bangkit.plagroid.utils.MSPEditText
android:id="#+id/et_mobile_number_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="phone"
android:padding="#dimen/et_padding"
android:textColor="#color/primary_text"
android:textSize="#dimen/et_textSize" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til_address"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="#string/et_hint_address"
android:textColorHint="#color/secondary_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/til_password_reg">
<com.adit.bangkit.plagroid.utils.MSPEditText
android:id="#+id/et_address_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:padding="#dimen/et_padding"
android:textColor="#color/primary_text"
android:textSize="#dimen/et_textSize"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til_pos_code"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="#string/et_hint_codepos"
android:textColorHint="#color/secondary_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/til_address">
<com.adit.bangkit.plagroid.utils.MSPEditText
android:id="#+id/et_pos_code_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:padding="#dimen/et_padding"
android:textColor="#color/primary_text"
android:textSize="#dimen/et_textSize"/>
</com.google.android.material.textfield.TextInputLayout>
<RadioGroup
android:id="#+id/rg_gender"
android:layout_width="match_parent"
android:layout_height="#dimen/profile_radio_button_height"
android:layout_marginStart="16dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="16dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="#id/btn_logout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/til_pos_code">
<com.adit.bangkit.plagroid.utils.MSPRadioButton
android:id="#+id/btn_gender_male"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="#dimen/profile_radio_button_marginStartEnd"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:background="#drawable/drawable_gender_selector_tab"
android:button="#null"
android:checked="true"
android:gravity="center"
android:text="#string/gender_lbl_male"
android:textColor="#drawable/drawable_gender_tab_text_color"
android:textStyle="bold"/>
<com.adit.bangkit.plagroid.utils.MSPRadioButton
android:id="#+id/btn_gender_female"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginEnd="#dimen/profile_radio_button_marginStartEnd"
android:layout_weight="1"
android:background="#drawable/drawable_gender_selector_tab"
android:button="#null"
android:gravity="center"
android:text="#string/gender_lbl_female"
android:textColor="#drawable/drawable_gender_tab_text_color"
android:textStyle="bold"/>
</RadioGroup>
<com.adit.bangkit.plagroid.utils.MSPButton
android:id="#+id/btn_logout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="16dp"
android:background="#drawable/button_background"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:paddingTop="#dimen/btn_padding"
android:paddingBottom="#dimen/btn_padding"
android:text="#string/lbl_btn_logout"
android:textColor="#color/white"
android:textSize="#dimen/btn_textSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/rg_gender"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
and this is my fireStoreClass :
class FireStoreClass {
private val mFirestore = FirebaseFirestore.getInstance()
fun registerUser(activity: RegisterActivity, userInfo: User){
mFirestore.collection(Constants.USERS)
.document(userInfo.id)
.set(userInfo, SetOptions.merge())
.addOnSuccessListener{
activity.userRegistrationSuccess()
}
.addOnFailureListener {e ->
activity.hideProgresDialog()
Log.e(
activity.javaClass.simpleName,
"Error While Registering User.",
e
)
}
}
fun getCurrentUserID(): String{
//Instance dari currentUser menggunakan FirebaseAuth
val currentUser = FirebaseAuth.getInstance().currentUser
//variabel yang digunakan untuk menetapkan currentUserID
var currentUserID = ""
if (currentUser != null){
currentUserID = currentUser.uid
}
return currentUserID
}
#SuppressLint("CommitPrefEdits")
fun getUsersDetails(activity: Activity){
mFirestore.collection(Constants.USERS)
.document(getCurrentUserID())
.get()
.addOnSuccessListener {document ->
Log.i(activity.javaClass.simpleName, document.toString())
//menerima document snapshot yang akan dikonversi ke User Data model object.
val user = document.toObject(User::class.java)!!
val username = " " + user.firstName + " " + user.lastName
val sharedPreferences = activity.getSharedPreferences(
Constants.PLAGRO_PREFERENCES,
Context.MODE_PRIVATE
)
val editor: SharedPreferences.Editor= sharedPreferences.edit()
editor.putString(
//key = logged_in_username
//value = firstname dan lastname
Constants.LOGGED_IN_USERNAME,
username
)
editor.apply()
//START
when(activity){
is LoginActivity -> {
activity.userLoggedInSuccess(user)
}
is SettingsActivity -> {
activity.loadUserDetailsSuccess(user)
}
}
//END
}
.addOnFailureListener { e ->
when(activity){
is LoginActivity ->{
activity.hideProgresDialog()
}
is SettingsActivity -> {
activity.hideProgresDialog()
}
}
Log.e(
activity.javaClass.simpleName,
e.toString()
)
}
}
fun updateUserProfileData(activity: Activity, userHashMap: HashMap<String, Any>){
mFirestore.collection(Constants.USERS).document(getCurrentUserID())
.update(userHashMap)
.addOnSuccessListener {
when (activity) {
is UserProfileActivity -> {
activity.userProfileUpdateSuccess()
}
}
}
.addOnFailureListener { e ->
when (activity) {
is UserProfileActivity -> {
activity.hideProgresDialog()
}
}
Log.e(
activity.javaClass.simpleName,
"Error while updating the user details",
e
)
}
}
fun uploadImageToCloudStorage(activity: Activity, ImageFileURI: Uri?){
val storageRef: StorageReference = FirebaseStorage.getInstance().reference.child(
Constants.USER_PROFILE_IMAGE + System.currentTimeMillis() + "."
+ Constants.getFileExtension(
activity, ImageFileURI
)
)
storageRef.putFile(ImageFileURI!!).addOnSuccessListener { taskSnapshot ->
Log.e(
"firebase Image URL",
taskSnapshot.metadata!!.reference!!.downloadUrl.toString()
)
taskSnapshot.metadata!!.reference!!.downloadUrl
.addOnSuccessListener { uri ->
Log.e("Downloadable Image URL", uri.toString())
when(activity){
is UserProfileActivity ->{
activity.imageUploadSuccess(uri.toString())
}
}
}
}
.addOnFailureListener { exception ->
when(activity){
is UserProfileActivity ->{
activity.hideProgresDialog()
}
}
Log.e(
activity.javaClass.simpleName,
exception.message,
exception
)
}
}
}
when i run the app and try to logout an user i got this error:
java.lang.IllegalArgumentException: Invalid document reference. Document references must have an even number of segments, but users has 1
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4341)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4373)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: java.lang.IllegalArgumentException: Invalid document reference. Document references must have an even number of segments, but users has 1
at com.google.firebase.firestore.DocumentReference.forPath(DocumentReference.java:81)
at com.google.firebase.firestore.CollectionReference.document(CollectionReference.java:104)
at com.adit.bangkit.plagroid.firestore.FireStoreClass.getUsersDetails(fireStoreClass.kt:136)
at com.adit.bangkit.plagroid.ui.activity.user.SettingsActivity.getUserDetails(SettingsActivity.kt:55)
at com.adit.bangkit.plagroid.ui.activity.user.SettingsActivity.onResume(SettingsActivity.kt:80)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1456)
at android.app.Activity.performResume(Activity.java:8125)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4331)
does anyone have solve this problem?
The error seems to come from this code inside getUsersDetails:
mFirestore.collection(Constants.USERS)
.document(getCurrentUserID())
So my guess is that getCurrentUserID() returns null or an empty string.
Given this implementation:
fun getCurrentUserID(): String{
//Instance dari currentUser menggunakan FirebaseAuth
val currentUser = FirebaseAuth.getInstance().currentUser
//variabel yang digunakan untuk menetapkan currentUserID
var currentUserID = ""
if (currentUser != null){
currentUserID = currentUser.uid
}
return currentUserID
}
The getCurrentUserID returns an empty string when FirebaseAuth.getInstance().currentUser is null. You'll want to deal with this in your getUsersDetails function by checking for null/empty
fun getUsersDetails(activity: Activity){
if (!TextUtils.isEmpty(getCurrentUserID()) { // 👈
mFirestore.collection(Constants.USERS)
.document(getCurrentUserID())
...
I am loading in Data from Cloud Firestore. That data is then being added as an Item to a RecyclerView and should be displayed on the screen. However, the RecyclerView remains empty.
The data is loaded in correctly from Cloud Firestore (I can tell because of the logs I added which are shown below).
So I cannot find out why the data is not being added to the RecyclerView correctly and displayed?
ActiveOrderActivity.kt
class ActiveOrderActivity : AppCompatActivity() {
private val aorderList = ArrayList<ActiveOrderModel>()
private val adapter = AOrdersAdapter(aorderList)
/* Access a Cloud Firestore instance from the Activity. */
val db = Firebase.firestore
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_active_order)
recyclerview.adapter = adapter
recyclerview.layoutManager = LinearLayoutManager(this)
recyclerview.setHasFixedSize(true)
db.collection("Orders - 18.3.2021")
.get()
.addOnSuccessListener { result ->
for (document in result) {
Log.i("", "IN LOOP FOR DOCUMENT: ActiveOrderActivity.\n")
val customerName = document.getField<String>("customer Name")
Log.i("", "$customerName: ActiveOrderActivity.\n")
val customerNumber = document.getField<String>("customer Number")
val customerPostal = document.getField<String>("eircode")
val customerAddress = document.getField<String>("address")
val paymentAmount = document.getField<String>("payment Amount")
val paymentType = document.getField<String>("payment Total")
val newItem = ActiveOrderModel(customerName = customerName,customerNumber = customerNumber,customerPostal = customerPostal,customerAddress = customerAddress,paymentAmount = paymentAmount,paymentType = paymentType)
aorderList.add(INDEX,newItem)
adapter.notifyItemInserted(INDEX)
}
}
}
}
AOrdersAdapter.kt
class AOrdersAdapter(private val aorderList: List<ActiveOrderModel> ) : RecyclerView.Adapter<AOrdersAdapter.AOrderViewHolder>() {
class AOrderViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val nameView = view.nameView
val addressView = view.address1View
val mobileView = view.mobileView
val eircodeView = view.eircodeView
val paymentView = view.paymentView
val paymentAmountView = view.paymentAmountView
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AOrderViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.active_order_item, parent, false)
return AOrderViewHolder(view)
}
override fun getItemCount(): Int {
return aorderList.size
}
override fun onBindViewHolder(holder: AOrderViewHolder, position: Int) {
val currentItem = aorderList[position]
holder.nameView.text = currentItem.customerName
holder.addressView.text = currentItem.customerNumber
holder.mobileView.text = currentItem.customerPostal
holder.eircodeView.text = currentItem.customerAddress
holder.paymentAmountView.text = currentItem.paymentAmount
holder.paymentView.text = currentItem.paymentType
}
}
activity_active_order.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainBody.dashboard.ordersActivites.ActiveOrderActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="wrap_content"
android:layout_height="699dp"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:clipToPadding="false"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/floatingActionButton"
app:layout_constraintVertical_bias="0.0"
tools:listitem="#layout/active_order_item" />
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/floatingActionButton"
android:layout_width="307dp"
android:layout_height="68dp"
android:layout_marginTop="88dp"
android:background="#drawable/pizaa_button2"
android:text="Main Menu"
android:textColor="#color/white"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
active_order_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/rowConstraintLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:padding="16dp"
android:layout_margin="4dp"
app:cardElevation="10dp"
app:cardCornerRadius="8dp"
app:cardPreventCornerOverlap="false">
<RelativeLayout
android:layout_width="800dp"
android:layout_height="match_parent"
android:padding="12dp">
<TextView
android:id="#+id/nameView"
android:layout_width="223dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="6dp"
android:layout_marginEnd="0dp"
android:text="George Matthews"
android:textColor="#color/shopColour"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/address1View"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/nameView"
android:layout_alignParentStart="true"
android:layout_marginStart="6dp"
android:layout_marginLeft="2dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="6dp"
android:text="123 Fakelands,\nHigher up Road,\nDublin"
android:textColor="#color/logoYellow"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/mobileView"
android:layout_width="144dp"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/productPriceView"
android:layout_marginStart="20dp"
android:layout_marginLeft="2dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="100dp"
android:layout_toEndOf="#+id/nameView"
android:text="089 215 2121"
android:textColor="#color/shopColour"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/eircodeView"
android:layout_width="87dp"
android:layout_height="wrap_content"
android:layout_below="#+id/mobileView"
android:layout_alignEnd="#+id/mobileView"
android:layout_marginStart="43dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="11dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="1dp"
android:layout_toEndOf="#+id/nameView"
android:text="A96 K4D8"
android:textColor="#color/logoYellow"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/paymentView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/productPriceView"
android:layout_marginStart="20dp"
android:layout_marginLeft="2dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="100dp"
android:layout_toEndOf="#+id/mobileView"
android:gravity="center"
android:text="Frank's Website"
android:textColor="#color/shopColour"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/paymentAmountView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/paymentView"
android:layout_alignEnd="#+id/paymentView"
android:layout_marginStart="144dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="-5dp"
android:layout_marginBottom="1dp"
android:layout_toEndOf="#+id/eircodeView"
android:gravity="center"
android:text="47.00"
android:textColor="#color/logoYellow"
android:textSize="20sp"
android:textStyle="bold" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
ActiveOrderModel.kt
data class ActiveOrderModel(
val customerName: String? = null,
val customerNumber: String? = null,
val customerPostal: String? = null,
val customerAddress: String? = null,
val paymentAmount: String? = null,
val paymentType: String? = null )
Here the running terminal shows that the data has been loaded correctly from the Cloud Firestore and the loop is working to iterate through all the entries in the Collection. Now each document should be added to the RecyclerView but the Recycler View is empty as shown below.
You need to update list in adapter to get desired result. Create a method in adapter as below -
fun updateList(list: List<ActiveOrderModel> ) {
this.aorderList = list
notifyDataSetChanged()
}
Update below lines in your activity
aorderList.add(INDEX,newItem)
adapter.updateList(aorderList)
adapter.notifyItemInserted(INDEX)
try this
fun initRecyclerView() {
mainRecycler.setLayoutManager(LinearLayoutManager(context))
var linearLayoutManager: LinearLayoutManager? = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
mainRecycler?.layoutManager = linearLayoutManager
val itemDecorator = VerticalSpacingItemDecorator(20)
mainRecycler.addItemDecoration(itemDecorator)
adapter = AOrdersAdapter(aorderList)
mainRecycler.setAdapter(adapter)
}
and this
for (document in result) {
Log.i("", "IN LOOP FOR DOCUMENT: ActiveOrderActivity.\n")
val customerName = document.getField<String>("customer Name")
Log.i("", "$customerName: ActiveOrderActivity.\n")
val customerNumber = document.getField<String>("customer Number")
val customerPostal = document.getField<String>("eircode")
val customerAddress = document.getField<String>("address")
val paymentAmount = document.getField<String>("payment Amount")
val paymentType = document.getField<String>("payment Total")
val newItem = ActiveOrderModel(customerName = customerName,customerNumber = customerNumber,customerPostal = customerPostal,customerAddress = customerAddress,paymentAmount = paymentAmount,paymentType = paymentType)
aorderList.add(INDEX,newItem)
adapter.notifyItemInserted(INDEX)
}
adapter?.notifyDataSetChanged()
use adapter?.notifyDataSetChanged()
and must check your arraylist not be empty.
I am trying to make a grid layout with expandable cards, but the problem is that when a card is expanded, its height gets bigger and so does the height of the other cards in the row (to match the height of the first card), but when the card is collapsed back, the height of all the cards does not change as if they were expanded. Anyone knows what could be the problem?
EDIT :
recyclerview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/misty_rose"
android:layout_margin="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Media -->
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_gravity="center_horizontal"
android:padding="8dp"
android:contentDescription="Photo"
android:src="#drawable/unsplash"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="#color/isabelline"
/>
<!-- Title, secondary and supporting text -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/misty_rose"
app:layout_constraintTop_toBottomOf="#+id/imageView"
android:padding="8dp">
<TextView
android:id="#+id/textViewCode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Code"
android:textAppearance="?attr/textAppearanceHeadline6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="#+id/iconExpandCard"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:padding="8dp"
android:src="#drawable/ic_baseline_expand_more_36"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/textViewDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Description"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewCode" />
<TextView
android:id="#+id/textViewPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Price"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewDescription"/>
<TextView
android:id="#+id/textViewComment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Comment"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewPrice"
android:visibility="gone"/>
<!-- Buttons -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewComment">
<com.google.android.material.button.MaterialButton
android:id="#+id/buttonMinusArticle"
style="?attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:width="88dp"
android:minWidth="40dp"
android:backgroundTint="#color/purple_200"
android:text="#string/minus"
android:textColor="#color/white" />
<EditText
android:id="#+id/editNumberOfProducts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="16dp"
android:inputType="numberDecimal|number"
android:text="#string/zero"
android:textAppearance="?attr/textAppearanceBody1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="18sp" />
<com.google.android.material.button.MaterialButton
android:id="#+id/buttonPlusArticle"
style="?attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="88dp"
android:minWidth="40dp"
android:backgroundTint="#color/purple_200"
android:text="#string/plus"
android:textColor="#color/white" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
And in ProductListAdapter.kt (the important part is in expandButton.setOnClickListener() ):
class ProductListAdapter() : ListAdapter<Product, ProductListAdapter.ProductViewHolder>(ProductsComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
return ProductViewHolder.create(parent)
}
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val current = getItem(position)
holder.bind(current!!)
}
class ProductViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val productItemView: TextView = itemView.findViewById(R.id.textViewCode)
private val productDescription : TextView = itemView.findViewById(R.id.textViewDescription)
private val productPrice : TextView = itemView.findViewById(R.id.textViewPrice)
fun bind(product: Product) {
productItemView.text = product.code
//productDescription.text = product.description
//productPrice.text = "Price " + product.client_price.toString()
}
companion object {
val mapOfProducts :HashMap<String, Int> = hashMapOf<String, Int>()
fun create(parent: ViewGroup): ProductViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.recyclerview_item, parent, false)
val minusButton : Button = view.findViewById(R.id.buttonMinusArticle)
val plusButton : Button = view.findViewById(R.id.buttonPlusArticle)
val productItemViewCode: TextView = view.findViewById(R.id.textViewCode)
val expandButton : androidx.appcompat.widget.AppCompatImageButton = view.findViewById(R.id.iconExpandCard)
val commentView : TextView = view.findViewById(R.id.textViewComment)
val cardView : CardView = view.findViewById(R.id.cardView)
expandButton.setOnClickListener{
if (commentView.visibility == View.GONE){
TransitionManager.beginDelayedTransition(cardView, AutoTransition())
commentView.visibility = View.VISIBLE
expandButton.setImageResource(R.drawable.ic_baseline_expand_less_36)
} else {
TransitionManager.beginDelayedTransition(cardView, AutoTransition())
commentView.visibility = View.GONE
expandButton.setImageResource(R.drawable.ic_baseline_expand_more_36)
}
}
val editNumberOfProducts: EditText = view.findViewById(R.id.editNumberOfProducts)
editNumberOfProducts.doAfterTextChanged {
val code = productItemViewCode.text.toString()
if (it.isNullOrBlank()) {
modifyText("0", view)
mapOfProducts.remove(code)
return#doAfterTextChanged
}
val originalText = it.toString()
try {
val number = originalText.toInt()
val numberText = originalText.toInt().toString()
if (originalText != numberText) {
modifyText(numberText, view)
}
if (number > 0) {
mapOfProducts[code] = number
d("CodeOfView", "$code $number")
}else {
mapOfProducts.remove(code)
}
} catch (e: Exception) {
modifyText("0", view)
mapOfProducts.remove(code)
}
}
minusButton.setOnClickListener {
var number = editNumberOfProducts.text.toString().toInt()
if (number>0) {
number -= 1
modifyText(number.toString(), view)
}
}
plusButton.setOnClickListener {
//val code = productItemViewCode.text.toString()
var number = editNumberOfProducts.text.toString().toInt()
number += 1
modifyText(number.toString(), view)
}
return ProductViewHolder(view)
}
private fun modifyText(numberText: String, view: View) {
val editNumberOfProducts = view.findViewById<EditText>(R.id.editNumberOfProducts)
editNumberOfProducts.setText(numberText)
editNumberOfProducts.setSelection(numberText.length)
}
}
}
class ProductsComparator : DiffUtil.ItemCallback<Product>() {
override fun areItemsTheSame(oldItem: Product, newItem: Product): Boolean {
return oldItem === newItem
}
override fun areContentsTheSame(oldItem: Product, newItem: Product): Boolean {
return oldItem.code == newItem.code
}
}
}
Example with images of the problem
I was facing a same issue, in my case it was vertical expandable cards and I managed to solve it by using
Adapter.notifyDataSetChanged()
in the right place.
I can see a flicker within my recycler view right at the top. The flicker seems to resemble the top lines of my drawable shapes in the recycler view item.xml. I have made various adjustments to lines and other things to see if I could prevent the flicker but nothing appears to be working.
Here is my code;
Activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".ScoreHistory">
<TextView
android:id="#+id/textView_history_title"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:gravity="center|center_horizontal|center_vertical"
android:padding="5dp"
android:text="#string/GameHistory_Title"
android:textAlignment="gravity"
android:textColor="#color/lime"
android:textStyle="bold"
app:autoSizeTextType="uniform"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/RV_scorehistory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView_history_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
My item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="55dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="#drawable/rv_lines"
android:gravity="center_vertical">
<TextView
android:id="#+id/TV_RV_ID"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="0dp"
android:gravity="center"
android:textAlignment="center"
app:layout_constraintEnd_toStartOf="#+id/TV_RV_DIFFICULTY"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/TV_RV_DIFFICULTY"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:gravity="center"
android:textAlignment="center"
app:layout_constraintBaseline_toBaselineOf="#+id/TV_RV_ID"
app:layout_constraintEnd_toStartOf="#+id/TV_RV_SUMTYPE"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight="4"
app:layout_constraintStart_toEndOf="#+id/TV_RV_ID" />
<TextView
android:id="#+id/TV_RV_SUMTYPE"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:gravity="center"
android:textAlignment="center"
app:layout_constraintBaseline_toBaselineOf="#+id/TV_RV_DIFFICULTY"
app:layout_constraintEnd_toStartOf="#+id/TV_RV_OutOfText"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight="3.5"
app:layout_constraintStart_toEndOf="#+id/TV_RV_DIFFICULTY" />
<TextView
android:id="#+id/TV_RV_OutOfText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:gravity="center"
android:text="#string/score_text"
app:layout_constraintBaseline_toBaselineOf="#+id/TV_RV_SUMTYPE"
app:layout_constraintEnd_toStartOf="#+id/TV_RV_SCORE"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toEndOf="#+id/TV_RV_SUMTYPE" />
<TextView
android:id="#+id/TV_RV_SCORE"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="6dp"
android:gravity="center"
android:textAlignment="center"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="#+id/TV_RV_OutOfText"
app:layout_constraintEnd_toStartOf="#+id/TV_RV_QCOUNT_TEXT"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight="1.5"
app:layout_constraintStart_toEndOf="#+id/TV_RV_OutOfText" />
<TextView
android:id="#+id/TV_RV_QCOUNT_TEXT"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:gravity="center"
android:text="#string/questions_text"
android:textAlignment="gravity"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="#+id/TV_RV_SCORE"
app:layout_constraintEnd_toStartOf="#+id/TV_RV_QCOUNT"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight=".75"
app:layout_constraintStart_toEndOf="#+id/TV_RV_SCORE" />
<TextView
android:id="#+id/TV_RV_QCOUNT"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:background="#drawable/target_icon"
android:gravity="center"
android:textAlignment="center"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="#+id/TV_RV_QCOUNT_TEXT"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight="1.5"
app:layout_constraintStart_toEndOf="#+id/TV_RV_QCOUNT_TEXT" />
</androidx.constraintlayout.widget.ConstraintLayout>
I set background resources here in my adapter
class ScoreHistoryAdaptor : ListAdapter<SavedScores, ScoreHistoryAdaptor.SavedScoreViewHolder>(WordsComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SavedScoreViewHolder {
return SavedScoreViewHolder.create(parent)
}
override fun onBindViewHolder(holder: SavedScoreViewHolder, position: Int) {
val current = getItem(position)
holder.bind(current.id,current.difficulty,current.sumtype,current.questioncount,current.answeredcorrectly)
}
class SavedScoreViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val IDItemView: TextView = itemView.findViewById(R.id.TV_RV_ID)
private val DiffultyItemView: TextView = itemView.findViewById(R.id.TV_RV_DIFFICULTY)
private val SumTypeItemView: TextView = itemView.findViewById(R.id.TV_RV_SUMTYPE)
private val qCountItemView: TextView = itemView.findViewById(R.id.TV_RV_QCOUNT)
private val ScoreItemView: TextView = itemView.findViewById(R.id.TV_RV_SCORE)
private var DIFFCODE = ""
private var SUMTYPECODE = ""
val myContext = SumTypeItemView.context
fun bind(ID: Int?,DIFFICULTY:String?,SUMTYPE:String?,QC:Int?,SCORE:Int?) {
IDItemView.text = ID.toString()
when (DIFFICULTY) {
myContext.resources.getString(R.string.diffLVL1) -> {DIFFCODE = DIFFICULTY; DiffultyItemView.setBackgroundResource(R.drawable.diff_easy_icon)}
myContext.resources.getString(R.string.diffLVL2) -> {DIFFCODE = DIFFICULTY ; DiffultyItemView.setBackgroundResource(R.drawable.diff_normal_icon)}
myContext.resources.getString(R.string.diffLVL3) -> {DIFFCODE = DIFFICULTY; DiffultyItemView.setBackgroundResource(R.drawable.diff_hard_icon) }
myContext.resources.getString(R.string.diffLVL4) -> {DIFFCODE = DIFFICULTY ; DiffultyItemView.setBackgroundResource(R.drawable.diff_impossible_icon)}
myContext.resources.getString(R.string.random) -> {DIFFCODE = DIFFICULTY ; DiffultyItemView.setBackgroundResource(R.drawable.diff_random_icon)}
}
DiffultyItemView.text = DIFFCODE
when (SUMTYPE) {
myContext.resources.getString(R.string.catMulti) -> {SUMTYPECODE = myContext.resources.getString(R.string.multi_symbol) }
myContext.resources.getString(R.string.catAdd) -> {SUMTYPECODE = myContext.resources.getString(R.string.add_symbol)}
myContext.resources.getString(R.string.catSub) -> {SUMTYPECODE = myContext.resources.getString(R.string.sub_symbol)}
myContext.resources.getString(R.string.catDiv) -> {SUMTYPECODE = myContext.resources.getString(R.string.div_symbol)}
myContext.resources.getString(R.string.catSqrR) -> {SUMTYPECODE = myContext.resources.getString(R.string.sqr_symbol) + "n"}
myContext.resources.getString(R.string.catSqrD) -> {SUMTYPECODE = "n" + myContext.resources.getString(R.string.sqrd_symbol)}
myContext.resources.getString(R.string.catCubeR) -> {SUMTYPECODE = myContext.resources.getString(R.string.cuber_symbol) + "n"}
myContext.resources.getString(R.string.catCubeD) -> {SUMTYPECODE = "n" + myContext.resources.getString(R.string.cubed_symbol)}
myContext.resources.getString(R.string.random) -> {SUMTYPECODE = myContext.resources.getString(R.string.random)}
}
when (IsScoreLessThanTarget(SCORE!!.toInt(),QC!!.toInt())){
true ->{ScoreItemView.setBackgroundResource(R.drawable.somewrong_icon)}
false ->{ScoreItemView.setBackgroundResource(R.drawable.allcorrect_icon)}
}
SumTypeItemView.setBackgroundResource(R.drawable.sumtype_icon)
SumTypeItemView.text = SUMTYPECODE
qCountItemView.text = QC.toString()
ScoreItemView.text = SCORE.toString()
}
companion object {
fun create(parent: ViewGroup): SavedScoreViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.row_item, parent, false)
return SavedScoreViewHolder(view)
}
}
}
class WordsComparator : DiffUtil.ItemCallback<SavedScores>() {
override fun areItemsTheSame(oldItem: SavedScores, newItem: SavedScores): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: SavedScores, newItem: SavedScores): Boolean {
return oldItem == newItem
}
}
}
private fun IsScoreLessThanTarget(score:Int,target:Int): Boolean{
return score < target
}
In another view using scrollview I get the same
Your issue is arising because in your my_item.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="55dp" <---- Fixed Height
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="#ae7f9c"
android:gravity="center_vertical">
and in your textviews like this one,
<TextView
android:id="#+id/TV_RV_ID"
android:layout_width="0dp"
android:layout_height="match_parent" <------ this hiding the background try using wrap_content
android:layout_margin="0dp"
android:gravity="center"
android:textAlignment="center"
app:layout_constraintEnd_toStartOf="#+id/TV_RV_DIFFICULTY"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
To solve this,
Try not giving a fixed height from my_item.xml container, use wrap_content
Add padding to the container constaintlayout
add android:layout_height="wrap_content" to your text views and center_vertical them,
then your issue will resolve, hope this helps
try not giving a fixed height to the container
My click listener are not working even if I check with a Toast inside of them, it use to work but after I made a couple of change in my viewModel it stop working, I can't figure out what went wrong. This happen in my detail activity only, but work on the recyclerview that call this detail activity via intent. I'm using Viewmodel, Livedata, databinding and Room. The recyclerview and the detail view are using the same viewmodel.
This is the code of my Detail activity:
class BuyDetailActivity : AppCompatActivity() {
private lateinit var sharedViewModel: BuySharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lateinit var buy: Buy
sharedViewModel = ViewModelProviders.of(this).get(BuySharedViewModel::class.java)
val position = intent.getIntExtra("position", 0)
sharedViewModel.allBuys.observe(this, Observer<List<Buy>> { buys ->
buy = buys[position]
val binding: com.example.drake.kunuk.databinding.ActivityBuyDetailBinding =
DataBindingUtil.setContentView(this, com.example.drake.kunuk.R.layout.activity_buy_detail)
binding.buy = buy
val agentNumber = buy.agentNumber
bnvContactAgent.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
com.example.drake.kunuk.R.id.action_call -> {
val callNumberUri = Uri.parse("tel:$agentNumber")
val callIntent = Intent(Intent.ACTION_DIAL, callNumberUri)
startActivity(callIntent)
}
com.example.drake.kunuk.R.id.action_sms -> {
val smsNumberUri = Uri.parse("sms:$agentNumber")
val smsIntent = Intent(Intent.ACTION_SENDTO, smsNumberUri)
startActivity(smsIntent)
}
com.example.drake.kunuk.R.id.action_email -> {
val uriText = "mailto:xxxxxxxx#gmail.com" +
"?subject=" + Uri.encode("I'm interested in $agentNumber") +
"&body=" + Uri.encode("Hello, ")
val uri = Uri.parse(uriText)
val sendIntent = Intent(Intent.ACTION_SENDTO)
sendIntent.data = uri
startActivity(Intent.createChooser(sendIntent, "Send email"))
}
}
false
}
// set animation duration via code, but preferable in your layout files by using the animation_duration attribute
expandableTextView.setAnimationDuration(750L)
// set interpolators for both expanding and collapsing animations
expandableTextView.setInterpolator(OvershootInterpolator())
// or set them separately
expandableTextView.expandInterpolator = OvershootInterpolator()
expandableTextView.collapseInterpolator = OvershootInterpolator()
// toggle the ExpandableTextView
buttonToggle.setOnClickListener {
buttonToggle.setText(if (expandableTextView.isExpanded) com.example.drake.kunuk.R.string.more else com.example.drake.kunuk.R.string.less)
expandableTextView.toggle()
}
// but, you can also do the checks yourself
buttonToggle.setOnClickListener {
if (expandableTextView.isExpanded) {
expandableTextView.collapse()
buttonToggle.setText(com.example.drake.kunuk.R.string.more)
} else {
expandableTextView.expand()
buttonToggle.setText(com.example.drake.kunuk.R.string.less)
}
}
//Open photoView activity when clicked
ivHouseDetail.setOnClickListener {
applicationContext
.startActivity(
Intent(
applicationContext,
ViewPagerActivity::class.java
)
.putExtra("imageList", buy.propertyImage)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
}
})
}
}
Here's my SharedViewmodel, use by both the fragment calling the detail activity and the detail activity.
class BuySharedViewModel(application: Application) : AndroidViewModel(application) {
private val repository: BuyRepository
var allBuys: LiveData<List<Buy>>
init {
val buyDao = KunukRoomDatabase.getDatabase(application, viewModelScope).buyDao()
val buyRemote = BuyRemote()
repository = BuyRepository.getInstance(buyDao , buyRemote)
//Use async because it return a result
viewModelScope.async { getAllBuys() }
allBuys = buyDao.loadAllBuys()
}
private suspend fun getAllBuys() {
repository.getBuys()
}
}
And finally this is the xml of the detail activity:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="buy" type="com.example.drake.kunuk.data.model.Buy"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent" android:layout_width="match_parent"
>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bnvContactAgent"
android:layout_width="match_parent"
android:background="#color/colorPrimary"
app:itemIconTint="#color/colorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/bottom_nav_contact_agent"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_bias="1.0"/>
<ScrollView
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_height="0dp" android:layout_width="0dp"
app:layout_constraintBottom_toTopOf="#+id/bnvContactAgent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".ui.buy.BuyDetailActivity">
<ImageView
android:layout_width="match_parent"
android:layout_height="230dp"
tools:srcCompat="#tools:sample/backgrounds/scenic"
android:id="#+id/ivHouseDetail"
android:scaleType="centerCrop"
android:contentDescription="#string/house"
app:imageUrl="#{buy.propertyImage}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
app:formatToUSD="#{buy.price}"
android:id="#+id/tvPriceDetail"
android:textStyle="bold"
android:textColor="#color/colorPrimaryText"
android:textSize="20sp"
tools:ignore="HardcodedText"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="#+id/ivHouseDetail" android:layout_marginStart="8dp"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:text="#{buy.address}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvAddressDetail"
android:textColor="#color/colorSecondaryText"
app:layout_constraintTop_toBottomOf="#+id/tvPriceDetail"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"/>
<TextView
android:text="#{Integer.toString(buy.numberOfRoom)}"
android:maxLength="3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvBedroom"
android:layout_marginTop="12dp"
android:textStyle="bold"
android:textColor="#color/colorPrimaryText"
app:layout_constraintTop_toBottomOf="#+id/tvAddressDetail"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" app:srcCompat="#drawable/ic_bed"
android:id="#+id/ivBedroom"
android:contentDescription="#string/bedroom_icon"
app:layout_constraintStart_toEndOf="#+id/tvBedroom"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="#+id/tvAddressDetail"/>
<TextView
android:text="#{Integer.toString(buy.numberOfBath)}"
android:maxLength="3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvBathroom"
android:textStyle="bold"
android:textColor="#color/colorPrimaryText"
app:layout_constraintStart_toEndOf="#+id/ivBedroom"
android:layout_marginStart="20dp" app:layout_constraintTop_toTopOf="#+id/ivBedroom"
android:layout_marginTop="4dp"/>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp" app:srcCompat="#drawable/ic_bathtub"
android:id="#+id/imageView2"
android:contentDescription="#string/bathroom_icon"
app:layout_constraintStart_toEndOf="#+id/tvBathroom"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="#+id/tvAddressDetail"/>
<TextView
android:text="#{Integer.toString(buy.numberOfCar)}"
android:maxLength="3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvGarage"
android:textStyle="bold"
android:textColor="#color/colorPrimaryText"
app:layout_constraintStart_toEndOf="#+id/imageView2"
android:layout_marginStart="20dp" app:layout_constraintTop_toTopOf="#+id/imageView2"
android:layout_marginTop="4dp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" app:srcCompat="#drawable/ic_garage"
android:id="#+id/imageView3"
android:contentDescription="#string/garage_icon"
app:layout_constraintStart_toEndOf="#+id/tvGarage"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="#+id/tvAddressDetail"/>
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
tools:layout_editor_absoluteY="281dp" tools:layout_editor_absoluteX="8dp"
app:layout_constraintBottom_toTopOf="#+id/tvDescTitle"
android:layout_marginBottom="4dp"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvDescTitle"
android:text="#string/description"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="#color/colorSecondaryText"
app:layout_constraintTop_toBottomOf="#+id/imageView3"
app:layout_constraintBottom_toTopOf="#id/expandableTextView"
app:layout_constraintStart_toStartOf="parent"/>
<at.blogc.android.views.ExpandableTextView
android:text="#{buy.propertyDesc}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/expandableTextView"
android:textColor="#color/colorSecondaryText"
android:maxLines="5"
android:ellipsize="end"
app:animation_duration="750"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintTop_toBottomOf="#+id/tvDescTitle"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/buttonToggle"
style="#style/Widget.MaterialComponents.Button.OutlinedButton"
android:text="#string/more"
app:goneUnless="#{true}"
app:layout_constraintTop_toBottomOf="#+id/expandableTextView"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp"/>
<TextView
app:photoCounter="#{buy.propertyImage}"
android:background="#99000000"
android:elevation="4dp"
android:padding="4dp"
android:textColor="#ffafffff"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="#+id/ivHouseDetail"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" tools:layout_editor_absoluteY="189dp"
tools:layout_editor_absoluteX="323dp" android:id="#+id/tvPhotoCounter"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
This code is my repository class, where I use the coroutines.
class BuyRepository (private val buyDao: BuyDao, private val buyRemote: BuyRemote) {
private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.Default + job)
companion object {
//For singleton instantiation
#Volatile private var instance: BuyRepository? = null
fun getInstance(buyDao: BuyDao, buyRemote: BuyRemote) =
instance ?: synchronized(this) {
instance ?: BuyRepository(buyDao, buyRemote)
.also { instance = it}
}
}
suspend fun getBuys(){
refresh()
}
private suspend fun refresh(){
val list = scope.async {buyRemote.loadBuys()}
list.await().forEach { buy -> insert(buy) }
}
//#WorkerThread
private fun insert(buy: Buy) {
buyDao.insertBuy(buy)
}
}
// toggle the ExpandableTextView
buttonToggle.setOnClickListener { // <- Set listener here
buttonToggle.setText(if (expandableTextView.isExpanded) com.example.drake.kunuk.R.string.more else com.example.drake.kunuk.R.string.less)
expandableTextView.toggle()
}
// but, you can also do the checks yourself
buttonToggle.setOnClickListener { // <- And overwritten here - seems bad
if (expandableTextView.isExpanded) {
expandableTextView.collapse()
buttonToggle.setText(com.example.drake.kunuk.R.string.more)
} else {
expandableTextView.expand()
buttonToggle.setText(com.example.drake.kunuk.R.string.less)
}
}
Looks to me like you're overwriting the click listener. So ... don't do that :)