Skip to content

Instantly share code, notes, and snippets.

@SaadArdati
Created June 7, 2023 17:44
Show Gist options
  • Save SaadArdati/fa0045ed5bf4d18662e8e9f9081bd826 to your computer and use it in GitHub Desktop.
Save SaadArdati/fa0045ed5bf4d18662e8e9f9081bd826 to your computer and use it in GitHub Desktop.
Box Transform Figma Replica
import 'package:flutter/material.dart';
import 'package:flutter_box_transform/flutter_box_transform.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Box Transform Figma Replica',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool cropping = false;
late Rect rect = Rect.fromCenter(
center: MediaQuery.of(context).size.center(Offset.zero),
width: 400,
height: 300,
);
late Rect cropRect = rect;
@override
Widget build(BuildContext context) {
return Scaffold(
// Enable and disable crop mode.
floatingActionButton: FloatingActionButton(
tooltip: cropping ? 'Disable cropping' : 'Enable cropping',
onPressed: () {
setState(() {
cropping = !cropping;
cropRect = rect;
});
},
child: Icon(cropping ? Icons.crop : Icons.crop_free),
),
body: Stack(
fit: StackFit.expand,
children: [
TransformableBox(
key: const ValueKey('Main TransformableBox'),
rect: rect,
onChanged: (result, event) {
setState(() {
rect = result.rect;
});
},
contentBuilder: (BuildContext context, Rect rect, Flip flip) {
return DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
color: cropping ? Colors.grey : Colors.blue,
width: cropping ? 0.75 : 2,
),
image: DecorationImage(
image: const AssetImage('assets/image.png'),
fit: BoxFit.fill,
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(!cropping ? 0 : 0.5),
BlendMode.hardLight,
),
),
),
);
},
visibleHandles: {
if (!cropping)
...HandlePosition.corners,
},
enabledHandles: {
if (!cropping)
...HandlePosition.corners,
},
cornerHandleBuilder: (context, handle) => DefaultCornerHandle(
handle: handle,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.blue,
width: 2,
),
),
),
),
if (cropping)
TransformableBox(
key: const ValueKey('Crop Region TransformableBox'),
rect: cropRect,
clampingRect: rect,
allowContentFlipping: false,
onChanged: (result, event) {
setState(() {
cropRect = result.rect;
});
},
contentBuilder: (BuildContext context, Rect rect, Flip flip) {
return Stack(
children: [
// const Positioned.fill(child: ColoredBox(color: Colors.red)),
Positioned.fromRect(
rect: Rect.fromCenter(
center: this.rect.center - rect.topLeft,
width: this.rect.width,
height: this.rect.height,
),
child: DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
width: 0.75,
),
image: const DecorationImage(
image: AssetImage('assets/image.png'),
fit: BoxFit.fill,
),
),
),
)
],
);
},
cornerHandleBuilder: (context, handle) => AngularHandle(
handle: handle,
color: Colors.blue,
hasShadow: false,
length: 16,
),
sideHandleBuilder: (context, handle) => AngularHandle(
handle: handle,
color: Colors.blue,
hasShadow: false,
length: 16,
),
),
],
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment