How to create an interface to get info from a Frag

2020-06-25 04:57发布

Over the past days I've desperately been trying to build an android app with a simple fragment (which I use twice). I want to pass the contents of the fragments' EditText-boxes to a new activity. I just can't figure out how to get those contents from the fragments. What I have so far is this:

I've got my edit_text_fragment.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <EditText 
        android:id="@+id/my_edit_text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="my hint" />
</LinearLayout>

and the corresponding MyEditTextFragment.java:

public class MyEditTextFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.edit_text_fragment, container, false);
        return view;
    }
}

I then use this fragment twice in my main.xml like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <fragment 
        android:id="@+id/detailfragment_placeholder"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        class="com.example.fragmenttester5.MyEditTextFragment" />
    <fragment 
        android:id="@+id/detailfragment_placeholder2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        class="com.example.fragmenttester5.MyEditTextFragment" />
    <Button 
        android:id="@+id/submit_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Submit all of it" />
</LinearLayout>

and in my MainActivity I hooked up the button to a new activity:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button submitButton = (Button) findViewById(R.id.submit_button);
        submitButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v){
                Intent intent = new Intent(MainActivity.this, OtherActivity.class);
                intent.putExtra("result1", "the_result_from_the_first_editText");
                intent.putExtra("result2", "the_result_from_the_second_editText");
                startActivity(intent);
            }
        });
    }
}

I think I now need to define some kind of interface in the Fragment, but I can't find how. I read a couple examples and tutorials (like this one), but they make no sense to me at all. I don't understand the code given and I just don't understand how to adjust it for my use case.

So my question; can anybody help me to get the contents of the fragment from within the activity? Examples would be very very welcome since I'm just banging my head against the wall here..

4条回答
看我几分像从前
2楼-- · 2020-06-25 05:08

You are right, that's kind of a standard way to pass data from a Fragment to an activity.

Basically you define a Listener interface which the Activity implements, and the Activity registers itself as a Listener with the Fragment.

Here's a simple example:

Fragment

class MyFragment extends Fragment {

    interface Listener {
        public void somethingHappenedInFragment(Object... anyDataYouWantToPassToActivity);
    }

    private Listener mListener;

    public void setListener(Listener listener) {
        mListener = listener;
    }

    // ... your code ...

    // Now here you pass the data to the activity
    mListener.somethingHappenedInFragment(some, data);

    // ... more of your code
 }

Activity

public MyActivity extends Activity implements MyFragment.Listener {

    // ... your code ...

    // creating the Fragment
    MyFragment f = new MyFragment();

    // register activity as listener
    f.setListener(this);

    // ... more of your code

    // implementation of MyFragment.Listener interface
    @Override
    public void somethingHappenedInFragment(Object... anyDataYouWantToPassToActivity) {
        // here you have the data passed from the fragment.
        for (Object o : anyDataYouWantToPassToActivity {
            System.out.println(o.toString();
        }
    }

}
查看更多
霸刀☆藐视天下
3楼-- · 2020-06-25 05:12

Activity will be received data from updateDetail() method in Fragment

//// Activity 
public class RssfeedActivity extends Activity implements MyListFragment.OnItemSelectedListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rssfeed);
        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Log.d("Annv - Fragment", "onClick here");
            }
        });
    }

    // if the wizard generated an onCreateOptionsMenu you can delete
    // it, not needed for this tutorial

    @Override
    public void onRssItemSelected(String link) {
        //        DetailFragment fragment = (DetailFragment) getFragmentManager()
        //                .findFragmentById(R.id.detailFragment);
        //        if (fragment != null && fragment.isInLayout()) {
        //          fragment.setText(link);
        //        } 
        //        Intent start = new Intent(this, RssfeedSecondActivity.class);
        //        startActivity(start);
        DetailFragment fragment = (DetailFragment) getFragmentManager()
                .findFragmentById(R.id.detailFragment);
        if (fragment != null && fragment.isInLayout()) {
            fragment.setText(link);
        }
    }

}
/// Fragment
public class MyListFragment extends Fragment {

    private OnItemSelectedListener listener;
    private OnItemStartActivityListener listenerStartAct;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_rsslist_overview,
                container, false);
        Button button = (Button) view.findViewById(R.id.button1);
        Log.d("Annv - Fragment", "run on " + getActivity().toString());
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                updateDetail();
            }
        });
        return view;
    }

    public interface OnItemSelectedListener {
        public void onRssItemSelected(String link);
    }

    public interface OnItemStartActivityListener {
        public void onRssStartActivity(String link);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof OnItemSelectedListener) {
            Log.d("Annv - Fragment", "activity " + activity.getLocalClassName());
            listener = (OnItemSelectedListener) activity;
        } else if (activity instanceof OnItemStartActivityListener) {
            Log.d("Annv - Fragment", "activity " + activity.getLocalClassName());
            listenerStartAct = (OnItemStartActivityListener) activity;
        } else {
            throw new ClassCastException(activity.toString()
                    + " must implemenet MyListFragment.OnItemSelectedListener");
        }
    }

    // May also be triggered from the Activity
    public void updateDetail() {
        // create fake data
        //        String newTime = String.valueOf(System.currentTimeMillis());
        //        // Send data to Activity
        //        listenerStartAct.onRssItemSelected(newTime);
        if (getActivity() instanceof OnItemSelectedListener) {
            listener.onRssItemSelected("start start");
        } else {
            String newTime = String.valueOf(System.currentTimeMillis());
            listenerStartAct.onRssStartActivity(newTime);
        }

    }

}
查看更多
虎瘦雄心在
4楼-- · 2020-06-25 05:18

On a high level, there are two tasks that you commonly need to solve with Fragments. The first is communicating data from an Activity to a Fragment. The second is communicating data from a Fragment to an Activity.

An Activity knows which Fragments it contains since it creates them, so it's easy to communicate that way - just call methods on the Fragment itself. But the inverse is not true; Fragments might be attached to any number of random Activities, so it doesn't know anything about it's parent.

The solution is to implement an interface that the Activity implements and the Fragment knows how to communicate with. That way, your Fragment has something it knows how to talk with. There are specific code examples for how to do it here: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

(In particular, check out the "Creating event callbacks to the activity" code examples).

查看更多
聊天终结者
5楼-- · 2020-06-25 05:35

So you'd create an Interface to talk with the Activity if the event happened in the Fragment. For situations like this, you can simply make an accessible method in the Fragment that the Activity can call. So

public class MyEditTextFragment extends Fragment {
    private EditText mEditText;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.edit_text_fragment, container, false);
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mEditText = (EditText) getView().findViewById(R.id.my_edit_text);
    }

    public Editable getText() {
        return mEditText.getText();
    }
}

Then

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final MyEditTextFragment fragment1 = (MyEditTextFragment)
            getFragmentManager().findFragmentById(R.id.detailfragment_placeholder);

        final MyEditTextFragment fragment2 = (MyEditTextFragment)
            getFragmentManager().findFragmentById(R.id.detailfragment_placeholder2);

        Button submitButton = (Button) findViewById(R.id.submit_button);
        submitButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v){

                String firstResult = fragment1.getText().toString();
                String secondResult = fragment2.getText().toString();

                Intent intent = new Intent(MainActivity.this, OtherActivity.class);
                intent.putExtra("result1", firstResult);
                intent.putExtra("result2", secondResult);
                startActivity(intent);
            }
        });
    }
}

This assumes that you assigned the Fragment tags in your FragmentTransaction. Be sure to check for null Fragments (omitted for brevity)

查看更多
登录 后发表回答