【问题标题】:passing argument to DialogFragment将参数传递给 DialogFragment
【发布时间】:2013-03-17 09:20:16
【问题描述】:

我需要将一些变量传递给DialogFragment,这样我才能执行一个操作。 Eclipse 建议我应该使用

Fragment#setArguments(Bundle)

但是我不知道如何使用这个功能。如何使用它将变量传递给我的对话框?

【问题讨论】:

标签: android android-dialogfragment


【解决方案1】:

使用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;
}

得到这样的参数

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

在此处查看完整示例
http://developer.android.com/reference/android/app/DialogFragment.html

【讨论】:

  • 你能在 MyDialogFragment 上设置私有变量而不是使用 bundle 吗?
  • @SIrCodealot 效果与在 Activity 或 Fragment 上设置变量相同。如果您遇到破坏并重新创建 DialogDragment 的事物(例如旋转更改),您将丢失所有变量。
  • 对于那些想知道为什么在这种情况下不使用重载构造函数的人,请参阅关于该主题的另一个非常有启发性的讨论:stackoverflow.com/questions/14011808/…
  • 我花了一分钟才发现 savedInstanceState 没有被使用。
【解决方案2】:

我曾经从我的列表视图中发送一些值

如何发送

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;
        }
    });

如何在DialogFragment的onCreate()方法中接收

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

// 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")

// 接收

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (getArguments() != null) {
            val mArgs = arguments
            var myDay= mArgs.getString("title")
        }
    }

【讨论】:

  • 更好的答案!
  • 谢谢! Kotlin 版本有所帮助。
  • 我对 Kotlin 版本做了同样的事情,但在接收参数时它总是为空。
【解决方案3】:

所以有两种方法可以将值从片段/活动传递到对话框片段:-

  1. 使用 make setter 方法创建对话框片段对象并传递值/参数。

  2. 通过捆绑传递值/参数。

方法一:

// 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
}

注意:- 这不是最好的方法

方法二:

// 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
}

注意:- 这是最好的方法。

【讨论】:

  • 您甚至可以使用 Gson 库将 Objects 或 ArrayList 作为字符串传递到 Bundle 中。
  • @duggu,为什么 getter 和 setter 不是最好的方法?
【解决方案4】:

正如 JafarKhQ 所指出的,作为使用 Fragments 的一般方式,您不应在构造函数中传递参数,而应使用 Bundle

Fragment 类中的内置方法是setArguments(Bundle)getArguments()

基本上,您所做的就是将您的所有 Parcelable 项目设置为一个捆绑包并将它们发送出去。
反过来,您的 Fragment 会将这些项目放入它的 onCreate 中,并对它们施展魔法。

DialogFragment 链接中显示的方式是在具有一种特定数据类型的多显示片段中执行此操作的一种方式,并且大多数时间都可以正常工作,但您也可以手动执行此操作。

【讨论】:

    【解决方案5】:

    只是我想向那些使用 kotlin 的人展示如何在 Kotlin 中执行 @JafarKhQ 所说的操作,这可能会帮助他们并节省主题时间:

    所以你必须创建一个companion objet来创建新的newInstance函数

    您可以根据需要设置函数的参数。 使用

     val args = Bundle()
    

    你可以设置你的参数。

    您现在可以使用args.putSomthing 添加您在 newInstance 函数中作为参数提供的参数。 putString(key:String,str:String) 添加字符串例如等等

    现在获取您可以使用的参数 arguments.getSomthing(Key:String)=> 喜欢arguments.getString("1")

    这是一个完整的例子

    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)
                }
            }
    
        }
      ...
    }
    

    现在如何创建你的对话框,你可以在另一个类中做这样的事情

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

    例如这样

    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)
            }
            ...
        }
    ..
    
    }
    

    【讨论】:

      【解决方案6】:

      就我而言,上面带有bundle-operate 的代码都不起作用;这是我的决定(我不知道它是否是正确的代码,但它适用于我的情况):

      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");
      
      [...]
      }
      

      【讨论】:

      • 1) 通过静态存储bodyText,您实际上不可能同时拥有该类的两个具有不同正文文本的实例。没有理由不将其存储为实例变量。 2) 使用 setArguments(Bundle) 发送参数的全部目的是操作系统可以重新创建片段,以防它在内存不足的情况下丢失等。使用您的解决方案,片段将被重新创建,正文将是使用的对话框的最后一个实例(因为它是静态的)。正确的解决方案是将正文设置为捆绑参数。
      猜你喜欢
      • 1970-01-01
      • 2019-09-27
      • 1970-01-01
      • 1970-01-01
      • 2013-01-27
      • 2013-11-19
      • 2011-01-06
      • 2013-07-19
      相关资源
      最近更新 更多