Android - How to co-ordinate Spinner and Fragments when going back? - android

I have a Spinner in my activity which works very simply: When the user selects an item in the spinner, the appropriate Fragment is shown in the activity by replacing the previously-shown fragment.
My spinner uses a SimpleCursorAdapter. And each fragment transaction is added to the back stack.
Everything works fine when selecting spinner items, but when I press the device's BACK button, the spinner selection is not updated.
I see FragmentManager has an addOnBackStackChangedListener() method, but I'm not sure if that is the best way to go (or if it could even work at all)...
So is there a convenient (or other) way to co-ordinate the spinner's selection with the current fragment when going back?
NB - I suppose what I'm ideally looking for would be some kind of Spinner/Fragment equivalent of the TabLayout/ViewPager's tabLayout.setupWithViewPager(viewPager) method.

Related

How should I save state of Fragment that contain a listview on android?

In my app there are two fragments and one activity. On all of them I used listview and fill the content from database. When rotate screen the position of content in activity don't change and start on correct way (as I googled and understand it is normal for activity because of "Bundle savedInstanceState"). My problem is with fragment part that both of the list on fragments are too long list and it could be annoying for end user when press back and came back to fragments start navigate to appropriate item. I googled and find some answer to my question but they don't work for me.
In this case, the states saving or restoring won't work anymore, because the listview was dynamically fill up by database or internet. when I facing this problem, I have a long size dataset for that listview, the rest datasets are coming because my data was show as pagination mode, user may scroll out far from first page, so when fragment destroying, all you can do just save the particular parameters to State Bundle, e.g. the page number, the selection index, the selection y-axis, finally restore the state by your own hands.

How to update the ActionBar Spinner when pressing the back button

I'm going mad soon, been reading Google search results for 10+ hours soon, without any luck.
I think i will drop this whole idea of using a spinner and just use tabs, but it still irritates me that i haven't found a solution. So i hope anyone could help me to understand this issue.
The project im creating has one MainActivityContainer (the main FrameLayout), and than multiple fragments (different layouts) that gets first added and than replaced inside the MainActivityContainer.
So the app only opens ONE activity and than changes pages through different fragments. This makes it super fast to change pages.
Everything except for the ActionBar Spinner works great. It doesnt get updated when pressing the back button, i.e it is still displaying the value for the last fragment.
I want to use the spinner so i easily can navigate between different fragments.
The app start page look something like this:
http://1drv.ms/1jkJpy2
The spinner items are:
1. home , 2. ImageBtn1, 3. ImageBtn2, etc.
So i can reach each destination by either clicking the image button or using the spinner. This is the functionality that i want.
But if i click imagebutton (instead of using the spinner) the value in the spinner (home) does not change to ImageBtn1. So even though i am on the page for ImageBtn1 the spinner shows "Home".
I fixed this by using actionBar.setSelectedNavigationItem(1); in the method for the ImageButton. So imagebuttons uses the spinners methods manually. This sets the spinner to the correct value even if pressing the imagebutton on the start page.
This all works well until i press the back button. Than i have the same problem again, the spinners value doesnt update.
So please explain to me how i can solve this. In other words: How to use a spinner actionbar with ONE activity and many fragments and still get the back button to update the spinner. I have began experimenting with the onBackPressed() method. But there has to be an easier way to achieve what i want to do???
Ok I figured out how to update the navigation spinner in the action bar!
In my problem, I always called actionBar.setSelectedNavigationItem(int); inside the onCreate() method of the activity. However, onCreate() is only called when first making a new activity. So whenever I pressed the back button, the onCreate() doesnt get called and the navigation spinner doesn't get updated. However, the onResume() function always gets called when an activity becomes visible to the user (whether the activity was just created or whether the user pressed the back button into it). So I simply called actionBar.setSelectedNavigationItem(int) in onResume() and the navigation spinner now updates whenever the user presses back!.
However, since you are using one activity with multiple fragments, you should probably put your actionBar.setSelectedNavigationItem(int) inside the onResume() of your fragments instead of the activity. And that should work!
I guess this is a good case for really learning and internalising the activity and fragment lifecycles. Back to more learning for me :).
I was wondering if you managed to find a solution? I have a similar problem to you.
In the activity, inside the onBackPressed() method, try calling getSupportFragmentManager().findFragmentByTag(TAG); where TAG is a string that you can give when adding each of the frames (have a different TAG for each fragment).
So in code, when you are putting the fragment in:
getSupportFragmentManager().beginTransaction().add(R.id...., new MyFragment(), "TAG1");
Then the onBackPressed method would look like:
#Override
public void onBackPressed() {
MyFragment myFragment = (MyFragment)getSupportFragmentManager().findFragmentByTag("TAG1");
if (myFragment.isVisible()) {
getActionBar().setSelectedNavigationItem(int);
}
}
Let me know if that works!
NEVER use NAVIGATION_MODE_LIST and onNavigationItemSelected it is not worth it !
#Override
public boolean onNavigationItemSelected(int position, long itemId)
You also cannot use menu's to do this:
#Override public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
due to inflation ordering.
Reasons:
(1) it generates a "hidden" spinner, for which you can not get the id.
(2) you cannot customize this spinner
(3) you save 30 lines of code, but are permanently limited if you want to add a second bi-directional spinner
(4) not even in the special case of "simple code" (one spinner), you lose to much.
(5) you cannot use tabs.
(6) without the id, you have no chance with fragments.
the key is actionBar.setCustomView(R.layout.action_bar_custom);
and spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()...
for each spinner.
Trust me I lost hours trying each solution.

