Basically, I have a MainActivity that displays different Fragments when clicked on menu options.
Stats, is a Fragment that displays 4 fragments in it. Every time it is displayed, will replace 4 FrameLayouts on the view.
The first time work perfectly, but when I change to different fragments and get back in Stats, it seems not to replace the FrameLayouts to Fragments...
Stats as follows:
public class StatsFragment extends Fragment {
private View rootView;
private MoreSoldBarChartFragment moreSold = MoreSoldBarChartFragment.newInstance(null);
private MoreIncomeBarChartFragment moreIncome = MoreIncomeBarChartFragment.newInstance(null);
private SoldLineChartFragment soldLine = SoldLineChartFragment.newInstance(null);
private IncomeLineChartFragment incomeLine = IncomeLineChartFragment.newInstance(null);
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_stats, container, false);
initViews();
return rootView;
}
public void initViews() {
replace(moreIncome, R.id.moreIncome);
replace(moreSold, R.id.moreSold);
replace(soldLine, R.id.soldLine);
replace(incomeLine, R.id.incomeLine);
}
private void replace(Fragment fragmentToReplace, int container) {
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(container, fragmentToReplace);
ft.commit();
}
public static StatsFragment newInstance(Bundle args) {
StatsFragment fragment = new StatsFragment();
fragment.setHasOptionsMenu(true);
fragment.setArguments(args);
return fragment;
}
}
You should be using getChildFragmentManager() to display Fragments within Fragments:
private void replace(Fragment fragmentToReplace, int container) {
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.replace(container, fragmentToReplace);
ft.commit();
}
As that ensures that the Fragments are properly handled when the parent's state is changed (i.e., when it is swapped with another Fragment and back). When you use getActivity.getSupportFragmentManager(), Fragments have no idea that these Fragments are related and can't restore the Fragments.
Related
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();
}
I am new to android, and i am facing this problem when the screen orientation is changed. The fragment gets called twice whenever screen orientation changes. Below is the sample of my code. I checked other posts, but couldnt find answer. Anyone guide me through this.
public class SampleFragment extends Fragment {
static final String TAG_NAME = SampleFragment.class.getSimpleName();
List<PhrToolBar> mToolBarList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
DaggerHelper.getAppProviderComponent().inject(this);
mRootView = null;
getActivity().setTitle("Personal Health Records");
mRootView = inflater.inflate(R.layout.sample_phr_main_fragment, container, false);
mBinding = DataBindingUtil.bind(mRootView);
mBinding.setViewModel(mViewModel);
setHasOptionsMenu(true);
return mRootView;
}
Simple add this code
if (savedInstanceState == null) {
// only create fragment if activity is started for the first time
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
} else {
// do nothing - fragment is recreated automatically
}
I have three Fragments attached to ViewPager. If i am Fragment1, and i have a button on Fragment1, i want on button click of that 'Fragment', access the Fragment3 but on the same time if i slide the page,i don't want to access the Fragment3. while sliding i want to access only up to Fragment2. How can i do this.
TabPagerAdapter.java:-
public class TabPagerAdapter extends FragmentStatePagerAdapter
{
public TabPagerAdapter(FragmentManager fragmentManager)
{
super(fragmentManager);
}
#Override
public Fragment getItem(int position)
{
switch (position)
{
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
}
return null;
}
#Override
public int getCount()
{
return 3;
}
I have implemented something very similar: Previously I had four fragments in my ViewPager, but then decided that I want to integrate two of those fragments more intimately by reducing the number of fragment that I can reach by sliding and switching back and forth between two fragments by using a button. The implementation took me a while, though. I did not manage to mess with the index of my fragmentList properly. In the end, the trick was to take out those two fragments from the ViewPager altogether and add a HolderFragment instead. Within this fragment I implemented the fragment transaction for hiding one and showing the other fragment.
Here is the code from my HolderFragment:
public class HolderFragment extends Fragment {
private Context context;
private Fragment currentFragment;
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_holder, container, false);
OneFragment oneFragment =
(OneFragment) Fragment.instantiate(context, OneFragment.class.getName());
OtherFragment otherFragment =
(OtherFragment) Fragment.instantiate(context, OtherFragment.class.getName());
// oneFragment selected on view creation
FragmentManager fm = this.getChildFragmentManager();
fm.beginTransaction().add(R.id.holder_fragment_holder, oneFragment).commit();
fm.beginTransaction().add(R.id.holder_fragment_holder, otherFragment).hide(mediaFragment)
.commit();
currentFragment = oneFragment;
return view;
}
public void switchFragments(Fragment fragment) {
if (!fragment.equals(currentFragment)) {
this.getChildFragmentManager().beginTransaction().hide(currentFragment).commit();
currentFragment = fragment;
this.getChildFragmentManager().beginTransaction().show(currentFragment).commit();
}
}
}
Then, whenever the switch button is pressed just call holderFragment.switchFragments(oneFragment) or holderFragment.switchFragments(otherFragment) from the activity that holds the ViewPager (and a reference to the HolderFragment).
Try this
mViewPager.setCurrentItem(your_position, true);
I'm using some fragments programmatically in activity. There is one button in my first fragment and when i click to this button, it replaces to second fragment.My second fragment's background is 90% transparent, and when it starts, i can see button which is situated in first fragment, and it also works. I want to stop or do something, because i dont want to see first fragment features and use it.
First Fragment
public class RegistrationFirstFragment extends Fragment {
RegistrationSecondFragment rf;
ImageButton btnNewUser,btnNewAgent;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//return super.onCreateView(inflater, container, savedInstanceState);
View v =inflater.inflate(R.layout.fragment_registration_first,container,false);
rf = new RegistrationSecondFragment();
btnNewUser = (ImageButton)v.findViewById(R.id.btnNewUserRegistrationFirstFragment);
btnNewAgent = (ImageButton)v.findViewById(R.id.btnNewAgentRegistrationFirstFragment);
btnNewUser.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), "Transaction completed succesfully", Toast.LENGTH_LONG).show();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.flRegistrationFirst, rf);
ft.commit();
}
});
return v;
}
}
Second Fragment
public class RegistrationSecondFragment extends Fragment {
RegistrationFirstFragment rtl;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rtl = new RegistrationFirstFragment();
//return super.onCreateView(inflater, container, savedInstanceState);
View v =inflater.inflate(R.layout.fragment_registration_second,container,false);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
// ft.replace(R.id.flRegistrationFirst, rf);
ft.remove(rtl);
ft.commit();
return v;
}
}
Main Activity
public class RegistrationActivity extends AppCompatActivity{
RegistrationFirstFragment fr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_registration);
fr = new RegistrationFirstFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.flRegistrationFragment,fr);
ft.commit();
}
}
You can put
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
(the parameter fragment would be an instance of your second fragment)
into your onClick(View view){...} method to change the fragment instead of adding it.
Next time code for understanding your problem btw ;)
Add to fragment layout android:clickable="true". Int his way fragment will catch event so the click will not be caught by "main fragment".
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
Give android:clickable="true" for Second Fragment root layout parent, when ever fragment opens It catches the click event of root and ignored previous click events.
Second One: If u use replace Fragment it's better than add fragment.
getActivity().getSupportFragmentManager().beginTransaction().replace
(R.id.YOUR_CONTAINER, 'FragmentObject').addToBackStack("TAG").commitAllowingStateLoss();
I have an app with fragments. It works fine.
One of the fragments has a button, and when pressed I want to change the view.
public class BikeRecap extends Fragment {
public static Activity activity;
public static Context context;
/** Called when the activity is first created. */
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
activity = getActivity();
context = activity.getApplicationContext();
View view = inflater.inflate(R.layout.bike_recap, container, false);
ImageButton details = (ImageButton) item.findViewById(R.id.details);
details.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
OpenNewView();
}
});
return view;
}
OpenNewView() should change the view, so, the user is in the same tab, but the content is different
Is it possible?
You can't have a fragment inside a fragment.
Try this code:
FragmentManager fragmentManager2 = getFragmentManager();
FragmentTransaction fragmentTransaction2 = fragmentManager2.beginTransaction();
DetailFragment fragment2 = new DetailFragment();
fragmentTransaction2.addToBackStack("abc");
fragmentTransaction2.hide(BikeRecap.this);
fragmentTransaction2.add(android.R.id.content, fragment2);
fragmentTransaction2.commit();
I think you can, pretty easily, do what you are trying to do. If OpenNewView is implemented by the Activity, instead of by the fragment:
getActivity().openNewView(...)
... then the Activity can easily replace the current fragment with a new one, using the standard transaction mechanism.
G. Blake Meike
Marakana
Programming Android 2ed is now in stores:
http://bit.ly/programmingandroid