Tengo una activity - MainActivity. Dentro de este Activity tengo dos fragments, ambos de los cuales he creado de forma declarativa en el xml.

Estoy tratando de pasar el String de entrada de texto por el usuario en Fragment A a la vista de texto en Fragment B. Sin embargo, esto está demostrando ser muy difícil. ¿Alguien sabe como puedo lograr esto?

Soy consciente de que un fragmento se puede obtener una referencia a la actividad usando getActivity(). Así que supongo que me gustaría empezar por ahí?

InformationsquelleAutor Javacadabra | 2012-12-04

10 Comentarios

  1. 108

    Tienen un aspecto en el que los desarrolladores de Android de la página:
    http://developer.android.com/training/basics/fragments/communicating.html#DefineInterface

    Básicamente, definir una interfaz en su Fragmento de Una, y deje que su Actividad implementar la Interfaz. Ahora usted puede llamar a la interfaz de método en su Fragmento, y su Actividad va a recibir el evento. Ahora en su actividad, usted puede llamar a su segundo Fragmento de actualizar el textview con el valor recibido

    Su Actividad implementa la interfaz (Ver FragmentA a continuación)

    public class YourActivity implements FragmentA.TextClicked{
        @Override
        public void sendText(String text){
            //Get Fragment B
            FraB frag = (FragB)
                getSupportFragmentManager().findFragmentById(R.id.fragment_b);
            frag.updateText(text);
        }
    }

    Fragmento de Un define una Interfaz, y se llama al método cuando sea necesario

    public class FragA extends Fragment{
    
        TextClicked mCallback;
    
        public interface TextClicked{
            public void sendText(String text);
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
    
            //This makes sure that the container activity has implemented
            //the callback interface. If not, it throws an exception
            try {
                mCallback = (TextClicked) activity;
            } catch (ClassCastException e) {
                throw new ClassCastException(activity.toString()
                    + " must implement TextClicked");
            }
        }
    
        public void someMethod(){
            mCallback.sendText("YOUR TEXT");
        }
    
        @Override
        public void onDetach() {
            mCallback = null; //=> avoid leaking, thanks @Deepscorn
            super.onDetach();
        }
    }

    Fragmento B tiene un método público para hacer algo con el texto

    public class FragB extends Fragment{
    
        public void updateText(String text){
            //Here you have it
        }
    }
    • Cómo sobre este caso, el fragmento de un enviado de cadena para el fragmento b y el fragmento b enviar algún resultado a fragmento, ambos fragmento se debe comunicar dentro de la actividad?
    • cuando yo uso getactivity en el fragmento B i obtener una Excepción de Puntero Nulo. Incluso textview es nulo en FragB. Alguna sugerencia?
    • en el caso de que usted probablemente todavía no se ha agregado Fragmento de la B a la actividad. Usted puede hacer esto mediante la inclusión en su actividad el archivo de diseño, o mediante el uso de la FragmentManager en la actividad, y añadir allí. Buena suerte
    • m obteniendo el valor en FragB y el valor se borra en onCreateView por favor ayuda
    • Tengo una duda. En lugar de implementar una interfaz que ¿por qué no llamar directamente a un método de host de la Actividad?
    • El Android link de Google es un ruso enlace.. dada la complejidad de la inter-fragmento de la comunicación, parece poético…
    • usted puede cambiar el idioma en la parte inferior derecha de la página 😉
    • genial.. gracias..no sé cómo acabé con el ruso..
    • de la implementación de una interfaz de ¿por qué no llamar directamente a un método de host de la Actividad». Porque cuando se utiliza la interfaz de tu código va a ser más genérico (por lo tanto, usted no debe actualizar el código de FragmentA si algunas otras necesidades de la actividad a marshall evento en el futuro)
    • por su respuesta, pero se fuga de la actividad aquí. No olvides: onDetach() { mCallback = null; }
    • No se puede ser más fácil, simplemente la creación de un método en FragmentA? (Tal vez si los datos no cambian en absoluto, o simplemente poner un bucle infinito)

  2. 23

    Algunos de los otros ejemplos (e incluso la documentación en el momento de escribir este artículo), el uso anticuado onAttach métodos. Aquí es un actualizado y completo ejemplo.

    La Comunicación básica entre los dos fragmentos

    Notas

    • Usted no quiere que los Fragmentos de hablar directamente el uno al otro o a la Actividad. Que los ata a una Actividad en particular y permite que la reutilización sea difícil.
    • La solución es hacer una devolución de llamada de escucha de la interfaz que la Actividad se va a implementar. Cuando el Fragmento que desea enviar un mensaje a otro Fragmento o su actividad principal, puede hacerlo a través de la interfaz.
    • Es ok para la Actividad de comunicarse directamente a su hijo fragmento de métodos públicos.
    • Así, la Actividad sirve como controlador, pasando los mensajes de un fragmento a otro.

    Código

    MainActivity.java

    public class MainActivity extends AppCompatActivity implements GreenFragment.OnGreenFragmentListener {
    
        private static final String BLUE_TAG = "blue";
        private static final String GREEN_TAG = "green";
        BlueFragment mBlueFragment;
        GreenFragment mGreenFragment;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //add fragments
            FragmentManager fragmentManager = getSupportFragmentManager();
    
            mBlueFragment = (BlueFragment) fragmentManager.findFragmentByTag(BLUE_TAG);
            if (mBlueFragment == null) {
                mBlueFragment = new BlueFragment();
                fragmentManager.beginTransaction().add(R.id.blue_fragment_container, mBlueFragment, BLUE_TAG).commit();
            }
    
            mGreenFragment = (GreenFragment) fragmentManager.findFragmentByTag(GREEN_TAG);
            if (mGreenFragment == null) {
                mGreenFragment = new GreenFragment();
                fragmentManager.beginTransaction().add(R.id.green_fragment_container, mGreenFragment, GREEN_TAG).commit();
            }
        }
    
        //The Activity handles receiving a message from one Fragment
        //and passing it on to the other Fragment
        @Override
        public void messageFromGreenFragment(String message) {
            mBlueFragment.youveGotMail(message);
        }
    }

    GreenFragment.java

    public class GreenFragment extends Fragment {
    
        private OnGreenFragmentListener mCallback;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_green, container, false);
    
            Button button = v.findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String message = "Hello, Blue! I'm Green.";
                    mCallback.messageFromGreenFragment(message);
                }
            });
    
            return v;
        }
    
        //This is the interface that the Activity will implement
        //so that this Fragment can communicate with the Activity.
        public interface OnGreenFragmentListener {
            void messageFromGreenFragment(String text);
        }
    
        //This method insures that the Activity has actually implemented our
        //listener and that it isn't null.
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            if (context instanceof OnGreenFragmentListener) {
                mCallback = (OnGreenFragmentListener) context;
            } else {
                throw new RuntimeException(context.toString()
                        + " must implement OnGreenFragmentListener");
            }
        }
    
        @Override
        public void onDetach() {
            super.onDetach();
            mCallback = null;
        }
    }

    BlueFragment.java

    public class BlueFragment extends Fragment {
    
        private TextView mTextView;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_blue, container, false);
            mTextView = v.findViewById(R.id.textview);
            return v;
        }
    
        //This is a public method that the Activity can use to communicate
        //directly with this Fragment
        public void youveGotMail(String message) {
            mTextView.setText(message);
        }
    }

    XML

    activity_main.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"
        android:padding="16dp">
    
        <!-- Green Fragment container -->
        <FrameLayout
            android:id="@+id/green_fragment_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_marginBottom="16dp" />
    
        <!-- Blue Fragment container -->
        <FrameLayout
            android:id="@+id/blue_fragment_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    
    </LinearLayout>

    fragment_green.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:background="#98e8ba"
                  android:padding="8dp"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
    
        <Button
            android:id="@+id/button"
            android:text="send message to blue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    
    </LinearLayout>

    fragment_blue.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:background="#30c9fb"
                  android:padding="16dp"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
    
        <TextView
            android:id="@+id/textview"
            android:text="TextView"
            android:textSize="24sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    
    </LinearLayout>
    • Si necesitamos comunicarnos bettween la Actividad y el fragmento de dos maneras, Crear y Java interfaz de archivo en lugar del declarado en la Actividad o el fragmento.
  3. 9

    El mejor y más recomendable es utilizar un compartida ViewModel.

    https://developer.android.com/topic/libraries/architecture/viewmodel#sharing

    De Google doc:

    public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
    
    public void select(Item item) {
        selected.setValue(item);
    }
    
    public LiveData<Item> getSelected() {
        return selected;
    }
    }
    
    
    public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
    }
    
    
    public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           //Update the UI.
        });
    }
    }

    ps: dos fragmentos que nunca se comunican directamente

  4. 4

    Considerar mis 2 fragmentos a y B, y Supongamos que necesito para pasar los datos de la B a la A.

    A continuación, crear una interfaz en la B, y pasar los datos a la Actividad Principal. No crear otra interfaz y pasar los datos a fragmentar A.

    Compartir un pequeño ejemplo:

    Fragmento de Una se parece a

    public class FragmentA extends Fragment implements InterfaceDataCommunicatorFromActivity {
    public InterfaceDataCommunicatorFromActivity interfaceDataCommunicatorFromActivity;
    String data;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        //TODO Auto-generated method stub
        return super.onCreateView(inflater, container, savedInstanceState);
    }
    
    @Override
    public void updateData(String data) {
        //TODO Auto-generated method stub
        this.data = data;
        //data is updated here which is from fragment B
    }
    
    @Override
    public void onAttach(Activity activity) {
        //TODO Auto-generated method stub
        super.onAttach(activity);
        try {
            interfaceDataCommunicatorFromActivity = (InterfaceDataCommunicatorFromActivity) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement TextClicked");
        }
    
    }
    
    }

    FragmentB parece

    class FragmentB extends Fragment {
    public InterfaceDataCommunicator interfaceDataCommunicator;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        //TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
    
        //call this inorder to send Data to interface
        interfaceDataCommunicator.updateData("data");
    }
    
    public interface InterfaceDataCommunicator {
        public void updateData(String data);
    }
    
    @Override
    public void onAttach(Activity activity) {
        //TODO Auto-generated method stub
        super.onAttach(activity);
        try {
            interfaceDataCommunicator = (InterfaceDataCommunicator) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement TextClicked");
        }
    
    }
    
    }

    Actividad principal es

    public class MainActivity extends Activity implements InterfaceDataCommunicator {
    public InterfaceDataCommunicatorFromActivity interfaceDataCommunicatorFromActivity;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    @Override
    public void updateData(String data) {
        //TODO Auto-generated method stub
        interfaceDataCommunicatorFromActivity.updateData(data);
    
    }
    
    public interface InterfaceDataCommunicatorFromActivity {
        public void updateData(String data);
    }
    
    }
    • ¿Por qué es variable differente para FragmentB cuando se compara con FragmentA y MainActivity? FragmentB es InterfaceDataCommunicator, pero para FragmentA y MainActivity es InterfaceDataCommunicatorFromActivity.
  5. 0

    Hay una manera sencilla para implementar la comunicación entre los fragmentos de una actividad utilizando componentes arquitectónicos. Los datos pueden ser transmitidos entre los fragmentos de una actividad utilizando ViewModel y LiveData.

    Fragmentos que intervienen en la comunicación necesita usar el mismo punto de vista de los objetos del modelo que está vinculado a la actividad del ciclo de vida. La vista del modelo de objeto contiene livedata objeto para el cual los datos se pasa por un fragmento y el segundo fragmento de escucha para los cambios en LiveData y recibe los datos enviados a partir de un fragmento de uno.

    Para completar ejemplo ver http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel

  6. 0

    Aprender » setTargetFragment() «

    Donde «startActivityForResult()» establece una relación entre 2 las actividades, «setTargetFragment()» define el llamante/llamado de la relación entre 2 fragmentos.

  7. 0

    Doy mi actividad de una interfaz en la que todos los fragmentos puede utilizar. Si usted tiene muchos fragmentos en la misma actividad, esto ahorra una gran cantidad de código de re-escritura y es una solución de limpieza /más modular que hacer una interfaz individual para cada fragmento con funciones similares. También me gusta cómo es modular. La desventaja, es que algunos de los fragmentos tendrá acceso a funciones que no necesitan.

        public class MyActivity extends AppCompatActivity
        implements MyActivityInterface {
    
            private List<String> mData; 
    
            @Override
            public List<String> getData(){return mData;}
    
            @Override
            public void setData(List<String> data){mData = data;}
        }
    
    
        public interface MyActivityInterface {
    
            List<String> getData(); 
            void setData(List<String> data);
        }
    
        public class MyFragment extends Fragment {
    
             private MyActivityInterface mActivity; 
             private List<String> activityData; 
    
             public void onButtonPress(){
                  activityData = mActivity.getData()
             }
    
            @Override
            public void onAttach(Context context) {
                super.onAttach(context);
                if (context instanceof MyActivityInterface) {
                    mActivity = (MyActivityInterface) context;
                } else {
                    throw new RuntimeException(context.toString()
                            + " must implement MyActivityInterface");
                }
            }
    
            @Override
            public void onDetach() {
                super.onDetach();
                mActivity = null;
            }
        } 
  8. -1

    Actualización

    Ignorar esta respuesta. No es que no funciona. Pero hay mejores métodos disponibles. Por otra parte, Android enfáticamente desalentar la comunicación directa entre los fragmentos. Ver oficial doc. Gracias usuario @Wahib Ul Haq por la punta.

    Respuesta Original

    Bien, puede crear una variable privada y setter en el Fragmento B, y establecer el valor de Un Fragmento de sí mismo,

    FragmentB.java

    private String inputString;
    ....
    ....
    
    public void setInputString(String string){
       inputString = string;
    }

    FragmentA.java

    //go to fragment B
    
    FragmentB frag  = new FragmentB();
    frag.setInputString(YOUR_STRING);
    //create your fragment transaction object, set animation etc
    fragTrans.replace(ITS_ARGUMENTS)

    O puede utilizar la Actividad como usted sugiere en la pregunta..

    • Eso es ahora, ¿cómo debe hacerlo porque viola un concepto fundamental de la modularidad. Android documentación dice : > Dos Fragmentos nunca debe comunicarse directamente. Los fragmentos deben ser conscientes el uno del otro, ser autónomo y trabajar de forma independiente.
    • actualizada la respuesta. Gracias por la sugerencia.
  9. -1

    Recientemente he creado una biblioteca que utiliza anotaciones para generar este tipo de fundición de código repetitivo para usted.
    https://github.com/zeroarst/callbackfragment

    Aquí es un ejemplo. Haga clic en un TextView en DialogFragment desencadena una devolución de llamada para MainActivity en onTextClicked a continuación, tomar la MyFagment instancia para interactuar con.

    public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback, MyDialogFragment.DialogListener {
    private static final String MY_FRAGM = "MY_FRAGMENT";
    private static final String MY_DIALOG_FRAGM = "MY_DIALOG_FRAGMENT";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getSupportFragmentManager().beginTransaction()
    .add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), MY_FRAGM)
    .commit();
    findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    MyDialogFragmentCallbackable.create().show(getSupportFragmentManager(), MY_DIALOG_FRAGM);
    }
    });
    }
    Toast mToast;
    @Override
    public void onClickButton(MyFragment fragment) {
    if (mToast != null)
    mToast.cancel();
    mToast = Toast.makeText(this, "Callback from " + fragment.getTag() + " to " + this.getClass().getSimpleName(), Toast.LENGTH_SHORT);
    mToast.show();
    }
    @Override
    public void onTextClicked(MyDialogFragment fragment) {
    MyFragment myFragm = (MyFragment) getSupportFragmentManager().findFragmentByTag(MY_FRAGM);
    if (myFragm != null) {
    myFragm.updateText("Callback from " + fragment.getTag() + " to " + myFragm.getTag());
    }
    }

    }

Dejar respuesta

Please enter your comment!
Please enter your name here