Persisting Actionbar Spinner state

Because of theming issues, I am using a custom view on the Actionbar, a Spinner. When the user selects a certain item, and then clicks a button, it changes the Actionbar to two buttons, Done/Discard, as Roman Nurik explains here: https://plus.google.com/+RomanNurik/posts/R49wVvcDoEW . Using Otto, the Activity is kept informed when that Fragment is stopped, so it can revert to the normal Actionbar with the Spinner. However, the Spinner doesn't retain selection - if "Manage stores", for example, was selected before clicking the button that changes the Actionbar, when it is "restored", "Manage stores" should be kept selected.
Currently I am using savedInstanceStates to save the selected item, but of course that only works for the "screens" that have the Spinner, and only works for application restarts or device rotation.
In your Spinner's onItemSelectedListener, save the selected position.
You can store the position in the SharedPreferences if you want the position to persist outside of the Activity's scope and after application restart. Or you can store it in a class variable if you want a temporary storage.
In your activity's onResume() method retrieve the stored position and use
spinner.setSelection(int position);

Advantage of ListFragment over a ListView or normal Fragment

I have an activity with a menu of items running down the left side that are textViews. when the user selects one of the textViews it will put a listView in the rest of the area of the activity taking up the other 2\3 of the screen. when the user touches a different textView on that left side menu of the page, it will open a different corresponding listView of items.
i was considering putting a large listview on the screen for this purpose. however one other way is instead of using a regular listView in the activity, i could put a list fragment in there and switch between fragments.
The third choice is to put a fragment in there and put a listView inside of that fragment. I have never used ListFragment before.
which would be the best plan considering that there will be no orientation change? the activity will be locked in the vertical / portrait orientation. this will be running on a tablet, not used on smaller devices like phones.
i don't know if i will need to use loaders, because the list will not be long and the contents of the list will be text only.
is there any advantage to using listFragment over the other choices?
The three choices for this activity:
activity with ListView on it
activity with ListFragment on it
activity with fragment on it that has ListView inside of theFragment`
A ListFragment is basically a slightly specialized Fragment which makes handling a ListView present in the layout of the Fragment easier by offering some convenience methods(like getListView() so you don't need to search for the widget yourself, a method to get the adapter of the ListView etc). If you need a Fragment with a ListView, use a ListFragment. So in the end it's about deciding between a ListView and a ListFragment.
Between the two options, taking in consideration your scenario, I would simply use a ListViewbecause it's plain simple. The need of a Loader isn't a problem as you could use the LoaderManager of the Activity for the ListView.
However, you didn't mention how the BACK button should be handled. If you want to offer the user the possibility of navigating back through his choices use a Listfragment to get that for free from the system.

Android: ListActivity design - changing the content of the List Adapter

I would like to write a rather simple content application which displays a list of textual items (along with a small pic).
I have a standard menu in which each menu item represents a different category of textual items (news, sports, leisure etc.). Pressing a menu item will display a list of textual items of this category.
Now, having a separate ListActivity for each category seems like an overkill (or does it?..)
Naturally, it makes much more sense to use one ListActivity and replace the data of its adapter when each category is loaded.
My concern is when "back" is pressed. The adapter is loaded with items of the current category and now I need to display list of the previous category (and enable clicking on list items too...).
Since I have only one activity - I thought of backup and load mechanism in onPause() and onResume() functions as well as making some distinction whether these function are invoked as a result of a "new" event (menu item selected) or by a "back" press.
This seems very cumbersome for such a trivial usage... Am I missing something here?
Thanks, Rob
If the user hits the back button your Activity will likely get garbage collected.
If you properly start your activity from the menu with the different categories through an Intent, with passing the category etc. and then choosing the content in the onCreate method, you will get a new Instance of your Activity every time the user chooses a category, that will be destroyed after the user hits the back button.
This behaviour is perfectly fine. You don't have to cope with strange error cases and populating the list will take some time so the object creation time of the new ListActivity will be no problem. Try to program it as easy as possible for you and then test if there is a performance problem in the end of doing so.

Categories

Resources