如何从DialogFragment获取数据到片段?

时间:2013-08-02 20:13:24

标签: android dialog android-fragments

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

6 个答案:

答案 0 :(得分:74)

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)将使用我们刚刚定义的片段来发送数据:

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的{​​{1}}的字符串。只需在DialogFragment匿名类中使用sendResult(int)方法,以便在需要时发送文本。

答案 1 :(得分:3)

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

使用layout xml文件制作用户界面。

然后创建一个扩展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按钮上单击调用接口方法,如

     @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;

}

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

答案 2 :(得分:2)

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

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

    mf.iWantNewData(data);
}

答案 3 :(得分:0)

根据Android Developers ...

,你想要什么

答案 4 :(得分:0)

此方法确保调用片段实现对话框的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);
            }
        });
        .....
    }
}

答案 5 :(得分:0)

一种更好,更简单的方法是使用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);
    }
}

在选择播放器的片段中,我在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();
        }
    });