티스토리 뷰

 

 

 

 

 

 

 

 

* custom view 

/**
 * 특정 영역 블러처리
 *
 * 부모 뷰의 특정 영역을 캡처후 블러 적용
 */
class BlurSurfaceView: View {
    // 캡처된 화면을 그리기 위한 Canvas 객체
    private var canvas: Canvas? = null
    // 블러 처리를 적용할 Bitmap 객체
    private lateinit var bitmap: Bitmap
    // 이 뷰의 부모 뷰
    private lateinit var parent: ViewGroup

    private var renderScript: RenderScript? = null
    private lateinit var blurScript: ScriptIntrinsicBlur
    private lateinit var outAllocation: Allocation

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    // 뷰의 크기가 변경될 때 호출됩니다. Bitmap과 Canvas를 초기화합니다.
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)

        init(measuredWidth, measuredHeight)
    }

    // Bitmap 및 Canvas를 초기화하는 메서드
    private fun init(measuredWidth: Int, measuredHeight: Int) {
        bitmap = Bitmap.createBitmap(
            measuredWidth,
            measuredHeight,
            Bitmap.Config.ARGB_8888
        )
        canvas = Canvas(bitmap)
    }

    // 뷰를 그리는 메서드, 캡처된 Bitmap을 화면에 렌더링합니다.
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        canvas.save()
        canvas.drawBitmap(bitmap, 0f, 0f, null)
        canvas.restore()
    }


    // 부모 뷰의 화면을 캡처하여 블러를 적용하는 메서드
    private fun getBackgroundAndDrawBehind() {
        val rootLocation = IntArray(2) // 부모 뷰의 위치를 저장하는 배열
        val viewLocation = IntArray(2) // 현재 뷰의 위치를 저장하는 배열

        parent.getLocationOnScreen(rootLocation)
        this.getLocationOnScreen(viewLocation)

        // 현재 뷰의 위치를 기준으로 부모 뷰의 상대 좌표 계산
        val left: Int = viewLocation[0] - rootLocation[0]
        val top: Int = viewLocation[1] - rootLocation[1]

        canvas?.save()
        canvas?.translate(-left.toFloat(), -top.toFloat()) // 상대 위치로 이동
        canvas?.let {
            parent.draw(it) // 부모 뷰를 캡처하여 Canvas에 그립니다.
        }
        canvas?.restore()
        blurWithRenderScript() // 블러 효과를 적용
    }

    private fun blurWithRenderScript() {
        renderScript = RenderScript.create(context)
        blurScript = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript))

        val inAllocation = Allocation.createFromBitmap(renderScript, bitmap)
        outAllocation = Allocation.createTyped(renderScript, inAllocation.type)
        blurScript.setRadius(20f)
        blurScript.setInput(inAllocation)

        blurScript.forEach(outAllocation)
        outAllocation.copyTo(bitmap)

        inAllocation.destroy()
    }

    // 부모 뷰를 설정하고, 뷰 트리 옵저버를 통해 캡처 작업을 트리거합니다.
    fun setParent(parent: ViewGroup){

        this.parent = parent
        this.parent.viewTreeObserver.removeOnPreDrawListener(drawListener)
        this.parent.viewTreeObserver.addOnPreDrawListener(drawListener)
    }

    // 뷰가 그려지기 전에 캡처 작업을 수행하는 리스너
    private val drawListener =
        ViewTreeObserver.OnPreDrawListener {
            getBackgroundAndDrawBehind()
            true
        }
}

 

 

* composable 


@Composable
fun BlurSurface(
    modifier: Modifier,
    parent: ViewGroup
) {
    Surface(
        modifier = modifier,
        color = Color.Transparent
    ) {
        AndroidView(
            factory = {
                BlurSurfaceView(parent.context)
            },
            modifier = Modifier
                .fillMaxSize(),
            update = { blurView ->
                blurView.setParent(
                    parent = parent
                )
            }
        )
    }
}

 

 

 

 

* 사용 예

val rootView: ViewGroup = (LocalContext.current as MainActivity).window.decorView.findViewById(android.R.id.content)

.....


Box(
    modifier = Modifier
        .fillMaxSize()
) {
    WebView(
        webView = webView,
        modifier = Modifier
            .fillMaxSize(),
        isBackKeyHandlingEnabled = isBackKeyHandlingEnabled,
        doBack = isBack,
    )

    BlurSurface(
        modifier = Modifier
            .size(200.dp)
            .align(Alignment.Center),
        parent = rootView
    )
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함