chore: default tabs

This commit is contained in:
Nathan Walker
2020-07-09 23:46:02 -07:00
parent 8100cf7089
commit 41f0573d8e
353 changed files with 55344 additions and 55344 deletions

View File

@@ -35,7 +35,7 @@ const TABID = '_tabId';
const INDEX = '_index';
interface PagerAdapter {
new (owner: Tabs): androidx.viewpager.widget.PagerAdapter;
new (owner: Tabs): androidx.viewpager.widget.PagerAdapter;
}
let PagerAdapter: PagerAdapter;
@@ -43,341 +43,341 @@ let TabsBar: any;
let appResources: android.content.res.Resources;
function makeFragmentName(viewId: number, id: number): string {
return 'android:viewpager:' + viewId + ':' + id;
return 'android:viewpager:' + viewId + ':' + id;
}
function getTabById(id: number): Tabs {
const ref = tabs.find((ref) => {
const tab = ref.get();
const ref = tabs.find((ref) => {
const tab = ref.get();
return tab && tab._domId === id;
});
return tab && tab._domId === id;
});
return ref && ref.get();
return ref && ref.get();
}
function initializeNativeClasses() {
if (PagerAdapter) {
return;
}
if (PagerAdapter) {
return;
}
class TabFragmentImplementation extends org.nativescript.widgets.FragmentBase {
private owner: Tabs;
private index: number;
private backgroundBitmap: android.graphics.Bitmap = null;
class TabFragmentImplementation extends org.nativescript.widgets.FragmentBase {
private owner: Tabs;
private index: number;
private backgroundBitmap: android.graphics.Bitmap = null;
constructor() {
super();
constructor() {
super();
return global.__native(this);
}
return global.__native(this);
}
static newInstance(tabId: number, index: number): TabFragmentImplementation {
const args = new android.os.Bundle();
args.putInt(TABID, tabId);
args.putInt(INDEX, index);
const fragment = new TabFragmentImplementation();
fragment.setArguments(args);
static newInstance(tabId: number, index: number): TabFragmentImplementation {
const args = new android.os.Bundle();
args.putInt(TABID, tabId);
args.putInt(INDEX, index);
const fragment = new TabFragmentImplementation();
fragment.setArguments(args);
return fragment;
}
return fragment;
}
public onCreate(savedInstanceState: android.os.Bundle): void {
super.onCreate(savedInstanceState);
const args = this.getArguments();
this.owner = getTabById(args.getInt(TABID));
this.index = args.getInt(INDEX);
if (!this.owner) {
throw new Error(`Cannot find TabView`);
}
}
public onCreate(savedInstanceState: android.os.Bundle): void {
super.onCreate(savedInstanceState);
const args = this.getArguments();
this.owner = getTabById(args.getInt(TABID));
this.index = args.getInt(INDEX);
if (!this.owner) {
throw new Error(`Cannot find TabView`);
}
}
public onCreateView(inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View {
const tabItem = this.owner.items[this.index];
public onCreateView(inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View {
const tabItem = this.owner.items[this.index];
return tabItem.nativeViewProtected;
}
return tabItem.nativeViewProtected;
}
public onDestroyView() {
const hasRemovingParent = this.getRemovingParentFragment();
public onDestroyView() {
const hasRemovingParent = this.getRemovingParentFragment();
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(appResources, this.backgroundBitmap);
this.owner._originalBackground = this.owner.backgroundColor || new Color('White');
this.owner.nativeViewProtected.setBackgroundDrawable(bitmapDrawable);
this.backgroundBitmap = null;
}
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(appResources, this.backgroundBitmap);
this.owner._originalBackground = this.owner.backgroundColor || new Color('White');
this.owner.nativeViewProtected.setBackgroundDrawable(bitmapDrawable);
this.backgroundBitmap = null;
}
super.onDestroyView();
}
super.onDestroyView();
}
public onPause(): void {
const hasRemovingParent = this.getRemovingParentFragment();
public onPause(): void {
const hasRemovingParent = this.getRemovingParentFragment();
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
this.backgroundBitmap = this.loadBitmapFromView(this.owner.nativeViewProtected);
}
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
this.backgroundBitmap = this.loadBitmapFromView(this.owner.nativeViewProtected);
}
super.onPause();
}
super.onPause();
}
private loadBitmapFromView(view: android.view.View): android.graphics.Bitmap {
// Another way to get view bitmap. Test performance vs setDrawingCacheEnabled
// const width = view.getWidth();
// const height = view.getHeight();
// const bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
// const canvas = new android.graphics.Canvas(bitmap);
// view.layout(0, 0, width, height);
// view.draw(canvas);
private loadBitmapFromView(view: android.view.View): android.graphics.Bitmap {
// Another way to get view bitmap. Test performance vs setDrawingCacheEnabled
// const width = view.getWidth();
// const height = view.getHeight();
// const bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
// const canvas = new android.graphics.Canvas(bitmap);
// view.layout(0, 0, width, height);
// view.draw(canvas);
view.setDrawingCacheEnabled(true);
const bitmap = android.graphics.Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
view.setDrawingCacheEnabled(true);
const bitmap = android.graphics.Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bitmap;
}
}
return bitmap;
}
}
const POSITION_UNCHANGED = -1;
const POSITION_NONE = -2;
const POSITION_UNCHANGED = -1;
const POSITION_NONE = -2;
class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
public items: Array<TabContentItem>;
private mCurTransaction: androidx.fragment.app.FragmentTransaction;
private mCurrentPrimaryItem: androidx.fragment.app.Fragment;
class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter {
public items: Array<TabContentItem>;
private mCurTransaction: androidx.fragment.app.FragmentTransaction;
private mCurrentPrimaryItem: androidx.fragment.app.Fragment;
constructor(public owner: Tabs) {
super();
constructor(public owner: Tabs) {
super();
return global.__native(this);
}
return global.__native(this);
}
getCount() {
const items = this.items;
getCount() {
const items = this.items;
return items ? items.length : 0;
}
return items ? items.length : 0;
}
getPageTitle(index: number) {
const items = this.items;
if (index < 0 || index >= items.length) {
return '';
}
getPageTitle(index: number) {
const items = this.items;
if (index < 0 || index >= items.length) {
return '';
}
return ''; // items[index].title;
}
return ''; // items[index].title;
}
startUpdate(container: android.view.ViewGroup): void {
if (container.getId() === android.view.View.NO_ID) {
throw new Error(`ViewPager with adapter ${this} requires a view containerId`);
}
}
startUpdate(container: android.view.ViewGroup): void {
if (container.getId() === android.view.View.NO_ID) {
throw new Error(`ViewPager with adapter ${this} requires a view containerId`);
}
}
instantiateItem(container: android.view.ViewGroup, position: number): java.lang.Object {
const fragmentManager = this.owner._getFragmentManager();
if (!this.mCurTransaction) {
this.mCurTransaction = fragmentManager.beginTransaction();
}
instantiateItem(container: android.view.ViewGroup, position: number): java.lang.Object {
const fragmentManager = this.owner._getFragmentManager();
if (!this.mCurTransaction) {
this.mCurTransaction = fragmentManager.beginTransaction();
}
const itemId = this.getItemId(position);
const name = makeFragmentName(container.getId(), itemId);
const itemId = this.getItemId(position);
const name = makeFragmentName(container.getId(), itemId);
let fragment: androidx.fragment.app.Fragment = fragmentManager.findFragmentByTag(name);
if (fragment != null) {
this.mCurTransaction.attach(fragment);
} else {
fragment = TabFragmentImplementation.newInstance(this.owner._domId, position);
this.mCurTransaction.add(container.getId(), fragment, name);
}
let fragment: androidx.fragment.app.Fragment = fragmentManager.findFragmentByTag(name);
if (fragment != null) {
this.mCurTransaction.attach(fragment);
} else {
fragment = TabFragmentImplementation.newInstance(this.owner._domId, position);
this.mCurTransaction.add(container.getId(), fragment, name);
}
if (fragment !== this.mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
if (fragment !== this.mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
const tabItems = this.owner.items;
const tabItem = tabItems ? tabItems[position] : null;
if (tabItem) {
tabItem.canBeLoaded = true;
}
const tabItems = this.owner.items;
const tabItem = tabItems ? tabItems[position] : null;
if (tabItem) {
tabItem.canBeLoaded = true;
}
return fragment;
}
return fragment;
}
getItemPosition(object: java.lang.Object): number {
return this.items ? POSITION_UNCHANGED : POSITION_NONE;
}
getItemPosition(object: java.lang.Object): number {
return this.items ? POSITION_UNCHANGED : POSITION_NONE;
}
destroyItem(container: android.view.ViewGroup, position: number, object: java.lang.Object): void {
if (!this.mCurTransaction) {
const fragmentManager = this.owner._getFragmentManager();
this.mCurTransaction = fragmentManager.beginTransaction();
}
destroyItem(container: android.view.ViewGroup, position: number, object: java.lang.Object): void {
if (!this.mCurTransaction) {
const fragmentManager = this.owner._getFragmentManager();
this.mCurTransaction = fragmentManager.beginTransaction();
}
const fragment: androidx.fragment.app.Fragment = <androidx.fragment.app.Fragment>object;
this.mCurTransaction.detach(fragment);
const fragment: androidx.fragment.app.Fragment = <androidx.fragment.app.Fragment>object;
this.mCurTransaction.detach(fragment);
if (this.mCurrentPrimaryItem === fragment) {
this.mCurrentPrimaryItem = null;
}
if (this.mCurrentPrimaryItem === fragment) {
this.mCurrentPrimaryItem = null;
}
const tabItems = this.owner.items;
const tabItem = tabItems ? tabItems[position] : null;
if (tabItem) {
tabItem.canBeLoaded = false;
}
}
const tabItems = this.owner.items;
const tabItem = tabItems ? tabItems[position] : null;
if (tabItem) {
tabItem.canBeLoaded = false;
}
}
setPrimaryItem(container: android.view.ViewGroup, position: number, object: java.lang.Object): void {
const fragment = <androidx.fragment.app.Fragment>object;
if (fragment !== this.mCurrentPrimaryItem) {
if (this.mCurrentPrimaryItem != null) {
this.mCurrentPrimaryItem.setMenuVisibility(false);
this.mCurrentPrimaryItem.setUserVisibleHint(false);
}
setPrimaryItem(container: android.view.ViewGroup, position: number, object: java.lang.Object): void {
const fragment = <androidx.fragment.app.Fragment>object;
if (fragment !== this.mCurrentPrimaryItem) {
if (this.mCurrentPrimaryItem != null) {
this.mCurrentPrimaryItem.setMenuVisibility(false);
this.mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
this.mCurrentPrimaryItem = fragment;
this.owner.selectedIndex = position;
this.mCurrentPrimaryItem = fragment;
this.owner.selectedIndex = position;
const tab = this.owner;
const tabItems = tab.items;
const newTabItem = tabItems ? tabItems[position] : null;
const tab = this.owner;
const tabItems = tab.items;
const newTabItem = tabItems ? tabItems[position] : null;
if (newTabItem) {
tab._loadUnloadTabItems(tab.selectedIndex);
}
}
}
if (newTabItem) {
tab._loadUnloadTabItems(tab.selectedIndex);
}
}
}
finishUpdate(container: android.view.ViewGroup): void {
this._commitCurrentTransaction();
}
finishUpdate(container: android.view.ViewGroup): void {
this._commitCurrentTransaction();
}
isViewFromObject(view: android.view.View, object: java.lang.Object): boolean {
return (<androidx.fragment.app.Fragment>object).getView() === view;
}
isViewFromObject(view: android.view.View, object: java.lang.Object): boolean {
return (<androidx.fragment.app.Fragment>object).getView() === view;
}
saveState(): android.os.Parcelable {
// Commit the current transaction on save to prevent "No view found for id 0xa" exception on restore.
// Related to: https://github.com/NativeScript/NativeScript/issues/6466
this._commitCurrentTransaction();
saveState(): android.os.Parcelable {
// Commit the current transaction on save to prevent "No view found for id 0xa" exception on restore.
// Related to: https://github.com/NativeScript/NativeScript/issues/6466
this._commitCurrentTransaction();
return null;
}
return null;
}
restoreState(state: android.os.Parcelable, loader: java.lang.ClassLoader): void {
//
}
restoreState(state: android.os.Parcelable, loader: java.lang.ClassLoader): void {
//
}
getItemId(position: number): number {
return position;
}
getItemId(position: number): number {
return position;
}
private _commitCurrentTransaction() {
if (this.mCurTransaction != null) {
this.mCurTransaction.commitNowAllowingStateLoss();
this.mCurTransaction = null;
}
}
}
private _commitCurrentTransaction() {
if (this.mCurTransaction != null) {
this.mCurTransaction.commitNowAllowingStateLoss();
this.mCurTransaction = null;
}
}
}
class TabsBarImplementation extends org.nativescript.widgets.TabsBar {
constructor(context: android.content.Context, public owner: Tabs) {
super(context);
class TabsBarImplementation extends org.nativescript.widgets.TabsBar {
constructor(context: android.content.Context, public owner: Tabs) {
super(context);
return global.__native(this);
}
return global.__native(this);
}
public onSelectedPositionChange(position: number, prevPosition: number): void {
const owner = this.owner;
if (!owner) {
return;
}
public onSelectedPositionChange(position: number, prevPosition: number): void {
const owner = this.owner;
if (!owner) {
return;
}
const tabStripItems = owner.tabStrip && owner.tabStrip.items;
const tabStripItems = owner.tabStrip && owner.tabStrip.items;
if (position >= 0 && tabStripItems && tabStripItems[position]) {
tabStripItems[position]._emit(TabStripItem.selectEvent);
owner._setItemColor(tabStripItems[position]);
}
if (position >= 0 && tabStripItems && tabStripItems[position]) {
tabStripItems[position]._emit(TabStripItem.selectEvent);
owner._setItemColor(tabStripItems[position]);
}
if (prevPosition >= 0 && tabStripItems && tabStripItems[prevPosition]) {
tabStripItems[prevPosition]._emit(TabStripItem.unselectEvent);
owner._setItemColor(tabStripItems[prevPosition]);
}
}
if (prevPosition >= 0 && tabStripItems && tabStripItems[prevPosition]) {
tabStripItems[prevPosition]._emit(TabStripItem.unselectEvent);
owner._setItemColor(tabStripItems[prevPosition]);
}
}
public onTap(position: number): boolean {
const owner = this.owner;
if (!owner) {
return false;
}
public onTap(position: number): boolean {
const owner = this.owner;
if (!owner) {
return false;
}
const tabStrip = owner.tabStrip;
const tabStripItems = tabStrip && tabStrip.items;
const tabStrip = owner.tabStrip;
const tabStripItems = tabStrip && tabStrip.items;
if (position >= 0 && tabStripItems[position]) {
tabStripItems[position]._emit(TabStripItem.tapEvent);
tabStrip.notify({
eventName: TabStrip.itemTapEvent,
object: tabStrip,
index: position,
});
}
if (position >= 0 && tabStripItems[position]) {
tabStripItems[position]._emit(TabStripItem.tapEvent);
tabStrip.notify({
eventName: TabStrip.itemTapEvent,
object: tabStrip,
index: position,
});
}
if (!owner.items[position]) {
return false;
}
if (!owner.items[position]) {
return false;
}
return true;
}
}
return true;
}
}
PagerAdapter = FragmentPagerAdapter;
TabsBar = TabsBarImplementation;
appResources = application.android.context.getResources();
PagerAdapter = FragmentPagerAdapter;
TabsBar = TabsBarImplementation;
appResources = application.android.context.getResources();
}
let defaultAccentColor: number = undefined;
function getDefaultAccentColor(context: android.content.Context): number {
if (defaultAccentColor === undefined) {
//Fallback color: https://developer.android.com/samples/SlidingTabsColors/src/com.example.android.common/view/SlidingTabStrip.html
defaultAccentColor = ad.resources.getPaletteColor(ACCENT_COLOR, context) || 0xff33b5e5;
}
if (defaultAccentColor === undefined) {
//Fallback color: https://developer.android.com/samples/SlidingTabsColors/src/com.example.android.common/view/SlidingTabStrip.html
defaultAccentColor = ad.resources.getPaletteColor(ACCENT_COLOR, context) || 0xff33b5e5;
}
return defaultAccentColor;
return defaultAccentColor;
}
function setElevation(grid: org.nativescript.widgets.GridLayout, tabsBar: org.nativescript.widgets.TabsBar, tabsPosition: string) {
const compat = <any>androidx.core.view.ViewCompat;
if (compat.setElevation) {
const val = DEFAULT_ELEVATION * layout.getDisplayDensity();
const compat = <any>androidx.core.view.ViewCompat;
if (compat.setElevation) {
const val = DEFAULT_ELEVATION * layout.getDisplayDensity();
if (tabsPosition === 'top') {
compat.setElevation(grid, val);
}
if (tabsPosition === 'top') {
compat.setElevation(grid, val);
}
compat.setElevation(tabsBar, val);
}
compat.setElevation(tabsBar, val);
}
}
export const tabs = new Array<WeakRef<Tabs>>();
function iterateIndexRange(index: number, eps: number, lastIndex: number, callback: (i) => void) {
const rangeStart = Math.max(0, index - eps);
const rangeEnd = Math.min(index + eps, lastIndex);
for (let i = rangeStart; i <= rangeEnd; i++) {
callback(i);
}
const rangeStart = Math.max(0, index - eps);
const rangeEnd = Math.min(index + eps, lastIndex);
for (let i = rangeStart; i <= rangeEnd; i++) {
callback(i);
}
}
export class Tabs extends TabsBase {
@@ -1001,12 +1001,12 @@ export class Tabs extends TabsBase {
}
function tryCloneDrawable(value: android.graphics.drawable.Drawable, resources: android.content.res.Resources): android.graphics.drawable.Drawable {
if (value) {
const constantState = value.getConstantState();
if (constantState) {
return constantState.newDrawable(resources);
}
}
if (value) {
const constantState = value.getConstantState();
if (constantState) {
return constantState.newDrawable(resources);
}
}
return value;
return value;
}

View File

@@ -17,73 +17,73 @@ export * from '../tab-navigation-base/tab-strip-item';
* Represents a swipeable tabs view.
*/
export class Tabs extends TabNavigationBase {
/**
* Gets or sets the items of the Tabs.
*/
items: Array<TabContentItem>;
/**
* Gets or sets the items of the Tabs.
*/
items: Array<TabContentItem>;
/**
* Gets or sets the tab strip of the Tabs.
*/
tabStrip: TabStrip;
/**
* Gets or sets the tab strip of the Tabs.
*/
tabStrip: TabStrip;
/**
* Gets or sets the selectedIndex of the Tabs.
*/
selectedIndex: number;
/**
* Gets or sets the selectedIndex of the Tabs.
*/
selectedIndex: number;
/**
* Gets or sets the swipe enabled state of the Tabs.
*/
swipeEnabled: boolean;
/**
* Gets or sets the swipe enabled state of the Tabs.
*/
swipeEnabled: boolean;
/**
* Gets or sets the number of offscreen preloaded tabs of the Tabs.
*/
offscreenTabLimit: number;
/**
* Gets or sets the number of offscreen preloaded tabs of the Tabs.
*/
offscreenTabLimit: number;
/**
* Gets or sets the position state of the Tabs.
*/
tabsPosition: 'top' | 'bottom';
/**
* Gets or sets the position state of the Tabs.
*/
tabsPosition: 'top' | 'bottom';
/**
* Gets or set the MDCTabBarAlignment of the tab bar icons in iOS. Defaults to "justified"
* Valid values are:
* - leading
* - justified
* - center
* - centerSelected
*/
iOSTabBarItemsAlignment: IOSTabBarItemsAlignment;
/**
* Gets or set the MDCTabBarAlignment of the tab bar icons in iOS. Defaults to "justified"
* Valid values are:
* - leading
* - justified
* - center
* - centerSelected
*/
iOSTabBarItemsAlignment: IOSTabBarItemsAlignment;
/**
* Gets the native [android widget](http://developer.android.com/reference/android/support/v4/view/ViewPager.html) that represents the user interface for this component. Valid only when running on Android OS.
*/
android: any /* android.view.View */; //android.support.v4.view.ViewPager;
/**
* Gets the native [android widget](http://developer.android.com/reference/android/support/v4/view/ViewPager.html) that represents the user interface for this component. Valid only when running on Android OS.
*/
android: any /* android.view.View */; //android.support.v4.view.ViewPager;
/**
* Gets the native iOS [UITabBarController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITabBarController_Class/) that represents the user interface for this component. Valid only when running on iOS.
*/
ios: any /* UITabBarController */;
/**
* Gets the native iOS [UITabBarController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITabBarController_Class/) that represents the user interface for this component. Valid only when running on iOS.
*/
ios: any /* UITabBarController */;
/**
* String value used when hooking to the selectedIndexChanged event.
*/
public static selectedIndexChangedEvent: string;
/**
* String value used when hooking to the selectedIndexChanged event.
*/
public static selectedIndexChangedEvent: string;
/**
* A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
* @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change").
* @param callback - Callback function which will be executed when event is raised.
* @param thisArg - An optional parameter which will be used as `this` context for callback execution.
*/
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
/**
* A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
* @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change").
* @param callback - Callback function which will be executed when event is raised.
* @param thisArg - An optional parameter which will be used as `this` context for callback execution.
*/
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
/**
* Raised when the selected index changes.
*/
on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any);
/**
* Raised when the selected index changes.
*/
on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any);
}
export const itemsProperty: Property<Tabs, TabContentItem[]>;

