【问题标题】:How to get data from DialogFragment to a Fragment?如何从 DialogFragment 获取数据到 Fragment?
【发布时间】:2013-08-04 05:27:55
【问题描述】:

想象一下,我有 FragmentA,我从中 startDialogFragment(框中有 EditText)。如何从EditText 取回值到FragmentA?我尝试制作thisthis 之类的东西,但没有成功。

【问题讨论】:

标签: android dialog android-fragments


【解决方案1】:

Fragment.onActivityResult() 方法在这种情况下很有用。它需要getTargetRequestCode(),这是您在片段之间设置的代码,以便可以识别它们。此外,它需要一个请求代码,如果代码运行良好,通常只需0,然后是一个Intent,您也可以附加一个字符串,像这样

Intent intent = new Intent();
intent.putExtra("STRING_RESULT", str);

另外,setTargetFragment(Fragment, requestCode) 应该用在发送结果的片段中以识别它。总体而言,请求片段中的代码如下所示:

FragmentManager fm = getActivity().getSupportFragmentManager();
DialogFragment dialogFragment = new DialogFragment();
dialogFragment.setTargetFragment(this, REQUEST_CODE);
dialogFragment.show();

发送数据的类(DialogFragment)会使用我们刚刚定义的这个Fragment来发送数据:

private void sendResult(int REQUEST_CODE) {
    Intent intent = new Intent();
    intent.putStringExtra(EDIT_TEXT_BUNDLE_KEY, editTextString);
    getTargetFragment().onActivityResult(
        getTargetRequestCode(), REQUEST_CODE, intent);
}

为了接收数据,我们在最初启动 DialogFragment 的 Fragment 中使用这种类型的类:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Make sure fragment codes match up 
    if (requestCode == DialogFragment.REQUEST_CODE) {
        String editTextString = data.getStringExtra(
            DialogFragment.EDIT_TEXT_BUNDLE_KEY);

此时,您的EditText 中的字符串来自父片段中的DialogFragment。只需在 TextChangeListener() 匿名类中使用 sendResult(int) 方法,以便在需要时发送文本。

【讨论】:

  • 谢谢,很有用
  • 您好,感谢您提供此解决方案...您能帮帮我吗?为什么我的 onActivityResult() 方法无法从我的对话框片段中捕获结果?当我有相同的代码时......提前致谢!
  • 这是将结果传回片段的正确方法!谢谢你的例子!
  • 代码中的小修正(我们必须使用Activity.RESULT_OK):getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);解雇();
【解决方案2】:

假设您正在将一些文件上传到服务器,点击上传按钮后,应打开一个对话框,提示输入标题和可选标签。对话框本身包含 2 个按钮,表示取消并继续。

使用布局 xml 文件根据需要制作 UI。

然后创建一个扩展 DialogFragment 的类。在 onCreateView() 方法中膨胀布局并初始化视图。

在该类中创建一个接口

 public interface uploadDialogInterface

   {
       public void senddata(String title, String tag);
   }

    uploadDialogInterface interfaceObj;
    String title="";
    String tag=" ";

重要的是你需要重写 onAttach() 方法

 @Override
public void onAttach(Context context) {
    super.onAttach(context);
    this.context=context;
    interfaceObj= (uploadDialogInterface) getTargetFragment();
}

并在on Button点击调用接口方法之类的

     @Override
public void onClick(View v) {
    int id=v.getId();
    if(id== R.id.vB_fud_cancel)
    {
        dismiss();
    }
    else if(id== R.id.vB_fud_upload)
    {
        title=mVideotitle.getText().toString();
        tag=mOptionaltag.getText().toString();
        if(mVideotitle.getText().toString().isEmpty()) {
            Snackbar.make(mVideotitle,"Please enter the video title", Snackbar.LENGTH_SHORT).show();
       }else
        {
            interfaceObj.senddata(title,tag);
            dismiss();

        }
    }
}

并且在您启动对话框的 Fragment 或 Activity 内部应该包含 setTargetFragment 属性。

private void callUploadDialog()
{
    UploadDialogFragment fragment = new UploadDialogFragment();
    fragment.setTargetFragment(this, 0);
    FragmentManager manager = getFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();
    ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_in);
    fragment.show(ft, "UploadDialogFragment");
    fragment.setCancelable(false);
}

