How can I replace fragment inside a fragment? - android

I have an Activity with a ViewPager, each page of the ViewPager has a Fragment.
Inside my Screen3Fragment I have a LinearLayout (lly_fragments) where I am showing some other fragments. I start by showing the fragment Screen3_1
public class Screen3Fragment extends Fragment {
private FragmentManager manager;
private FragmentTransaction transaction;
public static Screen3Fragment newInstance() {
final Screen3Fragment mf = new Screen3Fragment();
return mf;
}
public Screen3Fragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3, container, false);
Screen3_1Fragment frag31 = new Screen3_1Fragment();
manager = getChildFragmentManager();
transaction = manager.beginTransaction();
transaction.add(R.id.lly_fragments,frag31,"frag31");
transaction.addToBackStack("frag31");
transaction.commit();
return v;
}
}
This works fine without problems. Problem comes when, from within frag31 (which is inside Screen3Fragment), I want to call fragt32, for that I do the following.
public class Screen3_1Fragment extends Fragment {
private ImageButton imgbt_timer;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3_1,container,false);
imgbt_timer = (ImageButton) v.findViewById(R.id.bT_scr31_timer);
imgbt_timer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getChildFragmentManager().beginTransaction()
.replace(R.id.lly_fragments, new Screen3_2Fragment(), "frag32")
.commit();
}
});
return v;
}
}
As I read in other answers, the line transaction.replaceshould do the trick and replace the existing frag31 by the given frag32 inside the same given container lly_fragments.
However, I get java.lang.IllegalArgumentException: No view found for id..... I am not sure why.

getFragmentManager() will return always attributes from parent, in most cases the activities. getChildFragmentManager() wil return parent attributes (in your case, Screen3Fragment attributes). It should be used when you add a fragment inside a fragment.
In your case, Screen3Fragment should be added using getFragmentManager() and Screen3_1Fragment should be added using getChildFragmentManager() because Screen3_1Fragment is Screen3Fragment child. Screen3Fragment is the parent.
I recomand you to use always getFragmentManager() with add method, not replace because your parent will be the same.
getChildFragmentManager() can be used when you add a ViewPager inside a fragment.

You can use the callback, as following :
that worked for me, I hope my answers helps you
1) create a interface
public interface ChangeFragmentListener {
void onChangeFragmentLicked(int fragment);
}
2) implement the interface and transaction methods in your activity:
public class MainActivity extends AppCompatActivity implements ChangeFragmentListener {
FragmentTransaction fragmentTransaction;
Fragment1 fragment1;
Fragment2 fragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
fragment1 = new Fragment1();
fragment1.setChangeFragmentListener(this);
fragment2 = new Fragment2();
fragment2.setChangeFragmentListener(this);
initListeners();
}
void changeToFrag1() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container,fragment1, "");
fragmentTransaction.commit();
}
void changeToFrag2() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container, fragment2, "");
fragmentTransaction.commit();
}
#Override
public void onChangeFragmentLicked(int fragment) {
switch (fragment){
case 1:
changeToFrag1();
break;
case 2:
changeToFrag2();
break;
}
}
3) Create object from the interface to handle the callback:
public class Fragment1 extends Fragment {
private ChangeFragmentListener changeFragmentListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
view.findViewById(R.id.fragment1_textView).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
changeFragmentListener.onChangeFragmentLicked(2);
}
});
return view;
}
public Fragment1 setChangeFragmentListener(ChangeFragmentListener changeFragmentListener) {
this.changeFragmentListener = changeFragmentListener;
return this;
}
}

Related

replace fragment with another fragment along with remove view

I have one activity and two Fragments. FragmentA and FragmentB.
I need to implement like, Initially FragmentA should be there.
and After Button click FragmentB should be there.
in my condition when activity is being displayed,fragmentA is showing and when click to button,fragmentB placed at the bottom of fragmentA and do not replace FragmentA
My activity Code is:
public class FragmentActivity extends AppCompatActivity {
FrameLayout activityFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
activityFragment = (FrameLayout) findViewById(R.id.activityFragment);
Fragment fragment = new FragmentA();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.activityFragment, fragment);
transaction.commit();
}
public void goToFrag(View view) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment fragment = new FragmentB();
transaction.add(R.id.fragmentRoot, fragment);
transaction.commit();
}
}
my first fragment code:
public class FragmentA extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view=inflater.inflate(R.layout.fragment_a,container,false);
return view;
}
}
my second fragment code:
public class FragmentB extends Fragment {
public FragmentB() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view=inflater.inflate(R.layout.fragment_b,container,false);
return view;
}
}
First of all, you should always have a FrameLayout in xml to replace your fragments there, then you use different containers to add fragments activityFragment and fragmentRoot .You should replace fragments in one container. You can use either add or replace for FragmentManager , so it activityFragment is your container (which should be a framelayout as a wrapper as the docs suggest) you use
public void goToFrag(View view) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment fragment = new FragmentB();
transaction.replace(R.id.activityFragment, fragment); // use the same container where you switch A and B
transaction.commit();
}

