6

I am at beginner level in Android programming, so I need your sincere help for this. Anyone help me please.

I am trying to build a SLIDING UI using fragments

so my actual doubt is ... I have a Fragment (say Fragment A) it has a TextView and Button in it and another Fragment (say Fragment B). It has a TextView in it. I need to show the Fragment A's TextView's content in Fragment B's TextView, when I pressed the Button in FRAGMENT A. I tried many ways, unfortunately I didn't got the proper output. I am sure you peoples know about it. Please help me.

Thank you

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Sam
  • 4,046
  • 8
  • 31
  • 47
  • You should store the text in the parent Activity and pass it to FRAGMENT B when you load it. – dmaxi Mar 16 '13 at 10:02
  • @dmaxi But i dont know how to store text in the parent Activity – Sam Mar 16 '13 at 10:05
  • Create a String type member variable and don't forget to save it into Bundle in onSaveInstanceState() callback. You should also read the JavaDoc of Activity and Fragment. – dmaxi Mar 16 '13 at 10:17
  • @dmaxi can you give an example for this...it will be more helpful for me – Sam Mar 16 '13 at 11:47

6 Answers6

19

It should be done thought listener, so Fragments are still not depend on each other and can be used in one or two pane mode. Activity should handle listeners of both fragments.

Here is an example of activity with two Fragments:

package com.example;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;

import com.example.fragment.FragmentA;
import com.example.fragment.FragmentA.TextChangeListener;
import com.example.fragment.FragmentB;

public class ActivityAB extends FragmentActivity {

    FragmentA fragmentA;
    FragmentB fragmentB;

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

        FragmentManager manager = getSupportFragmentManager();
        fragmentA = (FragmentA) manager.findFragmentById(R.id.fragmentA);
        fragmentB = (FragmentB) manager.findFragmentById(R.id.fragmentB);

        fragmentA.setTextChangeListener(new TextChangeListener() {

            @Override
            public void onTextChange(CharSequence newText) {
                fragmentB.updateTextValue(newText);
            }
        });
    }

}

Here is Fragment A, that has custom listener for text change event.

package com.example.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.example.R;

public class FragmentA extends Fragment {

    TextChangeListener listener;

    public interface TextChangeListener {
        public void onTextChange(CharSequence newText);
    }

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

        Button btn = (Button) view.findViewById(R.id.button1);
        final TextView textView = (TextView) view.findViewById(R.id.textView1);

        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (null != listener) {
                    listener.onTextChange(textView.getText());
                }

            }
        });
        return view;
    }

    public void setTextChangeListener(TextChangeListener listener) {
        this.listener = listener;
    }
}

Here is Fragment B that has public method to update text field:

package com.example.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.R;

public class FragmentB extends Fragment {

    TextView textView;

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

    public void updateTextValue(CharSequence newText) {
        textView.setText(newText);
    }
}

ActivityAB xml Layout:

<?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:baselineAligned="false"
    android:orientation="horizontal" >

    <fragment
        android:id="@+id/fragmentA"
        android:name="com.example.fragment.FragmentA"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/fragmentB"
        android:name="com.example.fragment.FragmentB"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

Fragment A xml layout:

<?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" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is text"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show" />

</LinearLayout>

Fragment B xml layout:

<?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" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="(here will be text)"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>
andrew
  • 6,533
  • 1
  • 22
  • 19
  • hi,thanks for your reply..but this is not working for me..And one more thing i don't have two seperate fragment layout in activity ab(ofcourse i have two fragment class and corresponding layout xml file)...instead i have only one fragment layout and iam dynamcally changing the content..can you please try once more for me.. – Sam Mar 16 '13 at 12:41
  • The method `onTextChange` will be invoked during button click. So use this callback to replace fragment A with fragment B and also set the text that you receive, e.g. `fragmentB.updateTextValue(newText); this.showFragmentB();` – andrew Mar 16 '13 at 13:10
  • This advice doesn't apply in the general case. What about if you are using sub-fragments? A parent fragment and child fragment may well need to communicate with each other, without having to go all the way up to the containing Activity to do so. In certain cases the root Activity may house the whole application (ie: a tab-based application). There is no way every single communication between every single sub-component should be routed through one place (major violation of the Single Responsibility anti-pattern) – Marchy Mar 31 '14 at 20:38
