When I am trying to remove the snackbar's parent layout and recreate the snackbar with the same layout, the value of textView comes out blank.
I have also tried debugging the same, while using the debugger I am getting the text string but it is not displayed in the snackbar at runtime.
Here is the XML file of my custom SnackBar :
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/dr_toast_round_corners_10dp_red"
android:id="@+id/toast_container">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_error_red"
android:padding="@dimen/dimen_4dp"
android:layout_marginStart="@dimen/dimen_16dp"
android:layout_marginVertical="@dimen/dimen_12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_invalid_credentials"
android:layout_width="@dimen/dimen_0dp"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/dimen_16dp"
android:fontFamily="@font/inter_regular"
tools:text="@string/invalid_credentials_login"
android:textColor="@color/text_body_light"
android:textSize="@dimen/dimen_13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/iv_close"
app:layout_constraintStart_toEndOf="@+id/iv_error"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_close"
android:padding="@dimen/dimen_4dp"
android:layout_marginEnd="@dimen/dimen_24dp"
android:layout_marginVertical="@dimen/dimen_12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
And here is the SnackBar's code :
fun showCustomErrorSnackbar(view: ViewGroup, activity: Activity, message: String) {
snackbar = Snackbar.make(view, "", Snackbar.LENGTH_INDEFINITE)
snackbar.duration = 2000
val customLayout =
activity.layoutInflater.inflate(
R.layout.layout_custom_toast,
activity.findViewById(R.id.toast_container)
)
snackbar.view.setBackgroundColor(Color.TRANSPARENT)
val textview = customLayout.findViewById<AppCompatTextView>(R.id.tv_invalid_credentials)
textview.text = message
// now change the layout of the snackbar
val snackbarLayout = snackbar.view as Snackbar.SnackbarLayout
snackbarLayout.removeAllViewsInLayout()
// set padding of the all corners as 0
customLayout.setPadding(0, 0, 0, 0)
val layoutParameters = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
)
layoutParameters.gravity = Gravity.CENTER_HORIZONTAL
layoutParameters.setMargins(24, 16, 24, 0) //left = 24, top = 16, right = 24, bottom = 0
snackbarLayout.layoutParams = layoutParameters
val closeSnackbar = customLayout.findViewById<AppCompatImageView>(R.id.iv_close)
closeSnackbar.setOnClickListener {
snackbar.dismiss()
}
val parent = customLayout.parent as? ViewGroup
parent?.removeView(customLayout)
snackbarLayout.addView(customLayout, 0)
snackbar.show()
}
For the first time the snackbar is shown like this :
But soon after it is displayed like this :
Can anyone help me in solving this?
I want the snackbar to perform perfectly without skipping the texts or the layout. And Also I want to close the snackbar at the cross button click listener.
I have tried the code snippet you shared. A few refactorings and it was working perfectly for me. Below is the code that worked for me.
fun showCustomErrorSnackbar(
view: View,
message: String,
isFragmentView: Boolean
) {
if (!::customLayout.isInitialized) {
customLayout = layoutInflater.inflate(
R.layout.layout_custom_toast,
requireActivity().findViewById(R.id.toast_container)
)
}
val snackbar = Snackbar.make(view, "", Snackbar.LENGTH_INDEFINITE).apply { duration = 1500 }
(customLayout.parent as? ViewGroup)?.removeView(customLayout)
snackbar.view.setBackgroundColor(Color.TRANSPARENT)
customLayout.findViewById<AppCompatTextView>(R.id.tv_invalid_credentials).text = message
customLayout.findViewById<AppCompatImageView>(R.id.iv_close)
.setOnClickListener { snackbar.dismiss() }
val snackbarLayout = snackbar.view as Snackbar.SnackbarLayout
snackbarLayout.setPadding(0, 0, 0, 0)
(snackbarLayout.layoutParams as FrameLayout.LayoutParams).apply {
width = ViewGroup.LayoutParams.MATCH_PARENT
gravity = Gravity.TOP
}
val layoutParameters = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
).apply {
gravity = Gravity.CENTER_HORIZONTAL
setMargins(24, if (isFragmentView) 16 else 128, 24, 0)
}
customLayout.layoutParams = layoutParameters
snackbarLayout.addView(customLayout, 0)
snackbar.show()
}
Only a small refactoring is required in your code, instead of removing the view at the bottom before showing the snackbar. Try removing it at the top, once you initialize the snackbar using the Snackbar.make()
method.