最后你应该实现接口(在对话框片段中声明)并覆盖方法

@Override
public void senddata(String title,String optionaltag) {
    this.videoTitle=title;
    this.optionalTag=optionaltag;

}

我认为这篇文章对那些第一次使用对话框片段的人会有所帮助。我很难找到解决方案。希望这将在未来解决某人的问题。 (对不起语言)

【讨论】:

  • 如果在打开对话框后旋转?这不会使该接口对象引用旧片段(旋转之前的片段吗?)。不要以为这样就行了
【解决方案3】:

使用 Android ViewModel 是一种更好、更简单的方法。

这有助于更轻松地共享数据,而无需跨片段发送任何数据。您不仅可以对 DialogFragments 执行此操作,还可以对普通 Fragments 执行此操作。

来源:https://developer.android.com/topic/libraries/architecture/viewmodel

这就是我所做的

我的 ViewModel 如下所示

import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;

public class PlayerViewModel extends ViewModel {
    private final MutableLiveData<Player> selectedPlayer = new MutableLiveData<>();

    public LiveData<Player> getSelectedPlayer() {
        return selectedPlayer;
    }

    public void selectPlayer(Player player) {
        selectedPlayer.setValue(player);
    }
}

在我选择播放器的Fragment中,我在onCreate方法中使用如下代码来绑定ViewModel

playerViewModel = ViewModelProviders.of(getActivity()).get(PlayerViewModel.class);

当一个特定的玩家被选中时,使用下面的(你可以使用一个 ArrayAdapter、DialogFragment 的选择器或者任何你想显示玩家列表的东西)

playerViewModel = ViewModelProviders.of(getActivity()).get(PlayerViewModel.class);

最后,在需要显示播放器信息的片段中,在 onCreate 方法中执行以下操作

PlayerViewModel model = ViewModelProviders.of(getActivity()).get(PlayerViewModel.class);
model.getSelectedPlayer().observe(this, new Observer<Player>() {
    @Override
    public void onChanged(@Nullable Player selPlayer) {
        if (selPlayer != null)
            player = selPlayer;
            populateData();
        }
    });

【讨论】:

【解决方案4】:

您需要通过回调方法将对话框中的数据发送回 Activity,然后让 Activity 将该数据返回给您希望它转到的片段。只是一个简单的例子:

public void datFromDialog(String data){
    MyFragment mf = (MyFragment)getFragmentManager().findFragmentById(r.id.frag);

    mf.iWantNewData(data);
}

【讨论】:

  • 拜托,你能解释得更清楚或更完整吗
  • 你不直接在片段之间进行通信,活动是假设做片段之间的所有通信。片段不应该知道存在任何其他片段。所以基本上它是这样工作的。在片段中单击一个按钮,该按钮向活动发送回调以启动对话框。对话框已启动,任何需要完成的操作都已完成,然后单击另一个按钮将数据发送回活动,在该活动中,活动将使用新数据更新另一个片段
  • @tyczj 如何为 childfragment 做同样的事情?哪个没有id?
【解决方案5】:

你想要什么,根据Android Developers...

【讨论】:

    【解决方案6】:

    此方法确保调用片段实现对话框的onChangeListener。

    FragmentA(调用片段):

    MyDialogFragment f = new MyDialogFragment();
    Bundle args = new Bundle();
    args.putString("data", data);
    f.setArguments(args);
    // Set the calling fragment for this dialog.
    f.setTargetFragment(FragmentA.this, 0);
    f.show(getActivity().getSupportFragmentManager(), "MyDialogFragment");
    

    MyDialogFragment:

    import android.support.v4.app.DialogFragment;
    
    public class MyDialogFragment extends DialogFragment {
        public OnChangeListener onChangeListener;
    
        interface OnChangeListener{
            void onChange(Data data);
        }
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // Get the calling fragment and ensure that it implements onChangeListener.
            try {
                onChangeListener = (OnChangeListener) getTargetFragment();
            } catch (ClassCastException e) {
                throw new ClassCastException(
                    "The calling Fragment must implement MyDialogFragment.onChangeListener");
            }
        }
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            .....
            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // Send the data to the calling fragment.
                    onChangeListener.onChange(data);
                }
            });
            .....
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多