How to use data-binding in Dialog?

AndroidMvvmData BindingAndroid Databinding

Android Problem Overview


I am having trouble in implementing databinding in a Dialog. Is it possible?

Below is my xml.

http://schemas.android.com/apk/res/android">

<data>

    <variable
        name="olaBooking"
        type="com.example.myapp.viewmodels.ViewModel" />
</data>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.CardView
        android:id="@+id/cv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:elevation="4dp"
        android:padding="15dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:padding="15dp"
                android:text="OLA Cab Booked !"
                android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

            <View
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:background="@color/colorPrimaryDark" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="start|center"
                android:padding="15dp"
                android:text="Car Details" />

            <View
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:background="@color/colorPrimaryDark" />

            <TextView
                android:id="@+id/driverName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="@{olaBooking.driverName}" />

            <TextView
                android:id="@+id/carModel"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="@{olaBooking.getCarName}" />

            <TextView
                android:id="@+id/carNo"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="@{olaBooking.getCabNo}" />

            <TextView
                android:id="@+id/eta"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="@{olaBooking.getEta}" />
        </LinearLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

I want to bind the above layout in a Dialog. How is it possible? Below is my java code i tried but it's not working

        dialog.setContentView(R.layout.dialog_ola_booking_confirmed);
    DialogOlaBookingConfirmedBinding binding = DataBindingUtil.inflate(
            LayoutInflater.from(dialog.getContext()),
            R.layout.dialog_ola_booking_confirmed,
            (ViewGroup) dialog.findViewById(R.id.cv),
            false);
    ViewModel viewModel = new ViewModel(this, event.olaBooking);

Android Solutions


Solution 1 - Android

It is possible to use databinding in a Dialog, first to get the binding working on your Dialog you should inflate it first and pass it to the setContentView like this.

DialogOlaBookingConfirmedBinding binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout. dialog_ola_booking_confirmed, null, false);
setContentView(binding.getRoot());

Then you can pass the viewModel:

binding.setViewModel(new ViewModel(this, event.olaBooking));

And now you can see it working.

Solution 2 - Android

Here is a full example of an AlertDialog with Databinding:

import android.app.Dialog;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;


public class MyDialog extends DialogFragment {

    private static final String KEY_MY_INFO = "KEY_MY_INFO";

    private String myInfo;

    public static MyDialog newInstance(String myInfo) {
        MyDialog dialog = new MyDialog();
        Bundle bundle = new Bundle();
        bundle.putString(KEY_MY_INFO, myInfo);
        dialog.setArguments(bundle);
        return dialog;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myInfo = getArguments().getString(KEY_MY_INFO);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        FragmentActivity activity = getActivity();
        
        MyInfoBinding binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()),
                R.layout.my_info_dialog_layout, null, false);

        binding.setMyInfo(myInfo);

        return new AlertDialog.Builder(activity, R.style.AppCompatAlertDialogStyle)
                .setView(binding.getRoot())
                .create();
    }

}

Solution 3 - Android

You should not use DataBindingUtil for generated classes as said in Android Documentation

You should use generated binding class's inflate & bind method ( MyDialogBinding.inflate).

public void showDialog(final Context context) {
    Dialog dialog = new Dialog(context);
    MyDialogBinding binding = MyDialogBinding.inflate(LayoutInflater.from(context));
    dialog.setContentView(binding.getRoot());
    dialog.show();
}

###Can it be simpler? No!

Binding Document says for DataBindingUtil class's inflate method.

> Use this version only if layoutId is unknown in advance. Otherwise, > use the generated Binding's inflate method to ensure type-safe > inflation. DataBindingUtil.inflate(LayoutInflater.from(getContext()),R.layout.my_info_dialog_layout, null, false);

This is like finding binding generated class, when we have class already.

Instead use this
MyDialogBinding binding = MyDialogBinding.inflate(LayoutInflater.from(context));
    

or if you want make another class.

public class MyDialog extends Dialog {
    public MyDialog(@NonNull Context context) {
        super(context);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyDialogBinding binding = MyDialogBinding.inflate(LayoutInflater.from(getContext()));
        setContentView(binding.getRoot());
    }
}

Solution 4 - Android

You can do the same without calling getRoot().

View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_delete_confirmation, null, false);

mBinding = DialogDeleteConfirmationBinding.bind(view);

mBinding.setViewModel(viewModel);

builder.setView(view);

builder.create();

Solution 5 - Android

  mBinding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.dialog_select, null, false);
    setContentView(mBinding.getRoot());
    SelectDialogBean data = new SelectDialogBean();
    mBinding.setData(data);

Solution 6 - Android

If you don't want to extend Dialog, another possible solution could be:

Dialog dialog = new Dialog(this); // where "this" is the context

YourClassNameBinding binding = DataBindingUtil.inflate(dialog.getLayoutInflater(), R.layout.your_layout, null, false);
binding.setYourData(yourData);

dialog.setContentView(binding.getRoot());
dialog.show();

Hope it helps.

Solution 7 - Android

**

You should use activity inside of context for DialogFragment.

**

The problem when you use databinding in DialogFragment is theme is not respect to dark mode colors. If you have problem with this use LayoutInflater.from(activity) inside of LayoutInflater.from(context)

Solution 8 - Android

If your dialog shrink, Try this

I tried @Dullahan's answer, however the dialog seemed to shrink strangely. So I tried another ways, finally found solution.

<layout
    xmlns:android="http://schemas.android.com/apk/res/android">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/root"
        android:layout_width="300dp"
        android:layout_height="500dp">

        <!-- ... -->

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
class CustomDialog(context: Context) : Dialog(context) {
    private lateinit var binding: CustomDialogBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.custom_dialog)
        binding = CustomDialogBinding.bind(findViewById(R.id.root))
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNidhin RejoiceView Question on Stackoverflow
Solution 1 - AndroidRecaldevView Answer on Stackoverflow
Solution 2 - AndroidJoachimRView Answer on Stackoverflow
Solution 3 - AndroidKhemraj SharmaView Answer on Stackoverflow
Solution 4 - AndroidfarhanjkView Answer on Stackoverflow
Solution 5 - AndroidWangDaFuView Answer on Stackoverflow
Solution 6 - Androiduser10504386View Answer on Stackoverflow
Solution 7 - AndroidUmutTekinView Answer on Stackoverflow
Solution 8 - AndroidgalcyurioView Answer on Stackoverflow