I'm working with fragments with ViewPager concept. I'm creating a diary app in which I'm using only one fragment which gets all updates from database and show in it. Until this everything is fine...According to my requirement when i click on a button in fragment i need to show another fragment which allows the user to store the images.
My problem is.....
--If i use replace method in fragments it was not replacing properly in the sense if A is fragment which consists of viewpager and B is a fragment i want to replace.
--Then if i use replace B is visible but A also appears under the fragment B
FragmentManager m=getActivity().getSupportFragmentManager();
FragmentTransaction ft = getActivity().getSupportFragmentManager()
.beginTransaction();
Demobutton demobutton = new Demobutton();
ft.replace(R.id.lay, demobutton);
ft.commit();
Hope you guys understand my problem. If you feel my question is incomplete please let me know that.
I have two suggestions depending on how you use the DemoButton Fragment:
1) Maybe your issue is with nested fragments. You get the FragmentManager from the activity but if the Demobutton is already part of an fragment use getChildFragmentManager() of the outer fragment instead.
2) From my experience when using a ViewPager with Fragments the PagerAdapter of the ViewPager should do all the fragment transactions. You could extend and overwrite the class FragmentPagerAdapter from the support library in order to get the correct fragment in your ViewPager when you need it.
I've developed a small example app that achieves this without overwriting native classes.
The point is to use a fragment as a container.
In your ViewPagerAdapter:
#Override
public Fragment getItem(int position) {
/*
* IMPORTANT: This is the point. We create a RootFragment acting as
* a container for other fragments
*/
if (position == 0)
return new RootFragment();
else
return new StaticFragment();
}
RootFragment layout should look like:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root_frame" >
</FrameLayout>
You could review my complete explanation here: https://stackoverflow.com/a/21453571/1631136
Related
I'm learning about fragments I have some doubts. Consider following code:
FragmentManager fm = getFragmentManager();
Fragment MyFragment = new Fragment();
fm.beginTransaction().replace(R.id.my_container, MyFragment).addToBackStack(null).commit();
My question is:
what exactly does replace do?
What happens if I create many fragments this way (to replace previous ones in a container).
Can it in any way be bad for memory usage?
Is it considerably better just to change fragment's content?
Replace removes all the fragments that are in the container and adds the new fragment to the container. (if there isn't a fragment in the container then it just adds the new one).
If you create many fragments this way then every transaction is saved to the backstack so you can reverse the transaction by pressing the back button.
The only thing you can do is to create a variable fragmentTransaction and use the fm.beginTransaction() only once and not every time you want to replace the fragment in the container.
I don't think so, fragments should be modular and reusable.
You can read more here:
https://developer.android.com/guide/components/fragments.html
it simple put another "layer" on container.
appcrash
yes
No, fragment is the easiest way.
Using fragment & backstack tag to reference to a Fragment if you want to call fragment again and process Back button.
fm.beginTransaction().replace(R.id.my_container, MyFragment, "FRAGMENT_TAG").addToBackStack("FRAGMENT_BACKSTACK_TAG").commit();
So I basically have a button in 'DemosFragment' and when I click it, I want it to open another fragment (SettingsFragment), I understand now that I need an activity to fix this issue, as the button currently has an onClick method using intent/startActivity, so how would I go about creating an activity that just holds my fragment? I know that may sound weird they way I wrote it, I just started Android development, but basically I have a fragment and because I want a fragment to have a button to open another fragment, I figure I need an activity for the fragment I am trying to open, so how do I create that activity and what do I need to put in it? Thanks.
You need an activity with the following code:
public class ShowFragmentActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_fragment);
}
}
You also have to create a layout xml file called activity_show_fragment.xml in your res/layout folder:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.example.yourFragmentsClassName"
android:id="#+id/fragment_id"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
This should work for just displaying your fragment.
To launch the activity, paste this code in your button's onClick method:
Intent i = new Intent(this, ShowFragmentActivity.class);
startActivity(i);
It's always a good decision to look at the official docs: http://developer.android.com/reference/android/app/Fragment.html.
Hope that helps!
Wow! Your question requires a long answer, however is a good practice (and madatory too) that Fragments cannot communicates between each others, but they can be hosted by an Activity; in that case an Activity can manage the communication flow between them (fragments) and can be developed in several ways, Bundle, Intent and the Handler. Have a look to the ufficial Android documentation here:
http://developer.android.com/training/basics/fragments/index.html
The android docs section on building a flexible UI is a good example of how to start/load a Fragment from an Activity. In the example you will see that a FrameLayout in the Activity XML is used a the fragment container. This will be the View in which all of your fragments are displayed.
When you load your fragment with a FragmentTransaction the contents of your fragments layout will be displayed in the container View. In the above referenced example this takes place with SupportFragmentManager a class included with the android support library, for facilitating fragment transactions in earlier version of the operating system. SupportFramgnetManager requires that you extend FramentActivity and not just Activity. If you're not worried about backwards compatibility and are extending activity, not fragment activity, you can simply use getFragmentManager() instead.
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
After the initial add transaction you can switch between fragments using the replace method for your fragment transaction. Replace does exactly what it sounds like, it swaps one fragment for another. To accomplish this from within your firstframgnet use
SecondFragment secondFragment = new SecondFragment();
getActivity().getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, secondFragment).commit();
Notice that from within the fragment I used getActivity(). This allows you to reference the context of the host activity to access the fragment manager. When you are within the activity you do not need to use getactivity because the fragment manager is already accessible from that context.
I have an Activity called Mytaskonclick extends Activity and a Fragment called SentTaskFragment extends Fragment. I want to go from Mytaskonclick to SentTaskFragment on click of a button. I tried using the code
Intent ii=new Intent(Mytaskonclick.this,SentTaskFragment.class);
startActivity(ii);
But this code doesn't work. Can anyone suggest me how to do it?
Fragments does not work like this.You need to put a place holder in your activity, say FrameLayout for example and, inside on click, you get the fragment and attach it inside this placeholder. I suggest you read the Fragment Tutorial Here. It contains all what you need to know and extremely useful for you.
When you want to switch to a Fragment them you have to do that through FragmentManager. Pass that thae Fragment object into beginTransaction() method of FragmentManager along with the container layout which will hold the Fragment as below...
SentTaskFragment fragment = new SentTaskFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().add(R.id.frame_container, fragment).commit();
You can see some tutorial from below link...
Android Developer-Fragment
Multi-pane development in Android with Fragments - Tutorial
Android Fragments
Android Fragments Example
So I have enabled the setting to destroy actvities when you navigate away from an activity
Settings=>Developer Options=>Don't Keep activites
This should basically replicate an activity or fragment getting garbaged collected and then I have to restore the data via the bundle savedinstancestate.
So I understand how that works. But it seems when I navigate from fragment 1 to fragment 2 and then put the application in the background and then in the foreground(destroying the activity)
Both fragment 1 and fragment 2 show at the same time. In which only fragment 2 should be showing.
I do not know if this is something standard that I have to manage hiding and showing fragments onsavedinstance. Or if something in my code is breaking things. Below is how I push fragments which I hope is helpful:
public void pushFragmentWithAnimation(FragmentManager fm, int parentId, Fragment currentFrag, Fragment newFrag, int animEntry, int animExit) {
hideSoftKeyboard(currentFrag.getActivity());
FragmentTransaction ft = fm.beginTransaction();
// See: http://developer.android.com/reference/android/app/FragmentTransaction.html#setCustomAnimations(int, int, int, int)
ft.setCustomAnimations(animEntry, animExit, animEntry, animExit);
ft.add(parentId, newFrag, String.format("Entry%d", fm.getBackStackEntryCount())).hide(currentFrag).show(newFrag);
ft.addToBackStack(null);
ft.commit();
}
Fragment 1 is still in the backstack because when I press back I only see fragment 1. Let me know if you know why this is happening.
The lifecycle of XML added Fragments and programmatically added Fragments differ enough to make mixing them a bad idea, as explained in detail here.
The easiest way around this is to make all fragments programmatically added by replacing your XML inflated Fragment with a FrameLayout of the same ID, then in your onCreate add
FragmentManager fragMgr = getSupportFragmentManager();
if (null == fragMgr.findFragmentByTag(FRAG_TAG))
{
fragMgr.beginTransaction().
add(R.id.fragment, new Fragment1(), FRAG_TAG).commit();
}
Where FRAG_TAG is any unique string. This ensures that Fragment1 is only created if it is not already in the layout.
I am not entirely sure why this solution works. I assume its related to if the activity gets killed that it does not keep track of which fragment is currently shown and shows all of the fragments. So basically I needed to replace:
ft.add(parentId, newFrag, String.format("Entry%d", fm.getBackStackEntryCount())).hide(currentFrag).show(newFrag);
with
ft.replace(parentId, newFrag, tag);
Then when I create the initial fragment in the main activity. I only would do that when
if(savedInstanceState==null){
My updated code is below: https://github.com/CorradoDev/FragmentTest/tree/2c53f9f42e835da768f61b0233f3ab5b3adf2448
I'm struggling combining a tabbed ActionBar and fragments.
I'm using ActionBarSherlock to display three independent tabs, and my problem relates to the first tab exclusively. It's supposed to display items (called "coupons") in a combination of list and detail view. The other two tabs display different content and do not play a role here.
What I'm doing is the following:
The main activity creates three fragments for three tabs
Tab A (a list fragment) populates and renders its list
For clicks on the list I wrote a callback in the main activity that receives the clicked item's id and exchanges the list fragment with the detail fragment on the tab (at least its supposed to do so)
In that callback I create the to-be-displayed detail fragment and try to replace the list fragment with it.
Unfortunately I dont get beyond:
java.lang.IllegalArgumentException: No view found for id 0x7f040027
for fragment CouponDetailFragment{44f4e310 #1 id=0x7f040027}
I attached the relevant snippets at the end of the question. Any help is highly appreciated.
These are the relevant snippets:
public class MyCouponActivity extends SherlockFragmentActivity implements CouponListFragment.Callbacks
List fragment:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:name="foo.bar.CouponListFragment"
android:id="#+id/coupon_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Transaction for fragment exchange:
#Override
public void onItemSelected(final String id) {
final Bundle arguments = new Bundle();
arguments.putString(CouponDetailFragment.ARG_ITEM_ID, id);
final CouponDetailFragment fragment = new CouponDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction().replace(R.id.coupon_list, fragment).commit();
}
If you define a fragment in XML, it is fixed and you can't replace it with another fragment in a FragmentTransaction.
Your best bet would be to replace the <fragment /> with some sort of ViewGroup. Don't forget then you'd have to use a FragmentTransaction to add a CouponListFragment in the onCreate(..) of your Activity.