passer l'argument à DialogFragment

116

Je dois transmettre certaines variables à DialogFragment, pour pouvoir effectuer une action. Eclipse suggère que je devrais utiliser

Fragment#setArguments(Bundle)

Mais je ne sais pas comment utiliser cette fonction. Comment puis-je l'utiliser pour transmettre des variables à ma boîte de dialogue?

giozh
la source
Regardez l'exemple de code: androidxref.com/4.4.2_r1/xref/development/samples/ApiDemos/src/…
IgorGanapolsky

Réponses:

299

En utilisant newInstance

public static MyDialogFragment newInstance(int num) {
    MyDialogFragment f = new MyDialogFragment();

    // Supply num input as an argument.
    Bundle args = new Bundle();
    args.putInt("num", num);
    f.setArguments(args);

    return f;
}

Et obtenir les Args comme ça

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mNum = getArguments().getInt("num");
    ...
}

Voir l'exemple complet ici
http://developer.android.com/reference/android/app/DialogFragment.html

JafarKhQ
la source
Pouvez-vous simplement définir des variables privées sur MyDialogFragment au lieu d'utiliser bundle?
SIr Codealot
10
@SIrCodealot l'effet serait le même que la définition de variables sur Activity ou Fragment. Si vous faites face à quelque chose qui détruit et recrée le DialogDragment comme un changement de rotation, vous perdrez toutes les variables.
inmyth
2
Pour tous ceux qui se demandent pourquoi un constructeur surchargé n'est pas utilisé dans ce cas, voir une autre discussion sur le sujet qui est très instructive: stackoverflow.com/questions/14011808
...
Il m'a fallu une minute pour remarquer que le saveInstanceState n'est pas utilisé.
Odys
25

J'avais l'habitude d'envoyer des valeurs de ma liste

Comment envoyer

mListview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            Favorite clickedObj = (Favorite) parent.getItemAtPosition(position);

            Bundle args = new Bundle();
            args.putString("tar_name", clickedObj.getNameTarife());
            args.putString("fav_name", clickedObj.getName());

            FragmentManager fragmentManager = getSupportFragmentManager();
            TarifeDetayPopup userPopUp = new TarifeDetayPopup();
            userPopUp.setArguments(args);
            userPopUp.show(fragmentManager, "sam");

            return false;
        }
    });

Comment recevoir à l' intérieur de la méthode onCreate () de DialogFragment

    Bundle mArgs = getArguments();
    String nameTrife = mArgs.getString("tar_name");
    String nameFav = mArgs.getString("fav_name");
    String name = "";

// Téléchargement de Kotlin

 val fm = supportFragmentManager
        val dialogFragment = AddProgFargmentDialog() // my custom FargmentDialog
        var args: Bundle? = null
        args?.putString("title", model.title);
        dialogFragment.setArguments(args)
        dialogFragment.show(fm, "Sample Fragment")

// recevoir

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (getArguments() != null) {
            val mArgs = arguments
            var myDay= mArgs.getString("title")
        }
    }
Sam
la source
1
La meilleure réponse!
user55924
1
Je vous remercie ! La version Kotlin a aidé.
ArdenDev
6

Il y a donc deux façons de passer des valeurs d'un fragment / activité à un fragment de dialogue: -

  1. Créez un objet de fragment de dialogue avec la méthode make setter et passez la valeur / l'argument.

  2. Passez la valeur / l'argument à travers le bundle.

Méthode 1:

// Fragment or Activity 
@Override
public void onClick(View v) {
     DialogFragmentWithSetter dialog = new DialogFragmentWithSetter();
     dialog.setValue(header, body);
     dialog.show(getSupportFragmentManager(), "DialogFragmentWithSetter");         
}


//  your dialog fragment
public class MyDialogFragment extends DialogFragment {
    String header; 
    String body;
    public void setValue(String header, String body) {   
          this.header = header;
          this.body = body;
    }
    // use above variable into your dialog fragment
}

Remarque: - Ce n'est pas la meilleure façon de faire

Méthode 2:

// Fragment or Activity 
@Override
public void onClick(View v) {
     DialogFragmentWithSetter dialog = new DialogFragmentWithSetter();
     
     Bundle bundle = new Bundle();
     bundle.putString("header", "Header");
     bundle.putString("body", "Body");  
     dialog.setArguments(bundle);
     dialog.show(getSupportFragmentManager(), "DialogFragmentWithSetter");         
}


//  your dialog fragment
public class MyDialogFragment extends DialogFragment {
    String header; 
    String body;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
             header = getArguments().getString("header","");
             body = getArguments().getString("body","");
        }
    }
    // use above variable into your dialog fragment
}

Remarque: - C'est la meilleure façon de procéder.

duggu
la source
Vous pouvez même utiliser la bibliothèque Gson pour transmettre des objets ou ArrayList <Objects> en tant que chaînes dans le bundle.
Jeffrey
@duggu, pourquoi getter et setter n'est pas le meilleur moyen de le faire?
sky91
5

comme manière générale de travailler avec des fragments, comme JafarKhQ l'a noté, vous ne devez pas passer les paramètres dans le constructeur mais avec un Bundle .

