mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-18 13:51:27 +08:00
feat: implement BoxShadowDrawable
This commit is contained in:

committed by
Nathan Walker

parent
a822f2affb
commit
9a7d3ecb34
@ -7,11 +7,13 @@ export function navigatingTo(args: EventData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class BoxShadowModel extends Observable {
|
export class BoxShadowModel extends Observable {
|
||||||
private _selectedComponentType: string;
|
private _selectedComponentType: string = 'buttons';
|
||||||
private _selectedBackgroundType: string;
|
private _selectedBackgroundType: string;
|
||||||
private _selectedBorderType: string;
|
private _selectedBorderType: string;
|
||||||
private _selectedAnimation: string;
|
private _selectedAnimation: string;
|
||||||
private _boxShadow: string = '5 5 1 1 rgba(255, 0, 0, .9)';
|
private _boxShadow: string = '0 10 15 -3 rgba(200, 0, 0, 0.4)';
|
||||||
|
// private _boxShadow: string = '5 5 1 1 rgba(255, 0, 0, .9)';
|
||||||
|
// private _boxShadow: string = '5 5 5 10 rgba(255, 0, 0, .9)';
|
||||||
|
|
||||||
background: string;
|
background: string;
|
||||||
borderWidth: number;
|
borderWidth: number;
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
</Page.actionBar>
|
</Page.actionBar>
|
||||||
|
|
||||||
<GridLayout rows="*, auto, *" class="box-shadow-demo">
|
<GridLayout rows="*, auto, *" class="box-shadow-demo">
|
||||||
<StackLayout backgroundColor="#ededed" row="0" padding="20" id="boxShadowDemo">
|
<StackLayout backgroundColor="#ededed" row="0" id="boxShadowDemo">
|
||||||
<!-- layouts -->
|
<!-- layouts -->
|
||||||
<ScrollView height="100%" visibility="{{ selectedComponentType === 'layouts' ? 'visible' : 'collapsed' }}">
|
<ScrollView height="100%" visibility="{{ selectedComponentType === 'layouts' ? 'visible' : 'collapsed' }}">
|
||||||
<StackLayout>
|
<StackLayout padding="20">
|
||||||
<StackLayout
|
<StackLayout
|
||||||
width="300"
|
width="300"
|
||||||
height="100"
|
height="100"
|
||||||
@ -74,22 +74,6 @@
|
|||||||
<Label text="FlexboxLayout"></Label>
|
<Label text="FlexboxLayout"></Label>
|
||||||
</FlexboxLayout>
|
</FlexboxLayout>
|
||||||
|
|
||||||
<GridLayout
|
|
||||||
width="300"
|
|
||||||
height="100"
|
|
||||||
padding="4"
|
|
||||||
boxShadow="{{ appliedBoxShadow }}"
|
|
||||||
tap="{{ toggleAnimation }}"
|
|
||||||
>
|
|
||||||
<StackLayout
|
|
||||||
borderWidth="4"
|
|
||||||
borderRadius="20"
|
|
||||||
backgroundColor="white"
|
|
||||||
>
|
|
||||||
<Label text="BorderRadius + BoxShadow on parent container"></Label>
|
|
||||||
</StackLayout>
|
|
||||||
</GridLayout>
|
|
||||||
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
Binary file not shown.
@ -6,9 +6,8 @@ import { parse } from '../../css-value';
|
|||||||
import { path, knownFolders } from '../../file-system';
|
import { path, knownFolders } from '../../file-system';
|
||||||
import * as application from '../../application';
|
import * as application from '../../application';
|
||||||
import { profile } from '../../profiling';
|
import { profile } from '../../profiling';
|
||||||
import { Color } from '../../color';
|
|
||||||
import { Screen } from '../../platform';
|
|
||||||
import { CSSShadow } from './css-shadow';
|
import { CSSShadow } from './css-shadow';
|
||||||
|
import { Length, LengthType } from './style-properties';
|
||||||
export * from './background-common';
|
export * from './background-common';
|
||||||
|
|
||||||
interface AndroidView {
|
interface AndroidView {
|
||||||
@ -28,8 +27,12 @@ export namespace ad {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isSetColorFilterOnlyWidget(nativeView: android.view.View): boolean {
|
function isSetColorFilterOnlyWidget(nativeView: android.view.View): boolean {
|
||||||
|
// prettier-ignore
|
||||||
return (
|
return (
|
||||||
nativeView instanceof android.widget.Button || (nativeView instanceof androidx.appcompat.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
|
nativeView instanceof android.widget.Button
|
||||||
|
|| (nativeView instanceof androidx.appcompat.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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +51,15 @@ export namespace ad {
|
|||||||
androidView._cachedDrawable = constantState || drawable;
|
androidView._cachedDrawable = constantState || drawable;
|
||||||
}
|
}
|
||||||
const isBorderDrawable = drawable instanceof org.nativescript.widgets.BorderDrawable;
|
const isBorderDrawable = drawable instanceof org.nativescript.widgets.BorderDrawable;
|
||||||
const onlyColor = !background.hasBorderWidth() && !background.hasBorderRadius() && !background.clipPath && !background.image && !!background.color;
|
|
||||||
|
// prettier-ignore
|
||||||
|
const onlyColor = !background.hasBorderWidth()
|
||||||
|
&& !background.hasBorderRadius()
|
||||||
|
&& !background.hasBoxShadow()
|
||||||
|
&& !background.clipPath
|
||||||
|
&& !background.image
|
||||||
|
&& !!background.color;
|
||||||
|
|
||||||
if (!isBorderDrawable && drawable instanceof android.graphics.drawable.ColorDrawable && onlyColor) {
|
if (!isBorderDrawable && drawable instanceof android.graphics.drawable.ColorDrawable && onlyColor) {
|
||||||
drawable.setColor(background.color.android);
|
drawable.setColor(background.color.android);
|
||||||
drawable.invalidateSelf();
|
drawable.invalidateSelf();
|
||||||
@ -71,13 +82,19 @@ export namespace ad {
|
|||||||
// this is the fastest way to change only background color
|
// this is the fastest way to change only background color
|
||||||
nativeView.setBackgroundColor(background.color.android);
|
nativeView.setBackgroundColor(background.color.android);
|
||||||
} else if (!background.isEmpty()) {
|
} else if (!background.isEmpty()) {
|
||||||
let backgroundDrawable = drawable as org.nativescript.widgets.BorderDrawable;
|
let backgroundDrawable = drawable;
|
||||||
if (!isBorderDrawable) {
|
|
||||||
|
if (drawable instanceof org.nativescript.widgets.BoxShadowDrawable) {
|
||||||
|
// if we have BoxShadow's we have to get the underlying drawable
|
||||||
|
backgroundDrawable = drawable.getWrappedDrawable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backgroundDrawable instanceof org.nativescript.widgets.BorderDrawable) {
|
||||||
|
refreshBorderDrawable(view, backgroundDrawable);
|
||||||
|
} else {
|
||||||
backgroundDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), view.toString());
|
backgroundDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), view.toString());
|
||||||
refreshBorderDrawable(view, backgroundDrawable);
|
refreshBorderDrawable(view, backgroundDrawable);
|
||||||
nativeView.setBackground(backgroundDrawable);
|
nativeView.setBackground(backgroundDrawable);
|
||||||
} else {
|
|
||||||
refreshBorderDrawable(view, backgroundDrawable);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const cachedDrawable = androidView._cachedDrawable;
|
const cachedDrawable = androidView._cachedDrawable;
|
||||||
@ -228,24 +245,19 @@ function createNativeCSSValueArray(css: string): androidNative.Array<org.natives
|
|||||||
}
|
}
|
||||||
|
|
||||||
function drawBoxShadow(nativeView: android.view.View, view: View, boxShadow: CSSShadow) {
|
function drawBoxShadow(nativeView: android.view.View, view: View, boxShadow: CSSShadow) {
|
||||||
const color = boxShadow.color;
|
|
||||||
const shadowOpacity = color.a;
|
|
||||||
const shadowColor = new Color(shadowOpacity, color.r, color.g, color.b);
|
|
||||||
const cornerRadius = view.borderRadius; // this should be applied to the main view as well (try 20 with a transparent background on the xml to see the effect)
|
|
||||||
const config = {
|
const config = {
|
||||||
shadowColor: shadowColor.android,
|
shadowColor: boxShadow.color.android,
|
||||||
cornerRadius: cornerRadius,
|
cornerRadius: Length.toDevicePixels(view.borderRadius as LengthType, 0.0),
|
||||||
spreadRadius: boxShadow.spreadRadius,
|
spreadRadius: Length.toDevicePixels(boxShadow.spreadRadius, 0.0),
|
||||||
blurRadius: boxShadow.blurRadius,
|
blurRadius: Length.toDevicePixels(boxShadow.blurRadius, 0.0),
|
||||||
offsetX: boxShadow.offsetX,
|
offsetX: Length.toDevicePixels(boxShadow.offsetX, 0.0),
|
||||||
offsetY: boxShadow.offsetY,
|
offsetY: Length.toDevicePixels(boxShadow.offsetY, 0.0),
|
||||||
scale: Screen.mainScreen.scale,
|
|
||||||
};
|
};
|
||||||
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, JSON.stringify(config));
|
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, JSON.stringify(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearBoxShadow(nativeView: android.view.View) {
|
function clearBoxShadow(nativeView: android.view.View) {
|
||||||
// org.nativescript.widgets.Utils.clearBoxShadow(nativeView);
|
org.nativescript.widgets.Utils.clearBoxShadow(nativeView);
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CacheMode {
|
export enum CacheMode {
|
||||||
@ -279,13 +291,13 @@ export function initImageCache(context: android.content.Context, mode = CacheMod
|
|||||||
imageFetcher.initCache();
|
imageFetcher.initCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLivesync(args): void {
|
function onLiveSync(args): void {
|
||||||
if (imageFetcher) {
|
if (imageFetcher) {
|
||||||
imageFetcher.clearCache();
|
imageFetcher.clearCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
global.NativeScriptGlobals.events.on('livesync', onLivesync);
|
global.NativeScriptGlobals.events.on('livesync', onLiveSync);
|
||||||
|
|
||||||
global.NativeScriptGlobals.addEventWiring(() => {
|
global.NativeScriptGlobals.addEventWiring(() => {
|
||||||
application.android.on('activityStarted', (args) => {
|
application.android.on('activityStarted', (args) => {
|
||||||
|
@ -3,7 +3,14 @@
|
|||||||
module widgets {
|
module widgets {
|
||||||
|
|
||||||
export class Utils {
|
export class Utils {
|
||||||
public static drawBoxShadow(view: android.view.View, value: string);
|
public static drawBoxShadow(view: android.view.View, value: string): void;
|
||||||
|
public static clearBoxShadow(view: android.view.View): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BoxShadowDrawable {
|
||||||
|
public constructor(drawable: android.graphics.drawable.Drawable, value: string);
|
||||||
|
public getWrappedDrawable(): android.graphics.drawable.Drawable;
|
||||||
|
public toString(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CustomTransition extends androidx.transition.Visibility {
|
export class CustomTransition extends androidx.transition.Visibility {
|
||||||
|
@ -0,0 +1,154 @@
|
|||||||
|
package org.nativescript.widgets;
|
||||||
|
|
||||||
|
import android.graphics.BlurMaskFilter;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.LayerDrawable;
|
||||||
|
import android.graphics.drawable.ShapeDrawable;
|
||||||
|
import android.graphics.drawable.shapes.RectShape;
|
||||||
|
import android.graphics.drawable.shapes.RoundRectShape;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
|
public class BoxShadowDrawable extends LayerDrawable {
|
||||||
|
// Static parameters
|
||||||
|
protected final static int DEFAULT_BACKGROUND_COLOR = Color.WHITE;
|
||||||
|
protected final static String TAG = "BoxShadowDrawable";
|
||||||
|
|
||||||
|
// BoxShadow Parameters
|
||||||
|
protected int offsetX = 0;
|
||||||
|
protected int offsetY = 0;
|
||||||
|
protected int blurRadius = 0;
|
||||||
|
protected int spreadRadius = 0;
|
||||||
|
protected int shadowColor = Color.BLACK;
|
||||||
|
|
||||||
|
// Layers
|
||||||
|
protected final ShapeDrawable shadowLayer;
|
||||||
|
protected final ShapeDrawable overlayLayer;
|
||||||
|
protected final Drawable wrappedLayer;
|
||||||
|
|
||||||
|
protected float[] currentCornerRadii;
|
||||||
|
|
||||||
|
public BoxShadowDrawable(Drawable wrappedDrawable, String value) {
|
||||||
|
super(new Drawable[]{});
|
||||||
|
|
||||||
|
Log.d(TAG, "Constructing BoxShadowDrawable!");
|
||||||
|
|
||||||
|
this.shadowLayer = new ShapeDrawable(new RectShape());
|
||||||
|
this.overlayLayer = this.createOverlayLayer();
|
||||||
|
this.wrappedLayer = wrappedDrawable;
|
||||||
|
|
||||||
|
// add our layers
|
||||||
|
this.addLayer(shadowLayer);
|
||||||
|
this.addLayer(overlayLayer);
|
||||||
|
this.addLayer(wrappedLayer);
|
||||||
|
|
||||||
|
this.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to allow applying any bg changes on original Drawable
|
||||||
|
public Drawable getWrappedDrawable() {
|
||||||
|
return this.wrappedLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
try {
|
||||||
|
JSONObject config = new JSONObject(value);
|
||||||
|
offsetX = config.getInt("offsetX");
|
||||||
|
offsetY = config.getInt("offsetY");
|
||||||
|
blurRadius = config.getInt("blurRadius");
|
||||||
|
spreadRadius = config.getInt("spreadRadius");
|
||||||
|
shadowColor = config.getInt("shadowColor");
|
||||||
|
|
||||||
|
float[] outerRadius;
|
||||||
|
|
||||||
|
// if we are wrapping a BorderDrawable - we can get the radii from it
|
||||||
|
if(wrappedLayer instanceof BorderDrawable) {
|
||||||
|
BorderDrawable b = (BorderDrawable) wrappedLayer;
|
||||||
|
outerRadius = new float[]{
|
||||||
|
b.getBorderTopLeftRadius(),
|
||||||
|
b.getBorderTopLeftRadius(),
|
||||||
|
|
||||||
|
b.getBorderTopRightRadius(),
|
||||||
|
b.getBorderTopRightRadius(),
|
||||||
|
|
||||||
|
b.getBorderBottomRightRadius(),
|
||||||
|
b.getBorderBottomRightRadius(),
|
||||||
|
|
||||||
|
b.getBorderBottomLeftRadius(),
|
||||||
|
b.getBorderBottomLeftRadius(),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
int cornerRadius = 0;
|
||||||
|
try {
|
||||||
|
cornerRadius = config.getInt("cornerRadius");
|
||||||
|
} catch (JSONException ignore) {}
|
||||||
|
|
||||||
|
outerRadius = new float[8];
|
||||||
|
Arrays.fill(outerRadius, cornerRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Arrays.equals(outerRadius, currentCornerRadii)) {
|
||||||
|
Log.d(TAG, "Update layer shape");
|
||||||
|
shadowLayer.setShape(new RoundRectShape(outerRadius, null, null));
|
||||||
|
overlayLayer.setShape(new RoundRectShape(outerRadius, null, null));
|
||||||
|
|
||||||
|
// update current
|
||||||
|
currentCornerRadii = outerRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply new shadow parameters
|
||||||
|
this.applyShadow();
|
||||||
|
} catch (JSONException exception) {
|
||||||
|
Log.d(TAG, "Caught JSONException...");
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyShadow() {
|
||||||
|
Log.d(TAG, "applyShadow: " + this);
|
||||||
|
|
||||||
|
// apply boxShadow
|
||||||
|
shadowLayer.getPaint().setColor(shadowColor);
|
||||||
|
shadowLayer.getPaint().setMaskFilter(new BlurMaskFilter(
|
||||||
|
Float.MIN_VALUE + blurRadius,
|
||||||
|
BlurMaskFilter.Blur.NORMAL
|
||||||
|
));
|
||||||
|
shadowLayer.getPaint().setAntiAlias(true);
|
||||||
|
|
||||||
|
// apply insets that mimic offsets/spread to the shadowLayer
|
||||||
|
int inset = -spreadRadius;
|
||||||
|
Log.d(TAG, "Insets:"
|
||||||
|
+ "\n l: " + (inset + offsetX)
|
||||||
|
+ "\n t: " + (inset + offsetY)
|
||||||
|
+ "\n r: " + (inset - offsetX)
|
||||||
|
+ "\n b: " + (inset - offsetY)
|
||||||
|
);
|
||||||
|
this.setLayerInset(0,
|
||||||
|
inset + offsetX,
|
||||||
|
inset + offsetY,
|
||||||
|
inset - offsetX,
|
||||||
|
inset - offsetY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShapeDrawable createOverlayLayer() {
|
||||||
|
ShapeDrawable shapeDrawable = new ShapeDrawable(new RectShape());
|
||||||
|
shapeDrawable.getPaint().setColor(DEFAULT_BACKGROUND_COLOR);
|
||||||
|
|
||||||
|
return shapeDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BoxShadowDrawable { oX:" + offsetX + " oY:" + offsetY + " br:" + blurRadius + " sr:" + spreadRadius + " c:" + shadowColor + " }";
|
||||||
|
}
|
||||||
|
}
|
@ -1,108 +1,32 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.nativescript.widgets;
|
package org.nativescript.widgets;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author triniwiz
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
import android.util.Log;
|
||||||
import android.graphics.drawable.ShapeDrawable;
|
|
||||||
import android.graphics.drawable.shapes.RoundRectShape;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
public static void drawBoxShadow(View view, String value) {
|
public static void drawBoxShadow(View view, String value) {
|
||||||
try {
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
|
||||||
JSONObject config = new JSONObject(value);
|
return;
|
||||||
int shadowColor = config.getInt("shadowColor");
|
|
||||||
int cornerRadius = config.getInt("cornerRadius");
|
|
||||||
int spreadRadius = config.getInt("spreadRadius");
|
|
||||||
int blurRadius = config.getInt("blurRadius");
|
|
||||||
int configOffsetX = config.getInt("offsetX");
|
|
||||||
int configOffsetY = config.getInt("offsetY");
|
|
||||||
int scale = config.getInt("scale");
|
|
||||||
|
|
||||||
|
|
||||||
float cornerRadiusValue = cornerRadius * scale;
|
|
||||||
|
|
||||||
float shadowSpread = spreadRadius * scale;
|
|
||||||
|
|
||||||
// Set shadow layer
|
|
||||||
float[] outerRadius = {cornerRadiusValue, cornerRadiusValue, cornerRadiusValue, cornerRadiusValue, cornerRadiusValue, cornerRadiusValue, cornerRadiusValue, cornerRadiusValue};
|
|
||||||
|
|
||||||
// Default background for transparent/semi-transparent background so it doesn't see through the shadow
|
|
||||||
int defaultBackgroundColor = Color.WHITE;
|
|
||||||
RoundRectShape backgroundRectShape = new RoundRectShape(outerRadius, null, null);
|
|
||||||
ShapeDrawable backgroundDrawable = new ShapeDrawable(backgroundRectShape);
|
|
||||||
backgroundDrawable.getPaint().setColor(defaultBackgroundColor);
|
|
||||||
|
|
||||||
// shadow layer setup
|
|
||||||
RoundRectShape shadowRectShape = new RoundRectShape(outerRadius, null, null);
|
|
||||||
ShapeDrawable shadowShapeDrawable = new ShapeDrawable(shadowRectShape);
|
|
||||||
shadowShapeDrawable.getPaint().setShadowLayer(shadowSpread, 0, 0, shadowColor);
|
|
||||||
shadowShapeDrawable.getPaint().setAntiAlias(true);
|
|
||||||
|
|
||||||
// set shadow direction
|
|
||||||
Drawable[] drawableArray = new Drawable[3];
|
|
||||||
drawableArray[0] = shadowShapeDrawable;
|
|
||||||
drawableArray[1] = backgroundDrawable;
|
|
||||||
drawableArray[2] = view.getBackground();
|
|
||||||
LayerDrawable drawable = new LayerDrawable(drawableArray);
|
|
||||||
|
|
||||||
// workaround to show shadow offset (similar to ios's offsets)
|
|
||||||
int shadowInsetsLeft;
|
|
||||||
int shadowInsetsTop;
|
|
||||||
int shadowInsetsRight;
|
|
||||||
int shadowInsetsBottom;
|
|
||||||
|
|
||||||
float offsetX = configOffsetX - spreadRadius;
|
|
||||||
// ignore the following line, this is similar to the adjustedShadowOffset on ios.
|
|
||||||
// it is just used to experiment the amount of insets that need to be applied based
|
|
||||||
// on the offset provided. Need to use some real calculation to gain parity (ask Osei)
|
|
||||||
float insetScaleFactor = 4f / 5f;
|
|
||||||
|
|
||||||
if (configOffsetX == 0) {
|
|
||||||
shadowInsetsLeft = 0;
|
|
||||||
shadowInsetsRight = 0;
|
|
||||||
} else if (configOffsetX > 0) {
|
|
||||||
shadowInsetsLeft = (int) (shadowSpread * insetScaleFactor);
|
|
||||||
shadowInsetsRight = (int) ((offsetX < 0 ? 0 : offsetX) * scale * insetScaleFactor);
|
|
||||||
} else {
|
|
||||||
shadowInsetsLeft = (int) ((offsetX < 0 ? 0 : offsetX) * scale * insetScaleFactor);
|
|
||||||
shadowInsetsRight = (int) (shadowSpread * insetScaleFactor);
|
|
||||||
}
|
}
|
||||||
float offsetY = configOffsetY - spreadRadius;
|
Log.d("BoxShadowDrawable", "drawBoxShadow");
|
||||||
if (configOffsetY == 0) {
|
|
||||||
shadowInsetsTop = 0;
|
Drawable wrap = view.getBackground();
|
||||||
shadowInsetsBottom = 0;
|
if(wrap == null) {
|
||||||
} else if (configOffsetY >= 0) {
|
wrap = new ColorDrawable(Color.TRANSPARENT);
|
||||||
shadowInsetsTop = (int) (shadowSpread * insetScaleFactor);
|
} else if(wrap instanceof BoxShadowDrawable) {
|
||||||
shadowInsetsBottom = (int) ((offsetY < 0 ? 0 : offsetY) * scale * insetScaleFactor);
|
wrap = ((BoxShadowDrawable) view.getBackground()).getWrappedDrawable();
|
||||||
} else {
|
Log.d("BoxShadowDrawable", "already a BoxShadowDrawable, getting wrapped drawable:" + wrap.getClass().getName());
|
||||||
shadowInsetsTop = (int) ((offsetY < 0 ? 0 : offsetY) * scale * insetScaleFactor);
|
|
||||||
shadowInsetsBottom = (int) (shadowSpread * insetScaleFactor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this isn't really a shadow offset per se, but just having the some layer
|
// replace background
|
||||||
// drawable layer have an inset to mimic an offset (feels very hacky ugh)
|
Log.d("BoxShadowDrawable", "replacing background with new BoxShadowDrawable...");
|
||||||
drawable.setLayerInset(0, shadowInsetsLeft, shadowInsetsTop, shadowInsetsRight, shadowInsetsBottom);
|
view.setBackground(new BoxShadowDrawable(wrap, value));
|
||||||
|
|
||||||
// this is what it shadows look like without offsets - uncomment the following line,
|
|
||||||
// and comment out line above to see what the shadow without any inset modification looks like
|
|
||||||
// on android
|
|
||||||
// drawable.setLayerInset(0, shadowSpread, shadowSpread, shadowSpread, shadowSpread);
|
|
||||||
|
|
||||||
// make sure parent doesn't clip the shadows
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
View nativeView = view;
|
|
||||||
while (view.getParent() != null && view.getParent() instanceof ViewGroup) {
|
while (view.getParent() != null && view.getParent() instanceof ViewGroup) {
|
||||||
count++;
|
count++;
|
||||||
ViewGroup parent = (ViewGroup) view.getParent();
|
ViewGroup parent = (ViewGroup) view.getParent();
|
||||||
@ -112,11 +36,20 @@ public class Utils {
|
|||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nativeView = parent;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeView.setBackground(drawable);
|
public static void clearBoxShadow(View view) {
|
||||||
} catch (JSONException ignore) {
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log.d("BoxShadowDrawable", "clearBoxShadow.");
|
||||||
|
|
||||||
|
Drawable bg = view.getBackground();
|
||||||
|
if(bg instanceof BoxShadowDrawable) {
|
||||||
|
Drawable original = ((BoxShadowDrawable) view.getBackground()).getWrappedDrawable();
|
||||||
|
Log.d("BoxShadowDrawable", "BoxShadowDrawable found, resetting to original: " + original.getClass().getName());
|
||||||
|
view.setBackground(original);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user