mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-26 11:17:04 +08:00
Merge pull request #1554 from PeterStaev/action-item-custom-view
Action item custom view
This commit is contained in:
@ -220,6 +220,9 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="apps\tests\pages\tab-view.xml" />
|
<Content Include="apps\tests\pages\tab-view.xml" />
|
||||||
|
<Content Include="apps\ui-tests-app\action-bar\action-view.xml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Content>
|
||||||
<Content Include="apps\ui-tests-app\action-bar\system-icons.xml">
|
<Content Include="apps\ui-tests-app\action-bar\system-icons.xml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Content>
|
</Content>
|
||||||
@ -253,6 +256,9 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Content>
|
</Content>
|
||||||
<TypeScriptCompile Include="apps\ui-tests-app\animations\background.ts" />
|
<TypeScriptCompile Include="apps\ui-tests-app\animations\background.ts" />
|
||||||
|
<TypeScriptCompile Include="apps\ui-tests-app\action-bar\action-view.ts">
|
||||||
|
<DependentUpon>action-view.xml</DependentUpon>
|
||||||
|
</TypeScriptCompile>
|
||||||
<TypeScriptCompile Include="apps\ui-tests-app\pages\touch-event.ts" />
|
<TypeScriptCompile Include="apps\ui-tests-app\pages\touch-event.ts" />
|
||||||
<Content Include="apps\ui-tests-app\pages\touch-event.xml">
|
<Content Include="apps\ui-tests-app\pages\touch-event.xml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
|
@ -118,6 +118,27 @@ import actionBarModule = require("ui/action-bar");
|
|||||||
//The value should be a string such as 'ic_menu_search' if you want to display the built-in Android Menu Search icon for example.
|
//The value should be a string such as 'ic_menu_search' if you want to display the built-in Android Menu Search icon for example.
|
||||||
//For a full list of Android drawable names, please visit http://androiddrawables.com
|
//For a full list of Android drawable names, please visit http://androiddrawables.com
|
||||||
//
|
//
|
||||||
|
// ## Displaying Custom View in Action Items
|
||||||
|
//```XML
|
||||||
|
// <Page>
|
||||||
|
// <Page.actionBar>
|
||||||
|
// <ActionBar>
|
||||||
|
// <ActionBar.actionItems>
|
||||||
|
// <ActionItem>
|
||||||
|
// <ActionItem.actionView>
|
||||||
|
// <StackLayout orientation="horizontal">
|
||||||
|
// <Label text="Green" color="green"/>
|
||||||
|
// <Label text="Red" color="red"/>
|
||||||
|
// </StackLayout>
|
||||||
|
// </ActionItem.actionView>
|
||||||
|
// </ActionItem>
|
||||||
|
// </ActionBar.actionItems>
|
||||||
|
// </ActionBar>
|
||||||
|
// </Page.actionBar>
|
||||||
|
// ...
|
||||||
|
// </Page>
|
||||||
|
//```
|
||||||
|
//
|
||||||
// ## Setting Navigation Button
|
// ## Setting Navigation Button
|
||||||
//```XML
|
//```XML
|
||||||
// <Page>
|
// <Page>
|
||||||
@ -197,6 +218,37 @@ export function test_actionItem_page_property_inXML() {
|
|||||||
TKUnit.assertEqual(actionItem.page, p, "actionItem.page");
|
TKUnit.assertEqual(actionItem.page, p, "actionItem.page");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function test_actionItem_actionView_inXML() {
|
||||||
|
var p = <PageModule.Page>builder.parse(
|
||||||
|
"<Page> <Page.actionBar> <ActionBar> <ActionItem> <ActionItem.actionView>" +
|
||||||
|
"<Label/>" +
|
||||||
|
"</ActionItem.actionView> </ActionItem> </ActionBar> </Page.actionBar> </Page>");
|
||||||
|
|
||||||
|
var label = <LabelModule.Label>p.actionBar.actionItems.getItemAt(0).actionView;
|
||||||
|
TKUnit.assert(label instanceof LabelModule.Label, "ActionItem.actionView not loaded correctly");
|
||||||
|
};
|
||||||
|
|
||||||
|
export function test_actionItem_actionView_inherit_bindingContext_inXML() {
|
||||||
|
var p = <PageModule.Page>builder.parse(
|
||||||
|
"<Page> <Page.actionBar> <ActionBar> <ActionItem> <ActionItem.actionView>" +
|
||||||
|
"<Label text=\"{{ myProp }} \" />" +
|
||||||
|
"</ActionItem.actionView> </ActionItem> </ActionBar> </Page.actionBar> </Page>");
|
||||||
|
p.bindingContext = { myProp: "success" };
|
||||||
|
|
||||||
|
var label = <LabelModule.Label>p.actionBar.actionItems.getItemAt(0).actionView;
|
||||||
|
TKUnit.assert(label instanceof LabelModule.Label, "ActionItem.actionView not loaded correctly");
|
||||||
|
TKUnit.assertEqual(label.text, "success", "ActionItem.actionView");
|
||||||
|
};
|
||||||
|
|
||||||
|
export function test_ActionBar_is_not_empty_when_actionItem_actionView_is_set() {
|
||||||
|
var p = <PageModule.Page>builder.parse(
|
||||||
|
"<Page> <Page.actionBar> <ActionBar> <ActionItem> <ActionItem.actionView>" +
|
||||||
|
"<Label text=\"test\" />" +
|
||||||
|
"</ActionItem.actionView> </ActionItem> </ActionBar> </Page.actionBar> </Page>");
|
||||||
|
|
||||||
|
TKUnit.assertFalse(p.actionBar._isEmpty(), "ActionItem.actionView is set but ActionBar reports empty");
|
||||||
|
};
|
||||||
|
|
||||||
export function test_navigationButton_inherit_bindingContext_inXML() {
|
export function test_navigationButton_inherit_bindingContext_inXML() {
|
||||||
var p = <PageModule.Page>builder.parse(
|
var p = <PageModule.Page>builder.parse(
|
||||||
"<Page> <Page.actionBar> <ActionBar>" +
|
"<Page> <Page.actionBar> <ActionBar>" +
|
||||||
|
5
apps/ui-tests-app/action-bar/action-view.ts
Normal file
5
apps/ui-tests-app/action-bar/action-view.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import frame = require("ui/frame");
|
||||||
|
|
||||||
|
export function navigate(args) {
|
||||||
|
frame.topmost().navigate("action-bar/clean");
|
||||||
|
}
|
19
apps/ui-tests-app/action-bar/action-view.xml
Normal file
19
apps/ui-tests-app/action-bar/action-view.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<Page>
|
||||||
|
<Page.actionBar>
|
||||||
|
<ActionBar>
|
||||||
|
<ActionBar.actionItems>
|
||||||
|
<ActionItem>
|
||||||
|
<ActionItem.actionView>
|
||||||
|
<StackLayout orientation="horizontal">
|
||||||
|
<Label text="Green" color="green"/>
|
||||||
|
<Label text="Red" color="red"/>
|
||||||
|
</StackLayout>
|
||||||
|
</ActionItem.actionView>
|
||||||
|
</ActionItem>
|
||||||
|
</ActionBar.actionItems>
|
||||||
|
</ActionBar>
|
||||||
|
</Page.actionBar>
|
||||||
|
<StackLayout>
|
||||||
|
<Button text="go to cleared page" tap="navigate"/>
|
||||||
|
</StackLayout>
|
||||||
|
</Page>
|
@ -36,6 +36,7 @@ examples.set("actColor", "action-bar/color");
|
|||||||
examples.set("actBG", "action-bar/background");
|
examples.set("actBG", "action-bar/background");
|
||||||
examples.set("actStyle", "action-bar/all");
|
examples.set("actStyle", "action-bar/all");
|
||||||
examples.set("actIcons", "action-bar/system-icons");
|
examples.set("actIcons", "action-bar/system-icons");
|
||||||
|
examples.set("actView", "action-bar/action-view");
|
||||||
|
|
||||||
examples.set("basics", "bindings/basics");
|
examples.set("basics", "bindings/basics");
|
||||||
examples.set("xmlbasics", "bindings/xmlbasics");
|
examples.set("xmlbasics", "bindings/xmlbasics");
|
||||||
|
@ -344,6 +344,7 @@
|
|||||||
"apps/ui-tests-app/action-bar/clean.ts",
|
"apps/ui-tests-app/action-bar/clean.ts",
|
||||||
"apps/ui-tests-app/action-bar/color.ts",
|
"apps/ui-tests-app/action-bar/color.ts",
|
||||||
"apps/ui-tests-app/action-bar/system-icons.ts",
|
"apps/ui-tests-app/action-bar/system-icons.ts",
|
||||||
|
"apps/ui-tests-app/action-bar/action-view.ts",
|
||||||
"apps/ui-tests-app/animations/background.ts",
|
"apps/ui-tests-app/animations/background.ts",
|
||||||
"apps/ui-tests-app/app.ts",
|
"apps/ui-tests-app/app.ts",
|
||||||
"apps/ui-tests-app/bindings/basics.ts",
|
"apps/ui-tests-app/bindings/basics.ts",
|
||||||
|
@ -108,7 +108,14 @@ export class ActionBar extends view.View implements dts.ActionBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get _childrenCount(): number {
|
get _childrenCount(): number {
|
||||||
return this.titleView ? 1 : 0;
|
let actionViewsCount = 0;
|
||||||
|
this._actionItems.getItems().forEach((actionItem) => {
|
||||||
|
if (actionItem.actionView) {
|
||||||
|
actionViewsCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return actionViewsCount + (this.titleView ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -157,6 +164,12 @@ export class ActionBar extends view.View implements dts.ActionBar {
|
|||||||
if (this.titleView) {
|
if (this.titleView) {
|
||||||
callback(this.titleView);
|
callback(this.titleView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.actionItems.getItems().forEach((actionItem) => {
|
||||||
|
if (actionItem.actionView) {
|
||||||
|
callback(actionItem.actionView);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public _isEmpty(): boolean {
|
public _isEmpty(): boolean {
|
||||||
@ -263,7 +276,29 @@ export class ActionItem extends bindable.Bindable implements dts.ActionItem {
|
|||||||
"visibility", "ActionItem", new dependencyObservable.PropertyMetadata(enums.Visibility.visible, null, ActionItem.onItemChanged));
|
"visibility", "ActionItem", new dependencyObservable.PropertyMetadata(enums.Visibility.visible, null, ActionItem.onItemChanged));
|
||||||
|
|
||||||
private _actionBar: ActionBar;
|
private _actionBar: ActionBar;
|
||||||
|
private _actionView: view.View;
|
||||||
|
|
||||||
|
get actionView(): view.View {
|
||||||
|
return this._actionView;
|
||||||
|
}
|
||||||
|
set actionView(value: view.View) {
|
||||||
|
if (this._actionView !== value) {
|
||||||
|
ensureStyle();
|
||||||
|
if (this._actionView && this._actionBar) {
|
||||||
|
this._actionBar._removeView(this._actionView);
|
||||||
|
this._actionView.style._resetValue(style.horizontalAlignmentProperty, dependencyObservable.ValueSource.Inherited);
|
||||||
|
this._actionView.style._resetValue(style.verticalAlignmentProperty, dependencyObservable.ValueSource.Inherited);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._actionView = value;
|
||||||
|
|
||||||
|
this._addActionViewToActionBar();
|
||||||
|
|
||||||
|
if (this._actionBar) {
|
||||||
|
this._actionBar.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
get text(): string {
|
get text(): string {
|
||||||
return this._getValue(ActionItem.textProperty);
|
return this._getValue(ActionItem.textProperty);
|
||||||
}
|
}
|
||||||
@ -297,6 +332,7 @@ export class ActionItem extends bindable.Bindable implements dts.ActionItem {
|
|||||||
this._actionBar = value;
|
this._actionBar = value;
|
||||||
if (this._actionBar) {
|
if (this._actionBar) {
|
||||||
this.bindingContext = this._actionBar.bindingContext;
|
this.bindingContext = this._actionBar.bindingContext;
|
||||||
|
this._addActionViewToActionBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,6 +354,19 @@ export class ActionItem extends bindable.Bindable implements dts.ActionItem {
|
|||||||
menuItem.actionBar.update();
|
menuItem.actionBar.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _addActionViewToActionBar() {
|
||||||
|
if (this._actionView && !this._actionView._isAddedToNativeVisualTree && this._actionBar) {
|
||||||
|
ensureStyle();
|
||||||
|
this._actionView.style._setValue(style.horizontalAlignmentProperty, enums.HorizontalAlignment.center, dependencyObservable.ValueSource.Inherited);
|
||||||
|
this._actionView.style._setValue(style.verticalAlignmentProperty, enums.VerticalAlignment.center, dependencyObservable.ValueSource.Inherited);
|
||||||
|
this._actionBar._addView(this._actionView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public _addChildFromBuilder(name: string, value: any) {
|
||||||
|
this.actionView = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isVisible(item: dts.ActionItem) {
|
export function isVisible(item: dts.ActionItem) {
|
||||||
|
@ -266,7 +266,20 @@ export class ActionBar extends common.ActionBar {
|
|||||||
var item = <ActionItem>items[i];
|
var item = <ActionItem>items[i];
|
||||||
var menuItem = menu.add(android.view.Menu.NONE, item._getItemId(), android.view.Menu.NONE, item.text + "");
|
var menuItem = menu.add(android.view.Menu.NONE, item._getItemId(), android.view.Menu.NONE, item.text + "");
|
||||||
|
|
||||||
if (item.android.systemIcon) {
|
if (item.actionView && item.actionView.android) {
|
||||||
|
// With custom action view, the menuitem cannot be displayed in a popup menu.
|
||||||
|
item.android.position = enums.AndroidActionItemPosition.actionBar;
|
||||||
|
|
||||||
|
menuItem.setActionView(item.actionView.android);
|
||||||
|
// Note: When using a custom action view the toolbar's MenuItemClickListener is not triggered!
|
||||||
|
menuItem.getActionView().setOnClickListener(new android.view.View.OnClickListener({
|
||||||
|
onClick:
|
||||||
|
function () {
|
||||||
|
item._raiseTap();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else if (item.android.systemIcon) {
|
||||||
// Try to look in the system resources.
|
// Try to look in the system resources.
|
||||||
let systemResourceId = getSystemResourceId(item.android.systemIcon);
|
let systemResourceId = getSystemResourceId(item.android.systemIcon);
|
||||||
if (systemResourceId) {
|
if (systemResourceId) {
|
||||||
|
5
ui/action-bar/action-bar.d.ts
vendored
5
ui/action-bar/action-bar.d.ts
vendored
@ -117,6 +117,11 @@ declare module "ui/action-bar" {
|
|||||||
* Gets or sets the icon of the action item.
|
* Gets or sets the icon of the action item.
|
||||||
*/
|
*/
|
||||||
icon: string;
|
icon: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets or sets the custom action view of the action item.
|
||||||
|
*/
|
||||||
|
actionView: view.View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or sets the visibility of the action item.
|
* Gets or sets the visibility of the action item.
|
||||||
|
@ -134,7 +134,17 @@ export class ActionBar extends common.ActionBar {
|
|||||||
|
|
||||||
var barButtonItem: UIBarButtonItem;
|
var barButtonItem: UIBarButtonItem;
|
||||||
|
|
||||||
if (types.isNumber(item.ios.systemIcon)) {
|
if (item.actionView && item.actionView.ios) {
|
||||||
|
let buttonView: UIButton = UIButton.buttonWithType(UIButtonType.UIButtonTypeSystem);
|
||||||
|
// Disable the interaction of the custom view so that the tap event of the button is triggered
|
||||||
|
(<UIView>item.actionView.ios).userInteractionEnabled = false;
|
||||||
|
|
||||||
|
buttonView.addTargetActionForControlEvents(tapHandler, "tap", UIControlEvents.UIControlEventTouchUpInside);
|
||||||
|
buttonView.frame = CGRectMake(0, 0, item.actionView.getMeasuredWidth(), item.actionView.getMeasuredHeight());
|
||||||
|
buttonView.addSubview(item.actionView.ios);
|
||||||
|
barButtonItem = UIBarButtonItem.alloc().initWithCustomView(buttonView);
|
||||||
|
}
|
||||||
|
else if (types.isNumber(item.ios.systemIcon)) {
|
||||||
barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(item.ios.systemIcon, tapHandler, "tap");
|
barButtonItem = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(item.ios.systemIcon, tapHandler, "tap");
|
||||||
}
|
}
|
||||||
else if (item.icon) {
|
else if (item.icon) {
|
||||||
@ -212,12 +222,33 @@ export class ActionBar extends common.ActionBar {
|
|||||||
utils.layout.makeMeasureSpec(navBarHeight, utils.layout.AT_MOST));
|
utils.layout.makeMeasureSpec(navBarHeight, utils.layout.AT_MOST));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.actionItems.getItems().forEach((actionItem) => {
|
||||||
|
if (actionItem.actionView) {
|
||||||
|
view.View.measureChild(this, actionItem.actionView,
|
||||||
|
utils.layout.makeMeasureSpec(width, utils.layout.AT_MOST),
|
||||||
|
utils.layout.makeMeasureSpec(navBarHeight, utils.layout.AT_MOST));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// We ignore our width/height, minWidth/minHeight dimensions because it is against Apple policy to change height of NavigationBar.
|
// We ignore our width/height, minWidth/minHeight dimensions because it is against Apple policy to change height of NavigationBar.
|
||||||
this.setMeasuredDimension(navBarWidth, navBarHeight);
|
this.setMeasuredDimension(navBarWidth, navBarHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onLayout(left: number, top: number, right: number, bottom: number) {
|
public onLayout(left: number, top: number, right: number, bottom: number) {
|
||||||
view.View.layoutChild(this, this.titleView, 0, 0, right - left, this._navigationBarHeight);
|
view.View.layoutChild(this, this.titleView, 0, 0, right - left, this._navigationBarHeight);
|
||||||
|
this.actionItems.getItems().forEach((actionItem) => {
|
||||||
|
if (actionItem.actionView && actionItem.actionView.ios) {
|
||||||
|
let measuredWidth = actionItem.actionView.getMeasuredWidth();
|
||||||
|
let measuredHeight = actionItem.actionView.getMeasuredHeight();
|
||||||
|
let buttonView = (<UIView>actionItem.actionView.ios).superview;
|
||||||
|
|
||||||
|
view.View.layoutChild(this, actionItem.actionView, 0, 0, measuredWidth, measuredHeight);
|
||||||
|
if (buttonView) {
|
||||||
|
buttonView.frame = CGRectMake(0, 0, measuredWidth, measuredHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
super.onLayout(left, top, right, bottom);
|
super.onLayout(left, top, right, bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user