feat(TabStrip): add itemTap event (#7711)

This commit is contained in:
Vasil Chimev
2019-08-23 15:32:31 +03:00
committed by Manol Donev
parent caca2b82a2
commit 55c9cc9072
33 changed files with 610 additions and 360 deletions

View File

@@ -1,20 +1,20 @@
// Types
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
import { TabStrip } from "../tab-navigation-base/tab-strip";
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
import { TextTransform } from "../text-base";
// Requires
import {
TabNavigationBase, getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty
} from "../tab-navigation-base/tab-navigation-base";
import { Font } from "../styling/font";
import { getTransformedText } from "../text-base";
import { CSSType, Color } from "../core/view";
import { Frame, View } from "../frame";
import { RESOURCE_PREFIX, ad, layout, isFontIconURI } from "../../utils/utils";
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
import * as application from "../../application";
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
import { ad, isFontIconURI, layout, RESOURCE_PREFIX } from "../../utils/utils";
import { Color, CSSType } from "../core/view";
import { Frame, View } from "../frame";
import { Font } from "../styling/font";
import {
getIconSpecSize, itemsProperty, selectedIndexProperty, TabNavigationBase, tabStripProperty
} from "../tab-navigation-base/tab-navigation-base";
import { getTransformedText } from "../text-base";
// TODO: Impl trace
// import { isEnabled as traceEnabled, write as traceWrite } from "../../../trace";
@@ -126,10 +126,12 @@ function initializeNativeClasses() {
return false;
}
const tabStripItems = owner.tabStrip && owner.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 (!owner.items[position]) {
@@ -271,7 +273,7 @@ export class BottomNavigation extends TabNavigationBase {
this._bottomNavigationBar = (<any>nativeView).bottomNavigationBar;
(<any>this._bottomNavigationBar).owner = this;
if (this.tabStrip) {
this.tabStrip.setNativeView(this._bottomNavigationBar);
}
@@ -504,37 +506,37 @@ export class BottomNavigation extends TabNavigationBase {
private createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec {
const tabItemSpec = new org.nativescript.widgets.TabItemSpec();
if (tabStripItem.isLoaded) {
const titleLabel = tabStripItem.label;
let title = titleLabel.text;
// TEXT-TRANSFORM
const textTransform = titleLabel.style.textTransform;
if (textTransform) {
title = getTransformedText(title, textTransform);
}
tabItemSpec.title = title;
// BACKGROUND-COLOR
const backgroundColor = tabStripItem.style.backgroundColor;
if (backgroundColor) {
tabItemSpec.backgroundColor = backgroundColor.android;
}
// COLOR
const color = titleLabel.style.color;
if (color) {
tabItemSpec.color = color.android;
}
// FONT
const fontInternal = titleLabel.style.fontInternal;
if (fontInternal) {
tabItemSpec.fontSize = fontInternal.fontSize;
tabItemSpec.typeFace = fontInternal.getAndroidTypeface();
}
// ICON
const iconSource = tabStripItem.image && tabStripItem.image.src;
if (iconSource) {
@@ -546,7 +548,7 @@ export class BottomNavigation extends TabNavigationBase {
}
} else {
const icon = this.getIcon(tabStripItem);
if (icon) {
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
// tslint:disable-next-line:deprecation
@@ -558,13 +560,13 @@ export class BottomNavigation extends TabNavigationBase {
}
}
}
return tabItemSpec;
}
private getIcon(tabStripItem: TabStripItem): android.graphics.drawable.BitmapDrawable {
const iconSource = tabStripItem.image && tabStripItem.image.src;
let is: ImageSource;
if (isFontIconURI(iconSource)) {
const fontIconCode = iconSource.split("//")[1];
@@ -575,35 +577,35 @@ export class BottomNavigation extends TabNavigationBase {
} else {
is = fromFileOrResource(iconSource);
}
let imageDrawable: android.graphics.drawable.BitmapDrawable;
if (is && is.android) {
let image = is.android;
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
image = this.getFixedSizeIcon(image);
}
imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
} else {
// TODO
// traceMissingIcon(iconSource);
}
return imageDrawable;
}
private getFixedSizeIcon(image: android.graphics.Bitmap): android.graphics.Bitmap {
const inWidth = image.getWidth();
const inHeight = image.getHeight();
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
const widthPixels = iconSpecSize.width * layout.getDisplayDensity();
const heightPixels = iconSpecSize.height * layout.getDisplayDensity();
const scaledImage = android.graphics.Bitmap.createScaledBitmap(image, widthPixels, heightPixels, true);
return scaledImage;
}
@@ -660,7 +662,7 @@ export class BottomNavigation extends TabNavigationBase {
}
public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void {
const titleLabel = tabStripItem.label;
const titleLabel = tabStripItem.label;
const title = getTransformedText(titleLabel.text, value);
tabStripItem.nativeViewProtected.setText(title);
}

View File

@@ -1,21 +1,22 @@
// Types
import { TabStrip } from "../tab-navigation-base/tab-strip";
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
import { TabStrip } from "../tab-navigation-base/tab-strip";
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
import { TextTransform } from "../text-base";
//Requires
import {
TabNavigationBase, getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty
} from "../tab-navigation-base/tab-navigation-base";
import { Font } from "../styling/font";
import { getTransformedText } from "../text-base";
import { Frame } from "../frame";
import { ios as iosView, View, CSSType } from "../core/view";
import { ios as iosUtils, layout, isFontIconURI } from "../../utils/utils";
import { device } from "../../platform";
// Requires
import { Color } from "../../color";
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
import { device } from "../../platform";
import { ios as iosUtils, isFontIconURI, layout } from "../../utils/utils";
import { CSSType, ios as iosView, View } from "../core/view";
import { Frame } from "../frame";
import { Font } from "../styling/font";
import {
getIconSpecSize, itemsProperty, selectedIndexProperty, TabNavigationBase, tabStripProperty
} from "../tab-navigation-base/tab-navigation-base";
import { getTransformedText } from "../text-base";
// TODO:
// import { profile } from "../../profiling";
@@ -107,9 +108,12 @@ class UITabBarControllerDelegateImpl extends NSObject implements UITabBarControl
if (tabBarController.viewControllers) {
const position = tabBarController.viewControllers.indexOfObject(viewController);
if (position !== NSNotFound) {
const tabStripItems = owner.tabStrip && owner.tabStrip.items;
const tabStrip = owner.tabStrip;
const tabStripItems = tabStrip && tabStrip.items;
if (tabStripItems && tabStripItems[position]) {
tabStripItems[position]._emit(TabStripItem.tapEvent);
tabStrip.notify({ eventName: TabStrip.itemTapEvent, object: tabStrip, index: position });
}
}
}
@@ -555,7 +559,7 @@ export class BottomNavigation extends TabNavigationBase {
if (is && is.ios) {
image = is.ios;
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
image = this.getFixedSizeIcon(image);
}
@@ -575,7 +579,7 @@ export class BottomNavigation extends TabNavigationBase {
private getFixedSizeIcon(image: UIImage): UIImage {
const inWidth = image.size.width;
const inHeight = image.size.height;
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
const widthPts = iconSpecSize.width;

View File

@@ -3,8 +3,8 @@
* @module "ui/tab-navigation/tab-strip"
*/ /** */
import { View, Property } from "../../core/view";
import { Color } from "../../../color";
import { EventData, Property, View } from "../../core/view";
import { TabStripItem } from "../tab-strip-item";
/**
@@ -36,6 +36,34 @@ export class TabStrip extends View {
* @private
*/
_hasTitle: boolean;
/**
* String value used when hooking to itemTap event.
*/
public static itemTapEvent: 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);
/**
* Raised when an TabStripItem is tapped.
*/
on(event: "itemTap", callback: (args: TabStripItemEventData) => void, thisArg?: any);
}
/**
* Event data containing information for the TabStripItem's index.
*/
export interface TabStripItemEventData extends EventData {
/**
* The index of the TabStripItem.
*/
index: number;
}
export const iosIconRenderingModeProperty: Property<TabStrip, "automatic" | "alwaysOriginal" | "alwaysTemplate">;

View File

@@ -1,14 +1,14 @@
// Types
import { TabStrip as TabStripDefinition } from ".";
import { TabStripItem } from "../tab-strip-item";
import { TabNavigationBase } from "../tab-navigation-base";
// Types
import { Color } from "../../../color";
import { ViewBase, AddArrayFromBuilder, AddChildFromBuilder } from "../../core/view";
import { AddArrayFromBuilder, AddChildFromBuilder, EventData, ViewBase } from "../../core/view";
import { TabNavigationBase } from "../tab-navigation-base";
import { TabStripItem } from "../tab-strip-item";
import { TabStripItemEventData, TabStrip as TabStripDefinition } from "./";
// Requires
import {
View, Property, CSSType, backgroundColorProperty, backgroundInternalProperty,
colorProperty, fontInternalProperty, booleanConverter
import {
backgroundColorProperty, backgroundInternalProperty, booleanConverter,
colorProperty, CSSType, fontInternalProperty, Property, View
} from "../../core/view";
import { textTransformProperty } from "../../text-base";
@@ -20,6 +20,7 @@ export const highlightColorProperty = new Property<TabStrip, Color>({ name: "hig
@CSSType("TabStrip")
export class TabStrip extends View implements TabStripDefinition, AddChildFromBuilder, AddArrayFromBuilder {
public static itemTapEvent = "itemTap";
public items: TabStripItem[];
public isIconSizeFixed: boolean;
public iosIconRenderingMode: "automatic" | "alwaysOriginal" | "alwaysTemplate";
@@ -89,7 +90,7 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu
}
[colorProperty.setNative](value: Color) {
const parent = <TabNavigationBase>this.parent;
return parent && parent.setTabBarColor(value);
}
@@ -100,7 +101,7 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu
}
[fontInternalProperty.setNative](value: any) {
const parent = <TabNavigationBase>this.parent;
return parent && parent.setTabBarFontInternal(value);
}
@@ -111,7 +112,7 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu
}
[textTransformProperty.setNative](value: any) {
const parent = <TabNavigationBase>this.parent;
return parent && parent.setTabBarTextTransform(value);
}
@@ -122,11 +123,16 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu
}
[highlightColorProperty.setNative](value: number | Color) {
const parent = <TabNavigationBase>this.parent;
return parent && parent.setTabBarHighlightColor(value);
}
}
export interface TabStrip {
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
on(event: "itemTap", callback: (args: TabStripItemEventData) => void, thisArg?: any);
}
export const itemsProperty = new Property<TabStrip, TabStripItem[]>({
name: "items", valueChanged: (target, oldValue, newValue) => {
target.onItemsChanged(oldValue, newValue);

View File

@@ -5,15 +5,17 @@ import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
import { TextTransform } from "../text-base";
// Requires
import { getIconSpecSize, selectedIndexProperty, itemsProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
import { TabsBase, swipeEnabledProperty, offscreenTabLimitProperty } from "./tabs-common";
import { Font } from "../styling/font";
import { getTransformedText } from "../text-base";
import { Frame } from "../frame";
import { Color } from "../core/view";
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
import { RESOURCE_PREFIX, ad, layout, isFontIconURI } from "../../utils/utils";
import * as application from "../../application";
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
import { ad, isFontIconURI, layout, RESOURCE_PREFIX } from "../../utils/utils";
import { Color } from "../core/view";
import { Frame } from "../frame";
import { Font } from "../styling/font";
import {
getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty
} from "../tab-navigation-base/tab-navigation-base";
import { getTransformedText } from "../text-base";
import { offscreenTabLimitProperty, swipeEnabledProperty, TabsBase } from "./tabs-common";
export * from "./tabs-common";
@@ -265,10 +267,12 @@ function initializeNativeClasses() {
return false;
}
const tabStripItems = owner.tabStrip && owner.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 (!owner.items[position]) {
@@ -577,37 +581,37 @@ export class Tabs extends TabsBase {
private createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec {
const tabItemSpec = new org.nativescript.widgets.TabItemSpec();
if (tabStripItem.isLoaded) {
const nestedLabel = tabStripItem.label;
let title = nestedLabel.text;
// TEXT-TRANSFORM
const textTransform = nestedLabel.style.textTransform;
if (textTransform) {
title = getTransformedText(title, textTransform);
}
tabItemSpec.title = title;
// BACKGROUND-COLOR
const backgroundColor = tabStripItem.style.backgroundColor;
if (backgroundColor) {
tabItemSpec.backgroundColor = backgroundColor.android;
}
// COLOR
const color = nestedLabel.style.color;
if (color) {
tabItemSpec.color = color.android;
}
// FONT
const fontInternal = nestedLabel.style.fontInternal;
if (fontInternal) {
tabItemSpec.fontSize = fontInternal.fontSize;
tabItemSpec.typeFace = fontInternal.getAndroidTypeface();
}
// ICON
const iconSource = tabStripItem.image && tabStripItem.image.src;
if (iconSource) {
@@ -619,7 +623,7 @@ export class Tabs extends TabsBase {
}
} else {
const icon = this.getIcon(tabStripItem);
if (icon) {
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
// tslint:disable-next-line:deprecation
@@ -631,13 +635,13 @@ export class Tabs extends TabsBase {
}
}
}
return tabItemSpec;
}
private getIcon(tabStripItem: TabStripItem): android.graphics.drawable.BitmapDrawable {
const iconSource = tabStripItem.image && tabStripItem.image.src;
let is: ImageSource;
if (isFontIconURI(iconSource)) {
const fontIconCode = iconSource.split("//")[1];
@@ -648,35 +652,35 @@ export class Tabs extends TabsBase {
} else {
is = fromFileOrResource(iconSource);
}
let imageDrawable: android.graphics.drawable.BitmapDrawable;
if (is && is.android) {
let image = is.android;
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
image = this.getFixedSizeIcon(image);
}
imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
} else {
// TODO
// traceMissingIcon(iconSource);
}
return imageDrawable;
}
private getFixedSizeIcon(image: android.graphics.Bitmap): android.graphics.Bitmap {
const inWidth = image.getWidth();
const inHeight = image.getHeight();
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
const widthPixels = iconSpecSize.width * layout.getDisplayDensity();
const heightPixels = iconSpecSize.height * layout.getDisplayDensity();
const scaledImage = android.graphics.Bitmap.createScaledBitmap(image, widthPixels, heightPixels, true);
return scaledImage;
}
@@ -772,7 +776,7 @@ export class Tabs extends TabsBase {
}
public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void {
const nestedLabel = tabStripItem.label;
const nestedLabel = tabStripItem.label;
const title = getTransformedText(nestedLabel.text, value);
tabStripItem.nativeViewProtected.setText(title);
}

View File

@@ -1,19 +1,20 @@
// Types
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
import { TabStrip } from "../tab-navigation-base/tab-strip";
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
import { TextTransform } from "../text-base";
// Requires
import { getIconSpecSize, selectedIndexProperty, itemsProperty, tabStripProperty } from "../tab-navigation-base/tab-navigation-base";
import { TabsBase, swipeEnabledProperty } from "./tabs-common";
import { Font } from "../styling/font";
import { Frame } from "../frame";
import { ios as iosView, View } from "../core/view";
import { Color } from "../../color";
import { ios as iosUtils, layout, isFontIconURI } from "../../utils/utils";
// import { device } from "../../platform";
import { fromFileOrResource, fromFontIconCode, ImageSource } from "../../image-source";
import { ios as iosUtils, isFontIconURI, layout } from "../../utils/utils";
import { ios as iosView, View } from "../core/view";
import { Frame } from "../frame";
import { Font } from "../styling/font";
import {
getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty
} from "../tab-navigation-base/tab-navigation-base";
import { swipeEnabledProperty, TabsBase } from "./tabs-common";
// TODO
// import { profile } from "../../profiling";
@@ -44,9 +45,12 @@ class MDCTabBarDelegateImpl extends NSObject implements MDCTabBarDelegate {
owner._canSelectItem = false;
}
const tabStripItems = owner.tabStrip && owner.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 });
}
return shouldSelectItem;
@@ -856,7 +860,7 @@ export class Tabs extends TabsBase {
if (!this.tabStrip._hasImage) {
this.tabStrip._hasImage = !!image;
}
if (!this.tabStrip._hasTitle) {
this.tabStrip._hasTitle = !!title;
}
@@ -907,7 +911,7 @@ export class Tabs extends TabsBase {
if (is && is.ios) {
image = is.ios;
if (this.tabStrip && this.tabStrip.isIconSizeFixed) {
image = this.getFixedSizeIcon(image);
}
@@ -927,7 +931,7 @@ export class Tabs extends TabsBase {
private getFixedSizeIcon(image: UIImage): UIImage {
const inWidth = image.size.width;
const inHeight = image.size.height;
const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight });
const widthPts = iconSpecSize.width;