Communication between two fragment from different activity?

I have two activities in my app. In MainActivity I am loading 2 fragments Fragment1 and Fragment2. From Fragment1 i am jumping to Fragment2 and from Fragment2 I am jumping to Activity2 which contains Fragment2_1 From Fragment 2_1 I want to jump back to Fragment2 in MainActivity but I am getting an error when I try to do this.
I want to know is it possible to jump from 1 activity fragment to another activity fragment?
My code is:
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
Fragment fragment1=new Fragment1();
fragmentTransaction.replace(R.id.mainContainer,fragment1,"MainActivity");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
Fragment1.java:
public class Fragment1 extends Fragment {
public Fragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view=inflater.inflate(R.layout.fragment_fragment1, container, false);
Button buttonfrag1=(Button)view.findViewById(R.id.buttonfrag1);
buttonfrag1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragmentManager=getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
Fragment2 fragment2 = new Fragment2();
fragmentTransaction.replace(R.id.mainContainer,fragment2,"Fragment1");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return view;
}
Fragment2.java
public class Fragment2 extends Fragment {
public Fragment2() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2, container, false);
Button buttonfrag2=(Button)view.findViewById(R.id.buttonfrag2);
buttonfrag2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(getActivity(),Activity2.class);
startActivity(intent);
}
});
return view;
}
}
Activity2.java
public class Activity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
Fragment2_1 fragment2_1=new Fragment2_1();
fragmentTransaction.replace(R.id.frag2_1,fragment2_1,"Activity2");
fragmentTransaction.commit();
}
}
Fragment2_1.java
public class Fragment2_1 extends Fragment {
public Fragment2_1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2_1, container, false);
Button buttonfrag2_1=(Button)view.findViewById(R.id.buttonfrag2_1);
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
Fragment2 fragment2=new Fragment2();
fragmentTransaction.replace(R.id.mainContainer,fragment2,"frag2_1");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return view;
}
}
All code works fine but when I want to move from Fragment2_1 to Fragment1 my app crashes with an exception :
java.lang.IllegalArgumentException: No view found for id 0x7f0b0059 (saleskit.orbitsys.com.fragmentdemo:id/mainContainer) for fragment Fragment2{29eb9c90 #1 id=0x7f0b0059 frag2_1}
try this: in Fragment2_1
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.putExtra("frag", "fragment2");
startActivity(intent);
}
});
Now in Mainactivity onResume() load your desired fragment in maincontainer
in MainActivity
#Override
public void onResume(){
super.onResume();
Intent intent = getIntent();
if(intent.getExtras() != null)
{
String frag = intent.getStringExtra("frag");
}
switch(frag){
case "fragment2":
//here you can load Fragment2 to your activity as usual;
fragmentManager.beginTransaction().replace(R.id.mainContainer, new Fragment2()).commit();
break;
}
}
In your Fragment2_1 within your second activity you are trying to place Fragment2 in the container R.id.mainContainer. Your code below :
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
Fragment2 fragment2=new Fragment2();
fragmentTransaction.replace(R.id.mainContainer,fragment2,"frag2_1");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
But since you are currently inside your second activity that container doesn't exist (it is part of your first activity). You need to either load your your MainActivity again or finish Activity2 by calling finish(). If you do the later android will by itself take you back to your MainActivity and since you moved to Activity2 from Fragment2 android will also remember that and show you Fragment2.
Your Fragment2_1 should look like this:
public class Fragment2_1 extends Fragment {
public Fragment2_1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2_1, container, false);
Button buttonfrag2_1=(Button)view.findViewById(R.id.buttonfrag2_1);
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().finish();
}
});
return view;
}
}
OR, If you just want to show Fragment2 in your second activity you can do something like this :
public class Fragment2_1 extends Fragment {
public Fragment2_1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2_1, container, false);
Button buttonfrag2_1=(Button)view.findViewById(R.id.buttonfrag2_1);
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
Fragment2 fragment2=new Fragment2();
fragmentTransaction.replace(R.id.frag2_1,fragment2,"frag2");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return view;
}
}
R.id.frag2_1 is the container where you need to replace the fragment.
Note that : You will still be in your second activity. Just the fragment will be replaced.

android fragment replace to second fragment not working

