Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-13135] Android: Enable/disable tab navigation for Action Bar

GitHub Issuen/a
TypeNew Feature
PriorityMedium
StatusClosed
ResolutionFixed
Resolution Date2014-07-03T22:21:51.000+0000
Affected Version/sn/a
Fix Version/s2013 Sprint 15 API, 2013 Sprint 15, Release 3.2.0
ComponentsAndroid
Labels3.0.2GA, actionbar, android, exalture, module_actionbar, qe-testadded, tabGroup, triage
ReporterCarter Lathrop
AssigneeHieu Pham
Created2013-03-14T22:23:08.000+0000
Updated2014-09-09T15:08:13.000+0000

Description

We need the capability in Action Bar to turn tab navigation on/off [http://developer.android.com/reference/android/app/ActionBar.html#setNavigationMode(int)] This is important since if we open a lightweight window on top of the tab group which has an action bar, it's wrong to keep the tabs in view. This would make Android action bar navigation similar to iOS, which hides the tabs when opening a new window form the tab group. The current workaround is to hide() the entire action bar, and paint a "fake" action bar (title and icon only) on the lightweight window. Note it's not always possible to open a new activity with a heavyweight window - e.g. I have an ongoing process running in inside a webview which must be capable of firing/receiving events to other windows, thus the whole app must be one activity. Please enable the setNavigationMode method for the action bar API. Thanks Edited to add: it's not just a visual issue - if the action bar is disabled for a lightweight window (in order to hide the tab group) then the lightweight window will lose menu functionality. Titanium needs to embrace more of the Action Bar API ASAP in order to keep up with Android development.

Comments

  1. Carter Lathrop 2013-03-20

    Hi Mark, Thanks for the feature request. Moving to Ti-Mobile, keep a watch on this to see the progression. Also it may help to add example code to show the limitations of the current action bar support. Regards, Carter
  2. Mark Mokryn 2013-03-20

    I'm not sure if code can help, but here's a comparison between iPhone and Android: iPhone: assume you have a tab group with three tabs A, B, C, open a new window from C and you will still see the three tabs, and you can navigate between them. Anytime you are on "C" you will see the new window until you click "Back". Very intuitive.... Android: If you open a lightweight window over the tab group the 3 tabs are still showing, but you cannot navigate between them until you go "back" - this is clearly illogical behavior as the tabs appear "frozen". So the only current options in Ti are to do actionBar.hide() which is visually bad since you also lose the title bar portion of the action bar which you probably want to keep on the new window. The second option is to open a heavyweight window which starts a new activity with a new action bar - and this may not be good for the logic of the application (e.g. you must have something ongoing in the tab group, and can't allow it to be paused). So in many cases the best solution is to open a lightweight window and just change the navigation mode - this is what's done in many Android apps. You can view this as "parity" with iOS - iOS gives you tab group functionality after you open a child window, and changing the navigation mode in Android will give "similar" behavior, with full flexibility to the designer. It's a key feature!
  3. Carter Lathrop 2013-03-20

    Thank you for the clarification, you will be notified when engineering reviews this new feature request. You might want to add your past comment to the new feature description to solidify your point.
  4. Mark Mokryn 2013-03-20

    Here's an example showing how tabs can be toggled in Android: [tab examples](http://www.coderzheaven.com/2012/10/08/dynamically-adding-removing-toggling-removing-actionbar-tabs-android-part-2/) Eventually probably the entire Action Bar API should be covered by Ti, but IMHO setNavigationMode is the most urgent.
  5. Mark Mokryn 2013-03-29

    This was urgent for me so I submitted a [pull request](https://github.com/appcelerator/titanium_mobile/pull/4058). Hopefully you can approve it in time for 3.1.0 Here is the code to test, tested on iPhone, Android 2.x and ICS. Note that drop down list navigation is not yet supported by Titanium, but there is a need to hide/show the tab bar, and this does the job. The only thing I did not do is add NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS, to the Ti constants since I wasn't sure on your desired conventions - thus I'm just using 0 and 2 per the Android specs. Index.xml:
     
       <Alloy>
       	<TabGroup id="myTabs" backgroundColor="white" >
       		<Tab id="tab1" title="Tab 1" icon="KS_nav_views.png">
       			<Window id="win1" title="Tab 1">
       				<Label top=10 color="black">Check with iPhone, Android 2.x and 3+</Label>
       				<Button id="list" top=70 title="open childWin (same activity)" onClick="openChild"/>
       				<Button id="getNavMode" top=170 title="getNavigationMode()" onClick="getNavMode"/>
       			</Window>
       		</Tab>
       		<Tab id="tab2" title="Tab 2" icon="KS_nav_views.png">
       			<Window id="win2" title="Tab 2">
       				<Label color="#999">All the fun is in the other window</Label>
       			</Window>
       		</Tab>
       	</TabGroup>
       </Alloy>
       
    childWin.xml:
     
       <Alloy>
       	<Window id="childWin" backgroundColor="white">
       		<Label top=10 color="black">In iOS the tabs work</Label>
       		<Label top=30 color="black">in Android 2.x they are hidden</Label>
       		<Label top=50 color="black">in Android 3+, I hid them</Label>
       		<Button id="set0" top=100 title="Hide the Tabs" onClick="setStandard"/>
       		<Button id="set0" top=150 title="Show the Tabs" onClick="setTabs"/>
       		<Button id="getNavMode" top=200 title="getNavigationMode()" onClick="getNavMode"/>
       	</Window>
       </Alloy>
       
    index.js:
       var actionBar = null;
       
       function openChild() {
       	var win = Alloy.createController("childWin");
       	win.init(actionBar);
       	
       	if (Ti.Platform.name === 'android') {
       		if (actionBar) {
       			//made sure both property and setter work :)
       			//actionBar.setNavigationMode(0);
       			actionBar.navigationMode = 0;
       		}
       		win.getView().open();
       	} else {
       		$.tab1.open(win.getView());	
       	}
       }
       
       function getNavMode() {
       	if (actionBar) {
       		alert('The navigation mode is: ' + actionBar.getNavigationMode());
       	}
       }
       $.myTabs.addEventListener('open', function() {
       	if (Ti.Platform.name === 'android') {
       		var tabGroupAct = $.myTabs.getActivity();
       		actionBar = tabGroupAct.actionBar;
       		if (actionBar){
       			actionBar.title = "Rock n' Roll";
       		}
       	}
       });
       
       $.myTabs.open();
       
    childWin.js
       var actionBar = null;
       
       exports.init = function(bar) {
       	actionBar = bar;
       };
       		
       function setStandard() {
       	if (actionBar) {
       		actionBar.setNavigationMode(0);
       	}
       }
       
       function setTabs() {
       	if (actionBar) {
       		actionBar.setNavigationMode(2);
       	}	
       }
       
       function getNavMode() {
       	if (actionBar) {
       		// Made sure both property and getter work
       		//alert('The navigation mode is: ' + actionBar.getNavigationMode());
       		alert('The navigation mode is: ' + actionBar.navigationMode);
       	}
       }
       
       $.childWin.addEventListener('androidback', function() {
       	if (actionBar) {
       		actionBar.setNavigationMode(2);
       	}
       	$.childWin.close();
       });
       
    And your course don't forget to modify tiapp.xml to include this:
       <android xmlns:android="http://schemas.android.com/apk/res/android">
           <tool-api-level>16</tool-api-level>
           <manifest android:installLocation="preferExternal">
               <supports-screens android:anyDensity="false"/>
               <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14"
               </manifest>
       </android>
       
  6. Mark Mokryn 2013-03-31

  7. Mark Mokryn 2013-07-16

    If testing this on 3.2.0 then you need to add the following line to tiapp.xml to try my test code:
       <property name="ti.android.useLegacyWindow" type="bool">true</property>
       
    Since in 3.2.0 all windows are heavyweight and my demo code uses lightweight windows. Nevertheless - this doesn't affect the feature or the pull request - we still sometimes need to hide/show the tabs on Android, the "useLegacyWindow" is due to my demo code, not the code in the pull request. Additionally, obviously for SDK >= 3.1.1 must set android:minSdkVersion to at least 10.
  8. Hieu Pham 2013-07-29

    master PR: https://github.com/appcelerator/titanium_mobile/pull/4058
  9. Mark Mokryn 2014-07-02

  10. Eric Merriman 2014-07-03

    Since this particular ticket is for a feature, we will re-close it since it was implemented. The error mentioned will be tracked in the linked ticket: TIMOB-17084. I will move Mark M's comments to preserve them.

JSON Source