-2

I have two fragments and I want to show them in my screen one by one. They are managed by MainActivity. The first fragment contains a TextView and a Button. The second fragment contains an EditText and a Button. What I am trying to do is: The first fragment shows on screen, and when the user press the button I want my activity to show the second fragment, and when the user press the button from this fragment I want to send the text from the EditText to the first fragment and display it on the TextView. I used interface for listeners.

public class MainActivity extends AppCompatActivity implements Listener, ListenerTwo{

FragmentTransaction fragmentTransaction;

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

    fragmentTransaction =  getSupportFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragmentPlaceholder, new FragmentOne());
    fragmentTransaction.commit();


}

@Override
public void onButtonSelected() {
    fragmentTransaction =  getSupportFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragmentPlaceholder, new FragmentTwo());
    fragmentTransaction.commit();
}

@Override
public void onButtonPressed(String text) {
    FragmentOne fragmentOne = (FragmentOne)getSupportFragmentManager().findFragmentById(R.id.fragmentPlaceholder);

    if (fragmentOne != null)
        fragmentOne.setTextt(text);
}

}

In my FragmentOne:

    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    Button button = view.findViewById(R.id.button);
    textView = view.findViewById(R.id.textView);
    Listener listener = (Listener) getActivity();

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getContext(), "button clicked", Toast.LENGTH_SHORT).show();
            if (listener != null)
                listener.onButtonSelected();
        }
    });

}

public void setTextt (String text) {
    textView.setText(text);
}

In FragmentTwo:

    @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    Button button = view.findViewById(R.id.button2);
    EditText editText = view.findViewById(R.id.editText);
    ListenerTwo listener = (ListenerTwo) getActivity();

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getContext(), "button clicked", Toast.LENGTH_SHORT).show();
            if (listener != null)
                listener.onButtonPressed(editText.getText().toString());
        }
    });

}
  • 2
    maybe you should consider using `ViewModel` ? – Teo Jul 27 '21 at 11:11
  • Can you provide the full stack trace exception – Zain Jul 27 '21 at 11:13
  • Process: ro.scoalainformala.fragments, PID: 10116 java.lang.ClassCastException: ro.scoalainformala.fragments.FragmentTwo cannot be cast to ro.scoalainformala.fragments.FragmentOne at ro.scoalainformala.fragments.MainActivity.onButtonPressed(MainActivity.java:34) at ro.scoalainformala.fragments.FragmentTwo$1.onClick(FragmentTwo.java:36) at android.view.View.performClick(View.java:7448) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119) – Stefan Radulescu Jul 27 '21 at 11:14
  • Why you expecting that `getSupportFragmentManager().findFragmentById(R.id.fragmentPlaceholder)` would return instance of `FragmentOne` when you first replace it with `FragmentTwo` ? – Selvin Jul 27 '21 at 11:15
  • `FragmentOne fragmentOne = (FragmentOne)getSupportFragmentManager().findFragmentById(R.id.fragmentPlaceholder);` This must return fragmentTwo, because it is the current fragment in the placeholder – Zain Jul 27 '21 at 11:17
  • Should I replace first with FragmentOne and then call setTextt? – Stefan Radulescu Jul 27 '21 at 11:18
  • Yes you should do the transaction first – Zain Jul 27 '21 at 11:21
  • Why do you think that you can use view of the fragment which is after `onViewDestroyed` in its lifecycle ? – Selvin Jul 27 '21 at 11:21
  • ' public void onButtonPressed(String text) { fragmentTransaction.replace(R.id.fragmentPlaceholder, new FragmentOne()); fragmentTransaction.commit(); FragmentOne fragmentOne = (FragmentOne)getSupportFragmentManager().findFragmentById(R.id.fragmentPlaceholder); if (fragmentOne != null) fragmentOne.setTextt(text); }' – Stefan Radulescu Jul 27 '21 at 11:23
  • Now I have another error: java.lang.IllegalStateException: commit already called – Stefan Radulescu Jul 27 '21 at 11:24

1 Answers1

0

inside Activity in onButtonPressed method you are casting currently set FragmentTwo to FragmentOne. note that whe you are setting Fragment you are using fragmentTransaction.replace( <- REPLACE! you are loading fragments into R.id.fragmentPlaceholder, when new one is set, then previous is going to be destroyed

inside onButtonPressed you have to set again FragmentOne

fragmentTransaction =  getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragmentPlaceholder, new FragmentOne());
fragmentTransaction.commit();

these lines are common, are placed also in onCreate so they may be packed into one method called in these two places

for transfering some data into fragment you may use passing this object in a constructor, but better way would be to use Bundle, so:

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

@Override
public void onButtonPressed(String text) {
    showFragmentOne(text);
}

private void showFragmentOne(String text) {
    Fragment fragment = new FragmentOne();
    if (text!=null){
        Bundle bundle = new Bundle();
        bundle.putInt("text", text);
        fragment.setArguments(bundle);
    }

    fragmentTransaction =  getSupportFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragmentPlaceholder, fragment);
    fragmentTransaction.commit();
}

inside onViewCreated at the end of method check Bundle and set text

Bundle bundle = this.getArguments();
if (bundle != null) {
    String text = bundle.getString("text", null);
    if(text!=null) setTextt(text); // or just textView.setText(text);
}
snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • you still have wrong line there, casting to `FragmentOne fragmentOne = (FragmentOne)getSupportFragmentManager()`... – snachmsm Jul 27 '21 at 11:29
  • added snippet in my answer, there is also solution under linked stackoverflow topic – snachmsm Jul 27 '21 at 11:35
  • If I would like to transfer an object how would I do? – Stefan Radulescu Jul 27 '21 at 11:39
  • I've already answered your question, it was about `String`. I'm not your personal trainer, if you have any other question start new topic or just search, [answer is already on SO](https://stackoverflow.com/questions/5784231/how-to-pass-custom-object-in-bundle/46591617) – snachmsm Jul 27 '21 at 18:48