8000 fix: port boxshadow to background improvements · NativeScript/NativeScript@5baf6c7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5baf6c7

Browse files
committed
fix: port boxshadow to background improvements
1 parent b6deac2 commit 5baf6c7

File tree

2 files changed

+49
-141
lines changed

2 files changed

+49
-141
lines changed

packages/core/ui/core/view/index.android.ts

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { GestureTypes, GestureEventData } from '../../gestures';
44

55
// Types.
66
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty } from './view-common';
7-
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../../styling/style-properties';
7+
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length } from '../../styling/style-properties';
88
import { layout } from '../../../utils';
99
import { Trace } from '../../../trace';
1010
import { ShowModalOptions, hiddenProperty } from '../view-base';
@@ -14,7 +14,7 @@ import { perspectiveProperty, visibilityProperty, opacityProperty, horizontalAli
1414
import { CoreTypes } from '../../../core-types';
1515

1616
import { Background, ad as androidBackground } from '../../styling/background';
17-
import { refreshBorderDrawable } from '../../styling/background.android';
17+
import { BackgroundClearFlags, refreshBorderDrawable } from '../../styling/background.android';
1818
import { profile } from '../../../profiling';
1919
import { topmost } from '../../frame/frame-stack';
2020
import { Screen } from '../../../platform';
@@ -24,6 +24,7 @@ import lazy from '../../../utils/lazy';
2424
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties';
2525
import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, setupAccessibleView, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility';
2626
import * as Utils from '../../../utils';
27+
import { CSSShadow } from 'ui/styling/css-shadow';
2728

2829
export * from './view-common';
2930
// helpers (these are okay re-exported here)
@@ -46,6 +47,10 @@ const modalMap = new Map<number, DialogOptions>();
4647
let TouchListener: TouchListener;
4748
let DialogFragment: DialogFragment;
4849

50+
interface AndroidView {
51+
_cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable;
52+
}
53+
4954
interface DialogOptions {
5055
owner: View;
5156
fullscreen: boolean;
@@ -1101,18 +1106,56 @@ export class View extends ViewCommon {
11011106
nativeView.setBackground(cachedDrawable);
11021107
}
11031108
}
1109+
1110+
protected _drawBoxShadow(boxShadow: CSSShadow) {
1111+
const nativeView = this.nativeViewProtected;
1112+
const config = {
1113+
shadowColor: boxShadow.color.android,
1114+
cornerRadius: Length.toDevicePixels(this.borderRadius as CoreTypes.LengthType, 0.0),
1115+
spreadRadius: Length.toDevicePixels(boxShadow.spreadRadius, 0.0),
1116+
blurRadius: Length.toDevicePixels(boxShadow.blurRadius, 0.0),
1117+
offsetX: Length.toDevicePixels(boxShadow.offsetX, 0.0),
1118+
offsetY: Length.toDevicePixels(boxShadow.offsetY, 0.0),
1119+
};
1120+
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, JSON.stringify(config));
1121+
}
11041122
protected onBackgroundOrBorderPropertyChanged() {
11051123
const nativeView = <android.view.View & { _cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable }>this.nativeViewProtected;
11061124
if (!nativeView) {
11071125
return;
11081126
}
11091127

11101128
const background = this.style.backgroundInternal;
1129+
1130+
if (background.clearFlags & BackgroundClearFlags.CLEAR_BOX_SHADOW || background.clearFlags & BackgroundClearFlags.CLEAR_BACKGROUND_COLOR) {
1131+
// clear background if we're clearing the box shadow
1132+
// or the background has been removed
1133+
nativeView.setBackground(null);
1134+
}
1135+
11111136
const drawable = nativeView.getBackground();
1137+
const androidView = (<any>this) as AndroidView;
1138+
// use undefined as not set. getBackground will never return undefined only Drawable or null;
1139+
if (androidView._cachedDrawable === undefined && drawable) {
1140+
const constantState = drawable.getConstantState();
1141+
androidView._cachedDrawable = constantState || drawable;
1142+
}
11121143
const isBorderDrawable = drawable instanceof org.nativescript.widgets.BorderDrawable;
1113-
const onlyColor = !background.hasBorderWidth() && !background.hasBorderRadius() && !background.clipPath && !background.image && !!background.color;
1144+
1145+
// prettier-ignore
1146+
const onlyColor = !background.hasBorderWidth()
1147+
&& !background.hasBorderRadius()
1148+
&& !background.hasBoxShadow()
1149+
&& !background.clipPath
1150+
&& !background.image
1151+
&& !!background.color;
1152+
11141153
this._applyBackground(background, isBorderDrawable, onlyColor, drawable);
11151154

1155+
if (background.hasBoxShadow()) {
1156+
this._drawBoxShadow(background.getBoxShadow());
1157+
}
1158+
11161159
// TODO: Can we move BorderWidths as separate native setter?
11171160
// This way we could skip setPadding if borderWidth is not changed.
11181161
const leftPadding = Math.ceil(this.effectiveBorderLeftWidth + this.effectivePaddingLeft);
@@ -1124,6 +1167,8 @@ export class View extends ViewCommon {
11241167
} else {
11251168
nativeView.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
11261169
}
1170+
// reset clear flags
1171+
background.clearFlags = BackgroundClearFlags.NONE;
11271172
}
11281173
_redrawNativeBackground(value: android.graphics.drawable.Drawable | Background): void {
11291174
if (value instanceof Background) {

packages/core/ui/styling/background.android.ts

Lines changed: 1 addition & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,14 @@
11
import { View } from '../core/view';
22
import { LinearGradient } from './linear-gradient';
3-
import { CoreTypes } from '../../core-types';
4-
import { isDataURI, isFileOrResourcePath, layout, RESOURCE_PREFIX, FILE_PREFIX } from '../../utils';
3+
import { isDataURI, isFileOrResourcePath, RESOURCE_PREFIX, FILE_PREFIX } from '../../utils';
54
import { parse } from '../../css-value';
65
import { path, knownFolders } from '../../file-system';
76
import * as application from '../../application';
8-
import { profile } from '../../profiling';
9-
import { CSSShadow } from './css-shadow';
10-
import { Length } from './style-properties';
11-
import { BackgroundClearFlags } from './background-common';
127
export * from './background-common';
138

14-
interface AndroidView {
15-
_cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable;
16-
}
17-
189
// TODO: Change this implementation to use
1910
// We are using "ad" here to avoid namespace collision with the global android object
2011
export namespace ad {
21-
let SDK: number;
22-
function getSDK() {
23-
if (!SDK) {
24-
SDK = android.os.Build.VERSION.SDK_INT;
25-
}
26-
27-
return SDK;
28-
}
29-
30-
function isSetColorFilterOnlyWidget(nativeView: android.view.View): boolean {
31-
// prettier-ignore
32-
return (
33-
nativeView instanceof android.widget.Button
34-
|| (nativeView instanceof androidx.appcompat.widget.Toolbar && getSDK() >= 21)
35-
// There is an issue with the DrawableContainer which was fixed
36-
// for API version 21 and above: https://code.google.com/p/android/issues/detail?id=60183
37-
);
38-
}
39-
40-
export function onBackgroundOrBorderPropertyChanged(view: View) {
41-
const nativeView = <android.view.View>view.nativeViewProtected;
42-
if (!nativeView) {
43-
return;
44-
}
45-
46-
const background = view.style.backgroundInternal;
47-
48-
if (background.clearFlags & BackgroundClearFlags.CLEAR_BOX_SHADOW || background.clearFlags & BackgroundClearFlags.CLEAR_BACKGROUND_COLOR) {
49-
// clear background if we're clearing the box shadow
50-
// or the background has been removed
51-
nativeView.setBackground(null);
52-
}
53-
54-
let drawable = nativeView.getBackground();
55-
const androidView = (<any>view) as AndroidView;
56-
// use undefined as not set. getBackground will never return undefined only Drawable or null;
57-
if (androidView._cachedDrawable === undefined && drawable) {
58-
const constantState = drawable.getConstantState();
59-
androidView._cachedDrawable = constantState || drawable;
60-
}
61-
const isBorderDrawable = drawable instanceof org.nativescript.widgets.BorderDrawable;
62-
63-
// prettier-ignore
64-
const onlyColor = !background.hasBorderWidth()
65-
&& !background.hasBorderRadius()
66-
&& !background.hasBoxShadow()
67-
&& !background.clipPath
68-
&& !background.image
69-
&& !!background.color;
70-
71-
if (!isBorderDrawable && drawable instanceof android.graphics.drawable.ColorDrawable && onlyColor) {
72-
drawable.setColor(background.color.android);
73-
drawable.invalidateSelf();
74-
} else if (isSetColorFilterOnlyWidget(nativeView) && drawable && onlyColor) {
75-
if (isBorderDrawable && androidView._cachedDrawable) {
76-
if (!(androidView._cachedDrawable instanceof android.graphics.drawable.Drawable.ConstantState)) {
77-
return;
78-
}
79-
80-
drawable = androidView._cachedDrawable.newDrawable(nativeView.getResources());
81-
nativeView.setBackground(drawable);
82-
}
83-
84-
const backgroundColor = ((<any>drawable).backgroundColor = background.color.android);
85-
drawable.mutate();
86-
drawable.setColorFilter(backgroundColor, android.graphics.PorterDuff.Mode.SRC_IN);
87-
drawable.invalidateSelf(); // Make sure the drawable is invalidated. Android forgets to invalidate it in some cases: toolbar
88-
(<any>drawable).backgroundColor = backgroundColor;
89-
} else if (!isBorderDrawable && onlyColor) {
90-
// this is the fastest way to change only background color
91-
nativeView.setBackgroundColor(background.color.android);
92-
} else if (!background.isEmpty()) {
93-
let backgroundDrawable = drawable;
94-
95-
if (drawable instanceof org.nativescript.widgets.BoxShadowDrawable) {
96-
// if we have BoxShadow's we have to get the underlying drawable
97-
backgroundDrawable = drawable.getWrappedDrawable();
98-
}
99-
100-
if (backgroundDrawable instanceof org.nativescript.widgets.BorderDrawable) {
101-
refreshBorderDrawable(view, backgroundDrawable);
102-
} else {
103-
backgroundDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), view.toString());
104-
refreshBorderDrawable(view, <org.nativescript.widgets.BorderDrawable>backgroundDrawable);
105-
nativeView.setBackground(backgroundDrawable);
106-
}
107-
} else {
108-
const cachedDrawable = androidView._cachedDrawable;
109-
let defaultDrawable: android.graphics.drawable.Drawable = null;
110-
if (cachedDrawable) {
111-
if (cachedDrawable instanceof android.graphics.drawable.Drawable.ConstantState) {
112-
defaultDrawable = cachedDrawable.newDrawable(nativeView.getResources());
113-
} else if (cachedDrawable instanceof android.graphics.drawable.Drawable) {
114-
defaultDrawable = cachedDrawable;
115-
}
116-
}
117-
118-
nativeView.setBackground(defaultDrawable);
119-
}
120-
121-
if (background.hasBoxShadow()) {
122-
drawBoxShadow(nativeView, view, background.getBoxShadow());
123-
}
124-
125-
// TODO: Can we move BorderWidths as separate native setter?
126-
// This way we could skip setPadding if borderWidth is not changed.
127-
const leftPadding = Math.ceil(view.effectiveBorderLeftWidth + view.effectivePaddingLeft);
128-
const topPadding = Math.ceil(view.effectiveBorderTopWidth + view.effectivePaddingTop);
129-
const rightPadding = Math.ceil(view.effectiveBorderRightWidth + view.effectivePaddingRight);
130-
const bottomPadding = Math.ceil(view.effectiveBorderBottomWidth + view.effectivePaddingBottom);
131-
132-
nativeView.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
133-
134-
// reset clear flags
135-
background.clearFlags = BackgroundClearFlags.NONE;
136-
}
13712
}
13813

13914
function fromBase64(source: string): android.graphics.Bitmap {
@@ -253,18 +128,6 @@ function createNativeCSSValueArray(css: string): androidNative.Array<org.natives
253128
return nativeArray;
254129
}
255130

256-
function drawBoxShadow(nativeView: android.view.View, view: View, boxShadow: CSSShadow) {
257-
const config = {
258-
shadowColor: boxShadow.color.android,
259-
cornerRadius: Length.toDevicePixels(view.borderRadius as CoreTypes.LengthType, 0.0),
260-
spreadRadius: Length.toDevicePixels(boxShadow.spreadRadius, 0.0),
261-
blurRadius: Length.toDevicePixels(boxShadow.blurRadius, 0.0),
262-
offsetX: Length.toDevicePixels(boxShadow.offsetX, 0.0),
263-
offsetY: Length.toDevicePixels(boxShadow.offsetY, 0.0),
264-
};
265-
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, JSON.stringify(config));
266-
}
267-
268131
export enum CacheMode {
269132
none,
270133
memory,

0 commit comments

Comments
 (0)
0