How can I hide the actionbar in a single fragment? - android

I am using AppCompat for my theme in my app. Also, I am using a viewpager to manage some fragments.
Now I would to hide the actionbar in one of my fragments. How can I do that. I tried to hide the actionbar manually in the fragment like this
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBarActivity activity = (ActionBarActivity) this.getActivity();
ActionBar aBar = activity.getSupportActionBar();
aBar.hide();
}
but this hides the actionbar for all fragments. Any ideas?

When you load other fragments call (for example in onResume):
aBar.show();
Edit:
in each fragment that you want to have show the ActionBar put the following method:
#Override
public void onResume() {
super.onResume();
aBar.show();
}
in the OnResume method of the Fragment which you don't want the action bar to show do this:
#Override
public void onResume() {
super.onResume();
aBar.hide();
}
SInce you're using the view pager I assume you're using code similar to:
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
In which case in this method:
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
// add check here to determine if the selected item is the fragment you want to hide the action bar in...
// if so call aBar.hide();
// for example:
if(i == MY_NO_BAR_FRAGMENT) {
// when you set up the view fragment, you would set MY_NO_BAR_FRAGMENT to the index of that fragment in the view pagers list of pages.
aBar.hide();
}
}
}
}

Related

How to change position of Tab Navigation?

I currently have Tab Based app and the tabs are on bottom. Is there any way to put them up?
Add Tabs To Action Bar
To create tabs using ActionBar, you need to enable
NAVIGATION_MODE_TABS, then create several instances of ActionBar.Tab
and supply an implementation of the ActionBar.TabListener interface
for each one. For example, in your activity's onCreate() method, you
can use code similar to this:
#Override
public void onCreate(Bundle savedInstanceState) {
final ActionBar actionBar = getActionBar();
// Specify that tabs should be displayed in the action bar.
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create a tab listener that is called when the user changes tabs.
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// show the given tab
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
// hide the given tab
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// probably ignore this event
}
};
// Add 3 tabs, specifying the tab's text and TabListener
for (int i = 0; i < 3; i++) {
actionBar.addTab(actionBar.newTab().setText("Tab " + (i + 1)).setTabListener(tabListener));
}
}
How you handle the ActionBar.TabListener callbacks to change tabs
depends on how you've constructed your content. But if you're using
fragments for each tab with ViewPager as shown above, the following
section shows how to switch between pages when the user selects a tab
and also update the selected tab when the user swipes between pages.
From Docs.

Android refresh actionbar and title on fragment change

in my app i am developing an activity using the actionbar in NAVIGATION_MODE_TABS-mode.
Each tab is showing a fragment (list, detail).
Initially the list-tab is visibile.
The list is implementing setMultiChoicheModeListener() and modifies the ActionBar and the title of the activity if one or more items are selected.
How can i reset the title and the ActionBar to the inital value (title and actions) when the user clicks on the detail-tab without deselecting the items?
BTW Target-Platform is > 4.1 and i am not using the support library.
Thanks.
public class MyActivity extends Activity {
#Override
protected void onCreate (Bundle savedInstanceState) {
this.actionBar = getActionBar();
this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
....
for (Tab tab : getTabs())
{
//here are two tabs added (List and Detail)
this.actionBar.addTab(tab);
}
....
}
protected class NavigationTabListener implements ActionBar.TabListener {
private Fragment fragment;
....
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(newFragmentResourceId, this.fragment);
}
}
}
public class MyListViewFragment extends LinearLayout implements IListViewFragment {
....
#Override
public void initialize() {
inflate(getContext(), listLayoutResourceId, this);
this.myList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
this.myList.setMultiChoiceModeListener(new MultiChoiceModeListener() {
....
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
{
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(selectedItemsMenuResourceId, menu);
return true;
}
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked)
{
if (checked)
{
this.numberItemsSelected++;
adapter.setNewSelection(position);
}
else
{
this.numberItemsSelected--;
adapter.removeSelection(position);
}
mode.setTitle(getContext().getResources().getQuantityString(
R.plurals.items_selected, this.numberItemsSelected,
Integer.valueOf(this.numberItemsSelected)));
}
....
}
}
I am trying to implement the MVP pattern, but it's still in evaluation phase. The Activity acts as the presenter, the views are in separate classes.
For each Fragment i am also implementing the MVP apttern, but i think this is not interesting to solve the problem.
Some notes to the classes:
MyActivity creates two fragments (one for List, one for Detail view, the detail view has nothing to do with the selected items).
The initial view of the activity is the fragment with the list.
If the user selects some entries I am updating the action bar and the title through the callback of MultiChoiceModeListener.
But the user can now change the fragment by clicking on the "Detail" tab without deselecting the items or clicking to the new elements in the action bar, the result is that the detail fragment is shown, but the title of the activity is still the one I modified in the MultiChoiceModeListener, and there is also the check mark of the action bar visible (auto created by the system).
So the best way is I think to get somehow the current ActionMode, so I can invoke finish() to "reset" the ActionBar and the title.
Make sure you keep reference of the ActionMode in the ActionMode.Callback methods inside your activity which has the ActionBar.TabListener.
When a new tab is selected just finish the action mode, like:
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if(mActionMode != null){
mActionMode.finish();
}
ft.replace(newFragmentResourceId, this.fragment);
}
Make the ActionMode reference back to null when onDestroyActionMode(ActionMode) is called.

