Skip to content

Commit

Permalink
refactor(ios): change Ti.UI.TabbedBar to use UITabBar
Browse files Browse the repository at this point in the history
Fixes TIMOB-28373
  • Loading branch information
jquick-axway committed Mar 2, 2021
1 parent 78c00c4 commit 039318e
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 44 deletions.
6 changes: 1 addition & 5 deletions apidoc/Titanium/UI/ButtonBar.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
---
name: Titanium.UI.ButtonBar
summary: An iOS button bar component.
summary: A horizontal bar of joined buttons.
description: |
The button bar is a set of buttons joined into a single control.
On iOS, you can set up the buttons with either a title or image, but not both.
On Android, you can set up the buttons with a title, image, or both.
Use the <Titanium.UI.createButtonBar> method or **`<ButtonBar>`** Alloy element to create a button bar.
The [TabbedBar](Titanium.UI.iOS.TabbedBar) control is a button bar where the
last selected button mantains a pressed or selected state. The following discussion
applies to both button bar and tabbed bar.
extends: Titanium.UI.View
since: {android: "10.0.0", iphone: "0.8", ipad: "0.8", macos: "9.2.0"}
platforms: [android, iphone, ipad, macos]
Expand Down
56 changes: 26 additions & 30 deletions apidoc/Titanium/UI/TabbedBar.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
---
name: Titanium.UI.TabbedBar

