Home > Software design >  How to achieve this UI in Flutter?
How to achieve this UI in Flutter?

Time:11-19

enter image description here

I need a rearrangeable triangle as an indicator above the container widget, which also gets the gradient of the container applied.

Right now the red triangle is a custom paint, but I am open to do it in another way. The location of it must be customisable. Everything is good till the gradient comes into play, because I cannot append it to the triangle as well.

So what I would need is a widget which combines the two elements (triangle and container) and lets me define a decoration for it just like for a normal container. Any ideas on how to solve something like that?

CodePudding user response:

Use ClipPath()

ClipPath(
            clipper: ArrowClipper(),
            child: Container(
              height: arrowHeight,
              width: 40,
              decoration: BoxDecoration(
                //Your gradient...
              ),
            ),
          )
...
class ArrowClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final Path path = Path();

    path.moveTo(0, size.height);
    path.lineTo(size.width / 2, 0);
    path.lineTo(size.width, size.height);

    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}

CodePudding user response:

As an alternative to ClipPath you can use a Stack with a rotated container behind your button container. This should provide a little margin for error for a responsive UI. (For brevity I didn't style the blue button container as you seem to have that ok.)

enter image description here

You can control the position of the pointer with the first Positioned left: attribute.

You can run the below code in DartPad.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 300,
      height: 150,
      child: Stack(
        children: [
          Positioned(
            top: 12.5,
            left: 100,
            child: Transform.rotate(
              angle: 0.7854,
              child: Container(
                width: 25,
                height: 25,
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    colors: [
                      Colors.red,
                      Colors.orange,
                    ],
                    begin: FractionalOffset(0.0, 0.0),
                    end: FractionalOffset(1.0, 1.0),
                    stops: [0.0, 1.0],
                    tileMode: TileMode.clamp,
                  )
                ),
              )
            ),
          ),
          Positioned(
            top: 20,
            child: Container(
              width: 300,
              height: 100,
              color: Colors.blue,
              child: const SizedBox(width: 300, height: 100)
            ),
          )
        ])
      );
  }
}
  • Related