Tabs in Actionbarsherlock are always inside the actionbar?

I was running the demo from Actionbersherlock samples and noticed the tabs were always inside the actionbar as in the picture. How do I fix this?
thnx.
public class TabNavigation extends SherlockActivity implements ActionBar.TabListener {
private TextView mSelected;
#Override
public void onCreate(Bundle savedInstanceState) {
setTheme(SampleList.THEME); //Used for theme switching in samples
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_navigation);
mSelected = (TextView)findViewById(R.id.text);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (int i = 1; i <= 3; i++) {
ActionBar.Tab tab = getSupportActionBar().newTab();
tab.setText("Tab " + i);
tab.setTabListener(this);
getSupportActionBar().addTab(tab);
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction transaction) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction transaction) {
mSelected.setText("Selected: " + tab.getText());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction transaction) {
}
}
Code From here:
https://github.com/JakeWharton/ActionBarSherlock/blob/master/actionbarsherlock-samples/demos/src/com/actionbarsherlock/sample/demos/TabNavigation.java
Per the Action Bar Tabs guide:
the system adapts the action bar tabs for different screen sizes—placing them in the main action bar when the screen is sufficiently wide, or in a separate bar (known as the "stacked action bar") when the screen is too narrow
As ActionBarSherlock mimics the platform behavior, tabs will appear in the Action Bar if there is enough space. You cannot force the stacked action bar pattern as per other answers.
actionbarsherlock has different modes use the correct one
I use this:
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
and the tabs are below the bar.
the different modes should be listed in the samples and documentation

Action Bar Tabs without using Fragments?

