How to build UINavigationController-like behaviour in Android? - android

I'm aware the View structure for Android is completely different (ie. Activities instead of View Controllers) but I need to create a Navigation Bar that persists between views.
Is the best way really to have just one single Activity and then a lot of Fragments?
If so, has this implementation already been done somewhere else that I can use? It seems like something that would come up a lot as I've seen numerous Android apps do this.

I made a Framework (github) to provide a hierarchical navigation pattern, with animations to provide sense of navigation, rather than launching new Activities every time.
Here's how to use it:
Add the framework to your project as a Module
Add a new Java class in your project ("File - New - Java Class").
Note: If you are editing the Activity.java file that provides you the template, delete all its implementations and leave it empty.
Make it extend NavigationActivity
Implement all the NavigationActivity abstract methods
(in Android Studio if you click Alt + insert and select implement - methods all the function definitions are automatically generated).
public class NavigationTest extends NavigationActivity{
#Override
public Fragment firstFragment() {
//return the first fragment that will be shown
}
#Override
public Boolean showBackButtonInFirstFragment() {
//show back button already in the first Fragment
//set to True if this activity is called by another Activity
//the back button will then pop back to the previous Activity
}
#Override
public Boolean showMasterDetailLayoutInTablets() {
//set to false if you don't want a master-detail layout in tablets
}
}
Presenting a new Fragment
You can present a new fragment (with a nice animation) by calling the pushFragment method from NavigationActivity.
public void pushFragment(Fragment newFragment, animationType animation, boolean showAsDetailFragmentIfPossible)
newFragment (Fragment): New Fragment that will be presented
animation (animationType): Animation type enum: RIGHT_TO_LEFT, BOTTOM_TO_TOP, FLIP
showAsDetailFragmentIfPossible (boolean): If set as True, the user is in a Tablet, and you are using a master-detail layout, the Fragment will be shown in the detail Fragment (the panel in the right)!
Since you can access the activity from any Fragment with the getActivity() method, you can show a new Fragment from the currently displaying Fragment.
For example you can put this code within a button click listener:
NextFragment f = new NextFragment();
NavigationActivity nav =((NavigationActivity)getActivity());
nav.pushFragment(f,NavigationActivity.animationType.RIGHT_TO_LEFT,false);
You don't have to worry about implementing the back button behaviour. This is handled automatically by the NavigationActivity class.

Related

Android TablaLayout and NavigationDrawer

I have a two problems and struggle for a few days. I am not sure what the right way is.
I want to combine a tab layout with a view pager containing three fragments (the tab layout and the view pager are the home screen) and a navigation drawer.
And I think that everything you can navigate to from the drawer should be a fragment accept settings or something similar.
So should I let the tab layout in the layout of the main activities layout or should I put the this layout also in a fragment (so view pager with fragments inside a so calling home fragment)?
When starting the app I check if the user is logged in and if he is download data from Firebase. I do this in another fragment (data fragment) there I setretaininstance to true.
So currently one of the tab fragments needs the data from Firebase but soon all of them will need it.
How do I pass the data (Lists) from the data fragment to the tab fragments or the so called home fragment and then to the tabs.
I already tried interfaces but I don't know how to handle confirmation changes.
Considering the two problems or the combination of both how would you solve this / which design approach is better only use fragments or let the home screen inside the main activity and change the view when the user navigates from the drawer to fragment?
PS. I will add some code as soon as possible.
Thanks.
TabLayout and the ViewPager should be in the Activity layout since it makes more sense, as the Activity manages the Fragments. Also, navigation drawer should navigates through Activities, and Activities between Fragments. Again, that's the logical thing for a decent code organization, and it prevents repetitions in layout (AKA more than one button to navigate to the same fragment).
For the Firebase issue, I suggest you start the call in the Activity, and then call a function in all fragments with the retrieved information. Something like this:
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(MyFragment f : mFragmentList)
f.addData(dataSnapshot);
}
}
If you really want the Fragment to make the call to Firebase, then you can create you own Event and Listener set.
public class SnapshotRetrievedEvent {
private static List<SnapshotRetrievedListener> listeners = new ArrayList<>();
public static void addListener(SnapshotRetrievedListener listener){
listeners.add(listener);
}
public static void notify(DataSnapshot snapshot) {
for(SnapshotRetrievedListener listener : listeners)
listener.onSnapshotRetrived( snapshot );
}
}
public interface SnapshotRetrievedListene {
void onSnapshotRetrieved(DataSnapshot snapshot);
}
Then in your Fragment waiting for the snapshot, you add the listener like this:
SnapshotRetrievedEvent.addListener(
new SnapshotRetrievedListener(){
#Override
public void onSnapshotRetrieved(DataSnapshot snapshot){
// Do stuff
}
}
);
onSnapshotRetrieved will be called when you call SnapshotRetrievedEvent.notify(snapshot) in your other Fragment.
Hope this helps

Where to put the Fragment functional code?

