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.)
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)
),
)
])
);
}
}