It is maybe quite a newbie question but anyway. Since Tabhost is depreciated I tried to switch to the action bar tabs but I have my problems using fragments. Is there a possibility to use activities within the action bar tabs anyway?
I would appreciate any help.
Thanks.
If you're set on using Activities over Fragments you could just use an intent to launch your activity from your ActionBar.TabListener
startActivity(new Intent(thisActivity(), thatActivity.class));
You should also check out this comment about using Fragments over Activities
Is there a possibility to use activities within the action bar tabs anyway?
Fortunately, no.
That does not mean you have to use fragments, though. Your TabListener can do whatever it wants to affect the change in your UI. A brute-force solution would be to call setContentView() again, to dump all your old widgets and lay down a brand-new (presumably different) set.
It's possible to use an Activity with the ActionBar. Beware this is not intended behaviour though, but that doesn't mean it doesn't work perfectly.
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
//#SuppressLint("NewApi")
public class ActionBarActivity extends Activity {
private String TAG = getClass().getName();
private Intent i = null;
private ActionBar actionBar;
private Tab one;
private Tab two;
private Tab three;
// create a tab listener that is called when the user changes tabs
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
if (tab.getTag().equals("one")){
Log.d(TAG, "tab one selected");
i = new Intent(getApplicationContext(), One.class);
determineRun();
}
if (tab.getTag().equals("two")){
Log.d(TAG, "tab two selected");
i = new Intent(getApplicationContext(), Two.class);
determineRun();
}
if (tab.getTag().equals("three")){
Log.d(TAG, "tab three selected");
i = new Intent(getApplicationContext(), Three.class);
determineRun();
}
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
// TODO Auto-generated method stub
}
};
// we only need to start the Activity if it's not actually already the current Activity!
void determineRun(){
if (!TAG.equals(i.getComponent().getClassName())){
startActivity(i);
}
return;
}//end method
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setSubtitle(getResources().getString("subtitle"));
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
one = actionBar.newTab();
one.setText("Tab 1").setTag("one");
two = actionBar.newTab();
two.setText("Tab 2").setTag("two");
three = actionBar.newTab();
three.setText("Tab 3").setTag("three");
one.setTabListener(tabListener);
two.setTabListener(tabListener);
three.setTabListener(tabListener);
// You will have to set the selected Tab manually
// A good idea would be to create a subclass for each Tab based on this code
// Then, just create a new Activity which extends ActionBarActivity
actionBar.addTab(one, 0, false);
actionBar.addTab(two, 1, true); // selected Tab
actionBar.addTab(three, 2, false);
}//end method
#Override
public void onResume(){
super.onResume();
Log.d(TAG, "onResume()");
Log.d(TAG, ""+i.getComponent().getClassName());
// again, here you need to select the Tab manually
if (!TAG.equals(i.getComponent().getClassName())){
actionBar.selectTab(two); // selected Tab
}
}//end method
#Override
public void onPause(){
super.onPause();
Log.d(TAG, "onPause()");
}//end method
#Override
public void onBackPressed() {
super.onBackPressed();
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}//end method
}//end class
You probably want to override the animation in your Activity so the change of tabs is seemless.
To do so, modify the onCreate() method of your Activity which extends ActionBarActivity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(0, 0);
}//end method
if my understanding is correct, you want to use action bar to swap activity instead of fragment. in this case, please continue to read.
from the official document you can see, the actionbar feature defines a set of ui, position. if you want to implement actionbar with activity, the most important thing to do is
1. to associate your tab(position) with your activity.
2. add tablistener callback(instantiate your new activity, stop the current activity) every time the tab is click
the best design is to have the tablistener implemented a seperate class, so that each of your activity could use this class.

Action items from Viewpager initial fragment not being displayed