la méthode intégrée pour cela dans la Fragmentclasse est setArguments(Bundle)etgetArguments() .

En gros, ce que vous faites est de créer un lot avec tous vos Parcelablearticles et de les envoyer.
à son tour, votre Fragment recevra ces objets onCreateet leur fera de la magie.

la manière indiquée dans le DialogFragmentlien était une façon de le faire dans un fragment à apparition multiple avec un type spécifique de données et fonctionne bien la plupart du temps, mais vous pouvez également le faire manuellement.

thepoosh
la source
0

Dans mon cas, aucun des codes ci-dessus ne bundle-operatefonctionne; Voici ma décision (je ne sais pas si c'est du bon code ou non, mais ça marche dans mon cas):

public class DialogMessageType extends DialogFragment {
    private static String bodyText;

    public static DialogMessageType addSomeString(String temp){
        DialogMessageType f = new DialogMessageType();
        bodyText = temp;
        return f;
    };

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final String[] choiseArray = {"sms", "email"};
        String title = "Send text via:";
        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(title).setItems(choiseArray, itemClickListener);
        builder.setCancelable(true);
        return builder.create();
    }

    DialogInterface.OnClickListener itemClickListener = new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            switch (which){
                case 0:
                    prepareToSendCoordsViaSMS(bodyText);
                    dialog.dismiss();
                    break;
                case 1:
                    prepareToSendCoordsViaEmail(bodyText);
                    dialog.dismiss();
                    break;
                default:
                    break;
            }
        }
    };
[...]
}

public class SendObjectActivity extends FragmentActivity {
[...]

DialogMessageType dialogMessageType = DialogMessageType.addSomeString(stringToSend);
dialogMessageType.show(getSupportFragmentManager(),"dialogMessageType");

[...]
}
Kirill
la source
1) En stockant le bodyText de manière statique, vous rendez effectivement impossible d'avoir deux instances de cette classe en même temps, avec des corps de texte différents. Il n'y a aucune raison de ne pas le stocker en tant que variable d'instance à la place. 2) Le but de l'envoi d'arguments à l'aide de setArguments (Bundle) est que le système d'exploitation peut alors recréer le fragment au cas où il serait perdu dans une situation de mémoire insuffisante, etc. Avec votre solution, le fragment sera recréé, et le corps du texte sera être quelle que soit la dernière instance de la boîte de dialogue utilisée (car elle est statique). La solution correcte consiste à définir le corps du texte en tant que paramètre de regroupement.
JHH
0

Juste que je veux montrer comment faire ce que dit @JafarKhQ à Kotlin pour ceux qui utilisent kotlin qui pourrait les aider et gagner du temps sur le thème aussi:

vous devez donc créer un objet compagnon pour créer une nouvelle fonction newInstance

vous pouvez définir le paramètre de la fonction comme vous le souhaitez. en utilisant

 val args = Bundle()

vous pouvez définir vos arguments.

Vous pouvez maintenant utiliser args.putSomthingpour vous ajouter des arguments que vous donnez comme préamètre dans votre fonction newInstance. putString(key:String,str:String)pour ajouter une chaîne par exemple et ainsi de suite

Maintenant, pour obtenir l'argument, vous pouvez utiliser arguments.getSomthing(Key:String)=> commearguments.getString("1")

voici un exemple complet

class IntervModifFragment : DialogFragment(), ModContract.View
{
    companion object {
        fun newInstance(  plom:String,type:String,position: Int):IntervModifFragment {
            val fragment =IntervModifFragment()
            val args = Bundle()
            args.putString( "1",plom)
            args.putString("2",type)
            args.putInt("3",position)
            fragment.arguments = args
            return fragment
        }
    }

...
    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        fillSpinerPlom(view,arguments.getString("1"))
         fillSpinerType(view, arguments.getString("2"))
        confirmer_virme.setOnClickListener({on_confirmClick( arguments.getInt("3"))})


        val dateSetListener = object : DatePickerDialog.OnDateSetListener {
            override fun onDateSet(view: DatePicker, year: Int, monthOfYear: Int,
                                   dayOfMonth: Int) {
                val datep= DateT(year,monthOfYear,dayOfMonth)
                updateDateInView(datep.date)
            }
        }

    }
  ...
}

Maintenant, comment créer votre boîte de dialogue, vous pouvez faire quelque chose comme ça dans une autre classe

  val dialog = IntervModifFragment.newInstance(ListInter.list[position].plom,ListInter.list[position].type,position)

comme ça par exemple

class InterListAdapter(private val context: Context, linkedList: LinkedList<InterItem> ) : RecyclerView.Adapter<InterListAdapter.ViewHolder>()
{
   ... 
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        ...
        holder.btn_update!!.setOnClickListener {
           val dialog = IntervModifFragment.newInstance(ListInter.list[position].plom,ListInter.list[position].type,position)
           val ft = (context as AppCompatActivity).supportFragmentManager.beginTransaction()
            dialog.show(ft, ContentValues.TAG)
        }
        ...
    }
..

}
DINA TAKLIT
la source