Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
外部SDKのViewにマスク処理をする方法と罠
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Keita Kagurazaka
May 15, 2019
Programming
1.1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
外部SDKのViewにマスク処理をする方法と罠
potatotips #61
Keita Kagurazaka
May 15, 2019
More Decks by Keita Kagurazaka
See All by Keita Kagurazaka
三者三様 宣言的UI
kkagurazaka
0
550
SELECT FOR UPDATEの話
kkagurazaka
0
510
Mobileアプリのアーキテクチャ設計法
kkagurazaka
2
1.5k
原理から完全理解するDagger Hilt Migration
kkagurazaka
1
2k
今後のJetpackでAndroid開発はこう変わる!
kkagurazaka
16
6.4k
AWAのフルリニューアルを支えたアーキテクチャ
kkagurazaka
1
970
CQRS Architecture on Android
kkagurazaka
7
3.2k
suspending functionの裏側
kkagurazaka
3
480
coroutinesで非同期ページネーション
kkagurazaka
1
710
Other Decks in Programming
See All in Programming
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
430
yield再入門 #phpcon
o0h
PRO
0
980
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
160
FDEが実現するAI駆動経営の現在地
gonta
2
270
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
180
継続モナドとリアクティブプログラミング
yukikurage
3
700
PostgreSQL 18で考えるUUID主キー
kazuhiro1982
0
460
TSX の <Hoge<Fuga>> という構文に驚いた話 / tsx-type-argument-syntax
kanaru0928
0
210
『コードを書く以外の』エンジニアリング〜課金基盤移行プロジェクト推進のためのTips4選
yuriko1211
0
590
【やさしく解説 設計編・中級 #4】ルールの寿命と、システムの年輪
panda728
PRO
2
180
ITヒヤリハットを整理してみた ~ライフサイクルと原因から考える再発防止策~
koukimiura
1
140
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
670
Featured
See All Featured
Scaling GitHub
holman
464
140k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
460
The untapped power of vector embeddings
frankvandijk
2
1.8k
Building an army of robots
kneath
306
46k
A designer walks into a library…
pauljervisheath
211
24k
A Modern Web Designer's Workflow
chriscoyier
698
190k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
230
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
380
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
340
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Transcript
外部SDKのViewに マスク処理をする方法と罠 2019/05/15 potatotips #61 Keita Kagurazaka
AWAについて • 定額制音楽ストリーミングサービス • 歌詞表示機能あり
やりたいこと • 歌詞表示にグラデーションマスクを適用したい!
やりたいこと • 歌詞表示にグラデーションマスクを適用したい! ただし、歌詞表示Viewは 外部SDKのもので 手をいれることができない!
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) } }
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にすでに描画さ れているため
オフスクリーンバッファ 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) } }
オフスクリーンバッファ 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) }
オフスクリーンバッファ 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!
グラデーションマスク処理 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) } }
グラデーションマスク処理 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がエフェクトを持っている場合は気をつけよう
罠 • 対象のViewがエフェクトを持っている場合は気をつけよう OverScrollエフェクトがアルファをもっ ているので、このアルファでマスクがか かってしまう!
まとめ • ViewGroup#dispatchDrawで子Viewの描画をフックすれば子 Viewに自由自在にエフェクトがかけられる • オフスクリーンバッファを使うことを忘れずに • 子View自体がエフェクトを持っている場合に注意 • https://github.com/k-kagurazaka/sample-mask-sdk-view
Thanks!