14

After reading on http://developer.android.com/guide/topics/graphics/hardware-accel.html , my understanding on 3 different type of layering techniques are (Assume the device has GPU)

  • LAYER_TYPE_SOFTWARE - Draw is performed by software on software's off-screen bitmap memory. Software's off-screen bitmap will then transferred to GPU. GPU render the bitmap on screen.
  • LAYER_TYPE_NONE - GPU will draw directly on screen.
  • LAYER_TYPE_HARDWARE - Draw is performed by GPU on GPU's off-screen bitmap memory. GPU's off-screen bitmap will then render to screen by GPU.

When to use LAYER_TYPE_SOFTWARE

My understanding certain draw operation isn't supported by GPU like setShadowLayer. Hence, we need to switch to LAYER_TYPE_SOFTWARE, so that draw will be performed by software.

However, since there's software's off-screen bitmap memory transferred to GPU operation, things may appear slower.

When to use LAYER_TYPE_NONE

I think this is the default settings in most of the devices. So, I assume we should use this technique most of the time.

When to use LAYER_TYPE_HARDWARE

I have no idea when to use this technique. Any example will be very much appreciated, on when we should apply LAYER_TYPE_HARDWARE technique.

p/s Also, my understanding on LAYER_TYPE_... may appear wrong. Kindly correct me, if you find any mistake. Thank you.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • LAYER_TYPE_HARDWARE: The view is rendered in hardware into a hardware texture ,if the application is hardware accelerated. If the application is not hardware accelerated,this layer type behaves the same as LAYER_TYPE_SOFTWARE. – Radhey Nov 26 '14 at 14:20

3 Answers3

4

When to use LAYER_TYPE_HARDWARE

When I want to draw a text that cutout the parent view (allowing you to see through it) I use:

setLayerType(View.LAYER_TYPE_HARDWARE, null)

For example in my custom view:

init {
    setLayerType(View.LAYER_TYPE_HARDWARE, null)
}

private val textPaint = TextPaint(ANTI_ALIAS_FLAG).apply {
    textSize = size
    xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    createTextLayout(MeasureSpec.getSize(widthMeasureSpec))
    setMeasuredDimension(widthMeasureSpec, heightMeasureSpec)
}

private fun createTextLayout(textWidth: Int) {
    textLayout = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        StaticLayout.Builder
                .obtain(text, 0, text.length, textPaint, textWidth)
                .setAlignment(Layout.Alignment.ALIGN_CENTER)
                .build()
    } else {
        StaticLayout(text, textPaint, textWidth, Layout.Alignment.ALIGN_CENTER, 1f, 0f, true)
    }
}

...

override fun onDraw(canvas: Canvas?) {
    canvas?.drawCircle(width / 2f, height / 2f, width / 2f, circlePaint)

    canvas?.withTranslation(
            x = width / 2f - textLayout.width / 2f,
            y = height / 2f - textLayout.height / 2f
    ) {
        textLayout.draw(canvas)
    }
}

The result:

enter image description here

And without setting LAYER_TYPE_HARDWARE:

enter image description here

bitvale
  • 1,959
  • 1
  • 20
  • 27
2

Basically its like a drawing cache. if your custom view is expensive to render/draw but the content doesn't change too much often then i'd use the flag. otherwise your just stressing out the device to cache for no reason.

j2emanue
  • 60,549
  • 65
  • 286
  • 456
1

You should use most of the times LAYER_TYPE_HARDWARE as it is more efficient. But must take into account that not all Canvas Drawing Operations are supported with LAYER_TYPE_HARDWARE on specific API levels. So, you may need to switch to LAYER_TYPE_SOFTWARE if you need to do some unsupported drawing by hardware acceleration.

List of draw support operations across API levels: Link

Next link describes extensively hardware acceleration, which will hint you when to use it or not: Link

PerracoLabs
  • 16,449
  • 15
  • 74
  • 127