View File

@@ -26,432 +26,432 @@ const isPhone = Device.deviceType === 'Phone';
// Equivalent to dispatch_async(dispatch_get_main_queue(...)) call
const invokeOnRunLoop = (function () {
const runloop = CFRunLoopGetMain();
const runloop = CFRunLoopGetMain();
return (action: () => any) => {
CFRunLoopPerformBlock(runloop, kCFRunLoopDefaultMode, action);
CFRunLoopWakeUp(runloop);
};
return (action: () => any) => {
CFRunLoopPerformBlock(runloop, kCFRunLoopDefaultMode, action);
CFRunLoopWakeUp(runloop);
};
})();
class MDCTabBarDelegateImpl extends NSObject implements MDCTabBarDelegate {
public static ObjCProtocols = [MDCTabBarDelegate];
public static ObjCProtocols = [MDCTabBarDelegate];
private _owner: WeakRef<Tabs>;
private _owner: WeakRef<Tabs>;
public static initWithOwner(owner: WeakRef<Tabs>): MDCTabBarDelegateImpl {
let delegate = <MDCTabBarDelegateImpl>MDCTabBarDelegateImpl.new();
delegate._owner = owner;
public static initWithOwner(owner: WeakRef<Tabs>): MDCTabBarDelegateImpl {
let delegate = <MDCTabBarDelegateImpl>MDCTabBarDelegateImpl.new();
delegate._owner = owner;
return delegate;
}
return delegate;
}
public tabBarShouldSelectItem(tabBar: MDCTabBar, item: UITabBarItem): boolean {
const owner = this._owner.get();
const shouldSelectItem = owner._canSelectItem;
const selectedIndex = owner.tabBarItems.indexOf(item);
public tabBarShouldSelectItem(tabBar: MDCTabBar, item: UITabBarItem): boolean {
const owner = this._owner.get();
const shouldSelectItem = owner._canSelectItem;
const selectedIndex = owner.tabBarItems.indexOf(item);
if (owner.selectedIndex !== selectedIndex) {
owner._canSelectItem = false;
}
if (owner.selectedIndex !== selectedIndex) {
owner._canSelectItem = false;
}
const tabStrip = owner.tabStrip;
const tabStripItems = tabStrip && tabStrip.items;
const tabStrip = owner.tabStrip;
const tabStripItems = tabStrip && tabStrip.items;
if (tabStripItems && tabStripItems[selectedIndex]) {
tabStripItems[selectedIndex]._emit(TabStripItem.tapEvent);
tabStrip.notify({
eventName: TabStrip.itemTapEvent,
object: tabStrip,
index: selectedIndex,
});
}
if (tabStripItems && tabStripItems[selectedIndex]) {
tabStripItems[selectedIndex]._emit(TabStripItem.tapEvent);
tabStrip.notify({
eventName: TabStrip.itemTapEvent,
object: tabStrip,
index: selectedIndex,
});
}
return shouldSelectItem;
}
return shouldSelectItem;
}
public tabBarDidSelectItem(tabBar: MDCTabBar, selectedItem: UITabBarItem): void {
const owner = this._owner.get();
const tabBarItems = owner.tabBarItems;
const selectedIndex = tabBarItems.indexOf(selectedItem);
public tabBarDidSelectItem(tabBar: MDCTabBar, selectedItem: UITabBarItem): void {
const owner = this._owner.get();
const tabBarItems = owner.tabBarItems;
const selectedIndex = tabBarItems.indexOf(selectedItem);
owner.selectedIndex = selectedIndex;
}
owner.selectedIndex = selectedIndex;
}
}
class BackgroundIndicatorTemplate extends NSObject implements MDCTabBarIndicatorTemplate {
public static ObjCProtocols = [MDCTabBarIndicatorTemplate];
public static ObjCProtocols = [MDCTabBarIndicatorTemplate];
public indicatorAttributesForContext(context: MDCTabBarIndicatorContext): MDCTabBarIndicatorAttributes {
let attributes = new MDCTabBarIndicatorAttributes();
attributes.path = UIBezierPath.bezierPathWithRect(context.bounds);
public indicatorAttributesForContext(context: MDCTabBarIndicatorContext): MDCTabBarIndicatorAttributes {
let attributes = new MDCTabBarIndicatorAttributes();
attributes.path = UIBezierPath.bezierPathWithRect(context.bounds);
return attributes;
}
return attributes;
}
}
class UIPageViewControllerImpl extends UIPageViewController {
tabBar: MDCTabBar;
scrollView: UIScrollView;
tabBarDelegate: MDCTabBarDelegateImpl;
tabBar: MDCTabBar;
scrollView: UIScrollView;
tabBarDelegate: MDCTabBarDelegateImpl;
private _owner: WeakRef<Tabs>;
private _owner: WeakRef<Tabs>;
public static initWithOwner(owner: WeakRef<Tabs>): UIPageViewControllerImpl {
const handler = <UIPageViewControllerImpl>UIPageViewControllerImpl.alloc().initWithTransitionStyleNavigationOrientationOptions(UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation.Horizontal, null);
handler._owner = owner;
public static initWithOwner(owner: WeakRef<Tabs>): UIPageViewControllerImpl {
const handler = <UIPageViewControllerImpl>UIPageViewControllerImpl.alloc().initWithTransitionStyleNavigationOrientationOptions(UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation.Horizontal, null);
handler._owner = owner;
return handler;
}
return handler;
}
public viewDidLoad(): void {
const owner = this._owner.get();
public viewDidLoad(): void {
const owner = this._owner.get();
const tabBarItems = owner.tabBarItems;
const tabBar = MDCTabBar.alloc().initWithFrame(this.view.bounds);
const tabBarItems = owner.tabBarItems;
const tabBar = MDCTabBar.alloc().initWithFrame(this.view.bounds);
if (tabBarItems && tabBarItems.length) {
tabBar.items = NSArray.arrayWithArray(tabBarItems);
}
if (tabBarItems && tabBarItems.length) {
tabBar.items = NSArray.arrayWithArray(tabBarItems);
}
tabBar.delegate = this.tabBarDelegate = MDCTabBarDelegateImpl.initWithOwner(new WeakRef(owner));
tabBar.delegate = this.tabBarDelegate = MDCTabBarDelegateImpl.initWithOwner(new WeakRef(owner));
if (majorVersion <= 12 || !UIColor.labelColor) {
tabBar.tintColor = UIColor.blueColor;
tabBar.barTintColor = UIColor.whiteColor;
tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Normal);
tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Selected);
} else {
tabBar.tintColor = UIColor.systemBlueColor;
tabBar.barTintColor = UIColor.systemBackgroundColor;
tabBar.setTitleColorForState(UIColor.labelColor, MDCTabBarItemState.Normal);
tabBar.setTitleColorForState(UIColor.labelColor, MDCTabBarItemState.Selected);
tabBar.inkColor = UIColor.clearColor;
}
if (majorVersion <= 12 || !UIColor.labelColor) {
tabBar.tintColor = UIColor.blueColor;
tabBar.barTintColor = UIColor.whiteColor;
tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Normal);
tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Selected);
} else {
tabBar.tintColor = UIColor.systemBlueColor;
tabBar.barTintColor = UIColor.systemBackgroundColor;
tabBar.setTitleColorForState(UIColor.labelColor, MDCTabBarItemState.Normal);
tabBar.setTitleColorForState(UIColor.labelColor, MDCTabBarItemState.Selected);
tabBar.inkColor = UIColor.clearColor;
}
tabBar.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleBottomMargin;
tabBar.alignment = MDCTabBarAlignment.Justified;
tabBar.sizeToFit();
tabBar.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleBottomMargin;
tabBar.alignment = MDCTabBarAlignment.Justified;
tabBar.sizeToFit();
this.tabBar = tabBar;
this.view.addSubview(tabBar);
}
this.tabBar = tabBar;
this.view.addSubview(tabBar);
}
public viewWillAppear(animated: boolean): void {
super.viewWillAppear(animated);
const owner = this._owner.get();
if (!owner) {
return;
}
public viewWillAppear(animated: boolean): void {
super.viewWillAppear(animated);
const owner = this._owner.get();
if (!owner) {
return;
}
IOSHelper.updateAutoAdjustScrollInsets(this, owner);
IOSHelper.updateAutoAdjustScrollInsets(this, owner);
// Tabs can be reset as a root view. Call loaded here in this scenario.
if (!owner.isLoaded) {
owner.callLoaded();
}
}
// Tabs can be reset as a root view. Call loaded here in this scenario.
if (!owner.isLoaded) {
owner.callLoaded();
}
}
public viewDidLayoutSubviews(): void {
super.viewDidLayoutSubviews();
const owner = this._owner.get();
if (!owner) {
return;
}
public viewDidLayoutSubviews(): void {
super.viewDidLayoutSubviews();
const owner = this._owner.get();
if (!owner) {
return;
}
let safeAreaInsetsBottom = 0;
let safeAreaInsetsTop = 0;
let safeAreaInsetsBottom = 0;
let safeAreaInsetsTop = 0;
if (majorVersion > 10) {
safeAreaInsetsBottom = this.view.safeAreaInsets.bottom;
safeAreaInsetsTop = this.view.safeAreaInsets.top;
} else {
safeAreaInsetsTop = this.topLayoutGuide.length;
}
if (majorVersion > 10) {
safeAreaInsetsBottom = this.view.safeAreaInsets.bottom;
safeAreaInsetsTop = this.view.safeAreaInsets.top;
} else {
safeAreaInsetsTop = this.topLayoutGuide.length;
}
let scrollViewTop = 0;
let scrollViewHeight = this.view.bounds.size.height + safeAreaInsetsBottom;
let scrollViewTop = 0;
let scrollViewHeight = this.view.bounds.size.height + safeAreaInsetsBottom;
if (owner.tabStrip) {
scrollViewTop = this.tabBar.frame.size.height;
scrollViewHeight = this.view.bounds.size.height - this.tabBar.frame.size.height + safeAreaInsetsBottom;
let tabBarTop = safeAreaInsetsTop;
let tabBarHeight = this.tabBar.frame.size.height;
if (owner.tabStrip) {
scrollViewTop = this.tabBar.frame.size.height;
scrollViewHeight = this.view.bounds.size.height - this.tabBar.frame.size.height + safeAreaInsetsBottom;
let tabBarTop = safeAreaInsetsTop;
let tabBarHeight = this.tabBar.frame.size.height;
const tabsPosition = owner.tabsPosition;
if (tabsPosition === 'bottom') {
tabBarTop = this.view.frame.size.height - this.tabBar.frame.size.height - safeAreaInsetsBottom;
scrollViewTop = this.view.frame.origin.y;
scrollViewHeight = this.view.frame.size.height - safeAreaInsetsBottom;
}
const tabsPosition = owner.tabsPosition;
if (tabsPosition === 'bottom') {
tabBarTop = this.view.frame.size.height - this.tabBar.frame.size.height - safeAreaInsetsBottom;
scrollViewTop = this.view.frame.origin.y;
scrollViewHeight = this.view.frame.size.height - safeAreaInsetsBottom;
}
let parent = owner.parent;
let parent = owner.parent;
// Handle Angular scenario where Tabs is in a ProxyViewContainer
// It is possible to wrap components in ProxyViewContainers indefinitely
while (parent && !parent.nativeViewProtected) {
parent = parent.parent;
}
// Handle Angular scenario where Tabs is in a ProxyViewContainer
// It is possible to wrap components in ProxyViewContainers indefinitely
while (parent && !parent.nativeViewProtected) {
parent = parent.parent;
}
if (parent && majorVersion > 10) {
// TODO: Figure out a better way to handle ViewController nesting/Safe Area nesting
tabBarTop = Math.max(tabBarTop, parent.nativeView.safeAreaInsets.top);
}
if (parent && majorVersion > 10) {
// TODO: Figure out a better way to handle ViewController nesting/Safe Area nesting
tabBarTop = Math.max(tabBarTop, parent.nativeView.safeAreaInsets.top);
}
this.tabBar.frame = CGRectMake(0, tabBarTop, this.tabBar.frame.size.width, tabBarHeight);
} else {
this.tabBar.hidden = true;
}
this.tabBar.frame = CGRectMake(0, tabBarTop, this.tabBar.frame.size.width, tabBarHeight);
} else {
this.tabBar.hidden = true;
}
const subViews: NSArray<UIView> = this.view.subviews;
let scrollView: UIScrollView = null;
const subViews: NSArray<UIView> = this.view.subviews;
let scrollView: UIScrollView = null;
for (let i = 0; i < subViews.count; i++) {
const view: UIView = subViews[i];
if (view instanceof UIScrollView) {
scrollView = <UIScrollView>view;
}
}
for (let i = 0; i < subViews.count; i++) {
const view: UIView = subViews[i];
if (view instanceof UIScrollView) {
scrollView = <UIScrollView>view;
}
}
if (scrollView) {
// The part of the UIPageViewController that is changing the pages is a UIScrollView
// We want to expand it to the size of the UIPageViewController as it is not so by default
this.scrollView = scrollView;
if (scrollView) {
// The part of the UIPageViewController that is changing the pages is a UIScrollView
// We want to expand it to the size of the UIPageViewController as it is not so by default
this.scrollView = scrollView;
if (!owner.swipeEnabled) {
scrollView.scrollEnabled = false;
}
if (!owner.swipeEnabled) {
scrollView.scrollEnabled = false;
}
scrollView.frame = CGRectMake(0, scrollViewTop, this.view.bounds.size.width, scrollViewHeight); //this.view.bounds;
}
}
scrollView.frame = CGRectMake(0, scrollViewTop, this.view.bounds.size.width, scrollViewHeight); //this.view.bounds;
}
}
// Mind implementation for other controllers
public traitCollectionDidChange(previousTraitCollection: UITraitCollection): void {
super.traitCollectionDidChange(previousTraitCollection);
// Mind implementation for other controllers
public traitCollectionDidChange(previousTraitCollection: UITraitCollection): void {
super.traitCollectionDidChange(previousTraitCollection);
if (majorVersion >= 13) {
const owner = this._owner.get();
if (owner && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection(previousTraitCollection)) {
owner.notify({
eventName: IOSHelper.traitCollectionColorAppearanceChangedEvent,
object: owner,
});
}
}
}
if (majorVersion >= 13) {
const owner = this._owner.get();
if (owner && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection(previousTraitCollection)) {
owner.notify({
eventName: IOSHelper.traitCollectionColorAppearanceChangedEvent,
object: owner,
});
}
}
}
public viewWillTransitionToSizeWithTransitionCoordinator(size: CGSize, coordinator: UIViewControllerTransitionCoordinator): void {
super.viewWillTransitionToSizeWithTransitionCoordinator(size, coordinator);
coordinator.animateAlongsideTransitionCompletion(() => {
const owner = this._owner.get();
if (owner && owner.tabStrip && owner.tabStrip.items) {
const tabStrip = owner.tabStrip;
tabStrip.items.forEach((tabStripItem) => {
updateBackgroundPositions(tabStrip, tabStripItem, this.tabBar.alignment !== MDCTabBarAlignment.Justified || owner.selectedIndex !== tabStripItem._index ? owner._defaultItemBackgroundColor : null);
public viewWillTransitionToSizeWithTransitionCoordinator(size: CGSize, coordinator: UIViewControllerTransitionCoordinator): void {
super.viewWillTransitionToSizeWithTransitionCoordinator(size, coordinator);
coordinator.animateAlongsideTransitionCompletion(() => {
const owner = this._owner.get();
if (owner && owner.tabStrip && owner.tabStrip.items) {
const tabStrip = owner.tabStrip;
tabStrip.items.forEach((tabStripItem) => {
updateBackgroundPositions(tabStrip, tabStripItem, this.tabBar.alignment !== MDCTabBarAlignment.Justified || owner.selectedIndex !== tabStripItem._index ? owner._defaultItemBackgroundColor : null);
const index = tabStripItem._index;
const tabBarItemController = owner.viewControllers[index];
updateTitleAndIconPositions(tabStripItem, tabBarItemController.tabBarItem, tabBarItemController);
});
}
}, null);
}
const index = tabStripItem._index;
const tabBarItemController = owner.viewControllers[index];
updateTitleAndIconPositions(tabStripItem, tabBarItemController.tabBarItem, tabBarItemController);
});
}
}, null);
}
}
class UIPageViewControllerDataSourceImpl extends NSObject implements UIPageViewControllerDataSource {
public static ObjCProtocols = [UIPageViewControllerDataSource];
public static ObjCProtocols = [UIPageViewControllerDataSource];
private _owner: WeakRef<Tabs>;
private _owner: WeakRef<Tabs>;
public static initWithOwner(owner: WeakRef<Tabs>): UIPageViewControllerDataSourceImpl {
let dataSource = <UIPageViewControllerDataSourceImpl>UIPageViewControllerDataSourceImpl.new();
dataSource._owner = owner;
public static initWithOwner(owner: WeakRef<Tabs>): UIPageViewControllerDataSourceImpl {
let dataSource = <UIPageViewControllerDataSourceImpl>UIPageViewControllerDataSourceImpl.new();
dataSource._owner = owner;
return dataSource;
}
return dataSource;
}
public pageViewControllerViewControllerBeforeViewController(pageViewController: UIPageViewController, viewController: UIViewController): UIViewController {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
public pageViewControllerViewControllerBeforeViewController(pageViewController: UIPageViewController, viewController: UIViewController): UIViewController {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
const owner = this._owner.get();
let selectedIndex = owner.selectedIndex;
const owner = this._owner.get();
let selectedIndex = owner.selectedIndex;
if (selectedIndex === 0) {
return null;
}
if (selectedIndex === 0) {
return null;
}
selectedIndex--;
const prevItem = owner.items[selectedIndex];
let prevViewController = (<any>prevItem).__controller;
selectedIndex--;
const prevItem = owner.items[selectedIndex];
let prevViewController = (<any>prevItem).__controller;
// if (!prevViewController) {
// prevViewController = owner.getViewController(prevItem);
// }
// if (!prevViewController) {
// prevViewController = owner.getViewController(prevItem);
// }
owner._setCanBeLoaded(selectedIndex);
owner._loadUnloadTabItems(selectedIndex);
owner._setCanBeLoaded(selectedIndex);
owner._loadUnloadTabItems(selectedIndex);
return prevViewController;
}
return prevViewController;
}
public pageViewControllerViewControllerAfterViewController(pageViewController: UIPageViewController, viewController: UIViewController): UIViewController {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
public pageViewControllerViewControllerAfterViewController(pageViewController: UIPageViewController, viewController: UIViewController): UIViewController {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
const owner = this._owner.get();
let selectedIndex = owner.selectedIndex;
const owner = this._owner.get();
let selectedIndex = owner.selectedIndex;
if (selectedIndex === owner.items.length - 1) {
return null;
}
if (selectedIndex === owner.items.length - 1) {
return null;
}
selectedIndex++;
const nextItem = owner.items[selectedIndex];
let nextViewController = (<any>nextItem).__controller;
selectedIndex++;
const nextItem = owner.items[selectedIndex];
let nextViewController = (<any>nextItem).__controller;
// if (!nextViewController) {
// nextViewController = owner.getViewController(nextItem);
// }
// if (!nextViewController) {
// nextViewController = owner.getViewController(nextItem);
// }
owner._setCanBeLoaded(selectedIndex);
owner._loadUnloadTabItems(selectedIndex);
// nextItem.loadView(nextItem.view);
owner._setCanBeLoaded(selectedIndex);
owner._loadUnloadTabItems(selectedIndex);
// nextItem.loadView(nextItem.view);
return nextViewController;
}
return nextViewController;
}
public presentationCountForPageViewController(pageViewController: UIPageViewController): number {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
public presentationCountForPageViewController(pageViewController: UIPageViewController): number {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
return 0;
}
return 0;
}
public presentationIndexForPageViewController(pageViewController: UIPageViewController): number {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
public presentationIndexForPageViewController(pageViewController: UIPageViewController): number {
// TODO
// if (Trace.isEnabled()) {
// Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug);
// }
return 0;
}
return 0;
}
}
class UIPageViewControllerDelegateImpl extends NSObject implements UIPageViewControllerDelegate {
public static ObjCProtocols = [UIPageViewControllerDelegate];
public static ObjCProtocols = [UIPageViewControllerDelegate];
private _owner: WeakRef<Tabs>;
private _owner: WeakRef<Tabs>;
public static initWithOwner(owner: WeakRef<Tabs>): UIPageViewControllerDelegateImpl {
let delegate = <UIPageViewControllerDelegateImpl>UIPageViewControllerDelegateImpl.new();
delegate._owner = owner;
public static initWithOwner(owner: WeakRef<Tabs>): UIPageViewControllerDelegateImpl {
let delegate = <UIPageViewControllerDelegateImpl>UIPageViewControllerDelegateImpl.new();
delegate._owner = owner;
return delegate;
}
return delegate;
}
public pageViewControllerWillTransitionToViewControllers(pageViewController: UIPageViewController, viewControllers: NSArray<UIViewController>): void {
// const owner = this._owner.get();
// const ownerViewControllers = owner.viewControllers;
// const selectedIndex = owner.selectedIndex;
// const nextViewController = viewControllers[0];
// const nextViewControllerIndex = ownerViewControllers.indexOf(nextViewController);
// if (selectedIndex > nextViewControllerIndex) {
// owner.selectedIndex--;
// } else {
// owner.selectedIndex++;
// }
}
public pageViewControllerWillTransitionToViewControllers(pageViewController: UIPageViewController, viewControllers: NSArray<UIViewController>): void {
// const owner = this._owner.get();
// const ownerViewControllers = owner.viewControllers;
// const selectedIndex = owner.selectedIndex;
// const nextViewController = viewControllers[0];
// const nextViewControllerIndex = ownerViewControllers.indexOf(nextViewController);
// if (selectedIndex > nextViewControllerIndex) {
// owner.selectedIndex--;
// } else {
// owner.selectedIndex++;
// }
}
public pageViewControllerDidFinishAnimatingPreviousViewControllersTransitionCompleted(pageViewController: UIPageViewController, didFinishAnimating: boolean, previousViewControllers: NSArray<UIViewController>, transitionCompleted: boolean): void {
if (!transitionCompleted) {
return;
}
public pageViewControllerDidFinishAnimatingPreviousViewControllersTransitionCompleted(pageViewController: UIPageViewController, didFinishAnimating: boolean, previousViewControllers: NSArray<UIViewController>, transitionCompleted: boolean): void {
if (!transitionCompleted) {
return;
}
const owner = this._owner.get();
const ownerViewControllers = owner.viewControllers;
const selectedIndex = owner.selectedIndex;
const nextViewController = pageViewController.viewControllers[0];
const nextViewControllerIndex = ownerViewControllers.indexOf(nextViewController);
const owner = this._owner.get();
const ownerViewControllers = owner.viewControllers;
const selectedIndex = owner.selectedIndex;
const nextViewController = pageViewController.viewControllers[0];
const nextViewControllerIndex = ownerViewControllers.indexOf(nextViewController);
if (selectedIndex !== nextViewControllerIndex) {
owner.selectedIndex = nextViewControllerIndex;
owner._canSelectItem = true;
}
}
if (selectedIndex !== nextViewControllerIndex) {
owner.selectedIndex = nextViewControllerIndex;
owner._canSelectItem = true;
}
}
}
function iterateIndexRange(index: number, eps: number, lastIndex: number, callback: (i) => void) {
const rangeStart = Math.max(0, index - eps);
const rangeEnd = Math.min(index + eps, lastIndex);
for (let i = rangeStart; i <= rangeEnd; i++) {
callback(i);
}
const rangeStart = Math.max(0, index - eps);
const rangeEnd = Math.min(index + eps, lastIndex);
for (let i = rangeStart; i <= rangeEnd; i++) {
callback(i);
}
}
function updateBackgroundPositions(tabStrip: TabStrip, tabStripItem: TabStripItem, color: UIColor = null) {
let bgView = (<any>tabStripItem).bgView;
const index = tabStripItem._index;
let width = tabStrip.nativeView.frame.size.width / tabStrip.items.length;
const frame = CGRectMake(width * index, 0, width, tabStrip.nativeView.frame.size.width);
if (!bgView) {
bgView = UIView.alloc().initWithFrame(frame);
tabStrip.nativeView.insertSubviewAtIndex(bgView, 0);
(<any>tabStripItem).bgView = bgView;
} else {
bgView.frame = frame;
}
let bgView = (<any>tabStripItem).bgView;
const index = tabStripItem._index;
let width = tabStrip.nativeView.frame.size.width / tabStrip.items.length;
const frame = CGRectMake(width * index, 0, width, tabStrip.nativeView.frame.size.width);
if (!bgView) {
bgView = UIView.alloc().initWithFrame(frame);
tabStrip.nativeView.insertSubviewAtIndex(bgView, 0);
(<any>tabStripItem).bgView = bgView;
} else {
bgView.frame = frame;
}
const backgroundColor = tabStripItem.style.backgroundColor;
bgView.backgroundColor = color || (backgroundColor instanceof Color ? backgroundColor.ios : backgroundColor);
const backgroundColor = tabStripItem.style.backgroundColor;
bgView.backgroundColor = color || (backgroundColor instanceof Color ? backgroundColor.ios : backgroundColor);
}
function updateTitleAndIconPositions(tabStripItem: TabStripItem, tabBarItem: UITabBarItem, controller: UIViewController) {
if (!tabStripItem || !tabBarItem) {
return;
}
if (!tabStripItem || !tabBarItem) {
return;
}
// For iOS <11 icon is *always* above the text.
// For iOS 11 icon is above the text *only* on phones in portrait mode.
const orientation = controller.interfaceOrientation;
const isPortrait = orientation !== UIInterfaceOrientation.LandscapeLeft && orientation !== UIInterfaceOrientation.LandscapeRight;
const isIconAboveTitle = majorVersion < 11 || (isPhone && isPortrait);
// For iOS <11 icon is *always* above the text.
// For iOS 11 icon is above the text *only* on phones in portrait mode.
const orientation = controller.interfaceOrientation;
const isPortrait = orientation !== UIInterfaceOrientation.LandscapeLeft && orientation !== UIInterfaceOrientation.LandscapeRight;
const isIconAboveTitle = majorVersion < 11 || (isPhone && isPortrait);
if (!tabStripItem.iconSource) {
if (isIconAboveTitle) {
tabBarItem.titlePositionAdjustment = {
horizontal: 0,
vertical: -20,
};
} else {
tabBarItem.titlePositionAdjustment = { horizontal: 0, vertical: 0 };
}
}
if (!tabStripItem.iconSource) {
if (isIconAboveTitle) {
tabBarItem.titlePositionAdjustment = {
horizontal: 0,
vertical: -20,
};
} else {
tabBarItem.titlePositionAdjustment = { horizontal: 0, vertical: 0 };
}
}
if (!tabStripItem.title) {
if (isIconAboveTitle) {
tabBarItem.imageInsets = new UIEdgeInsets({
top: 6,
left: 0,
bottom: -6,
right: 0,
});
} else {
tabBarItem.imageInsets = new UIEdgeInsets({
top: 0,
left: 0,
bottom: 0,
right: 0,
});
}
}
if (!tabStripItem.title) {
if (isIconAboveTitle) {
tabBarItem.imageInsets = new UIEdgeInsets({
top: 6,
left: 0,
bottom: -6,
right: 0,
});
} else {
tabBarItem.imageInsets = new UIEdgeInsets({
top: 0,
left: 0,
bottom: 0,
right: 0,
});
}
}
}
export class Tabs extends TabsBase {

View File

@@ -15,37 +15,37 @@ export * from '../tab-navigation-base/tab-strip-item';
export const traceCategory = 'TabView';
export module knownCollections {
export const items = 'items';
export const items = 'items';
}
@CSSType('Tabs')
export class TabsBase extends TabNavigationBase implements TabsDefinition {
public swipeEnabled: boolean;
public offscreenTabLimit: number;
public tabsPosition: 'top' | 'bottom';
public iOSTabBarItemsAlignment: IOSTabBarItemsAlignment;
public swipeEnabled: boolean;
public offscreenTabLimit: number;
public tabsPosition: 'top' | 'bottom';
public iOSTabBarItemsAlignment: IOSTabBarItemsAlignment;
}
// TODO: Add Unit tests
export const swipeEnabledProperty = new Property<TabsBase, boolean>({
name: 'swipeEnabled',
defaultValue: true,
valueConverter: booleanConverter,
name: 'swipeEnabled',
defaultValue: true,
valueConverter: booleanConverter,
});
swipeEnabledProperty.register(TabsBase);
// TODO: Add Unit tests
// TODO: Coerce to max number of items?
export const offscreenTabLimitProperty = new Property<TabsBase, number>({
name: 'offscreenTabLimit',
defaultValue: 1,
valueConverter: (v) => parseInt(v),
name: 'offscreenTabLimit',
defaultValue: 1,
valueConverter: (v) => parseInt(v),
});
offscreenTabLimitProperty.register(TabsBase);
export const tabsPositionProperty = new Property<TabsBase, 'top' | 'bottom'>({
name: 'tabsPosition',
defaultValue: 'top',
name: 'tabsPosition',
defaultValue: 'top',
});
tabsPositionProperty.register(TabsBase);