mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 11:42:04 +08:00
Segmented bar styles
This commit is contained in:
@ -14,7 +14,7 @@ export function checkNativeItemsTextColor(bar: segmentedBarModule.SegmentedBar):
|
||||
// isValid = bar.color && bar.color.android === t.getCurrentTextColor();
|
||||
// }
|
||||
|
||||
for(let i = 0, itemsLength = bar.items.length; i < itemsLength; i++) {
|
||||
for (let i = 0, itemsLength = bar.items.length; i < itemsLength; i++) {
|
||||
let textView = <android.widget.TextView>bar.items[0].nativeView;
|
||||
isValid = bar.color && bar.color.android === textView.getCurrentTextColor();
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import * as TKUnit from "../../TKUnit";
|
||||
import * as segmentedBarTestsNative from "./segmented-bar-tests-native";
|
||||
import {buildUIAndRunTest} from "../helper";
|
||||
import {View} from "ui/core/view";
|
||||
import {BindingOptions} from "ui/core/bindable";
|
||||
import {Observable} from "data/observable";
|
||||
import {Color} from "color";
|
||||
import { buildUIAndRunTest } from "../helper";
|
||||
import { View } from "ui/core/view";
|
||||
import { BindingOptions } from "ui/core/bindable";
|
||||
import { Observable } from "data/observable";
|
||||
import { Color } from "color";
|
||||
|
||||
// >> article-require-segmentedbar-module
|
||||
import * as segmentedBarModule from "ui/segmented-bar";
|
||||
@ -77,7 +77,7 @@ export var testWhenItemsAreBoundTheTextColorIsPreserved = function () {
|
||||
}
|
||||
|
||||
segmentedBar.bind(options, model);
|
||||
|
||||
|
||||
TKUnit.assert(segmentedBarTestsNative.checkNativeItemsTextColor(segmentedBar), "Items text color not preserved" + "; Expected: " + segmentedBar.color);
|
||||
});
|
||||
}
|
||||
@ -181,13 +181,13 @@ export var testSelectedIndexChangedIsReisedCorrectlyIfSelectedIndexIsSet = funct
|
||||
var newIndex;
|
||||
var segmentedBar = _createSegmentedBar();
|
||||
|
||||
segmentedBar.on(segmentedBarModule.SegmentedBar.selectedIndexChangedEvent, (args : segmentedBarModule.SelectedIndexChangedEventData) => {
|
||||
segmentedBar.on(segmentedBarModule.SegmentedBar.selectedIndexChangedEvent, (args: segmentedBarModule.SelectedIndexChangedEventData) => {
|
||||
oldIndex = args.oldIndex;
|
||||
newIndex = args.newIndex;
|
||||
});
|
||||
|
||||
segmentedBar.items = _createItems(10);
|
||||
|
||||
|
||||
buildUIAndRunTest(segmentedBar, function (views: Array<View>) {
|
||||
var segmentedBar = <segmentedBarModule.SegmentedBar>views[0];
|
||||
|
||||
@ -262,7 +262,7 @@ export function test_SettingNumberAsTitleFromXML_DoesNotThrow() {
|
||||
let item = new segmentedBarModule.SegmentedBarItem();
|
||||
(<any>item).title = 1;
|
||||
segmentedBar.items = [item];
|
||||
|
||||
|
||||
buildUIAndRunTest(segmentedBar, function (views: Array<View>) {
|
||||
TKUnit.assertEqual(item.title, "1");
|
||||
});
|
||||
|
@ -126,7 +126,7 @@ export function getComponentModule(elementName: string, namespace: string, attri
|
||||
throw new Error(`Css file with path "${cssFilePath}" cannot be found!`);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Css file atribute is valid only for pages!");
|
||||
throw new Error("Css file attribute is valid only for pages!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export function _isSet(cssProperty: CssProperty<any, any>, instance: Style): boo
|
||||
|
||||
export function _printUnregisteredProperties(): void {
|
||||
print(symbolPropertyMap);
|
||||
print(cssSymbolPropertyMap)
|
||||
print(cssSymbolPropertyMap);
|
||||
}
|
||||
|
||||
const enum ValueSource {
|
||||
@ -132,11 +132,11 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor, defi
|
||||
this.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.get = function (this: T): U {
|
||||
return key in this ? this[key] : defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
this.nativeValueChange = function (owner: T, value: U): void {
|
||||
const currentValue = key in owner ? owner[key] : defaultValue;
|
||||
@ -160,7 +160,7 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor, defi
|
||||
owner.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
symbolPropertyMap[key] = this;
|
||||
}
|
||||
@ -219,7 +219,7 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
const originalValue: U = coerceKey in target ? target[coerceKey] : defaultValue;
|
||||
// need that to make coercing but also fire change events
|
||||
this.set.call(target, originalValue);
|
||||
}
|
||||
};
|
||||
|
||||
this.set = function (this: T, value: U): void {
|
||||
const reset = value === unsetValue;
|
||||
@ -283,11 +283,11 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
this.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.get = function (): U {
|
||||
return key in this ? this[key] : defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
this.nativeValueChange = function (owner: T, value: U): void {
|
||||
const currentValue = key in owner ? owner[key] : defaultValue;
|
||||
@ -312,7 +312,7 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
owner.requestLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
symbolPropertyMap[key] = this;
|
||||
}
|
||||
@ -387,7 +387,7 @@ export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> imp
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const setInheritedValue = setFunc(ValueSource.Inherited);
|
||||
this.setInheritedValue = setInheritedValue;
|
||||
@ -403,6 +403,7 @@ export class CssProperty<T extends Style, U> implements definitions.CssProperty<
|
||||
|
||||
public readonly name: string;
|
||||
public readonly cssName: string;
|
||||
public readonly cssLocalName: string;
|
||||
|
||||
protected readonly cssValueDescriptor: PropertyDescriptor;
|
||||
protected readonly localValueDescriptor: PropertyDescriptor;
|
||||
@ -417,8 +418,8 @@ export class CssProperty<T extends Style, U> implements definitions.CssProperty<
|
||||
const name = options.name;
|
||||
this.name = name;
|
||||
|
||||
const cssName = `css-${options.cssName}`;
|
||||
this.cssName = cssName;
|
||||
this.cssName = `css-${options.cssName}`;
|
||||
this.cssLocalName = options.cssName;
|
||||
|
||||
const key = Symbol(name + ":propertyKey");
|
||||
this.key = key;
|
||||
@ -593,6 +594,9 @@ export class CssProperty<T extends Style, U> implements definitions.CssProperty<
|
||||
this.registered = true;
|
||||
Object.defineProperty(cls.prototype, this.name, this.localValueDescriptor);
|
||||
Object.defineProperty(cls.prototype, this.cssName, this.cssValueDescriptor);
|
||||
if (this.cssLocalName !== this.cssName) {
|
||||
Object.defineProperty(cls.prototype, this.cssLocalName, this.localValueDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,7 +638,7 @@ export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U>
|
||||
if (reset) {
|
||||
// If unsetValue - we want to reset this property.
|
||||
let parent = view.parent;
|
||||
let style = parent ? parent.style : null
|
||||
let style = parent ? parent.style : null;
|
||||
// If we have parent and it has non-default value we use as our inherited value.
|
||||
if (style && style[sourceKey] > ValueSource.Default) {
|
||||
newValue = style[name];
|
||||
@ -712,7 +716,7 @@ export class InheritedCssProperty<T extends Style, U> extends CssProperty<T, U>
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const setDefaultFunc = setFunc(ValueSource.Default);
|
||||
const setInheritedFunc = setFunc(ValueSource.Inherited);
|
||||
@ -731,6 +735,7 @@ export class ShorthandProperty<T extends Style, P> implements definitions.Shorth
|
||||
public readonly key: symbol;
|
||||
public readonly name: string;
|
||||
public readonly cssName: string;
|
||||
public readonly cssLocalName: string;
|
||||
|
||||
protected readonly cssValueDescriptor: PropertyDescriptor;
|
||||
protected readonly localValueDescriptor: PropertyDescriptor;
|
||||
@ -739,14 +744,13 @@ export class ShorthandProperty<T extends Style, P> implements definitions.Shorth
|
||||
public readonly sourceKey: symbol;
|
||||
|
||||
constructor(options: definitions.ShorthandPropertyOptions<P>) {
|
||||
const name = options.name;
|
||||
this.name = name;
|
||||
this.name = options.name;
|
||||
|
||||
const key = Symbol(name + ":propertyKey");
|
||||
const key = Symbol(this.name + ":propertyKey");
|
||||
this.key = key;
|
||||
|
||||
const cssName = `css-${options.cssName}`;
|
||||
this.cssName = cssName;
|
||||
this.cssName = `css-${options.cssName}`;
|
||||
this.cssLocalName = `${options.cssName}`;
|
||||
|
||||
const converter = options.converter;
|
||||
|
||||
@ -792,6 +796,9 @@ export class ShorthandProperty<T extends Style, P> implements definitions.Shorth
|
||||
this.registered = true;
|
||||
Object.defineProperty(cls.prototype, this.name, this.localValueDescriptor);
|
||||
Object.defineProperty(cls.prototype, this.cssName, this.cssValueDescriptor);
|
||||
if (this.cssLocalName !== this.cssName) {
|
||||
Object.defineProperty(cls.prototype, this.cssLocalName, this.localValueDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,5 +965,5 @@ export function makeParser<T>(isValid: (value: any) => boolean): (value: any) =>
|
||||
} else {
|
||||
throw new Error("Invalid value: " + value);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { SegmentedBar as SegmentedBarDefinition, SegmentedBarItem as SegmentedBarItemDefinition, SelectedIndexChangedEventData } from "ui/segmented-bar";
|
||||
import {
|
||||
ViewBase, View, AddChildFromBuilder, AddArrayFromBuilder,
|
||||
Property, CoercibleProperty, CssProperty, Color, Style
|
||||
Property, CoercibleProperty, InheritedCssProperty, Color, Style
|
||||
} from "ui/core/view";
|
||||
|
||||
export * from "ui/core/view";
|
||||
@ -45,7 +45,9 @@ export abstract class SegmentedBarBase extends View implements SegmentedBarDefin
|
||||
if (!this.items) {
|
||||
this.items = new Array<SegmentedBarItemBase>();
|
||||
}
|
||||
this.items.push(<SegmentedBarItemBase>value);
|
||||
let item = <SegmentedBarItemBase>value;
|
||||
this.items.push(item);
|
||||
this._addView(item);
|
||||
selectedIndexProperty.coerce(this);
|
||||
}
|
||||
}
|
||||
@ -111,5 +113,5 @@ export const itemsProperty = new Property<SegmentedBarBase, SegmentedBarItemDefi
|
||||
});
|
||||
itemsProperty.register(SegmentedBarBase);
|
||||
|
||||
export const selectedBackgroundColorProperty = new CssProperty<Style, Color>({ name: "selectedBackgroundColor", cssName: "selected-background-color", equalityComparer: Color.equals, valueConverter: (v) => new Color(v) })
|
||||
export const selectedBackgroundColorProperty = new InheritedCssProperty<Style, Color>({ name: "selectedBackgroundColor", cssName: "selected-background-color", equalityComparer: Color.equals, valueConverter: (v) => new Color(v) });
|
||||
selectedBackgroundColorProperty.register(Style);
|
||||
|
@ -8,6 +8,7 @@ export * from "./segmented-bar-common";
|
||||
const R_ID_TABS = 0x01020013;
|
||||
const R_ID_TABCONTENT = 0x01020011;
|
||||
const R_ATTR_STATE_SELECTED = 0x010100a1;
|
||||
const TITLE_TEXT_VIEW_ID = 16908310; // http://developer.android.com/reference/android/R.id.html#title
|
||||
|
||||
let apiLevel: number;
|
||||
// TODO: Move this into widgets.
|
||||
@ -56,9 +57,13 @@ export class SegmentedBarItem extends SegmentedBarItemBase {
|
||||
return this._textView;
|
||||
}
|
||||
|
||||
public setNativeView(textView: android.widget.TextView): void {
|
||||
this._textView = textView;
|
||||
if (textView) {
|
||||
public setupNativeView(tabIndex: number): void {
|
||||
// TabHost.TabSpec.setIndicator DOES NOT WORK once the title has been set.
|
||||
// http://stackoverflow.com/questions/2935781/modify-tab-indicator-dynamically-in-android
|
||||
const titleTextView = <android.widget.TextView>this.parent.android.getTabWidget().getChildAt(tabIndex).findViewById(TITLE_TEXT_VIEW_ID);
|
||||
|
||||
this._textView = titleTextView;
|
||||
if (titleTextView) {
|
||||
applyNativeSetters(this);
|
||||
if (this.titleDirty) {
|
||||
this._update();
|
||||
@ -68,15 +73,6 @@ export class SegmentedBarItem extends SegmentedBarItemBase {
|
||||
|
||||
private titleDirty: boolean;
|
||||
public _update(): void {
|
||||
// if (this._parent && this._parent.android) {
|
||||
// // TabHost.TabSpec.setIndicator DOES NOT WORK once the title has been set.
|
||||
// // http://stackoverflow.com/questions/2935781/modify-tab-indicator-dynamically-in-android
|
||||
// const tabIndex = this._parent.items.indexOf(this);
|
||||
// const titleTextViewId = 16908310; // http://developer.android.com/reference/android/R.id.html#title
|
||||
// const titleTextView = <android.widget.TextView>this._parent.android.getTabWidget().getChildAt(tabIndex).findViewById(titleTextViewId);
|
||||
// titleTextView.setText(this.title || "");
|
||||
// }
|
||||
|
||||
const tv = this._textView;
|
||||
if (tv) {
|
||||
let title = this.title;
|
||||
@ -168,15 +164,12 @@ class TabContentFactory extends java.lang.Object implements android.widget.TabHo
|
||||
let owner = this.owner.get();
|
||||
if (owner) {
|
||||
let tv = new android.widget.TextView(owner._context);
|
||||
let index = parseInt(tag);
|
||||
// This is collapsed by default and made visibile
|
||||
// This is collapsed by default and made visible
|
||||
// by android when TabItem becomes visible/selected.
|
||||
// TODO: Try commenting visigility change.
|
||||
// TODO: Try commenting visibility change.
|
||||
tv.setVisibility(android.view.View.GONE);
|
||||
tv.setMaxLines(1);
|
||||
tv.setEllipsize(android.text.TextUtils.TruncateAt.END);
|
||||
|
||||
(<SegmentedBarItem>owner.items[index]).setNativeView(tv);
|
||||
return tv;
|
||||
} else {
|
||||
throw new Error(`Invalid owner: ${this.owner}`);
|
||||
@ -233,6 +226,7 @@ export class SegmentedBar extends SegmentedBarBase {
|
||||
let tabHost = this.android;
|
||||
this._addingTab = true;
|
||||
tabHost.addTab(tab);
|
||||
tabItem.setupNativeView(index);
|
||||
this._addingTab = false;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import * as application from "application";
|
||||
import * as kam from "ui/animation/keyframe-animation";
|
||||
let keyframeAnimationModule: typeof kam;
|
||||
function ensureKeyframeAnimationModule() {
|
||||
if (!keyframeAnimationModule){
|
||||
if (!keyframeAnimationModule) {
|
||||
keyframeAnimationModule = require("ui/animation/keyframe-animation");
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ function ensureKeyframeAnimationModule() {
|
||||
import * as capm from "./css-animation-parser";
|
||||
let cssAnimationParserModule: typeof capm;
|
||||
function ensureCssAnimationParserModule() {
|
||||
if (!cssAnimationParserModule){
|
||||
if (!cssAnimationParserModule) {
|
||||
cssAnimationParserModule = require("./css-animation-parser");
|
||||
}
|
||||
}
|
||||
@ -48,15 +48,16 @@ export class CssState {
|
||||
private applyDescriptors(view: ViewBase, ruleset: RuleSet): void {
|
||||
let style = view.style;
|
||||
ruleset.declarations.forEach(d => {
|
||||
let name = `css-${d.property}`;
|
||||
if (name in style) {
|
||||
try {
|
||||
style[name] = d.value;
|
||||
} catch (e) {
|
||||
traceWrite(`Failed to apply property [${d.property}] with value [${d.value}] to ${view}. ${e}`, traceCategories.Error, traceMessageType.error)
|
||||
try {
|
||||
// Use the "css-" prefixed name, so that CSS value source is set.
|
||||
let cssPropName = `css-${d.property}`;
|
||||
if (cssPropName in style) {
|
||||
style[cssPropName] = d.value;
|
||||
} else {
|
||||
view[d.property] = d.value;
|
||||
}
|
||||
} else {
|
||||
view[d.property] = d.value;
|
||||
} catch (e) {
|
||||
traceWrite(`Failed to apply property [${d.property}] with value [${d.value}] to ${view}. ${e}`, traceCategories.Error, traceMessageType.error);
|
||||
}
|
||||
});
|
||||
|
||||
@ -228,7 +229,7 @@ export class StyleScope {
|
||||
(<Keyframes[]>nodes.filter(isKeyframe)).forEach(node => keyframes[node.name] = node);
|
||||
|
||||
let rulesets = fromAstNodes(nodes);
|
||||
if (rulesets && rulesets.length){
|
||||
if (rulesets && rulesets.length) {
|
||||
ensureCssAnimationParserModule();
|
||||
rulesets.forEach(rule => rule[animationsSymbol] = cssAnimationParserModule.CssAnimationParser.keyframeAnimationsFromCSSDeclarations(rule.declarations));
|
||||
}
|
||||
@ -262,7 +263,7 @@ export class StyleScope {
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveFileNameFromUrl(url: string, appDirectory: string, fileExists: (string) => boolean): string {
|
||||
export function resolveFileNameFromUrl(url: string, appDirectory: string, fileExists: (name: string) => boolean): string {
|
||||
let fileName: string = typeof url === "string" ? url.trim() : "";
|
||||
|
||||
if (fileName.indexOf("~/") === 0) {
|
||||
@ -282,21 +283,24 @@ export function resolveFileNameFromUrl(url: string, appDirectory: string, fileEx
|
||||
return null;
|
||||
}
|
||||
|
||||
export function applyInlineStyle(view: ViewBase, style: string) {
|
||||
try {
|
||||
let localStyle = `local { ${style} }`;
|
||||
let inlineRuleSet = StyleScope.createSelectorsFromCss(localStyle, null, {});
|
||||
let inlineSelector = new InlineSelector(inlineRuleSet[0]);
|
||||
view.inlineStyleSelector = inlineSelector;
|
||||
if (view._cssState) {
|
||||
view._cssState.apply();
|
||||
} else {
|
||||
let styleScope = new StyleScope();
|
||||
styleScope.applySelectors(view);
|
||||
export function applyInlineStyle(view: ViewBase, styleStr: string) {
|
||||
let localStyle = `local { ${styleStr} }`;
|
||||
let inlineRuleSet = StyleScope.createSelectorsFromCss(localStyle, null, {});
|
||||
const style = view.style;
|
||||
|
||||
inlineRuleSet[0].declarations.forEach(d => {
|
||||
// Use the actual property name so that a local value is set.
|
||||
let name = d.property;
|
||||
try {
|
||||
if (name in style) {
|
||||
style[name] = d.value;
|
||||
} else {
|
||||
view[name] = d.value;
|
||||
}
|
||||
} catch (e) {
|
||||
traceWrite(`Failed to apply property [${d.property}] with value [${d.value}] to ${view}. ${e}`, traceCategories.Error, traceMessageType.error);
|
||||
}
|
||||
} catch (ex) {
|
||||
traceWrite("Applying local style failed: " + ex, traceCategories.Error, traceMessageType.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isKeyframe(node: Node): node is Keyframes {
|
||||
|
Reference in New Issue
Block a user