Upgrade to Pro — share decks privately, control downloads, hide ads and more …

外部SDKのViewにマスク処理をする方法と罠

 外部SDKのViewにマスク処理をする方法と罠

potatotips #61

Keita Kagurazaka

May 15, 2019
Tweet

More Decks by Keita Kagurazaka

Other Decks in Programming

Transcript

  1. 外部SDKのViewに
    マスク処理をする方法と罠
    2019/05/15 potatotips #61
    Keita Kagurazaka

    View Slide

  2. AWAについて
    ● 定額制音楽ストリーミングサービス
    ● 歌詞表示機能あり

    View Slide

  3. やりたいこと
    ● 歌詞表示にグラデーションマスクを適用したい!

    View Slide

  4. やりたいこと
    ● 歌詞表示にグラデーションマスクを適用したい!
    ただし、歌詞表示Viewは
    外部SDKのもので
    手をいれることができない!

    View Slide

  5. ViewGroup#dispatchDraw
    class MaskLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
    ) : FrameLayout(context, attrs, defStyleAttr) {
    override fun dispatchDraw(canvas: Canvas) {
    // canvasにchild viewを描画する
    super.dispatchDraw(canvas)
    }
    }

    View Slide

  6. ViewGroup#dispatchDraw
    class MaskLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
    ) : FrameLayout(context, attrs, defStyleAttr) {
    override fun dispatchDraw(canvas: Canvas) {
    // canvasにchild viewを描画する
    super.dispatchDraw(canvas)
    }
    }
    ここで単にcanvasにマスク処理する
    のはNG
    後ろのViewはcanvasにすでに描画さ
    れているため

    View Slide

  7. オフスクリーンバッファ
    private var canvasBitmap: Bitmap? = null
    private var canvas: Canvas? = null
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    // ViewGroupと同じ大きさのBitmapとCanvasを用意
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
    .also { canvas = Canvas(it) }
    }

    View Slide

  8. オフスクリーンバッファ
    override fun dispatchDraw(canvas: Canvas) {
    val offScreenBitmap = canvasBitmap ?: return super.dispatchDraw(canvas)
    val offScreenBuffer = this.canvas ?: return super.dispatchDraw(canvas)
    // オフスクリーンバッファをクリア
    offScreenBuffer.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
    // オフスクリーンバッファに子Viewを描画
    super.dispatchDraw(offScreenBuffer)
    // オフスクリーンバッファの内容を渡ってきたcanvasに描画
    canvas.drawBitmap(offScreenBitmap, 0f, 0f, null)
    }

    View Slide

  9. オフスクリーンバッファ
    override fun dispatchDraw(canvas: Canvas) {
    val offScreenBitmap = canvasBitmap ?: return super.dispatchDraw(canvas)
    val offScreenBuffer = this.canvas ?: return super.dispatchDraw(canvas)
    // オフスクリーンバッファをクリア
    offScreenBuffer.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
    // オフスクリーンバッファに子Viewを描画
    super.dispatchDraw(offScreenBuffer)
    // オフスクリーンバッファの内容を渡ってきたcanvasに描画
    canvas.drawBitmap(offScreenBitmap, 0f, 0f, null)
    }
    ここでoffScreenBitmapを加工すれば
    OK!

    View Slide

  10. グラデーションマスク処理
    private var maskPaint: Paint? = null
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    maskPaint = Paint().apply {
    shader = LinearGradient(
    0f, 0f, 0f, h.toFloat(),
    intArrayOf(Color.TRANSPARENT, Color.WHITE,
    Color.WHITE, Color.TRANSPARENT),
    floatArrayOf(0f, 0.15f, 0.85f, 1f),
    Shader.TileMode.CLAMP
    )
    xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
    }
    }

    View Slide

  11. グラデーションマスク処理
    override fun dispatchDraw(canvas: Canvas) {
    val offScreenBitmap = canvasBitmap ?: return super.dispatchDraw(canvas)
    val offScreenBuffer = this.canvas ?: return super.dispatchDraw(canvas)
    val mask = maskPaint ?: return super.dispatchDraw(canvas)
    offScreenBuffer.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
    super.dispatchDraw(offScreenBuffer)
    offScreenBuffer.drawRect(0f, 0f,
    offScreenBitmap.width.toFloat(), offScreenBitmap.height.toFloat(),
    mask
    )
    canvas.drawBitmap(offScreenBitmap, 0f, 0f, null)
    }

    View Slide


  12. ● 対象のViewがエフェクトを持っている場合は気をつけよう

    View Slide


  13. ● 対象のViewがエフェクトを持っている場合は気をつけよう
    OverScrollエフェクトがアルファをもっ
    ているので、このアルファでマスクがか
    かってしまう!

    View Slide

  14. まとめ
    ● ViewGroup#dispatchDrawで子Viewの描画をフックすれば子
    Viewに自由自在にエフェクトがかけられる
    ● オフスクリーンバッファを使うことを忘れずに
    ● 子View自体がエフェクトを持っている場合に注意
    ● https://github.com/k-kagurazaka/sample-mask-sdk-view

    View Slide

  15. Thanks!

    View Slide