My situation is I have a Activity(only FrameLayout),one fragment has a butoon that it's function is changing to second fragmnet,but when i set replace and commit.It's fail.
I tried this function success brfore,but it's not working now.
Is anyone can tell me the problem ? It will be grateful.
The first fragment code:
public class StartPage extends Fragment implements View.OnClickListener {
}
public static StartPage newInstance() {
return new StartPage();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.start_page_fragment, container, false);
//findViews();
imageRegistered = (ImageView) view.findViewById(R.id.imageRegistered);
imageRegistered.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragment=getFragmentManager();
FragmentTransaction transaction=fragment.beginTransaction();
transaction.replace(R.id.frameStartPage,Register.newInstance(),null);
transaction.commit();
Toast.makeText(getActivity(),"Test",Toast.LENGTH_SHORT).show();
}
});
return view;
}
and it's my frameLayout on the Activity:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frameStartPage"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.huaweb_system.taiwanuniversityhome.MainActivity">
</FrameLayout>
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
if (savedInstanceState == null) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frameStartPage, StartPage.newInstance());
transaction.commit();
}
}
}
second fragment:
public class Register extends Fragment implements View.OnClickListener {
public static StartPage newInstance() {
return new StartPage();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.register_activity, container, false);
findViews();
return view;
}
}
Actually getting instance using new operator and using newInstance() static method is same.
Problem is in your code :
public static StartPage newInstance() {
return new StartPage();
}
you are using the same method in both the fragments StartPage and Register.
Therefore You should change newInstance method of your Register fragment like this
public static Register newInstance() {
return new Register();
}

How to use shared element transition between FirstFragment (including RecyclerView) and SecondFragment

I could implement shared element transition between two fragments WITHOUT RECYCLERVIEW!!!
This is FirstFragment:
public class FirstFragment extends Fragment {
ImageView img_small;
LinearLayout layout_ofc_cities;
LinearLayout layout;
public FirstFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
img_small = (ImageView) view.findViewById(R.id.img_small);
layout_ofc_cities = (LinearLayout) view.findViewById(R.id.layout_ofc_cities);
layout = (LinearLayout) view.findViewById(R.id.layout);
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_trans));
setExitTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.fade));
SecondFragment secondFragment = new SecondFragment();
secondFragment.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_trans));
secondFragment.setEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.fade));
FragmentTransaction ft = getFragmentManager().beginTransaction()
.replace(R.id.container, secondFragment)
.addToBackStack(null)
.addSharedElement(layout_ofc_cities, "transitionTxt")
.addSharedElement(img_small, "transitionImg");
ft.commit();
}
}
});
return view;
}
}
and this is SecondFragment:
public class SecondFragment extends Fragment {
public SecondFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_second, container, false);
return view;
}
}
And it works!
but when I implements a RecyclerView in FirstFragment to use SharedElementTransition for a LinearLayout and an ImageView of RecyclerView to a LinearLayout and an ImageView in SecondFragment it doesn't work.
I want a sample code with two Fragments that the first one has RecyclerView in it, with animation between their shared elements. Can anyone help me?
I found the answer:
the solution is on this page:
http://jemsdevmobile.com/2016/02/11/lollipop-transition-between-activities/
just you need to change xml tags. for example change "imageview" to "ImageView"

Fragments the right way

I'm trying out some fragments right now. I've got a fragment with a button and when I click that button I switch to another fragment. Now when I push on the back button I return to the first fragment that's good. Now when I click again on that button a new fragment is started. So I always start a new fragment. I think thats not the way it needs to be done. Is there a better way to for example resume the already created fragment?
My code:
public static class PlaceholderFragment extends Fragment{
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
Button test = (Button)rootView.findViewById(R.id.button);
test.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View view)
{
Log.d("Test", "Button clicked.");
TestFrag newFragment = new TestFrag();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
return rootView;
}
}
public static class TestFrag extends Fragment {
public TestFrag() {
Log.d("Test","New fragment");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main2, container, false);
return rootView;
}
}
When you use the fragment transaction you can specify a tag for the fragment
fragmentTransaction.add(R.id.main_fragment, newFragment, fragTag);
fragmentTransaction.commit();
Then later you can find a fragment by tag from the fragmentManager
newFragment = fragMan.findFragmentByTag(fragTag);
if newFragment then is null you should create the Fragment since it wasnt found by the tag
Thanks to Joakim:
fragmentTransaction.add(R.id.main_fragment, newFragment, fragTag); fragmentTransaction.commit();
Then later you can find a fragment by tag from the fragmentManager
newFragment = fragMan.findFragmentByTag(fragTag); if newFragment then is null you should create the Fragment since it wasnt found by the tag. If the tag isn't null you can just add and commit the new one.

Categories

Resources