Skip to content

Instantly share code, notes, and snippets.

@ruthwikkk
Created October 7, 2023 13:36
Show Gist options
  • Save ruthwikkk/e0065056b03a62785eb3a32ad48bed0b to your computer and use it in GitHub Desktop.
Save ruthwikkk/e0065056b03a62785eb3a32ad48bed0b to your computer and use it in GitHub Desktop.
Final Code for BlurSurface
@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
)
}
)
}
}
class BlurSurfaceView: View {
private var canvas: Canvas? = null
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)
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
init(measuredWidth, measuredHeight)
}
private fun init(measuredWidth: Int, measuredHeight: Int) {
bitmap = Bitmap.createBitmap(
measuredWidth,
measuredHeight,
Bitmap.Config.ARGB_8888
)
canvas = Canvas(bitmap)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save()
canvas.drawBitmap(bitmap, 0f, 0f, null)
canvas.restore()
}
private fun getBackgroundAndDrawBehind() {
//Arrays to store the co-ordinates
val rootLocation = IntArray(2)
val viewLocation = IntArray(2)
parent.getLocationOnScreen(rootLocation) //get the parent co-ordinates
this.getLocationOnScreen(viewLocation) //get view co-ordinates
//Calculate relative co-ordinates
val left: Int = viewLocation[0] - rootLocation[0]
val top: Int = viewLocation[1] - rootLocation[1]
canvas?.save()
canvas?.translate(-left.toFloat(), -top.toFloat()) //translates the initial position
canvas?.let {
parent.draw(it)
}
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
}
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val decorView = window.decorView
val rootView = decorView.findViewById(android.R.id.content) as ViewGroup
setContent {
Theme {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Black
) {
val context = LocalContext.current
Box(
modifier = Modifier
.fillMaxSize()
.horizontalScroll(rememberScrollState())
) {
Image(
painter = painterResource(id = R.drawable.background),
contentDescription = "background",
contentScale = ContentScale.FillHeight
)
}
Box(
modifier = Modifier
.wrapContentSize()
.border(
width = 2.dp,
color = Color.Yellow
)
) {
BlurSurface(
modifier = Modifier.size(240.dp),
parent = rootView
)
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment