Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-27474] NavigationBar/ActionBar parity between Android and iOS

GitHub Issuen/a
TypeImprovement
PriorityNone
StatusOpen
ResolutionUnresolved
Affected Version/sRelease 8.2.0
Fix Version/sn/a
ComponentsAndroid, iOS
Labelsn/a
ReporterJan Vennemann
AssigneeJan Vennemann
Created2019-10-16T14:15:05.000+0000
Updated2019-10-16T16:03:16.000+0000

Description

With the introduction of [NavigationWindow](https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.NavigationWindow) as a cross platform component in 8.0.0 we now have some parity issues when it comes to configuring the native ActionBar/NavigationBar.

iOS

On iOS the underlying NavigationBar can easily be configured with a bunch of properties directly in the containing Window. Namely these are: - leftNavButton - leftNavButtons - rightNavButton - rightNavButtons - hideBackButton - titleControl *Example*
<Alloy>
    <TabGroup>
        <Tab>
            <Window class="container">
                <LeftNavButton platform=ios>
                    <Button title="Back" onClick="closeWindow" />
                </LeftNavButton>
            </Window>
        </Tab>
    </TabGroup>
</Alloy>

Android

Android offers similar customization, but requires a completely different API. Users need to manually grab a window's activity and then configure the actionBar property. In addition the activity also offers onCreateOptionsMenu to create a dropdown menu that can be opened from the ActionBar. Alloy already provides some convenient elements to configure these two properties directly from within a Window. *Example*
<Alloy>
    <Window title="My Test App">
        <ActionBar id="actionbar" title="My XML Menu" onHomeIconItemSelected="doMenuClick" />
        <Menu>
            <MenuItem id="item1" title="Settings" onClick="openSettings" />
            <MenuItem id="item2" title="Search" onClick="doSearch" />
        </Menu>
        <Label id="label">Welcome!</Label>
    </Window>
</Alloy>

Proposed solution

We need a common abstraction of the native ActionBar/NavigationBar that allows for easy configuration on both platforms. Alloy already has some custom behavior that differs from our classic API, although it is specific to the Android ActionBar. This proposal builds upon a similar approach but with cross-platform parity in mind.

ActionBar

Introduce a new actionBar property that transparently handles the ActionBar/NavigationBar setup behind the scenes using our existing API. We should do this via our bootstrapping mechanism for a JS only solution that won't require any changes to our native core.

API proposal

interface ActionBar {
  title?: string
  titleView?: Ti.UI.View
  navigationButton?: NavigationButton
  items?: ActionItem[],
  icon?: string // Android only
}

interface NavigationButton {
  title?: string // iOS only
  icon?: string // Android only
  click?: (e: Event): void // Android only
}

interface ActionItem {
  android?: ActionItemOptions<ActionItemPositionAndroid>
  ios?: ActionItemOptions<ActionItemPositionIos>
  click: (e: Event): void
  hidden: bool
}

enum ActionItemPositionAndroid {
  ActionBar = "actionBar" // Ti.Android.SHOW_AS_ACTION_ALWAYS
  ActionBarIfRoom = "actionBarIfRoom" // Ti.Android.SHOW_AS_ACTION_IF_ROOM
  ActionBarWithText = "actionBarWithText" // Ti.Android.SHOW_AS_ACTION_WITH_TEXT
  Popup = "popup" // Ti.Android.SHOW_AS_ACTION_NEVER
  CollapseActionView = "collapseActionView" // Titanium.Android.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
}

enum ActionItemPositionIos {
  Left = "left"
  Right = "right"
}

interface ActionItemOptions<T> {
  position: T
  icon: string | number
  title: string
  actionView: Ti.UI.View // Android only
}

Ti.UI.Window.actionBar: ActionBar;
All of the properties on ActionBar are optional. If not set, our current default behavior is used.

Title text and view

const win = Ti.UI.createWindow();
win.actionBar.title = 'Test' // instead of win.title
In addition to setting a simple text as in the example above, users can set a custom view.
const titleView = Ti.UI.createView({ layout: 'horizontal' });
const imageView = Ti.UI.createImageView({ image: '/logo.png' });
const titleLabel = Ti.UI.createLabel({ text: 'My App', left: 5 });
titleView.add(imageView);
titleView.add(titleLabel);
win.actionBar.titleView = titleView;

Navigation button

The navigationButton represents the default back navigation button to the left.
win.actionBar.navigationButton.title = 'Prev';

Android Specifics / Limitations

On Android you *cannot* set the title. However you *can* set an icon.

iOS Specifics / Limitations

On iOS you can *only* change the title of the button.

Action items

The available buttons / menu of the native ActionBar/Navigation can be controlled with action items.
const onSave = () => { console.log('Saved') };
const onCancel = () => { console.log('Canceled') };
win.actionBar.items = [
  {
    click: onSave,
    android: {
      title: 'Save',
      icon: 'item1.png'
      position: 'actionBar'
    },
    ios: {
      icon: Titanium.UI.iOS.SystemButton.SAVE
      position: 'right'
    }
  },
  {
    click: onCancel,
    android: {
      title: 'Cancel',
      icon: 'item2.png'
      position: 'actionBar'
    },
    ios: {
      icon: Titanium.UI.iOS.SystemButton.CANCEL
      position: 'left'
    }
  }
]

Comments

No comments

JSON Source