I'm trying to use recycler view in an AlertDialog.
I want the recycler view to occupy 100% of AlertDialog width.
I use this xml code
<?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="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/TV_DownloadablesDialogTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/file_downloads"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/RV_DownloadablesDialogRecycler"
android:layout_width="0dp"
android:layout_height="250dp"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/TV_DownloadablesDialogTitle"
tools:listitem="@layout/downloadables_dialog_item_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
in android studio preview it looks like this
but at runtime it actually looks like this.
Notice how the TextView
is responsive to the constraint layout but the RecyclerView
isn't.
here is how I show the AlertDialog.
private void showDownloadablesDialog(LinkedList<Downloadable> downloadableList) {
View downloadablesDialogView = getLayoutInflater().inflate(R.layout.downloadables_dialog, null, false);
RecyclerView downloadablesRecycler = downloadablesDialogView.findViewById(R.id.RV_DownloadablesDialogRecycler);
DownloadablesDialogAdapter adapter = new DownloadablesDialogAdapter(this, downloadableList);
downloadablesRecycler.setAdapter(adapter);
downloadablesRecycler.setLayoutManager(new LinearLayoutManager(this));
new AlertDialog.Builder(this)
.setView(downloadablesDialogView)
.setPositiveButton(R.string.ok, (dialogView, which) -> {
})
.create()
.show();
}
This previous code is executed inside the Activity class.
I tried changing android:layout_width
to match_parent
but I got the same results.
but When I set it to a fixed width it work but I don't want to use fixed width as it will not make the app responsive on different screen sizes.
EDIT: I noticed when I clicked on the Remove Button it fixed itself somehow.
here is the logic of the remove button inside onBindViewHolder()
in the recycler adapter
holder.BFileRemove.setOnClickListener((button) -> {
Intent intent = new Intent(context, NetworkService.class);
intent.setAction(NetworkService.ACTION_MODIFY_DOWNLOADABLE);
intent.putExtra(NetworkService.EXTRA_MODIFY_TYPE, NetworkService.VALUE_MODIFY_DELETE);
intent.putExtra(NetworkService.EXTRA_MODIFY_DELETE_UUID, downloadables.get(holder.downloadableIndex).uuid);
downloadables.remove(holder.downloadableIndex);
notifyItemRemoved(holder.downloadableIndex);
context.startService(intent);
});
It seems that the problem might be in initial layout calculation. Even though the RecyclerView's width is set to 0dp with constraints, allowing it to expand within the AlertDialog, the layout pass might not be considering these constraints correctly.
Use below code to auto adjust the width of recycler view:
private void showDownloadablesDialog(LinkedList<Downloadable> downloadableList) {
View downloadablesDialogView = getLayoutInflater().inflate(R.layout.downloadables_dialog, null, false);
RecyclerView downloadablesRecycler = downloadablesDialogView.findViewById(R.id.RV_DownloadablesDialogRecycler);
DownloadablesDialogAdapter adapter = new DownloadablesDialogAdapter(this, downloadableList);
downloadablesRecycler.setAdapter(adapter);
downloadablesRecycler.setLayoutManager(new LinearLayoutManager(this));
AlertDialog alertDialog = new AlertDialog.Builder(this)
.setView(downloadablesDialogView)
.setPositiveButton(R.string.ok, (dialogView, which) -> {})
.create();
alertDialog.setOnShowListener(dialogInterface -> {
Window window = alertDialog.getWindow();
if (window != null) {
View decorView = window.getDecorView();
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
ViewGroup.LayoutParams layoutParams = downloadablesRecycler.getLayoutParams();
layoutParams.width = decorView.getWidth();
downloadablesRecycler.setLayoutParams(layoutParams);
}
});
}
});
alertDialog.show();
}