main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(debugShowCheckedModeBanner: false, home: UITest()));
}
class UITest extends StatefulWidget {
const UITest({
Key? key,
}) : super(key: key);
@override
State<UITest> createState() => _UITestState();
}
class _UITestState extends State<UITest> {
List<int> widgetIds = [0, 1];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: widgetIds.reversed
.map((id) => StackItem(
id: id,
isTop: id == widgetIds.first,
text: id == 0 ? 'Product Details' : 'Product Features',
onTap: () {
setState(() {
widgetIds = [widgetIds.last, ...widgetIds.getRange(0, 1)];
});
},
))
.toList(),
),
);
}
}
class StackItem extends StatelessWidget {
final int id;
final bool isTop;
final String text;
final VoidCallback onTap;
const StackItem({
Key? key,
required this.id,
required this.isTop,
required this.text,
required this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Positioned(
left: id * (MediaQuery.of(context).size.width / 2),
child: GestureDetector(
onTap: isTop ? null : onTap,
child: Container(
height: 64,
width: MediaQuery.of(context).size.width / 2,
decoration: ShapeDecoration(
color: isTop ? Colors.green : Colors.grey.withOpacity(0.25),
shape: const MessageBorder(),
),
child: Center(child: Text(text)),
),
),
);
}
}
class MessageBorder extends ShapeBorder {
final bool usePadding;
const MessageBorder({this.usePadding = true});
@override
EdgeInsetsGeometry get dimensions =>
EdgeInsets.only(bottom: usePadding ? 20 : 0);
@override
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
throw UnimplementedError();
}
@override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
rect = Rect.fromPoints(rect.topLeft, rect.bottomRight - const Offset(0, 20));
return Path()
..addRRect(RRect.fromRectAndCorners(
rect,
topLeft: const Radius.circular(20),
topRight: const Radius.circular(20),
))
..moveTo(rect.bottomRight.dx, rect.bottomRight.dy)
..relativeLineTo(20, 0)
..quadraticBezierTo(rect.bottomRight.dx, rect.bottomRight.dy,
rect.centerRight.dx, rect.centerRight.dy)
..close()
..moveTo(rect.bottomLeft.dx, rect.bottomLeft.dy)
..relativeLineTo(-20, 0)
..quadraticBezierTo(rect.bottomLeft.dx, rect.bottomLeft.dy,
rect.centerLeft.dx, rect.centerLeft.dy);
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {}
@override
ShapeBorder scale(double t) => this;
}