I have mentioned this answer in http://mobi-app-dev.blogspot.in/2014/01/android-transactions.html.
Check which events needs to be intercepted and which are to be passed to the child views: http://developer.android.com/training/gestures/viewgroup.html
Instead of using my swipe gesture listener in frame-layout on which fragments are attached, now I am using it on the relative-layouts which are the root-views of the fragments.
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean intercepted = super.onInterceptTouchEvent(event);
// In general, we don't want to intercept touch events. They should be
// handled by the child view.
gestureDetector.onTouchEvent(event);
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean touched = super.onTouchEvent(event);
gestureDetector.onTouchEvent(event);
return touched;
}
Here are some tips that I follow now while using fragments in my activities:
Effective management of transactions for fragment:
[Note: In case you are using FragmentStatePagerAdapter, you can play with replacing a fragment with another fragment at a particular index in the list of fragment that you are using as a data for this adapter, in a way that you are in the same tab but its content is changed without changing the tab. Then use notifyDataSetChanged(). Here you do not use transactions, but otherwise you do].
- Use Fragment.instantiate() to initialize your fragments instead of constructor.
- Use listeners to update/delete the reference of instance (from the collection used to refer them) of fragment onCreateView and onDestroy.
- Use getView() to get the root view of fragment every where and on update functionality.
- Do not keep track of instances, infact avoid static pointers where ever possible.
- Use getSupportFragment instead of keeping reference of FragmentManager in view pager adapter or elsewhere.
- Use attach detatch on transaction hide view, to get rid of child views on Fragment's root view and re initialize. This is because only one fragment needs to be visible at a time, the others need to detach. Therefore re-attach on demand.
- getActivity() or getApplicationContext() whatever applicable, instead of keeping a global variable to keep references to context.
- onConfiguration change (orientation, keyboard, resize): do in activity and pass it to active fragment which manages it. Important: If you do want to use fragments for transactions, do not declare them in layouts. Provide container (layout) id in add fragment transaction.
- A Fragment transaction should be done in an event call, not anywhere else, and such an event should not be repetitive. This prevents Illegal Argument Exception.
- There is a ViewPager method where you do not have to use Fragments.Instead, you can use Views, or ViewGroups. This replaces the nesting of fragments.
- Detect the level of fragments, that means if you want a fragment 'B' to replace existing fragment 'A', and when you want to go back to show fragment 'A' when pressing back on 'B', put that transaction in back stack.
Tip : Carefull while adding swipe feature because there are other clickable views. Swipe with intercept touch on RootView returning false but analysing touches.
One more thing: you should observe that having one fragment in one container at a time resolves another issue: If there are two fragments , one on the top of the other, the clicks from one fragment goes to the other fragment that is beneath. So hide or replace to have just one fragment at a time. Back-Stack helps in maintaining the navigation levels, and on configuration change or update, try to update the same instance of the target active fragment, instead of doing transactions because that changes the order of fragments navigated.