日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android clippling使用

發(fā)布時間:2023/12/8 Android 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android clippling使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Android clipping

Clipping

在Android中如果多個view嵌套的會引起overdraw,很多時候一些view被覆蓋了,對用戶是不可見的,但是依然會進(jìn)行繪制,這個時候使用clipping來進(jìn)行對不可見區(qū)域進(jìn)行裁剪,可以減少overdraw提高gpu的效率。
如下圖所示:使用clipping rectangle就可以實現(xiàn)對view的裁剪。

使用clipping能達(dá)到的效果

clipping的使用也很簡單:
1、裁剪出想要渲染的部分

canvas.clipRect(clipRectLeft,clipRectTop, clipRectRight,clipRectBottom)

如下只想渲染出300*300大小的區(qū)域

val rect2 = Rect(100, 100, 400, 400)canvas.clipRect(rect2)canvas.drawBitmap(bgBitmap, 0f, 0f, null)

2、裁剪出不需要渲染的部分

canvas.clipOutRect(clipRectLeft,clipRectTop, clipRectRight,clipRectBottom)

如下?lián)傅糁虚g300*300的區(qū)域

val rect2 = Rect(100, 100, 400, 400)if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {canvas.clipRect(rect2,Region.Op.DIFFERENCE)} else {canvas.clipOutRect(rect2)}canvas.drawBitmap(bgBitmap, 0f, 0f, null)

可以定義一個剪輯區(qū)域,并保存該狀態(tài)。 然后平移畫布,添加剪輯區(qū)域并旋轉(zhuǎn)。 做一些繪圖后,可以恢復(fù)原來的裁剪狀態(tài),可以繼續(xù)做不同的平移和傾斜變換,如圖所示。

clip方法

clip和clipOut方法的區(qū)別:通過clip的區(qū)域是顯示的區(qū)域,通過clipOut方法是把該區(qū)域不顯示。

實例

其實是兩張圖片疊加在一起形成的,后面是一個全屏的背景圖,加上一個橢圓柱。

兩張圖片疊加的部分對用戶不可見,屬于過度繪制區(qū),為了減少過度繪制對性能的影響可以用clipping方法對重疊的部分進(jìn)行裁剪。
裁剪
可以先渲染出底部圓柱,然后再從背景中摳出底部區(qū)域的大小不用渲染,最后渲染背景:

上圖中黑色區(qū)域代表clipOut區(qū)域
通過計算出底部圓柱的高度和寬度來對背景圖進(jìn)行一次裁剪這里自定義一個ClipImageDrawable繼承了Drawable

class ClippedImageDrawable(context: Context) : Drawable() {companion object {private const val TAG = "ClippedImageDrawable"}private var bgBitmap: Bitmap =BitmapFactory.decodeResource(context.resources, R.drawable.book_detail_bg)private val shelfBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.bookshelf)override fun draw(canvas: Canvas) {Log.d(TAG, "width ${bounds.width()} height ${bounds.height()}")bounds.width()val top = 0.71 * bounds.height()val bottom = bounds.height()val rect = Rect(0, top.toInt(), shelfBitmap.width, bottom)canvas.drawBitmap(shelfBitmap, 0f, top.toFloat(), null)if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {canvas.clipRect(rect, Region.Op.DIFFERENCE)} else {canvas.clipOutRect(rect)}canvas.drawBitmap(bgBitmap, 0f, 0f, null)}override fun setAlpha(alpha: Int) {}override fun setColorFilter(colorFilter: ColorFilter?) {}override fun getOpacity(): Int {return PixelFormat.TRANSLUCENT} }

上面代碼中先拿到背景和圓柱的bitmap對象,然后再背景圖中裁剪出一個跟圓柱大小的rect,再執(zhí)行

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {canvas.clipRect(rect, Region.Op.DIFFERENCE)} else {canvas.clipOutRect(rect)}