In the application I am developing I am using a ViewPager with fragments and each fragment constructs its own menu independently of all of the other fragments in the ViewPager.
The issue is that sometimes the fragments that are initialised by the ViewPager by default (i.e in it's initial state) are not having their items populated into the action items menu. What's worse is that this issue only occurs intermittently. If I swipe through the ViewPager enough so that the fragments are forced to re-initialise them selves, when I swipe back, the menu populates correctly.
Activity code:
package net.solarnz.apps.fragmentsample;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
public class FragmentSampleActivity extends Activity {
private ViewPagerAdapter mViewPagerAdapter;
private ViewPager mViewPager;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (mViewPagerAdapter == null) {
mViewPagerAdapter = new ViewPagerAdapter(getFragmentManager());
}
mViewPager = (ViewPager) findViewById(R.id.log_pager);
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setCurrentItem(0);
}
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 8;
}
#Override
public Fragment getItem(int position) {
Fragment f = Fragment1.newInstance(position);
// f.setRetainInstance(true);
f.setHasOptionsMenu(true);
return f;
}
}
}
Fragment code:
package net.solarnz.apps.fragmentsample;
import android.app.Fragment;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
public class Fragment1 extends Fragment {
int mNum;
static Fragment newInstance(int num) {
Fragment1 f = new Fragment1();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mNum = getArguments() != null ? getArguments().getInt("num") : 0;
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_list, menu);
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/log_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_refresh"
android:title="Refresh"
android:icon="#android:drawable/ic_delete"
android:showAsAction="ifRoom|withText" />
</menu>
Action menu being populated:
http://i.stack.imgur.com/QFMDd.png
Action menu not being populated:
http://i.stack.imgur.com/sH5Pp.png
You should read this (by xcolw...)
Through experimentation it seems like the root cause is invalidateOptionsMenu getting called more than one without a break on the main thread to process queued up jobs. A guess - this would matter if some critical part of menu creation was deferred via a post, leaving the action bar in a bad state until it runs.
There are a few spots this can happen that aren't obvious:
calling viewPager.setCurrentItem multiple times for the same item
calling viewPager.setCurrentItem in onCreate of the activity. setCurrentItem causes an option menu invalidate, which is immediately followed by the activity's option menu invalidate
Workarounds I've found for each
Guard the call to viewPager.setCurrentItem
if (viewPager.getCurrentItem() != position)
viewPager.setCurrentItem(position);
Defer the call to viewPager.setCurrentItem in onCreate
public void onCreate(...) {
...
view.post(new Runnable() {
public void run() {
// guarded viewPager.setCurrentItem
}
}
}
After these changes options menu inside the view pager seems to work as expected. I hope someone can shed more light into this.
source http://code.google.com/p/android/issues/detail?id=29472
The simple answer is to not use menus within fragments in the ViewPager.
If you do need to use menus within the fragments, what I suggest is loading the menu's through the onCreateOptionsMenu method in the parent Activity. Obviously you will need to be able to determine which menu to show.
I was able to achieve this by using class reflection.
You will also need to use the invalidateOptionsMenu method each time you switch pages. You will need a OnPageChangeListener to call this when the ViewPager changes pages.
I also had same issue. In my case I have one activity with viewpager that contains two fragments, every fragment inflate its own action menu but fragment actions menu not shown.
View pager adapter code
public class ScreensAdapter extends FragmentPagerAdapter {
public TrackerScreensAdapter(Context context, FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 2;
}
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = new Fragment1();
break;
case 1:
fragment = new Fragment2();
break;
}
return fragment;
}
}
Activity on create
screensAdapter = new ScreensAdapter(this, getFragmentManager());
viewPager.setAdapter(screensAdapter);
This way my viewPager has two fragments, every fragment fire its own task in onActivityCreated, obtain data and draw its layout based on obtained data. Also every fragment has onCreateOptionsMenu
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
MyTask task = new MyTask();
task.setTaskListener(this);
task.execute();
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
}
Spent many times to solve this problem and figure out why fragment menu not shows.
All that I was need is
screenAdapter = new ScreenAdapter(this, getFragmentManager());
viewPager.post(new Runnable() {
public void run() {
viewPager.setAdapter(screenAdapter);
}
});
In my case I traced the root cause of the issue to what I believe is a bug in FragmentStatePagerAdapter which is calling Fragment#setMenuVisibility to false and failing to properly set it back to true when it restores it's state.
Workarounds:
Use FragmentPagerAdapter instead of FragmentStatePagerAdapter
If you must use FragmentStatePagerAdapter, in your adapter subclass override setPrimaryItem like so:
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
//This is a workaround for a bug in FragmentStatePagerAdapter
Fragment currentItem = getItem(position);
if (currentItem != null) {
currentItem.setMenuVisibility(true);
currentItem.setUserVisibleHint(true);
}
}
First create a method in the sub class of FragmentPagerAdapter to get the current fragment
public SherlockFragment getFragment() {
return currentFragment;
}
#Override
public void onTabSelected(final Tab tab, FragmentTransaction ft) {
((SherlockFragmentActivity) mContext).invalidateOptionsMenu();
Fragment f = ((SherlockFragmentActivity) mContext)
.getSupportFragmentManager().findFragmentByTag(
makeFragmentName(tab.getPosition()));
currentFragment=(SherlockFragment) f;
}
Now override below methods in Main Actvity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (mTabsAdapter.getPositionOfTabSelected() != 0) {
menu.add("Read").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Write").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Clear").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Factory data reset").setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
return super.onCreateOptionsMenu(menu);
}
Now call the onOptionItemSelected from activity to fragment
#Override
public boolean onOptionsItemSelected(MenuItem item) {
mTabsAdapter.getFragment().onOptionsItemSelected(item);
return super.onOptionsItemSelected(item);
}
I solved a very similar issue in which the Action bar icons assigned by the fragment inside of a ViewPager were disappearing onPause(). They would reappear when the Fragment came back into view and the user swiped left or right, but not immediately. The solution was calling notifyDataSetChanged() on the PagerAdapter in the onResume() method of the fragment.
#Override
public void onResume() {
mPagerAdapter.notifyDataSetChanged();
}
I was having this problem with the Action Bar Items while I was using HorizontalScrollView to show the tabs but I changed to PagerTitleStrip and the problem was solved.
Perhaps this information can help someone else.
My solution to this problem was to only inflate fragment menus if the fragment is currently visible. This solution may be too specific for your purposes, but it might help someone.
In the main activity:
boolean isFragmentVisible(int fragmentIndex) { ... }
In onCreateOptionsMenu() in your fragment:
if ( getActivity().isFragmentVisible(HOME_FRAGMENT_POS) ) {
inflater.inflate(R.menu.menu_home_fragment, menu);
}

Categories

Resources