feat(android): tab view icon rendering mode (#9605)

Co-authored-by: wSedlacek <wsedlacekc@gmail.com>
This commit is contained in:
William Sedlacek
2022-02-16 19:10:31 -08:00
committed by Nathan Walker
parent 08028dd9f4
commit 66d8afffc1
9 changed files with 104 additions and 11 deletions

View File

@ -1,14 +1,19 @@
import { isIOS } from '@nativescript/core';
import { EventData } from '@nativescript/core/data/observable';
import { Button } from '@nativescript/core/ui/button';
import { TabView } from '@nativescript/core/ui/tab-view';
let iconModes = ['automatic', 'alwaysOriginal', 'alwaysTemplate', undefined];
let iconModes = isIOS ? ['automatic', 'alwaysOriginal', 'alwaysTemplate', undefined] : ['alwaysOriginal', 'alwaysTemplate', undefined];
export const onNavigate = updateButtons;
export function onChangeRenderingMode(args: EventData) {
let tabView = (<Button>args.object).page.getViewById<TabView>('tab-view');
if (isIOS) {
tabView.iosIconRenderingMode = <'automatic' | 'alwaysOriginal' | 'alwaysTemplate'>iconModes[(iconModes.indexOf(tabView.iosIconRenderingMode) + 1) % iconModes.length];
} else {
tabView.androidIconRenderingMode = <'alwaysOriginal' | 'alwaysTemplate'>iconModes[(iconModes.indexOf(tabView.androidIconRenderingMode) + 1) % iconModes.length];
}
updateButtons(args);
}
@ -16,6 +21,7 @@ function updateButtons(args) {
let button = <Button>args.object;
let tabView = button.page.getViewById<TabView>('tab-view');
for (let i = 0, length = tabView.items.length; i < length; i++) {
(<Button>tabView.items[i].view).text = '' + tabView.iosIconRenderingMode;
const value = isIOS ? tabView.iosIconRenderingMode : tabView.androidIconRenderingMode;
(<Button>tabView.items[i].view).text = '' + value;
}
}

View File

@ -1,14 +1,19 @@
import { isIOS } from '@nativescript/core';
import { EventData } from '@nativescript/core/data/observable';
import { Button } from '@nativescript/core/ui/button';
import { TabView } from '@nativescript/core/ui/tab-view';
let iconModes = ['automatic', 'alwaysOriginal', 'alwaysTemplate', undefined];
let iconModes = isIOS ? ['automatic', 'alwaysOriginal', 'alwaysTemplate', undefined] : ['alwaysOriginal', 'alwaysTemplate', undefined];
export const onNavigate = updateButtons;
export function onChangeRenderingMode(args: EventData) {
let tabView = (<Button>args.object).page.getViewById<TabView>('tab-view');
if (isIOS) {
tabView.iosIconRenderingMode = <'automatic' | 'alwaysOriginal' | 'alwaysTemplate'>iconModes[(iconModes.indexOf(tabView.iosIconRenderingMode) + 1) % iconModes.length];
} else {
tabView.androidIconRenderingMode = <'alwaysOriginal' | 'alwaysTemplate'>iconModes[(iconModes.indexOf(tabView.androidIconRenderingMode) + 1) % iconModes.length];
}
updateButtons(args);
}
@ -16,6 +21,7 @@ function updateButtons(args) {
let button = <Button>args.object;
let tabView = button.page.getViewById<TabView>('tab-view');
for (let i = 0, length = tabView.items.length; i < length; i++) {
(<Button>tabView.items[i].view).text = '' + tabView.iosIconRenderingMode;
const value = isIOS ? tabView.iosIconRenderingMode : tabView.androidIconRenderingMode;
(<Button>tabView.items[i].view).text = '' + value;
}
}

View File

@ -1,7 +1,7 @@
import { TabViewItem as TabViewItemDefinition } from '.';
import { Font } from '../styling/font';
import { TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty, tabTextColorProperty, tabBackgroundColorProperty, tabTextFontSizeProperty, selectedTabTextColorProperty, androidSelectedTabHighlightColorProperty, androidOffscreenTabLimitProperty, traceCategory, traceMissingIcon } from './tab-view-common';
import { TabViewBase, TabViewItemBase, itemsProperty, selectedIndexProperty, tabTextColorProperty, tabBackgroundColorProperty, tabTextFontSizeProperty, selectedTabTextColorProperty, androidSelectedTabHighlightColorProperty, androidOffscreenTabLimitProperty, traceCategory, traceMissingIcon, androidIconRenderingModeProperty } from './tab-view-common';
import { textTransformProperty, getTransformedText } from '../text-base';
import { CoreTypes } from '../../core-types';
import { ImageSource } from '../../image-source';
@ -699,6 +699,16 @@ export class TabView extends TabViewBase {
}
}
private getNativeRenderingMode(mode: 'alwaysOriginal' | 'alwaysTemplate'): number {
switch (mode) {
case 'alwaysTemplate':
return org.nativescript.widgets.TabIconRenderingMode.template;
default:
case 'alwaysOriginal':
return org.nativescript.widgets.TabIconRenderingMode.original;
}
}
public updateAndroidItemAt(index: number, spec: org.nativescript.widgets.TabItemSpec) {
this._tabLayout.updateItemAt(index, spec);
}
@ -710,6 +720,13 @@ export class TabView extends TabViewBase {
this._viewPager.setOffscreenPageLimit(value);
}
[androidIconRenderingModeProperty.getDefault](): 'alwaysOriginal' | 'alwaysTemplate' {
return 'alwaysOriginal';
}
[androidIconRenderingModeProperty.setNative](value: 'alwaysOriginal' | 'alwaysTemplate') {
this._tabLayout.setIconRenderingMode(this.getNativeRenderingMode(value));
}
[selectedIndexProperty.setNative](value: number) {
const smoothScroll = this.androidTabsPosition === 'top';

View File

@ -112,6 +112,14 @@ export class TabView extends View {
*/
iosIconRenderingMode: 'automatic' | 'alwaysOriginal' | 'alwaysTemplate';
/**
* Gets or sets the rendering mode of tab icons on Android. Defaults to "original"
* Valid values are:
* - alwaysOriginal
* - alwaysTemplate
*/
androidIconRenderingMode: 'alwaysOriginal' | 'alwaysTemplate';
/**
* Gets or sets the number of tabs that should be retained to either side of the current tab in the view hierarchy in an idle state.
* Tabs beyond this limit will be recreated from the TabView when needed.
@ -160,3 +168,4 @@ export const selectedTabTextColorProperty: CssProperty<Style, Color>;
export const androidSelectedTabHighlightColorProperty: CssProperty<Style, Color>;
export const androidOffscreenTabLimitProperty: Property<TabView, number>;
export const iosIconRenderingModeProperty: Property<TabView, 'automatic' | 'alwaysOriginal' | 'alwaysTemplate'>;
export const androidIconRenderingModeProperty: Property<TabView, 'alwaysOriginal' | 'alwaysTemplate'>;

View File

@ -93,6 +93,7 @@ export class TabViewBase extends View implements TabViewDefinition, AddChildFrom
public androidTabsPosition: 'top' | 'bottom';
public androidSwipeEnabled: boolean;
public iosIconRenderingMode: 'automatic' | 'alwaysOriginal' | 'alwaysTemplate';
public androidIconRenderingMode: 'alwaysOriginal' | 'alwaysTemplate';
get androidSelectedTabHighlightColor(): Color {
return this.style.androidSelectedTabHighlightColor;
@ -250,6 +251,9 @@ itemsProperty.register(TabViewBase);
export const iosIconRenderingModeProperty = new Property<TabViewBase, 'automatic' | 'alwaysOriginal' | 'alwaysTemplate'>({ name: 'iosIconRenderingMode', defaultValue: 'automatic' });
iosIconRenderingModeProperty.register(TabViewBase);
export const androidIconRenderingModeProperty = new Property<TabViewBase, 'alwaysOriginal' | 'alwaysTemplate'>({ name: 'androidIconRenderingMode', defaultValue: 'alwaysOriginal' });
androidIconRenderingModeProperty.register(TabViewBase);
export const androidOffscreenTabLimitProperty = new Property<TabViewBase, number>({
name: 'androidOffscreenTabLimit',
defaultValue: 1,

View File

@ -394,6 +394,11 @@
setImageLoadedListener(listener: image.Worker.OnImageLoadedListener): void;
}
export enum TabIconRenderingMode {
original,
template
}
export class TabLayout extends android.widget.HorizontalScrollView {
constructor(context: android.content.Context);
constructor(context: android.content.Context, attrs: android.util.AttributeSet);
@ -401,6 +406,8 @@
setSelectedIndicatorColors(color: Array<number>): void;
getSelectedIndicatorColors(): Array<number>;
setIconRenderingMode(mode: TabIconRenderingMode): void;
getIconRenderingMode(): TabIconRenderingMode;
setTabTextColor(color: number): void;
getTabTextColor(): number;
setSelectedTabTextColor(color: number): void;

View File

@ -0,0 +1,6 @@
package org.nativescript.widgets;
public enum TabIconRenderingMode {
template,
original
}

View File

@ -131,6 +131,14 @@ public class TabLayout extends HorizontalScrollView {
return this.mSelectedIndicatorColors;
}
public void setIconRenderingMode(TabIconRenderingMode mode) {
mTabStrip.setIconRenderingMode(mode);
}
public TabIconRenderingMode getIconRenderingMode() {
return mTabStrip.getIconRenderingMode();
}
public void setTabTextColor(int color){
mTabStrip.setTabTextColor(color);
}

View File

@ -18,6 +18,7 @@ package org.nativescript.widgets;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@ -26,6 +27,9 @@ import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ImageView;
import androidx.core.widget.ImageViewCompat;
class TabStrip extends LinearLayout {
@ -51,6 +55,7 @@ class TabStrip extends LinearLayout {
private int mTabTextColor;
private int mSelectedTabTextColor;
private float mTabTextFontSize;
private TabIconRenderingMode mIconRenderingMode;
private boolean mShouldUpdateTabsTextColor;
@ -88,6 +93,7 @@ class TabStrip extends LinearLayout {
// Default selected color is the same as mTabTextColor
mSelectedTabTextColor = mTabTextColor;
mIconRenderingMode = TabIconRenderingMode.original;
mShouldUpdateTabsTextColor = true;
@ -106,6 +112,15 @@ class TabStrip extends LinearLayout {
invalidate();
}
void setIconRenderingMode(TabIconRenderingMode mode) {
mIconRenderingMode = mode;
updateTabsTextColor();
}
TabIconRenderingMode getIconRenderingMode() {
return mIconRenderingMode;
}
void setTabTextColor(int color){
mTabTextColor = color;
updateTabsTextColor();
@ -128,16 +143,31 @@ class TabStrip extends LinearLayout {
mShouldUpdateTabsTextColor = value;
}
private void updateTabsTextColor(){
private void updateTabsTextColor() {
if (mShouldUpdateTabsTextColor) {
final int childCount = getChildCount();
int greyColor = Color.parseColor("#A2A2A2");
for (int i = 0; i < childCount; i++){
LinearLayout linearLayout = (LinearLayout)getChildAt(i);
ImageView imageView = (ImageView)linearLayout.getChildAt(0);
TextView textView = (TextView)linearLayout.getChildAt(1);
if (i == mSelectedPosition){
textView.setTextColor(mSelectedTabTextColor);
if (mIconRenderingMode == TabIconRenderingMode.template) {
ColorStateList tint;
if (i == mSelectedPosition) {
tint = ColorStateList.valueOf(mSelectedTabTextColor);
} else {
tint = ColorStateList.valueOf(greyColor);
}
else {
ImageViewCompat.setImageTintList(imageView, tint);
} else {
ImageViewCompat.setImageTintList(imageView, null);
}
if (i == mSelectedPosition) {
textView.setTextColor(mSelectedTabTextColor);
} else {
textView.setTextColor(mTabTextColor);
}
}