summary: A button bar that maintains a selected state.
summary: A stand-alone bar of tabs.
description: |
A tabbed bar is a button bar that
maintains a state (visually distinguished as a pressed or selected look).
It is closely related to the `ButtonBar` control. See the description of
[ButtonBar](Titanium.UI.ButtonBar) for information on styling tabbed bars and buttons
bars.
This view shows the same tab bar seen in a <Titanium.UI.TabGroup>,
but without the window management. This is intended for apps that want to set up their
own custom tab group like user interface.
Before Titanium 10.0.0, this view would show a
[segmented control](https://developer.apple.com/design/human-interface-guidelines/ios/controls/segmented-controls/)
on iOS. If you want to use a segmented control in Titanium 10.0.0 and higher, then use
<Titanium.UI.OptionBar> instead.
Use the <Titanium.UI.createTabbedBar> method to create a Tabbed Bar.
extends: Titanium.UI.View
platforms: [iphone, ipad, android, macos]
Expand All @@ -21,49 +24,44 @@ excludes:

events:
- name: click
summary: Fired when a button is clicked.
summary: Fired when a tab is clicked.
properties:
- name: index
summary: Index of the clicked button.
summary: Index of the clicked tab.
type: Number
properties:
- name: index
summary: Index of the currently selected button.
summary: Index of the currently selected tab.
type: Number
- name: labels
summary: Array of labels for the tabbed bar.
description: |
The labels can be specified either using an array of strings, in which case
each string defines the title for a button, or using an array of simple
each string defines the title for a tab, or using an array of simple
dictionary objects, <BarItemType>, which can specify title, image, width and
enabled state for each button.
enabled state for each tab.
type: [Array<String>, Array<BarItemType>]
- name: style
summary: Style of the tabbed bar.
description: |
Specify one of the constants:
For iOS:
[Titanium.UI.iOS.SystemButtonStyle](Titanium.UI.iOS.SystemButtonStyle),
either `PLAIN`, `BORDERED`, or `BAR`.
The `BAR` style specifies a more compact style and allows the bar's background
color or gradient to show through.
For Android:
[Titanium.UI.TABS_STYLE_*]
In Android [style](Titanium.UI.TabbedBar.style) is only supported in the creation dictionary
of the proxy.
[TABS_STYLE_BOTTOM_DEFAULT](Titanium.UI.Android.TABS_STYLE_DEFAULT) is a style intended for
tabs that are displayed at the top of the window.
[TABS_STYLE_BOTTOM_NAVIGATION](Titanium.UI.Android.TABS_STYLE_BOTTOM_NAVIGATION) is a style intended
for tabs shown at the bottom of the window. This style only supports up to 5 tabs.
availability: creation
type: Number
default: Titanium.UI.iOS.SystemButtonStyle.PLAIN for iOS, Ti.UI.TABS_STYLE_DEFAULT for Android
constants: Titanium.UI.Android.TABS_STYLE_*
default: Ti.UI.TABS_STYLE_DEFAULT
since: "8.0.0"
platforms: [android]
examples:
- title: Simple Tabbed Bar with 3 items
example: |
``` js
var bb1 = Ti.UI.createTabbedBar({
labels: ['One', 'Two', 'Three'],
backgroundColor: '#336699',
style: Ti.UI.iOS.SystemButtonStyle.BAR,
width: 200,
height: 25,
width: Ti.UI.FILL,
top: 50
});
win.add(bb1);
Expand All @@ -75,8 +73,6 @@ examples:
var win = Ti.UI.createWindow({ layout: 'vertical' });
var tabbedBar = Ti.UI.createTabbedBar({
labels: ['One', 'Two', 'Three'],
backgroundColor: '#336699',
height: '10%',
width: Ti.UI.FILL
});
var scrollView = Ti.UI.createScrollView({
Expand Down
9 changes: 4 additions & 5 deletions apidoc/Titanium/UI/iOS/SystemButtonStyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ summary: |
A set of constants for the system button styles that can be used for the button `style` property.
description: |
These constants represent standard iOS system button styles that affect the
[Button](Titanium.UI.Button), [ButtonBar](Titanium.UI.ButtonBar), and
[TabbedBar](Titanium.UI.iOS.TabbedBar) UI elements.
[Button](Titanium.UI.Button) and [ButtonBar](Titanium.UI.ButtonBar) UI elements.
The different styles are used in different places. For normal buttons which are **not**
contained in a nav bar, toolbar, button bar or tabbed bar, the following styles apply:
Expand All @@ -28,9 +27,9 @@ description: |
* `BORDERED`. Simple button style with a rounded border and a light blue background.
* `DONE`. Like the bordered button, but with a dark blue background.
For `TabbedBar` and `ButtonBar` controls, styles have the following meaning:
For `ButtonBar`, styles have the following meaning:
* `PLAIN`. Default style for `ButtonBar` and `TabbedBar`.
* `PLAIN`. Default style.
* `BORDERED`. Creates a bar like the `PLAIN` bar, but with a heavier border.
translucent buttons that allow the bar's background color to show through.
extends: Titanium.Proxy
Expand All @@ -43,7 +42,7 @@ properties:
description: |
Default style for normal buttons. May also be used for toolbar buttons.
When used with [ButtonBar](Titanium.UI.ButtonBar) or [TabbedBar](Titanium.UI.iOS.TabbedBar),
When used with [ButtonBar](Titanium.UI.ButtonBar),
specifies a standard bar with a heavier border.
type: Number
permission: read-only
Expand Down
15 changes: 15 additions & 0 deletions iphone/Classes/TiUITabbedBar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2021-Present by Axway, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
#import <TitaniumKit/TiUIView.h>

@interface TiUITabbedBar : TiUIView <LayoutAutosizing, UITabBarDelegate> {
NSInteger selectedIndex;
BOOL controlSpecifiedWidth;
UITabBar *tabBar;
}

@end
174 changes: 174 additions & 0 deletions iphone/Classes/TiUITabbedBar.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2021-Present by Axway, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
#import "TiUITabbedBar.h"
#import <TitaniumKit/TiUtils.h>
#import <TitaniumKit/TiViewProxy.h>
#import <TitaniumKit/Webcolor.h>

@implementation TiUITabbedBar

#ifdef TI_USE_AUTOLAYOUT
- (void)initializeTiLayoutView
{
[super initializeTiLayoutView];
[self setDefaultHeight:TiDimensionAutoSize];
[self setDefaultWidth:TiDimensionAutoSize];
}
#endif

- (id)init
{
self = [super init];
if (self != nil) {
selectedIndex = -1;
}
return self;
}

- (void)dealloc
{
RELEASE_TO_NIL(tabBar);
[super dealloc];
}

- (BOOL)hasTouchableListener
{
// since this guy only works with touch events, we always want them
// just always return YES no matter what listeners we have registered
return YES;
}

- (UITabBar *)tabBar
{
if (tabBar == nil) {
CGRect ourBoundsRect = [self bounds];
tabBar = [[UITabBar alloc] initWithFrame:ourBoundsRect];
[tabBar setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
[tabBar setDelegate:self];
[self addSubview:tabBar];
}
return tabBar;
}

#pragma mark UITabBarDelegate methods

- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
// Fetch the index of the selected tab.
NSInteger newIndex = [[self tabBar].items indexOfObject:item];

// Update the proxy's "index" property. (This is in case the property didn't exist to begine with.)
[self.proxy replaceValue:NUMINTEGER(newIndex) forKey:@"index" notification:NO];

// Do not continue if selection hasn't changed.
if (newIndex == selectedIndex) {
return;
}

// Store current selection.
selectedIndex = newIndex;

// Fire a "click" event.
if ([self.proxy _hasListeners:@"click"]) {
NSDictionary *event = [NSDictionary dictionaryWithObject:NUMINTEGER(newIndex) forKey:@"index"];
[self.proxy fireEvent:@"click" withObject:event];
}
}

- (id)accessibilityElement
{
return [self tabBar];
}

- (void)setTintColor_:(id)value
{
UIColor *color = [[TiUtils colorValue:value] color];
[[self tabBar] setTintColor:color];
}

- (void)setBackgroundColor_:(id)value
{
UIColor *color = [[TiUtils colorValue:value] color];
[[self tabBar] setBarTintColor:color];
}

- (void)setIndex_:(id)value
{
// Fetch given index and make sure it's within bounds.
// Note: Only allow index of -1 if no tabs exist. A tab must always be selected.
NSInteger givenIndex = [TiUtils intValue:value def:-1];
NSInteger tabCount = [self tabBar].items.count;
if (tabCount > 0) {
selectedIndex = MIN(givenIndex, (tabCount - 1));
selectedIndex = MAX(selectedIndex, 0);
} else {
selectedIndex = -1;
}

// If above applied a floor/ceiling to index, then update property.
if ((selectedIndex != givenIndex) || ([self.proxy valueForKey:@"index"] == nil)) {
[self.proxy replaceValue:@(selectedIndex) forKey:@"index" notification:NO];
}

// Select the tab.
if (selectedIndex >= 0) {
tabBar.selectedItem = tabBar.items[selectedIndex];
}
}

- (void)setStyle_:(id)value
{
DebugLog(@"[WARN] The style property has been deprecated in 3.4.2 and no longer has any effect");
}

- (void)setLabels_:(id)value
{
// Create the TabBar, if not done already.
[self tabBar];

// Remove all tabs if given a null/empty array.
if (IS_NULL_OR_NIL(value)) {
[tabBar setItems:@[] animated:NO];
selectedIndex = -1;
return;
}

// Create a tab for each "Ti.UI.BarItemType" object in the given array.
ENSURE_ARRAY(value);
NSMutableArray *itemsArray = [[NSMutableArray alloc] init];
for (id nextEntry in value) {
UITabBarItem *tabItem = [[UITabBarItem alloc] init];
if ([nextEntry isKindOfClass:[NSDictionary class]]) {
tabItem.title = [TiUtils stringValue:@"title" properties:nextEntry];
tabItem.image = [TiUtils image:[nextEntry objectForKey:@"image"] proxy:[self proxy]];
tabItem.enabled = [TiUtils boolValue:@"enabled" properties:nextEntry def:YES];
tabItem.accessibilityLabel = [TiUtils stringValue:@"accessibilityLabel" properties:nextEntry];
} else if ([nextEntry isKindOfClass:[NSString class]]) {
tabItem.title = [TiUtils stringValue:nextEntry];
}
[itemsArray addObject:tabItem];
[tabItem release];
}
[tabBar setItems:itemsArray animated:YES];
[itemsArray release];

// Restore the last tab selection if possible.
NSInteger index = [TiUtils intValue:[self.proxy valueForUndefinedKey:@"index"] def:(int)selectedIndex];
[self setIndex_:@(index)];
}

- (CGFloat)contentWidthForWidth:(CGFloat)value
{
return value;
}

- (CGFloat)contentHeightForWidth:(CGFloat)value
{
return [[self tabBar] sizeThatFits:CGSizeMake(value, 0)].height;
}

@end
6 changes: 2 additions & 4 deletions iphone/Classes/TiUITabbedBarProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
#if defined(USE_TI_UITABBEDBAR)
#import "TiUITabbedBarProxy.h"
#import "TiUIButtonBar.h"
#import "TiUITabbedBar.h"

@implementation TiUITabbedBarProxy

Expand All @@ -26,9 +26,7 @@ - (NSString *)apiName

- (TiUIView *)newView
{
TiUIButtonBar *result = [[TiUIButtonBar alloc] init];
[result setTabbedBar:YES];
return result;
return [[TiUITabbedBar alloc] init];
}

USE_VIEW_FOR_CONTENT_WIDTH
Expand Down
6 changes: 6 additions & 0 deletions iphone/iphone/Titanium.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
03C262D525EA176700EBE0F2 /* TiUITabbedBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 03C262D425EA176700EBE0F2 /* TiUITabbedBar.m */; };
0BF9338A1CA0948D0091C7EC /* TiUIiOSStepper.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BF933891CA0948D0091C7EC /* TiUIiOSStepper.m */; };
0BFAD90F1CA1B86B00A04BF7 /* TiUIiOSStepperProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BFAD90E1CA1B86B00A04BF7 /* TiUIiOSStepperProxy.m */; };
1592CC2E1C47148D00C3DB83 /* TiUIiOSTableViewScrollPositionProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1592CC2D1C47148D00C3DB83 /* TiUIiOSTableViewScrollPositionProxy.m */; };
Expand Down Expand Up @@ -296,6 +297,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
03C262D225EA176700EBE0F2 /* TiUITabbedBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiUITabbedBar.h; sourceTree = "<group>"; };
03C262D425EA176700EBE0F2 /* TiUITabbedBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUITabbedBar.m; sourceTree = "<group>"; };
0BF933881CA0948D0091C7EC /* TiUIiOSStepper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiUIiOSStepper.h; sourceTree = "<group>"; };
0BF933891CA0948D0091C7EC /* TiUIiOSStepper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIiOSStepper.m; sourceTree = "<group>"; };
0BFAD90D1CA1B86B00A04BF7 /* TiUIiOSStepperProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiUIiOSStepperProxy.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1731,6 +1734,8 @@
children = (
6CF8E95721CDA58700519245 /* TiUITabbedBarProxy.h */,
6CF8E95821CDA58800519245 /* TiUITabbedBarProxy.m */,
03C262D225EA176700EBE0F2 /* TiUITabbedBar.h */,
03C262D425EA176700EBE0F2 /* TiUITabbedBar.m */,
);
name = TabbedBar;
sourceTree = "<group>";
Expand Down Expand Up @@ -2302,6 +2307,7 @@
848C259A145F3FE200E1B0F1 /* TiDOMCommentProxy.m in Sources */,
CA0D39EB1B7F74F8009D534C /* TiAppiOSSearchableIndexProxy.m in Sources */,
848C259F145F46C300E1B0F1 /* TiDOMPIProxy.m in Sources */,
03C262D525EA176700EBE0F2 /* TiUITabbedBar.m in Sources */,
848C25A4145F501700E1B0F1 /* TiDOMDocFragProxy.m in Sources */,
84D541A31460B2E0005338D1 /* TiDOMNotationProxy.m in Sources */,
84D541A81460B3C9005338D1 /* TiDOMEntityProxy.m in Sources */,
Expand Down

0 comments on commit 039318e

Please sign in to comment.