Files
NativeScript/tns-core-modules/ui/styling/background.android.ts
2017-03-28 18:08:59 +03:00

170 lines
7.5 KiB
TypeScript

import { View } from "../core/view";
import { isNullOrUndefined, isFunction, getClass } from "../../utils/types";
import { CacheLayerType, layout } from "../../utils/utils";
import { parse } from "../../css-value";
export * from "./background-common"
// TODO: Change this implementation to use
// We are using "ad" here to avoid namespace collision with the global android object
export module ad {
let SDK: number;
function getSDK() {
if (!SDK) {
SDK = android.os.Build.VERSION.SDK_INT;
}
return SDK;
}
let _defaultBackgrounds = new Map<string, android.graphics.drawable.Drawable.ConstantState>();
function isSetColorFilterOnlyWidget(nativeView: android.view.View): boolean {
return (
nativeView instanceof android.widget.Button ||
(nativeView instanceof android.support.v7.widget.Toolbar
&& getSDK() >= 21 // There is an issue with the DrawableContainer which was fixed for API version 21 and above: https://code.google.com/p/android/issues/detail?id=60183
)
);
}
export function onBackgroundOrBorderPropertyChanged(view: View) {
let nativeView = <android.view.View>view.nativeView;
if (!nativeView) {
return;
}
let background = view.style.backgroundInternal;
let backgroundDrawable = nativeView.getBackground();
let cache = <CacheLayerType>view.nativeView;
let viewClass = getClass(view);
// always cache the default background constant state.
if (!_defaultBackgrounds.has(viewClass) && !isNullOrUndefined(backgroundDrawable)) {
_defaultBackgrounds.set(viewClass, backgroundDrawable.getConstantState());
}
if (isSetColorFilterOnlyWidget(nativeView)
&& !isNullOrUndefined(backgroundDrawable)
&& isFunction(backgroundDrawable.setColorFilter)
&& !background.hasBorderWidth()
&& !background.hasBorderRadius()
&& !background.clipPath
&& isNullOrUndefined(background.image)
&& !isNullOrUndefined(background.color)) {
let backgroundColor = (<any>backgroundDrawable).backgroundColor = background.color.android;
backgroundDrawable.mutate();
backgroundDrawable.setColorFilter(backgroundColor, android.graphics.PorterDuff.Mode.SRC_IN);
backgroundDrawable.invalidateSelf(); // Make sure the drawable is invalidated. Android forgets to invalidate it in some cases: toolbar
(<any>backgroundDrawable).backgroundColor = backgroundColor;
}
else if (!background.isEmpty()) {
if (!(backgroundDrawable instanceof org.nativescript.widgets.BorderDrawable)) {
backgroundDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), view.toString());
refreshBorderDrawable(view, <org.nativescript.widgets.BorderDrawable>backgroundDrawable);
org.nativescript.widgets.ViewHelper.setBackground(nativeView, backgroundDrawable);
}
else {
refreshBorderDrawable(view, <org.nativescript.widgets.BorderDrawable>backgroundDrawable);
}
// This should be done only when backgroundImage is set!!!
if ((background.hasBorderWidth() || background.hasBorderRadius() || background.clipPath) && getSDK() < 18) {
// Switch to software because of unsupported canvas methods if hardware acceleration is on:
// http://developer.android.com/guide/topics/graphics/hardware-accel.html
if (cache.layerType === undefined) {
cache.layerType = cache.getLayerType();
cache.setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);
}
}
}
else {
if (_defaultBackgrounds.has(viewClass)) {
org.nativescript.widgets.ViewHelper.setBackground(nativeView, _defaultBackgrounds.get(viewClass).newDrawable());
}
if (cache.layerType !== undefined) {
cache.setLayerType(cache.layerType, null);
cache.layerType = undefined;
}
}
// TODO: Can we move BorderWidths as separate native setter?
// This way we could skip setPadding if borderWidth is not changed.
let leftPadding = Math.ceil(view.effectiveBorderLeftWidth + view.effectivePaddingLeft);
let topPadding = Math.ceil(view.effectiveBorderTopWidth + view.effectivePaddingTop);
let rightPadding = Math.ceil(view.effectiveBorderRightWidth + view.effectivePaddingRight);
let bottomPadding = Math.ceil(view.effectiveBorderBottomWidth + view.effectivePaddingBottom);
nativeView.setPadding(
leftPadding,
topPadding,
rightPadding,
bottomPadding
);
}
}
function refreshBorderDrawable(view: View, borderDrawable: org.nativescript.widgets.BorderDrawable) {
let background = view.style.backgroundInternal;
if (background) {
let backgroundPositionParsedCSSValues: native.Array<org.nativescript.widgets.CSSValue> = null;
let backgroundSizeParsedCSSValues: native.Array<org.nativescript.widgets.CSSValue> = null;
if (background.position) {
backgroundPositionParsedCSSValues = createNativeCSSValueArray(background.position);
}
if (background.size) {
backgroundSizeParsedCSSValues = createNativeCSSValueArray(background.size);
}
let blackColor = android.graphics.Color.BLACK;
borderDrawable.refresh(
(background.borderTopColor && background.borderTopColor.android !== undefined) ? background.borderTopColor.android : blackColor,
(background.borderRightColor && background.borderRightColor.android !== undefined) ? background.borderRightColor.android : blackColor,
(background.borderBottomColor && background.borderBottomColor.android !== undefined) ? background.borderBottomColor.android : blackColor,
(background.borderLeftColor && background.borderLeftColor.android !== undefined) ? background.borderLeftColor.android : blackColor,
background.borderTopWidth,
background.borderRightWidth,
background.borderBottomWidth,
background.borderLeftWidth,
background.borderTopLeftRadius,
background.borderTopRightRadius,
background.borderBottomRightRadius,
background.borderBottomLeftRadius,
background.clipPath,
(background.color && background.color.android) ? background.color.android : 0,
(background.image && background.image.android) ? background.image.android : null,
background.repeat,
background.position,
backgroundPositionParsedCSSValues,
background.size,
backgroundSizeParsedCSSValues
);
//console.log(`>>> ${borderDrawable.toDebugString()}`);
}
}
function createNativeCSSValueArray(css: string): native.Array<org.nativescript.widgets.CSSValue> {
if (!css) {
return null;
}
let cssValues = parse(css);
let nativeArray = Array.create(org.nativescript.widgets.CSSValue, cssValues.length);
for (let i = 0, length = cssValues.length; i < length; i++) {
nativeArray[i] = new org.nativescript.widgets.CSSValue(
cssValues[i].type,
cssValues[i].string,
cssValues[i].unit,
cssValues[i].value
);
}
return nativeArray;
}