【问题标题】:How to send data from one fragment to another without a button click event?如何在没有按钮单击事件的情况下将数据从一个片段发送到另一个片段?
【发布时间】:2017-10-17 09:47:14
【问题描述】:

我正在用片段做一些测试来研究它。我有一个疑问。

我有一个主要活动,其工具栏只有一个项目,当单击该项目时,我添加了一个具有列表视图的片段 A。

然后我点击列表视图的一个项目,片段 A 被移除,其片段 B 被替换为片段 A。片段 B 有一个文本视图来显示片段 A 上单击项目的文本。

要将片段A中列表视图上单击项目的数据传递给片段B的文本视图,我还需要在片段B xml上添加一个按钮,当单击此按钮时,单击项目的数据是发送到片段 B 并且 textview 使用正确的单击项目文本进行更新。

但它不可能自动做到这一点?如果在 addText(String text) 方法上调用此方法“sendDataToFragmentB(View view)”,则会出现NullPointerException in FragmentB.addText(java.lang.String)。但是,如果我在 fragmentb xml 中有一个带有 onClick="sendDataTofragmentB" 的按钮,当单击该按钮时,它可以工作。

界面:

public interface Listener {
    public void addText(String text);
}

主要活动

public class MainActivity extends AppCompatActivity implements Listener {

    Toolbar toolbar;
    FragmentManager manager;
    private String text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        manager = getFragmentManager();

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        getSupportActionBar().setTitle("Pets");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        String msg = "";

        if (item.getItemId() == R.id.search) {
                msg = "search";
                AddFragmentA();
        }
        Toast.makeText(this, msg + "clicked !", Toast.LENGTH_SHORT).show();
        return super.onOptionsItemSelected(item);
    }
    @Override
    public void addText(String text) {
        this.text = text;

        Toast.makeText(this, "Text Received in Activity" + text, Toast.LENGTH_SHORT).show();
        sendDataToFragmentB();
    }
    public void sendDataToFragmentB(View view) {

            FragmentB fragmentB = (FragmentB) manager.findFragmentByTag("fragB");
            fragmentB.addText(text);

    }
}

片段 A:

public class FragmentA extends Fragment {
    private static final String TAG = FragmentA.class.getSimpleName();
    private ListView listItems;

    private String[] items = {
            "item1",
            "item2",
    };

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_a, container, false);
        listItems = (ListView) view.findViewById(R.id.listviewInFragment);

        ArrayAdapter<String> adapter =
                new ArrayAdapter<String>(getActivity().getApplicationContext(),
                        android.R.layout.simple_list_item_1, android.R.id.text1, items);
        listItems.setAdapter(adapter);

        listItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                int positionCode = i;
                String clickedValue = (String) adapterView.getItemAtPosition(i);

                Listener listener = (Listener) getActivity();
                listener.addText(clickedValue);

                Toast.makeText(getActivity().getApplicationContext(), clickedValue, Toast.LENGTH_SHORT).show();
                removeFragmentA();
                AddFragmentB();
            }

        });

        return view;
    }

    public void removeFragmentA(){
        FragmentA fragmentA = (FragmentA) getFragmentManager().findFragmentByTag("fragA");
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        if(fragmentA !=null){
            transaction.remove(fragmentA);
            transaction.commit();
        }
        else{
            Toast.makeText(this.getActivity(), "Fragment A not found", Toast.LENGTH_SHORT).show();
        }
    }
    public void AddFragmentB(){

        FragmentB fragmentB = new FragmentB();
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.add(R.id.container, fragmentB, "fragB");
        transaction.commit();
    }
}

片段 B:

public class FragmentB extends Fragment {
    private TextView txvResult;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_b, container, false);
        txvResult = (TextView) view.findViewById(R.id.txvResult);
        return view;
    }
    public void addText(String text){
        String result = text;
        txvResult.setText(result);
    }
}

【问题讨论】:

  • 虽然还有另一个问题会影响到这一点,但您至少应该尝试按照您现在的代码进行推理。在onItemClick(),看看事情的顺序。你真的想在换掉Fragments 之前打电话给listener.addText() 吗?在创建 FragmentB 实例之前?
  • 而不是一个监听器,它不会以包的形式发送数据并直接在那里访问它
  • 谢谢。捆绑包也有同样的问题。但问题在于 String text = getArguments().getString("clickedValue"); 中的 onCreateView 方法;

标签: android fragment


【解决方案1】:

简短回答:您想使用捆绑包。你可以试试这样的

public void AddFragmentB(String clickedText){


    FragmentB fragmentB = new FragmentB();

    Bundle bundle = new Bundle();
    bundle.putString(R.string.clicked_text_key, clickedText);
    fragmentB.setArguments(bundle);

    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.add(R.id.container, fragmentB, "fragB");
    transaction.commit();
}

片段B

@Nullable  
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_b, container, false);
    txvResult = (TextView) view.findViewById(R.id.txvResult);

    addText();

    return view;
}
public void addText(){
    String result = getArguments().getString(R.string.clicked_text_key);
    txvResult.setText(result);
}

见:How to transfer some data to another Fragment?

【讨论】:

  • 谢谢,但也不起作用。它在 widget.TetView.setTex() 上出现空对象引用。
  • addText() 需要在fragmentB.onCreateView()之后调用,或者可能在其中(连接txvResult之后)
  • 我编辑了答案,以便您可以看到用法——我猜您在视图膨胀之前调用了 addText,这意味着 txvResult 将为空。
【解决方案2】:

您可以在EventBus Sticky Event 中尝试使用StickyEvent。单击项目时,只需发布​​一个粘性事件,如

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));

那么添加FragmentB之后,就可以在subscribe方法中接收事件了。

【讨论】:

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