mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 20:11:24 +08:00
Fix crash where some android Drawables doesn't implement getConstantState... (#4742)
Changed all places where getConstantState was used.
This commit is contained in:
@ -459,7 +459,16 @@ export class View extends ViewCommon {
|
||||
[backgroundInternalProperty.getDefault](): android.graphics.drawable.Drawable {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
const drawable = nativeView.getBackground();
|
||||
return drawable ? drawable.getConstantState().newDrawable(nativeView.getResources()) : null;
|
||||
if (drawable) {
|
||||
const constantState = drawable.getConstantState();
|
||||
if (constantState) {
|
||||
return constantState.newDrawable(nativeView.getResources());
|
||||
} else {
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
[backgroundInternalProperty.setNative](value: android.graphics.drawable.Drawable | Background) {
|
||||
this._redrawNativeBackground(value);
|
||||
|
@ -12,15 +12,15 @@ const R_ATTR_STATE_SELECTED = 0x010100a1;
|
||||
const TITLE_TEXT_VIEW_ID = 16908310; // http://developer.android.com/reference/android/R.id.html#title
|
||||
|
||||
interface TabChangeListener {
|
||||
new (owner: SegmentedBar): android.widget.TabHost.OnTabChangeListener;
|
||||
new(owner: SegmentedBar): android.widget.TabHost.OnTabChangeListener;
|
||||
}
|
||||
|
||||
interface TabContentFactory {
|
||||
new (owner: SegmentedBar): android.widget.TabHost.TabContentFactory;
|
||||
new(owner: SegmentedBar): android.widget.TabHost.TabContentFactory;
|
||||
}
|
||||
|
||||
interface TabHost {
|
||||
new (context: android.content.Context, attrs: android.util.AttributeSet): android.widget.TabHost;
|
||||
new(context: android.content.Context, attrs: android.util.AttributeSet): android.widget.TabHost;
|
||||
}
|
||||
|
||||
let apiLevel: number;
|
||||
@ -144,17 +144,18 @@ export class SegmentedBarItem extends SegmentedBarItemBase {
|
||||
this.nativeViewProtected.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value);
|
||||
}
|
||||
|
||||
[selectedBackgroundColorProperty.getDefault](): android.graphics.drawable.Drawable.ConstantState {
|
||||
[selectedBackgroundColorProperty.getDefault](): android.graphics.drawable.Drawable {
|
||||
const viewGroup = <android.view.ViewGroup>this.nativeViewProtected.getParent();
|
||||
return viewGroup.getBackground().getConstantState();
|
||||
return viewGroup.getBackground();
|
||||
}
|
||||
[selectedBackgroundColorProperty.setNative](value: Color | android.graphics.drawable.Drawable.ConstantState) {
|
||||
const viewGroup = <android.view.ViewGroup>this.nativeViewProtected.getParent();
|
||||
[selectedBackgroundColorProperty.setNative](value: Color | android.graphics.drawable.Drawable) {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
const viewGroup = <android.view.ViewGroup>nativeView.getParent();
|
||||
if (value instanceof Color) {
|
||||
const color = value.android;
|
||||
const backgroundDrawable = viewGroup.getBackground();
|
||||
if (apiLevel > 21 && backgroundDrawable && typeof backgroundDrawable.setColorFilter === "function") {
|
||||
const newDrawable = backgroundDrawable.getConstantState().newDrawable();
|
||||
if (apiLevel > 21 && backgroundDrawable) {
|
||||
const newDrawable = tryCloneDrawable(backgroundDrawable, nativeView.getResources());
|
||||
newDrawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
org.nativescript.widgets.ViewHelper.setBackground(viewGroup, newDrawable);
|
||||
} else {
|
||||
@ -164,15 +165,26 @@ export class SegmentedBarItem extends SegmentedBarItemBase {
|
||||
arr[0] = R_ATTR_STATE_SELECTED;
|
||||
stateDrawable.addState(arr, colorDrawable);
|
||||
stateDrawable.setBounds(0, 15, viewGroup.getRight(), viewGroup.getBottom());
|
||||
|
||||
org.nativescript.widgets.ViewHelper.setBackground(viewGroup, stateDrawable);
|
||||
}
|
||||
} else {
|
||||
org.nativescript.widgets.ViewHelper.setBackground(viewGroup, value.newDrawable());
|
||||
const backgroundDrawable = tryCloneDrawable(value, nativeView.getResources());
|
||||
org.nativescript.widgets.ViewHelper.setBackground(viewGroup, backgroundDrawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
export class SegmentedBar extends SegmentedBarBase {
|
||||
nativeViewProtected: android.widget.TabHost;
|
||||
private _tabContentFactory: android.widget.TabHost.TabContentFactory;
|
||||
|
@ -6,7 +6,7 @@ import * as application from "../../application";
|
||||
export * from "./background-common"
|
||||
|
||||
interface AndroidView {
|
||||
_cachedDrawableConstState: android.graphics.drawable.Drawable.ConstantState;
|
||||
_cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable;
|
||||
}
|
||||
|
||||
// TODO: Change this implementation to use
|
||||
@ -41,8 +41,9 @@ export module ad {
|
||||
const drawable = nativeView.getBackground();
|
||||
const androidView = <any>view as AndroidView;
|
||||
// use undefined as not set. getBackground will never return undefined only Drawable or null;
|
||||
if (androidView._cachedDrawableConstState === undefined && drawable) {
|
||||
androidView._cachedDrawableConstState = drawable.getConstantState();
|
||||
if (androidView._cachedDrawable === undefined && drawable) {
|
||||
const constantState = drawable.getConstantState();
|
||||
androidView._cachedDrawable = constantState || drawable;
|
||||
}
|
||||
|
||||
if (isSetColorFilterOnlyWidget(nativeView)
|
||||
@ -77,10 +78,19 @@ export module ad {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: newDrawable for BitmapDrawable will fail if we don't specify resource. Use the other overload.
|
||||
const defaultDrawable = androidView._cachedDrawableConstState ? androidView._cachedDrawableConstState.newDrawable(nativeView.getResources()) : null;
|
||||
const cachedDrawable = androidView._cachedDrawable;
|
||||
let defaultDrawable: android.graphics.drawable.Drawable;
|
||||
if (cachedDrawable instanceof android.graphics.drawable.Drawable.ConstantState) {
|
||||
defaultDrawable = cachedDrawable.newDrawable(nativeView.getResources())
|
||||
} else if (cachedDrawable instanceof android.graphics.drawable.Drawable) {
|
||||
defaultDrawable = cachedDrawable;
|
||||
} else {
|
||||
defaultDrawable = null;
|
||||
}
|
||||
|
||||
org.nativescript.widgets.ViewHelper.setBackground(nativeView, defaultDrawable);
|
||||
androidView._cachedDrawableConstState = undefined;
|
||||
// TODO: Do we need to clear the drawable here? Can't we just reuse it again?
|
||||
androidView._cachedDrawable = undefined;
|
||||
|
||||
if (cache.layerType !== undefined) {
|
||||
cache.setLayerType(cache.layerType, null);
|
||||
|
@ -412,14 +412,14 @@ export class TabView extends TabViewBase {
|
||||
selectedIndexProperty.coerce(this);
|
||||
}
|
||||
|
||||
[tabBackgroundColorProperty.getDefault](): android.graphics.drawable.Drawable.ConstantState {
|
||||
return this._tabLayout.getBackground().getConstantState();
|
||||
[tabBackgroundColorProperty.getDefault](): android.graphics.drawable.Drawable {
|
||||
return this._tabLayout.getBackground();
|
||||
}
|
||||
[tabBackgroundColorProperty.setNative](value: android.graphics.drawable.Drawable.ConstantState | Color) {
|
||||
[tabBackgroundColorProperty.setNative](value: android.graphics.drawable.Drawable | Color) {
|
||||
if (value instanceof Color) {
|
||||
this._tabLayout.setBackgroundColor(value.android);
|
||||
} else {
|
||||
this._tabLayout.setBackground(value ? value.newDrawable() : null);
|
||||
this._tabLayout.setBackground(tryCloneDrawable(value, this.nativeViewProtected.getResources));
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,4 +447,15 @@ export class TabView extends TabViewBase {
|
||||
const color = value instanceof Color ? value.android : value;
|
||||
tabLayout.setSelectedIndicatorColors([color]);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user