mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
chore: default tabs
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
112
nativescript-core/ui/tabs/index.d.ts
vendored
112
nativescript-core/ui/tabs/index.d.ts
vendored
@@ -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[]>;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user