Setshadowlayer Android API Differences

setShadowLayer Android API differences

setShadowLayer() is only supported on text when hardware acceleration is on. Hardware acceleration is on by default when targetSdk=14 or higher. An easy workaround is to put your View in a software layer: myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null).

Android canvas setShadowLayer greatly decreases performance

While digging around to find a way to speed up my large text shadows, I stumbled on this question and answer:

setShadowLayer Android API differences

By using:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

I drastically sped up all the text shadows in my app.

Here is a sample of how I use it:

/**
* Set a backlight (shadow) on the passed TextView.
* @param textView
*/
void setBacklight(TextView textView) {
if (textView != null) {
float textSize = textView.getTextSize();

textView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

textView.setShadowLayer(textSize,0,0,getColor(R.color.color_backlight));
}
}

According to this doc:

https://developer.android.com/guide/topics/graphics/hardware-accel.html

It says that you can disable hardware acceleration for the view.

I don't know why, but somehow this magically speeds up my TextView shadow layers.

I know, I know. That method doesn't exist for the Canvas or Paint classes. So to answer the specific question (so I don't get blasted by everyone...), you could set that on the View that you intend to draw the canvas. Like this:

void inTheShadows(View view) {
float left = 0f;
float top = 0f;
float right = 10f;
float bottom = 10f;
Canvas canvas = new Canvas();
Paint paint = new Paint();

paint.setShadowLayer(8.f, 0, 0, 0xff000000);

canvas.drawRect(left, top, right, bottom, paint);

view.setLayerType(View.LAYER_TYPE_SOFTWARE,null);

view.onDrawForeground(canvas);
}

Achieve setShadowLayer effect during drawCircle (or drawRoundRect) without turning off hardware acceleration

I had found a way to achieve such. First, we construct the ball + shadow off-screen image. Note, by using off-screen bitmap drawing technique, no GPU will be involved. The key is, don't use the Canvas from onDraw to perform drawCircle.

Instead, construct our very own Canvas, backed by an off-screen bitmap.

private Bitmap generateBallBitmap() {
final int ballShadowSize = Utils.dpToPixel(BALL_SHADOW_SIZE);

Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(historyChartBallColor);
paint.setShadowLayer(ballShadowSize, ballShadowSize, ballShadowSize, historyChartBallShadow);

Bitmap bitmap = Bitmap.createBitmap((int)((ballSize + ballShadowSize)*2f), (int)((ballSize + ballShadowSize)*2f), Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.TRANSPARENT);
Canvas canvas = new Canvas(bitmap);
canvas.drawCircle(ballSize, ballSize, ballSize, paint);

return bitmap;
}

In custom view onDraw function, just draw the off-screen bitmap directly.

if (null == this.ballBitmap) {
this.ballBitmap = generateBallBitmap();
}
canvas.drawBitmap(this.ballBitmap, px - this.ballSize, py, null);

For the entire process, I merely depend on the default value of layer type, without calling setLayerType explicitly.

The outcome is fast, yet shadow effect is visible too.

Is there an equivalent to setShadowLayer when defining shapes in XML in Android?

Using XML, there's no real way to do this that I know of. I've seen some suggestions of making a second box of the same shape behind the item, and just filling it with black, but I don't feel that's a good solution. I've been trying to find a way to do this myself for a while.

If it helps, here's a link to a similar question I posted, along with some code. I got it working for some images, but it still seems to have trouble finding the alpha channel sometimes. Basically, I've overridden ImageView and put this in the onDraw() method:

@Override 
protected void onDraw(Canvas canvas)
{
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.omen);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShadowLayer(5.5f, 6.0f, 6.0f, Color.BLACK);
canvas.drawColor(Color.GRAY);
canvas.drawRect(50, 50, 50 + bmp.getWidth(), 50 + bmp.getHeight(), paint);
canvas.drawBitmap(bmp, 50, 50, null);
}

That was just testing, though, so obviously a lot of the parameters would have to be more generic. I haven't had a lot of time to work on it lately though, but maybe this will help you find your answer.

Android Paint setShadowLayer() ignores color of its Paint

You have made your inner bitmap too small and it custs the edges of the rectange. Try this:

    Bitmap outerBm = Bitmap.createBitmap( 
rect.width(), rect.height(), Bitmap.Config.ARGB_8888);
Bitmap innerBm = Bitmap.createBitmap(
rect.width() + 50, rect.height() + 50, Bitmap.Config.ARGB_8888);

Canvas outerCanvas = new Canvas(outerBm);
Canvas innerCanvas = new Canvas(innerBm);
outerCanvas.rotate(3);

rect.left += 25;
rect.top += 25;
rect.right -= 25;
rect.bottom -= 25;

Paint shadowPaint = new Paint();
shadowPaint.setColor(Color.BLUE);;
shadowPaint.setShadowLayer(12, 12, 12, 0xFF555555);

innerCanvas.drawRect(rect, shadowPaint);

outerCanvas.drawBitmap(innerBm, 0, 0, null);

Possible bug with shadow layer?

You can try this maybe by changing the radius :

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

<!-- Drop Shadow Stack -->
<item>
<shape>
<corners android:radius="12dp" />

<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />

<solid android:color="#00CCCCCC" />
</shape>
</item>
<item>
<shape>
<corners android:radius="12dp" />

<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />

<solid android:color="#10CCCCCC" />
</shape>
</item>
<item>
<shape>
<corners android:radius="12dp" />

<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />

<solid android:color="#20CCCCCC" />
</shape>
</item>
<item>
<shape>
<corners android:radius="12dp" />

<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />

<solid android:color="#30CCCCCC" />
</shape>
</item>
<item>
<shape>
<corners android:radius="12dp" />

<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />

<solid android:color="#50CCCCCC" />
</shape>
</item>

<!-- Background -->
<item>
<shape>
<solid android:color="@android:color/white" />

<corners android:radius="12dp" />
</shape>
</item>

</layer-list>

Shadow layer work with the emulator but not on an actual device

I'm not sure, but this maybe because of hardware acceleration. setShadowLayer doen't work if view accelerated. Try to disable acceleration for whole app and check. Read this.

Unsupported Drawing Operations

setShadowLayer(): works with text only

Use a software layer type to force a view to be rendered in software. If a view that is hardware accelerated (for instance, if your whole application is hardware acclerated), is having rendering problems, this is an easy way to work around limitations of the hardware rendering pipeline.

Use setLayerType to set layer type to individual views or turn off acceleration in your manifest for whole app.



Related Topics



Leave a reply



Submit