mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 01:43:14 +08:00
feat(SegmentedBar): selectedTextColor added and selectedBackgroundColor improvements (#10474)
This commit is contained in:
@ -1,4 +1,9 @@
|
||||
import * as segmentedBarModule from '@nativescript/core/ui/segmented-bar';
|
||||
import { Color } from '@nativescript/core';
|
||||
|
||||
export function getNativeTabWidget(bar: segmentedBarModule.SegmentedBar): android.widget.TabWidget {
|
||||
return (<android.widget.TabHost>bar.android).getTabWidget();
|
||||
}
|
||||
|
||||
export function getNativeItemsCount(bar: segmentedBarModule.SegmentedBar): number {
|
||||
return (<android.widget.TabHost>bar.android).getTabWidget().getTabCount();
|
||||
@ -25,3 +30,54 @@ export function checkNativeItemsTextColor(bar: segmentedBarModule.SegmentedBar):
|
||||
export function setNativeSelectedIndex(bar: segmentedBarModule.SegmentedBar, index: number): void {
|
||||
(<android.widget.TabHost>bar.android).setCurrentTab(index);
|
||||
}
|
||||
|
||||
export var checkBackgroundColorUpdatedAfterItemSelected = function (bar: segmentedBarModule.SegmentedBar): boolean {
|
||||
let isValid = 0;
|
||||
bar.selectedIndex = 0;
|
||||
bar.selectedTextColor = new Color('green');
|
||||
bar.selectedBackgroundColor = new Color('red');
|
||||
|
||||
const tabWidget = getNativeTabWidget(bar);
|
||||
if (tabWidget) {
|
||||
for (let i = 0; i < tabWidget.getTabCount(); i++) {
|
||||
const view = tabWidget.getChildTabViewAt(i);
|
||||
const item = bar.items[i];
|
||||
const textView = item?.nativeViewProtected;
|
||||
|
||||
const newDrawable = tryCloneDrawable(view.getBackground(), view.getResources());
|
||||
newDrawable.setColorFilter(new android.graphics.Paint(bar.selectedBackgroundColor.android).getColorFilter());
|
||||
|
||||
if (bar.selectedIndex == i) {
|
||||
if (view.getBackground() !== newDrawable) {
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>> newDrawable', view.getBackground());
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>> bar.selectedBackgroundColor.android', newDrawable);
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>> selectedBackgroundColor', newDrawable.getColorFilter(), view.getBackground().getColorFilter());
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>> selectedBackgroundColor', newDrawable.hashCode(), view.hashCode());
|
||||
|
||||
isValid++;
|
||||
break;
|
||||
} else if (textView.getCurrentTextColor() !== bar.selectedTextColor) {
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>>');
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>>');
|
||||
console.log('>>>>>>>>>>>>>>>>>>>>>> selectedTextColor');
|
||||
|
||||
isValid++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return isValid === 0;
|
||||
};
|
||||
|
@ -5,3 +5,5 @@ export declare function getNativeItemsCount(bar: segmentedBarModule.SegmentedBar
|
||||
export declare function setNativeSelectedIndex(bar: segmentedBarModule.SegmentedBar, index: number): void;
|
||||
|
||||
export declare function checkNativeItemsTextColor(bar: segmentedBarModule.SegmentedBar): boolean;
|
||||
|
||||
export declare function checkBackgroundColorUpdatedAfterItemSelected(bar: segmentedBarModule.SegmentedBar): boolean;
|
||||
|
@ -276,3 +276,21 @@ export function test_SettingNumberAsTitleFromXML_DoesNotThrow() {
|
||||
TKUnit.assertEqual(item.title, '1');
|
||||
});
|
||||
}
|
||||
|
||||
/*export function testBackgroundColorUpdatedAfterItemSelected() {
|
||||
let segmentedBar = new segmentedBarModule.SegmentedBar();
|
||||
let item1 = new segmentedBarModule.SegmentedBarItem();
|
||||
(<any>item1).title = 1;
|
||||
let item2 = new segmentedBarModule.SegmentedBarItem();
|
||||
(<any>item2).title = 2;
|
||||
let item3 = new segmentedBarModule.SegmentedBarItem();
|
||||
(<any>item3).title = 3;
|
||||
let item4 = new segmentedBarModule.SegmentedBarItem();
|
||||
(<any>item4).title = 4;
|
||||
|
||||
segmentedBar.items = [item1, item2, item3, item4];
|
||||
|
||||
buildUIAndRunTest(segmentedBar, function (views: Array<View>) {
|
||||
TKUnit.assertTrue(segmentedBarTestsNative.checkBackgroundColorUpdatedAfterItemSelected(segmentedBar));
|
||||
});
|
||||
}*/
|
||||
|
@ -7,7 +7,20 @@
|
||||
<SegmentedBarItem title="Item 3" />
|
||||
</SegmentedBar.items>
|
||||
</SegmentedBar>
|
||||
<SegmentedBar selectedIndex="2" style="margin: 5; color: blue; background-color: yellow; font-weight: bold; font-size: 20; font-style: italic; font-family: monospace; height: 72; border-width: 2; border-radius: 7; border-color:green; selected-background-color: red;">
|
||||
<SegmentedBar selectedIndex="2" style="margin: 5; color: blue; background-color: yellow; font-weight: bold; font-size: 20; font-style: italic; font-family: monospace; height: 72; border-width: 2; border-radius: 7; border-color:green; selected-background-color: red;selected-text-color: green">
|
||||
<SegmentedBar.items>
|
||||
<SegmentedBarItem title="Item 1" />
|
||||
<SegmentedBarItem title="Item 2" />
|
||||
<SegmentedBarItem title="Item 3" />
|
||||
</SegmentedBar.items>
|
||||
</SegmentedBar>
|
||||
<SegmentedBar selectedIndex="2"
|
||||
selectedTextColor="#00ffd9"
|
||||
color="red"
|
||||
android:backgroundColor="#A8A8A8"
|
||||
selectedBackgroundColor="blue"
|
||||
android:borderRadius="6"
|
||||
>
|
||||
<SegmentedBar.items>
|
||||
<SegmentedBarItem title="Item 1" />
|
||||
<SegmentedBarItem title="Item 2" />
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Font } from '../styling/font';
|
||||
import { SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty } from './segmented-bar-common';
|
||||
import { SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty, selectedTextColorProperty } from './segmented-bar-common';
|
||||
import { isEnabledProperty } from '../core/view';
|
||||
import { colorProperty, fontInternalProperty, fontSizeProperty } from '../styling/style-properties';
|
||||
import { Color } from '../../color';
|
||||
import { layout } from '../../utils';
|
||||
import { SDK_VERSION } from '../../utils/constants';
|
||||
import { Trace } from '../../trace';
|
||||
|
||||
export * from './segmented-bar-common';
|
||||
|
||||
@ -51,8 +52,13 @@ function initializeNativeClasses(): void {
|
||||
|
||||
onTabChanged(id: string): void {
|
||||
const owner = this.owner;
|
||||
if (owner.shouldChangeSelectedIndex()) {
|
||||
owner.selectedIndex = parseInt(id);
|
||||
if (owner) {
|
||||
setTimeout(() => {
|
||||
owner.setTabColor(id);
|
||||
});
|
||||
if (owner.shouldChangeSelectedIndex()) {
|
||||
owner.selectedIndex = parseInt(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,7 +171,7 @@ export class SegmentedBarItem extends SegmentedBarItemBase {
|
||||
const backgroundDrawable = viewGroup.getBackground();
|
||||
if (SDK_VERSION > 21 && backgroundDrawable) {
|
||||
const newDrawable = tryCloneDrawable(backgroundDrawable, nativeView.getResources());
|
||||
newDrawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
newDrawable.setColorFilter(new android.graphics.Paint(color).getColorFilter());
|
||||
viewGroup.setBackground(newDrawable);
|
||||
} else {
|
||||
const stateDrawable = new android.graphics.drawable.StateListDrawable();
|
||||
@ -292,4 +298,42 @@ export class SegmentedBar extends SegmentedBarBase {
|
||||
tabWidget.setEnabled(value);
|
||||
}
|
||||
}
|
||||
public setTabColor(index) {
|
||||
try {
|
||||
const tabWidget = this.nativeViewProtected?.getTabWidget();
|
||||
if (tabWidget) {
|
||||
const unselectedTextColor = this.getColorForAndroid(this.color ?? '#6e6e6e');
|
||||
const selectedTextColor = this.getColorForAndroid(this?.selectedTextColor ?? '#000000');
|
||||
const unselectedBackgroundColor = this.getColorForAndroid(this?.backgroundColor ?? '#dbdbdb');
|
||||
const selectedBackgroundColor = this.getColorForAndroid(this?.selectedBackgroundColor ?? this?.backgroundColor ?? 'blue');
|
||||
if (tabWidget) {
|
||||
for (let i = 0; i < tabWidget.getTabCount(); i++) {
|
||||
const view = tabWidget.getChildTabViewAt(i);
|
||||
const item = this.items[i];
|
||||
const textView = item?.nativeViewProtected;
|
||||
view.setBackgroundColor(unselectedBackgroundColor);
|
||||
if (textView) {
|
||||
textView.setTextColor(unselectedTextColor);
|
||||
}
|
||||
if (index == i) {
|
||||
view.setBackgroundColor(selectedBackgroundColor);
|
||||
if (textView) {
|
||||
textView.setTextColor(selectedTextColor);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Trace.error(e);
|
||||
}
|
||||
}
|
||||
private getColorForAndroid(color: string | Color): number {
|
||||
if (typeof color === 'string') {
|
||||
return new Color(color).android;
|
||||
} else if (color instanceof Color) {
|
||||
return color.android;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
packages/core/ui/segmented-bar/index.d.ts
vendored
10
packages/core/ui/segmented-bar/index.d.ts
vendored
@ -44,6 +44,11 @@ export class SegmentedBar extends View implements AddChildFromBuilder, AddArrayF
|
||||
*/
|
||||
selectedBackgroundColor: Color;
|
||||
|
||||
/**
|
||||
* Gets or sets the selected text color of the SegmentedBar component.
|
||||
*/
|
||||
selectedTextColor: Color;
|
||||
|
||||
/**
|
||||
* Gets or sets the items of the SegmentedBar.
|
||||
*/
|
||||
@ -90,3 +95,8 @@ export const selectedBackgroundColorProperty: CssProperty<Style, Color>;
|
||||
* Gets or sets the items dependency property of the SegmentedBar.
|
||||
*/
|
||||
export const itemsProperty: Property<SegmentedBar, SegmentedBarItem[]>;
|
||||
|
||||
/**
|
||||
* Gets or sets the selected text color property of the SegmentedBar.
|
||||
*/
|
||||
export const selectedTextColorProperty: CssProperty<Style, Color>;
|
||||
|
@ -2,7 +2,8 @@ import { Font } from '../styling/font';
|
||||
import { SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty } from './segmented-bar-common';
|
||||
import { colorProperty, fontInternalProperty } from '../styling/style-properties';
|
||||
import { Color } from '../../color';
|
||||
import { iOSNativeHelper } from '../../utils';
|
||||
import { Trace } from '../../trace';
|
||||
import { SDK_VERSION } from '../../utils';
|
||||
export * from './segmented-bar-common';
|
||||
|
||||
export class SegmentedBarItem extends SegmentedBarItemBase {
|
||||
@ -68,14 +69,11 @@ export class SegmentedBar extends SegmentedBarBase {
|
||||
}
|
||||
|
||||
[selectedBackgroundColorProperty.getDefault](): UIColor {
|
||||
const currentOsVersion = iOSNativeHelper.MajorVersion;
|
||||
|
||||
return currentOsVersion < 13 ? this.ios.tintColor : this.ios.selectedSegmentTintColor;
|
||||
return SDK_VERSION < 13 ? this.ios.tintColor : this.ios.selectedSegmentTintColor;
|
||||
}
|
||||
[selectedBackgroundColorProperty.setNative](value: UIColor | Color) {
|
||||
const currentOsVersion = iOSNativeHelper.MajorVersion;
|
||||
const color = value instanceof Color ? value.ios : value;
|
||||
if (currentOsVersion < 13) {
|
||||
if (SDK_VERSION < 13) {
|
||||
this.ios.tintColor = color;
|
||||
} else {
|
||||
this.ios.selectedSegmentTintColor = color;
|
||||
@ -92,6 +90,8 @@ export class SegmentedBar extends SegmentedBarBase {
|
||||
const attrs = currentAttrs ? currentAttrs.mutableCopy() : NSMutableDictionary.new();
|
||||
attrs.setValueForKey(color, NSForegroundColorAttributeName);
|
||||
bar.setTitleTextAttributesForState(attrs, UIControlState.Normal);
|
||||
// Set the selected text color
|
||||
this.setSelectedTextColor(bar);
|
||||
}
|
||||
|
||||
[fontInternalProperty.getDefault](): Font {
|
||||
@ -105,6 +105,27 @@ export class SegmentedBar extends SegmentedBarBase {
|
||||
attrs.setValueForKey(font, NSFontAttributeName);
|
||||
bar.setTitleTextAttributesForState(attrs, UIControlState.Normal);
|
||||
}
|
||||
setSelectedTextColor(bar: UISegmentedControl) {
|
||||
try {
|
||||
const selectedTextColor = this.getColorForIOS(this?.selectedTextColor ?? this?.color ?? '#000000');
|
||||
if (!selectedTextColor) {
|
||||
Trace.write(`unable te set selectedTextColor`, Trace.categories.Error);
|
||||
}
|
||||
const selectedText = bar.titleTextAttributesForState(UIControlState.Selected);
|
||||
const attrsSelected = selectedText ? selectedText.mutableCopy() : NSMutableDictionary.new();
|
||||
attrsSelected.setValueForKey(selectedTextColor, NSForegroundColorAttributeName);
|
||||
bar.setTitleTextAttributesForState(attrsSelected, UIControlState.Selected);
|
||||
} catch (e) {
|
||||
console.error(`SegmentedBar:`, e);
|
||||
}
|
||||
}
|
||||
private getColorForIOS(color: string | Color): UIColor {
|
||||
if (typeof color === 'string') {
|
||||
return new Color(color).ios;
|
||||
} else if (color instanceof Color) {
|
||||
return color.ios;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NativeClass
|
||||
@ -122,6 +143,7 @@ class SelectionHandlerImpl extends NSObject {
|
||||
const owner = this._owner?.deref();
|
||||
if (owner) {
|
||||
owner.selectedIndex = sender.selectedSegmentIndex;
|
||||
owner.setSelectedTextColor(sender);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,13 @@ export abstract class SegmentedBarBase extends View implements SegmentedBarDefin
|
||||
this.style.selectedBackgroundColor = value;
|
||||
}
|
||||
|
||||
public get selectedTextColor(): Color {
|
||||
return this.style.selectedTabTextColor;
|
||||
}
|
||||
public set selectedTextColor(value: Color) {
|
||||
this.style.selectedTabTextColor = value;
|
||||
}
|
||||
|
||||
public _addArrayFromBuilder(name: string, value: Array<any>): void {
|
||||
if (name === 'items') {
|
||||
this.items = value;
|
||||
@ -141,6 +148,16 @@ export const selectedBackgroundColorProperty = new InheritedCssProperty<Style, C
|
||||
name: 'selectedBackgroundColor',
|
||||
cssName: 'selected-background-color',
|
||||
equalityComparer: Color.equals,
|
||||
defaultValue: new Color('blue'),
|
||||
valueConverter: (v) => new Color(v),
|
||||
});
|
||||
selectedBackgroundColorProperty.register(Style);
|
||||
|
||||
export const selectedTextColorProperty = new InheritedCssProperty<Style, Color>({
|
||||
name: 'selectedTextColor',
|
||||
cssName: 'selected-text-color',
|
||||
equalityComparer: Color.equals,
|
||||
defaultValue: new Color('black'),
|
||||
valueConverter: (v) => new Color(v),
|
||||
});
|
||||
selectedTextColorProperty.register(Style);
|
||||
|
@ -206,6 +206,7 @@ export class Style extends Observable implements StyleDefinition {
|
||||
|
||||
//SegmentedBar-specific props
|
||||
public selectedBackgroundColor: Color;
|
||||
public selectedTextColor: Color;
|
||||
|
||||
// Page-specific props
|
||||
public statusBarStyle: 'light' | 'dark';
|
||||
|
@ -94,6 +94,9 @@ export function isLandscape(): boolean {
|
||||
return isDeviceOrientationLandscape || isStatusBarOrientationLandscape;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use Utils.SDK_VERSION instead which is a float of the {major}.{minor} verison
|
||||
*/
|
||||
export const MajorVersion = NSString.stringWithString(UIDevice.currentDevice.systemVersion).intValue;
|
||||
|
||||
export function openFile(filePath: string): boolean {
|
||||
|
Reference in New Issue
Block a user