上面的canvas.clipRect(rect, Region.Op.DIFFERENCE)就是把rect和背景相交的部分裁剪,在Build.VERSION_CODES.O以上的版本可以使用canvas.clipOutRect(rect)方法。
注意上面代碼的順序:
1、先用canvas.drawBitmap底部的圓柱。
2、使用clip裁剪出圓柱圖片的rect。
3、最后再繪制背景bitmp
在activity中用一下方式使用

val drawable = ClippedImageDrawable(this) val imageView = ImageView(this).apply {val param = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)scaleType = ImageView.ScaleType.FIT_XYlayoutParams = paramsetImageDrawable(drawable) } setContentView(imageView)

給imageView設(shè)置drawable,效果如下:

看上面效果圖中,圓柱和背景的相交處有兩個空白,這是因為圓柱圖片是一個長方形并且頂部有兩處空白,這樣繪制出來就達(dá)不到設(shè)計給的效果。這里的原因是在使用clip的時候用的是一個rect形狀,要達(dá)到背景和圓柱融合的效果,使用rect形狀是不行的。
可以使用clipoutPath方法來裁剪出想要的區(qū)域。
上面圓柱頂部的弧度可以用二次賽貝爾曲線來實現(xiàn)https://www.tweenmax.com.cn/tool/bezier/。

繪制二階Bezier曲線
/** * 從上一個點開始,繪制二階Bezier曲線 * (x1,y1)為控制點, (x2,y2)為終點 * 如果之前沒有調(diào)用過 moveTo(),則默認(rèn)從 (0,0)作為起點繪制。 /
public void quadTo(float x1, float y1, float x2, float y2) ;
/* * 和quadTo相同,只不過這里是使用的是相對坐標(biāo)。 */
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)

結(jié)合path和貝塞爾曲線繪制出底部的區(qū)域
path.moveTo(0f, top.toFloat()+40)
path.quadTo(
(bounds.width() / 2).toFloat(), top.toFloat()-50, bounds.width().toFloat(),
(top + 60).toFloat()
)
path.lineTo(bounds.width().toFloat(), bounds.height().toFloat())
path.lineTo(0f, bounds.height().toFloat())

如下圖對底部區(qū)域執(zhí)行clipOut之后

最終實現(xiàn)代碼

package com.example.android.clippingexampleimport android.content.Context import android.graphics.* import android.graphics.drawable.Drawable import android.os.Build import android.util.Log/*** create by 胡漢君* date 2021/8/21 17:39*/ class ClippedImageDrawable(context: Context) : Drawable() {companion object {private const val TAG = "ClippedImageDrawable"}private var bgBitmap: Bitmap =BitmapFactory.decodeResource(context.resources, R.drawable.book_detail_bg)private val shelfBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.bookshelf)private val path = Path()override fun draw(canvas: Canvas) {Log.d(TAG, "width ${bounds.width()} height ${bounds.height()}")path.reset()bounds.width()val top = 0.71 * bounds.height()path.moveTo(0f, top.toFloat()+40)path.quadTo((bounds.width() / 2).toFloat(), top.toFloat()-50, bounds.width().toFloat(),(top + 60).toFloat())path.lineTo(bounds.width().toFloat(), bounds.height().toFloat())path.lineTo(0f, bounds.height().toFloat())path.close()canvas.drawBitmap(shelfBitmap, 0f, top.toFloat(), null)if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {canvas.clipPath(path, Region.Op.DIFFERENCE)} else {canvas.clipOutPath(path)}canvas.drawBitmap(bgBitmap, 0f, 0f, null)}override fun setAlpha(alpha: Int) {}override fun setColorFilter(colorFilter: ColorFilter?) {}override fun getOpacity(): Int {return PixelFormat.TRANSLUCENT} }

效果

參考
1、https://medium.com/android-news/simplifying-layouts-with-layer-list-drawables-2f750ea1504e
2、https://blog.zen.ly/implementing-custom-drawables-part-1-5530a98cefc9
3、https://developer.android.google.cn/codelabs/advanced-android-kotlin-training-clipping-canvas-objects?hl=vi#0

總結(jié)

以上是生活随笔為你收集整理的Android clippling使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。