Just a general question about working with Fragments and Activitys for android development: where does the business end of the functional code go for Fragments loaded into an Activity dynamically? (i.e. a fragment's OnClickListeners, OnCheckedChangedListeners, button logic methods...)
Do they go in the Fragment class, or the Activity class?
All the GUI logic for views attached to a fragment should be contained inside the fragment itself.
Thus a fragment should be as self contained as possible.
You can, though, if necessary do callbacks to your activity based on fragment GUI interaction. This can easily be done like this inside the fragment:
#Override
public void onAttach(Activity activity) {
if (!(activity instanceof SherlockFragmentActivity)) {
throw new IllegalStateException(getClass().getSimpleName()
+ " must be attached to a SherlockFragmentActivity.");
}
mActivity = (SherlockFragmentActivity) activity;
super.onAttach(activity);
}
In this specific case the reason for gaining a reference to SherlockFragmentActivity is to gain access to the support menu inflater mActivity.getSupportMenuInflater(), hence the construction can of course also serve to gain information from the underlying activity.
This probably depends on how much the Fragment's functionalities have in common, and how many, let's say Buttons, have to be handled.
I personally (and it's probably most common practice) handle onClick(...) events separately for each Fragment, meaning that I let each Fragment implement it's own OnClickListener.
Furthermore, when handling everything through the Activity, probably not all the components that react to click-events are in memory at all times and can be reached via findViewById(...), depending on which Fragment is currently displayed and how your user-interface is built up in general.
they always in fragment class because fragment is one type of component in android which we can reuse it. if we put onclick and oncheckchanged in activity then what meaning of reusing that component??
for more information about please go through following step:
Link 1 for basic level of information about fragment and how to handle them
Link 2 for dealing with multi pane fragment
Standard site for fragment
It depends:
If fragment can handle logic which is self sufficient(complete) then that code can be handled by fragment. e.g. on click call phone number.
If fragment have UI whose action is activity specific, then you want to add listener in activity.
e.g. master detail view like email client, on tablet user click on title fragment1 which have list of email titles, then handler on click in activity can show detail fragment2 in activity.
In all you want to keep fragment reusable.

Why are the fragments communicating through the container Activity are called reusable?

I'm wondering why are the Fragments communicating through the container Activity are called reusable.
From: http://developer.android.com/guide/components/fragments.html I know that:
You should design each fragment as a modular and reusable activity
component. That is, because each fragment defines its own layout and
its own behavior with its own lifecycle callbacks, you can include one
fragment in multiple activities, so you should design for reuse and
avoid directly manipulating one fragment from another fragment.
Let's take an example; I have a DateSetFragment which contains two buttons; first button fires TimePickerDialog (FragmentDialog) which allows user to pick an hour and the second one DatePickerDialog (FragmentDialog) which allows user to pick a day. At the end gathered data should be sent back to the DateSetFragment.
According the: http://developer.android.com/training/basics/fragments/communicating.html:
All Fragment-to-Fragment communication is done through the associated
Activity. Two Fragments should never communicate directly.
communication between fragments should be done via interfaces through the container activity. Given that I should send my collected data from both Fragment Dialogs to the container activity and then from the Activity back to the DateSetFragment. I don't see how this make my DateSetFragment reusable and modular in any way. Doing so I have to implement fragment interfaces and some crucial logic in my container Activity which makes it connected with it.
The question is; Is it wrong in this situation if Fragment Dialogs will communicate directly with the DateSetFragment ?
It is "modular" because those interfaces are well defined and explicitly implemented by the hosting activity.
Anywhere you drop that fragment in, if the activity implements the callback interface defined by the fragment events the activity can choose what to do depending on what environment the fragment is attached in.
Example,
DatePickerFragment extends Fragment {
public interface DatePickerFragmentEventListener {
public void onDateSelected(DateTime dt);
}
}
Activity1 extends Activity implements DatePickerFragmentEventListener {
DatePickerFragment mDatePickerFragment;
OtherFragment mFragment2;
#Override
public void onDateSelected(DateTime dt) {
mFragment2.setSomeViewsText(dt.toString());
}
}
Activity2 extends Activity implements DatePickerFragmentEventListener {
DatePickerFragment mDatePickerFragment;
#Override
public void onDateSelected(DateTime dt) {
SharedPrefClient c = SharedPrefClient.getInstance();
c.setExpirationDateTime(dt);
}
}
I have a dateTimePickerFragment (or whatever), in one activity I have 2 fragments, when you change the date on the picker I want to update the other fragment's text view to display that date. In another activity I might use that exact same callback to write the chosen date to SharedPreferences.
The point is that the Fragment is a contained piece of UI interaction, and certain events it will notify the enclosing Activity of what just happened to it, so that the activity dictates that the result of an action on the fragment does to either other fragment or the application itself. There is no reason to implement a custom fragment for each and every situation.

Use Activity or Fragment in Android Application

I am new in android. I often use Activity to change from one screen to another screen with other function. Example from Home Page to Popular page. After that, i know about fragment but i never use it before. So, if i have a application with multi tab on a screen, not use TabHost here. Function of every tab very diffrent, ex : tab Home, tab Popular, tab News, tab Profile ... like Instagram App. I must use that
Activity to change Screen to another Screen, it means: i have Home Activity, Popular Activity, ... and change Activity when change Sreen. Each Activity have each layout.
Use fragment within one Activity. We have multi fragment, example HomeFragment, Popular Fragment... chang replace Fragment when change Screen.
What way is better ?
I want to ask when use only phone screen. ( small size screen, not for tablet).
It's important to think of Android devices as more of a spectrum, than clear "phone" vs. "tablet" buckets. There are many instances where you might want to show more information on screen on medium and large screens. Sometimes, this translates to showing two "Activities" at once.
Using Fragments requires little overhead, but adds measurable flexibility, especially when considered early in the development process. If you use Fragments properly, adapting to larger screens is extremely simple. However, there are a few "gotchas" that may make Fragments appear to be more daunting that they actually are:
Fragment classes must always be declared public (if it's a nested class, it must be static).
In the parent Activity (or FragmentActivity), only add the root Fragment if savedInstanceState == null. If you are managing the state of your Fragment properly, everything is handled for you (scroll position, EditText values, etc).
The parent Activity must call through to onSavedInstanceState in order for the Fragment to properly restore it's state.
setRetainInstance(true) should only be used for "headless" Fragments. This is when you use a Fragment that has no UI, and isn't added to the back stack, which is typically used to do life-cycle dependent work.
Fragments declared in XML cannot be used in a FragmentTransaction (and vice-versa).
Think of a Fragment as a modular view, that provides hooks (callbacks) to it's Activity when something important happens. The Activity decides, based on the available space, whether to launch a new Activity, or show a new Fragment.
You can use either way. If you decide to use the Activity solution, create a base activity class that contains all the Tab functionality. You don't want to implement that in every Activity over and over again.
public class BaseActivity extends Activity {
#Override
public void onCreate(...) {
// Init tabs
}
// Methods for tab handling
}
Every Activity (Popular, Profile, Home, ...) extends BaseActivity
public class PopularActivity extends BaseActivity {
#Override
public void onCreate(...) {
super.onCreate(...);
// Init only the popular activity elements here
}
}
This way you implement the tab functionality only once and get it in every activity.

Android UINavigationController-like feature

On the iPhone I use a Navigation Controller to push and pop Views from. Very handy.
Is there an equivalent in Android?
This is an old question, but I believe the answer has changed. It is now possible to imitate the Nav stack in iOS in android using Fragments.
http://developer.android.com/reference/android/app/Fragment.html
Basically instead of jumping from Activity to Activity you instead stay in one Activity that controls the display, organization, and animation of Fragments which each contain their own behavior much like the NavController / UIViewController model in iOS.
It is also backwards compatible as a static library so you can implement it on pre-Honeycomb devices.
Strategies for Honeycomb & backward compatibility
Typically in android, each view is displayed in its own Activity. You can read about activities in the application fundamentals documentation. To move to a new Activity, or view, you use an intent.
If you haven't done so yet, I'd highly recommend reading through those introductary android docs. They aren't too long, and do a good job of explaning the basic program structure.
I made a Framework (github) to provide a hierarchical navigation pattern, with animations to provide sense of navigation, rather than launching new Activities every time.
Here's how to use it:
Add the framework to your project as a Module
Add a new Java class in your project ("File - New - Java Class").
Note: If you are editing the Activity.java file that provides you the template, delete all its implementations and leave it empty.
Make it extend NavigationActivity
Implement all the NavigationActivity abstract methods
(in Android Studio if you click Alt + insert and select implement - methods all the function definitions are automatically generated).
public class NavigationTest extends NavigationActivity{
#Override
public Fragment firstFragment() {
//return the first fragment that will be shown
}
#Override
public Boolean showBackButtonInFirstFragment() {
//show back button already in the first Fragment
//set to True if this activity is called by another Activity
//the back button will then pop back to the previous Activity
}
#Override
public Boolean showMasterDetailLayoutInTablets() {
//set to false if you don't want a master-detail layout in tablets
}
}
Presenting a new Fragment
You can present a new fragment (with a nice animation) by calling the pushFragment method from NavigationActivity.
public void pushFragment(Fragment newFragment, animationType animation, boolean showAsDetailFragmentIfPossible)
newFragment (Fragment): New Fragment that will be presented
animation (animationType): Animation type enum: RIGHT_TO_LEFT, BOTTOM_TO_TOP, FLIP
showAsDetailFragmentIfPossible (boolean): If set as True, the user is in a Tablet, and you are using a master-detail layout, the Fragment will be shown in the detail Fragment (the panel in the right)!
Since you can access the activity from any Fragment with the getActivity() method, you can show a new Fragment from the currently displaying Fragment.
For example you can put this code within a button click listener:
NextFragment f = new NextFragment();
NavigationActivity nav =((NavigationActivity)getActivity());
nav.pushFragment(f,NavigationActivity.animationType.RIGHT_TO_LEFT,false);
You don't have to worry about implementing the back button behaviour. This is handled automatically by the NavigationActivity class.
There are thee basic types in Android to show UI in Android:
View
Fragment
Activity
Google IO 2018 introduced Navigation component which should make life easier. It is a wrapper under a standard mechanisms.
Here you can find NavGraph which looks like storyboard and NavController which help to navigate to destination

Categories

Resources