2

I have code in flutter and I have to write an app in android (kotlin). How can I convert flutter painter to display in android compose?

import 'dart:math' as math;
import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class FaceOutline extends CustomPainter {
  final Color frameColor;

  FaceOutline(this.frameColor);

  @override
  void paint(ui.Canvas canvas, ui.Size size) {
    final Path path = Path();
    final Rect rect = Rect.fromCenter(
      center: size.center(Offset.zero),
      width: size.width * 0.95,
      height: size.width * 0.95,
    );

    path.addArc(
      rect.translate(0.0, -rect.height * 0.4),
      math.pi * 9.0 / 8.0,
      math.pi * 2.0 / 8.0,
    );
    path.addArc(
      rect.translate(0.0, -rect.height * 0.4),
      math.pi * 13.0 / 8.0,
      math.pi * 2.0 / 8.0,
    );
    path.addArc(
      rect.translate(0.0, rect.height * 0.00),
      math.pi * 1.0 / 8.0,
      math.pi * 2.0 / 8.0,
    );
    path.addArc(
      rect.translate(0.0, rect.height * 0.00),
      math.pi * 5.0 / 8.0,
      math.pi * 2.0 / 8.0,
    );

    canvas.drawPath(
      path,
      Paint()
        ..filterQuality = FilterQuality.low
        ..isAntiAlias = true
        ..strokeWidth = 8
        ..strokeCap = StrokeCap.round
        ..strokeJoin = StrokeJoin.round
        ..style = PaintingStyle.stroke
        ..color = frameColor
        ..blendMode = BlendMode.screen,
    );
  }

  @override
  bool shouldRepaint(FaceOutline oldDelegate) {
    return frameColor != oldDelegate.frameColor;
  }
}

I can use xml or compose to display it in kotlin but I have to know how can I write that flutter's code in native android in Compose view.

You can check code: https://dartpad.dev/?id=b426645ba864beaa66d18212128a71cd

It's what I want to have:

enter image description here

Thracian
  • 43,021
  • 16
  • 133
  • 222
Captivity
  • 279
  • 5
  • 21
  • If you post an image of what this code does this it will be fairly easy to convert to Jetpack Compose since most of the code is similar with Jetpack Compose Canvas, and even more with Android Canvas. – Thracian Aug 10 '22 at 15:31
  • I've updated my post. You can see what I want to have – Captivity Aug 11 '22 at 08:32

2 Answers2

2

Jetpack Compose Canvas counterpart of this is as below

Things to note. Path is inside remember to not create a new instance on any recompositions and we set path once when it's empty

If BlendMode is needed to apply we should either set alpha of Canvas less than 1f or use a layer as in this answer

@Composable
private fun FaceOutlineComposable(modifier: Modifier, frameColor: Color) {

    val path = remember { Path() }

    Canvas(modifier = modifier) {

        if (path.isEmpty) {

            val canvasWidth = size.width
            val canvasHeight = size.height
            val width = size.width * 0.95f

            val rect = Rect(
                offset = Offset((canvasWidth - width) / 2, (canvasHeight - width) / 2),
                size = Size(width, width)
            )

            path.apply {
                addArcRad(
                    rect.translate(0.0f, -rect.height * 0.4f),
                    (Math.PI * 9.0 / 8.0).toFloat(),
                    (Math.PI * 2.0 / 8.0).toFloat(),
                )
                addArcRad(
                    rect.translate(0.0f, -rect.height * 0.4f),
                    (Math.PI * 13.0 / 8.0).toFloat(),
                    (Math.PI * 2.0 / 8.0).toFloat(),
                )
                addArcRad(
                    rect,
                    (Math.PI * 1.0 / 8.0).toFloat(),
                    (Math.PI * 2.0 / 8.0).toFloat(),
                )
                addArcRad(
                    rect,
                    (Math.PI * 5.0 / 8.0).toFloat(),
                    (Math.PI * 2.0 / 8.0).toFloat(),
                )
            }
        }
        
        // This is for applying blend modes
        with(drawContext.canvas.nativeCanvas) {
            val checkPoint = saveLayer(null, null)

            drawPath(
                path = path,
                color = frameColor,
                style = Stroke(
                    width = 8.dp.toPx(),
                    cap = StrokeCap.Round,
                    join = StrokeJoin.Round
                ),
                blendMode = BlendMode.Screen
            )

            restoreToCount(checkPoint)
        }
    }
}

Usage

FaceOutlineComposable(
    modifier = Modifier
        .fillMaxSize()
        .background(Color(0xff12252a)),
    frameColor = Color(0xff2196F3)
)

Result

Thracian
  • 43,021
  • 16
  • 133
  • 222
  • 1
    Thank you for this question. I added this question to my favorites. I might check it if i need to create a face outline for cropping since i'm current building an image cropper for compose – Thracian Aug 11 '22 at 10:39
0

Short answer : There is no converter Flutter <-> Android. You'll have to re-write it yourself.


Long answer :
What you're asking is to convert a specific Language (Dart) with specific Framework methods (Flutter) to another Language (Kotlin) working with another SDK (Android).
This is not possible unless you find someone mad enough to map every function of both language/framework and who publishes this converter online.

You'll have to re-develop it yourself either by :

  • Doing it with Jetpack Compose (if you worked a lot with Flutter, it'll be simple enough to learn)
  • Creating a view from scratch with a ConstraintLayout (which is easier to handle than the basic LinearLayout/RelativeLayout combos)
  • Displaying a Canvas in your view, and drawing on it with the Paint object.
    I think this solution is the best for you since a lot of methods are quite alike between Flutter and Android. See the example below
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    canvas.apply {
        // Draw the shadow
        drawOval(shadowBounds, shadowPaint)

        // Draw the label text
        drawText(data[mCurrentItem].mLabel, textX, textY, textPaint)

        // Draw the pie slices
        data.forEach {
            piePaint.shader = it.mShader
            drawArc(bounds,
                    360 - it.endAngle,
                    it.endAngle - it.startAngle,
                    true, piePaint)
        }

        // Draw the pointer
        drawLine(textX, pointerY, pointerX, pointerY, textPaint)
        drawCircle(pointerX, pointerY, pointerSize, mTextPaint)
    }
}

Documentation is here

FDuhen
  • 4,097
  • 1
  • 15
  • 26
  • Thank you for your long answer. I've updated my post and attached view which I want to have. I want to write it in Compose. – Captivity Aug 11 '22 at 08:33