2

It sounds as if your setup might be something like - MainActivity w/ FragmentA [added] and FragmentB [added]. For this case, I would delegate messages/actions between the two fragments through the MainActivity. Allowing MainActivity to handle the messages/actions also facilitates 'special' orchestrations which might be needed in a more complex situation between the Fragments. For example:

public interface FragmentCommunicator
{
    public void sendMessage ( String broadcastMessage );
    public void takeAction ( String name, int action, Fragment frag );
}

public class MainActivity extends Activity implements FragmentCommunicator
{
    Fragment fragA;
    Fragment fragB;
    ...
    @Override
    public void sendMessage ( String msg )
    {
        if ( msg.Contains("Send To fragA") )
            fragA.receiveMsg(msg);
        ...
    }
    @Override
    public void takeAction ( String name, int action, Fragment frag )
    {
    if ( action == CLOSE )
            removeFragment( name, frag );
        ...
    }
}

public class FragmentA extends Fragment
{
    ...
@Override
public void onClick(View v)
{   
     FragmentCommunicator inter = (FragmentCommunicator) getActivity();
     inter.sendMessage("the txt/information/etc you want to send to fragB");    
}
}

public class FragmentB extends Fragment
{
    ...
    public void receiveMsg ( String msg )
    {
        textView.setText(msg);
    }
}

I forgot to post the send portion of FragmentA. Hope this helps.

0

Communication between two fragments should always be via their fragment activity in order to keep a loose coupling between the fragments , So if you want to send some data from one fragment A to another fragment B you can create listener and implement it in your fragment activity and from inside fragmentA you can fire the event using that listener and send data to fragment activity, So now the fragment activity will be having the object of fragment B also and so fragment activity can directly call the method of fragment B and send data to fragment B...

Karan_Rana
  • 2,813
  • 2
  • 26
  • 35
0

developer.android.com

To allow a Fragment to communicate up to its Activity, you can define an interface in the Fragment class and implement it within the Activity. The Fragment captures the interface implementation during its onAttach() lifecycle method and can then call the Interface methods in order to communicate with the Activity.

Example:- http://wiki.workassis.com/android-fragment-communication/

ref:- https://developer.android.com/training/basics/fragments/communicating.html

Bikesh M
  • 8,163
  • 6
  • 40
  • 52
0

i like the activity to be the middle man between fragment to fragment communication. but the other thing i like is using an event bus architecture which also offers decoupling.

j2emanue
  • 60,549
  • 65
  • 286
  • 456
-1

Its actually pretty easy, just follow these steps:

  1. So you created the two fragments A and B, now create their brains, i.e, Java class files. Lets call them JClass A (for Fragment A) and JClass B(for Fragment B)

2.You got button in you Frag A, so go to JClass A, and in that get the String text the user types and the button pressed event like this: // just override the onCreate method.

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.<name of your fragment A.xml file>,container,false);

    userInput = (EditText)view.findViewById(R.id.<Id that you gave to EditText field in which user enters text>);

    Button myButton = (Button)view.findViewById(R.id.<id of your Button>);
    myButton.setOnClickListener(
            new Button.OnClickListener(){
                public void onClick(View v){
                    JClassB.setText(userInput.getText().toString());/*Replace JClassB with the java class of Fragment B*/

                }
            }
    );

    return view;
}
  1. And finally in your JClass B(java file for fragment B):

    public class BottomSectionFrag extends Fragment {

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

    }

Voila!!

P.S. This is my first ever post on stackOverFlow :D

Peace Out.