简体   繁体   中英

HOW Android View compares to a composable

In the view World we can just use View.draw(canvas) to draw view on our Canvas (which might be connected to bitmap). But here in compose how can we achieve the same.

We have a draw modifier but it has no method draw(canvas)

Update

What I need?

I wanted to blur a composable function by wrapping it inside a Blur Composable. Suppose xyz() is any random composabel function.

 @Composable
fun xyz(){
// compose logic.
}

I want to create another fun called Blur().

@Composable
fun Blur(content: @Composable() -> Unit){
//Blur logic.
}

The Blur composable takes any composable function (say xyz()) as input and Blurs it.

How I am going to implement it?

I thought I would take the same approach which the BlurView (A view blur library) takes.

  • The Blur View is a frame layout.
  • it blurs its content.
  • The BlurView first creates the bitmap of the content; blurs it; then draws it.
  • The function used to create teh bitmap of the content is view.draw(canvas: Canvas)

Why I need this?

I thought of creating my version of BlurView in compose. I know in compose there is a Modifier.blur; but since this is only supported in api 31( I guess) so I can't use it in my project.

In Compose there is a Canvas composable function available with DrawScope . You can make use of that to draw.

DrawScope has drawImage function to take ImageBitmap . As you have Bitmap need to convert that using Bitmap.asImageBitmap()

As noted in another reply you can create a composable that uses a canvas and this will give you access to many of the same drawing methods you have in a regular View canvas.

@Composable
fun MyCanvasComposable(
    data: List<Int>, //some example data to pass in
    modifier: Modifier = Modifier
) {
        Canvas() {
            .. content here     
        }
}

Within the canvas you will be inside a DrawScope, which will allow you to do the canvas drawing as previous.

I'll add some examples assuming we're pulling the drawing logic into extension methods.

Examples:

Drawing some Text

internal fun DrawScope.plotXAxis(    
        //some custom rendering here followed by this method    
        drawPath(path, pathBrush, 0.5f)
}

Drawing a Path

internal fun DrawScope.plotXAxis( //some custom rendering here followed by this method drawPath(path, pathBrush, 0.5f) }

In order to put your canvas on another layout you would call MyCanvasComposable with whatever layout modifiers are appropriate.

If you're trying to render other composables on top of the canvas the way you would do that is to just wrap the whole thing in a box and add the views before or after the canvas draw.

Example:

 val myPainter = painterResource(id = R.drawable.src_image) Box { Image( painter = myPainter ) Canvas() {.. content here.. } Text( "some text") }

In the above example you could also just call MyCanvasComposable instead of Canvas() .

Note also Image will render before the canvas and Text will render after, which is to say on top of the canvas.

If you want to have a Bitmap that has been blurred from your View function or methods like RenderScript mentioned here , and draw landmarks or shapes on it you can use androidx.compose.ui.graphics.Canvas instead of androidx.compose.foundation.Canvas

val option = BitmapFactory.Options()
option.apply {
    inPreferredConfig = Bitmap.Config.ARGB_8888
    inMutable = true
}

val imageBitmap = RenderEffect.createBitmapEffect(Bitmap bitmap)

for api 31-

private Bitmap blur(Bitmap original, float radius) {
  Bitmap bitmap = Bitmap.createBitmap(
      original.getWidth(), original.getHeight(),
      Bitmap.Config.ARGB_8888);

  RenderScript rs = RenderScript.create(this);

  Allocation allocIn = Allocation.createFromBitmap(rs, original);
  Allocation allocOut = Allocation.createFromBitmap(rs, bitmap);

  ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(
      rs, Element.U8_4(rs));
  blur.setInput(allocIn);
  blur.setRadius(radius);
  blur.forEach(allocOut);

  allocOut.copyTo(bitmap);
  rs.destroy();
  return bitmap;
} 

I'm not on my PC at the moment, when i'm available i will add it as modifier.

// 🔥 This is a function that returns Canvas which can be used to draw on an
// ImageBitmap that was sent as param. ImageBitmap that returned can be
// be used to display on Image or can be saved to a physical file.

val canvas: androidx.compose.ui.graphics.Canvas = Canvas(imageBitmap)

val paint = remember {
    Paint().apply {
        style = PaintingStyle.Stroke
        strokeWidth = 10f
        color = Color(0xff29B6F6)

    }
}

canvas.drawRect(0f, 0f, 200f, 200f, paint = paint)
canvas.drawCircle(
    Offset(
        imageBitmap.width / 2 - 75f,
        imageBitmap.height / 2 + 75f
    ), 150.0f, paint
)


// This bitmap has image and the drawing from canvas
Image(bitmap = imageBitmap, contentDescription = null)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM