Related
anyone has an idea on how's the best way to position widgets in orbit AROUND another (circular) widget in flutter like this?
Thank you very much for any help you can give :D
You can Use Stack Widget . For your Idea here is the Example:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new ExampleWidget()));
}
class ExampleWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
Widget bigCircle = new Container(
width: 300.0,
height: 300.0,
decoration: new BoxDecoration(
color: Colors.orange,
shape: BoxShape.circle,
),
);
return new Material(
color: Colors.black,
child: new Center(
child: new Stack(
children: <Widget>[
bigCircle,
new Positioned(
child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.favorite_border),
top: 10.0,
left: 130.0,
),
new Positioned(
child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.timer),
top: 120.0,
left: 10.0,
),
new Positioned(
child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.place),
top: 120.0,
right: 10.0,
),
new Positioned(
child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.local_pizza),
top: 240.0,
left: 130.0,
),
new Positioned(
child: new CircleButton(onTap: () => print("Cool"), iconData: Icons.satellite),
top: 120.0,
left: 130.0,
),
],
),
),
);
}
}
class CircleButton extends StatelessWidget {
final GestureTapCallback onTap;
final IconData iconData;
const CircleButton({Key key, this.onTap, this.iconData}) : super(key: key);
#override
Widget build(BuildContext context) {
double size = 50.0;
return new InkResponse(
onTap: onTap,
child: new Container(
width: size,
height: size,
decoration: new BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: new Icon(
iconData,
color: Colors.black,
),
),
);
}
}
/// from https://gist.github.com/pskink/50554a116698f03a862a356c38b75eb3#file-rotary_dial-dart-L225
Iterable<Rect> getBounds(Rect rect, int length) sync* {
final s = Size.square(rect.shortestSide / 6.5);
final radius = (rect.shortestSide - s.shortestSide) * 0.40;
for (var i = 0; i < length; i++) {
/// distance +
final angle = i * pi / 6 + pi * .01;
final center = rect.center + Offset(cos(angle), sin(angle)) * radius;
yield Rect.fromCenter(center: center, width: s.width, height: s.height);
}
}
class Avatar3xBtnMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
final double iconSize;
Avatar3xBtnMultiChildLayoutDelegate(this.iconSize);
#override
void performLayout(Size size) {
int id = 1;
getBounds(Offset.zero & size, 3).forEach(
(rect) {
layoutChild(id, BoxConstraints.tight(rect.size));
positionChild(id, rect.centerRight);
id++;
},
);
}
#override
bool shouldRelayout(
covariant Avatar3xBtnMultiChildLayoutDelegate oldDelegate) {
return true;
}
}
And using it
class CAPG extends StatefulWidget {
const CAPG({Key? key}) : super(key: key);
#override
State<CAPG> createState() => _CAPGState();
}
class _CAPGState extends State<CAPG> {
double value = 300;
final iconSize = 24.0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Slider(
value: value,
max: 500,
onChanged: (v) {
setState(() {
value = v;
});
}),
Container(
width: value,
height: value,
clipBehavior: Clip.none,
decoration: BoxDecoration(
color: Colors.cyanAccent.withOpacity(.2),
shape: BoxShape.circle,
border: Border.all(),
),
child: CustomMultiChildLayout(
delegate: Avatar3xBtnMultiChildLayoutDelegate(iconSize),
children: [
LayoutId(
id: 1,
child: Material(
color: Colors.purple,
shape: CircleBorder(),
child: Icon(Icons.one_k, size: iconSize),
)),
LayoutId(
id: 2,
child: Material(
color: Colors.purple,
shape: CircleBorder(),
child: Icon(Icons.two_k, size: iconSize),
)),
LayoutId(
id: 3,
child: Material(
color: Colors.purple,
shape: CircleBorder(),
child: Icon(Icons.three_k_outlined, size: iconSize),
),
),
],
),
)
],
),
),
);
}
}
What I have done till now is make widget draggable and a drag target according to my requirements. What i want is when the user drops the draggable container into the drag target i want to show that dragged widget inside that big drag target container and able to score if that is the right option or not.
second problem i am having is that i am using Text to speech for the sound and it is not working i tried many things but still it isn't working. i have a play button and give it a letter like A,B,D,G etc. whenever user presses the button i want to play the sound of that button and drag the right container into the drag target. Thankyou for your help.
// ignore_for_file: prefer_const_constructors, file_names, non_constant_identifier_names
import 'package:dyslexia/pages/round_2/Q8sound.dart';
import 'package:dyslexia/utilities/nextButton.dart';
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
import '../../utilities/QuestionWidget.dart';
class Q1DAD extends StatefulWidget {
const Q1DAD({Key? key}) : super(key: key);
#override
State<Q1DAD> createState() => _Q1DADState();
}
class _Q1DADState extends State<Q1DAD> {
String question =
"Listen to this letter sound and then choose the letter whose sound you hear";
var changeButton = false;
var score = 0;
final FlutterTts flutterTts = FlutterTts();
speak(word) async {
await flutterTts.setLanguage("en-US");
await flutterTts.setPitch(1);
await flutterTts.setVolume(10.0);
await flutterTts.speak(word);
}
var word = "M";
bool isPlayingMsg = false;
bool draged = false;
bool showDRag = false;
#override
Widget build(BuildContext context) {
bool isPlayingMsg = false;
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
backgroundColor: Colors.cyan,
title: Text("AD&DY"),
),
body: Padding(
padding: const EdgeInsets.all(14.0),
child: Column(children: [
QuestionWidget(question: question),
SizedBox(height: MediaQuery.of(context).size.height * 0.05),
Material(
elevation: 5,
color: Colors.cyan[50],
child: ListTile(
onTap: () async {
speak(word);
isPlayingMsg = true;
},
leading: Icon(isPlayingMsg ? Icons.stop : Icons.play_arrow),
title: Text(isPlayingMsg ? "Stop" : "Play",
textScaleFactor: 1.2,
style: TextStyle(
color: Colors.black,
)),
),
),
Divider(
thickness: 1.0,
),
SizedBox(height: MediaQuery.of(context).size.height * 0.05),
Column(
children: [
DragTarget1(),
SizedBox(height: MediaQuery.of(context).size.height * 0.07),
Wrap(
spacing: 10,
runSpacing: 5,
children: [
draggableWord("M", false, score),
draggableWord("N", false, score),
draggableWord("O", false, score),
draggableWord("R", false, score),
],
),
],
),
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
nextButton(changeButton: changeButton, Location: Q8sound()),
]),
),
);
}
int acceptedData = 0;
Widget DragTarget1() {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DragTarget<int>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Material(
elevation: 10,
borderRadius: BorderRadius.circular(80),
child: Container(
height: 100.0,
width: 250.0,
color: Color.fromARGB(255, 78, 166, 178),
child: draged
? Container(
height: 50,
width: 70,
color: Colors.lightGreenAccent,
child: Align(
child: Text(word),
),
)
: Center(
child: Text('Drag target here'),
),
),
);
},
onAccept: (int data) {
setState(() {
draged = true;
showDRag = true;
});
},
),
],
);
}
Widget draggableWord(word, option, score) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
showDRag
? SizedBox()
: Draggable<int>(
// Data is the value this Draggable stores.
data: 10,
feedback: Container(
color: Colors.yellow[100],
height: 50,
width: 70,
child: Center(child: Text(word)),
),
childWhenDragging: Material(
elevation: 5,
borderRadius: BorderRadius.circular(10),
child: Container(
height: 50.0,
width: 70.0,
color: Colors.grey,
child: Center(
child: Text(""),
),
),
),
child: Material(
elevation: 5,
borderRadius: BorderRadius.circular(10),
child: Container(
height: 50,
width: 70,
color: Colors.lightGreenAccent,
child: Center(
child: Text(word),
),
),
),
)
],
);
}
}
here is my question widget
import 'package:flutter/material.dart';
class QuestionWidget extends StatelessWidget {
const QuestionWidget({
Key? key,
required this.question,
}) : super(key: key);
final String question;
#override
Widget build(BuildContext context) {
return Material(
elevation: 12,
color: Color.fromARGB(255, 125, 200, 210),
shadowColor: Colors.grey,
borderRadius: BorderRadius.circular(8),
child: Container(
height: 80,
width: 280,
alignment: Alignment.center,
child: Text(question,
textScaleFactor: 1.2,
style: TextStyle(
color: Colors.black,
))),
);
}
}
How do I get a draggable container like this, which when reaches a certain point gets vanished and a function could be called at that time. Also, the visibility of text is also decreasing and arrow icon is rotating according to the length. How can I achieve this functionality?
I have written a code, and I can add visibility widget for same. But, how to constraint it and what is the best way of doing it? Please help me out -
import 'package:flutter/material.dart';
class SwipeButton extends StatefulWidget {
const SwipeButton({Key? key}) : super(key: key);
#override
_SwipeButtonState createState() => _SwipeButtonState();
}
class _SwipeButtonState extends State<SwipeButton> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
color: Colors.orange,
width: MediaQuery.of(context).size.width * 0.9,
height: 50,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Draggable<int>(
data: 10,
feedback: Container(
height: 20.0,
width: 20.0,
color: Colors.white,
child: const Center(
child: Icon(
Icons.arrow_forward,
size: 12,
),
),
),
axis: Axis.horizontal,
childWhenDragging: Container(
height: 20.0,
width: 20.0,
color: Colors.orange,
child: const Center(
child: Text(''),
),
),
child: Container(
height: 20.0,
width: 20.0,
color: Colors.white,
child: const Center(
child: Icon(
Icons.arrow_forward,
size: 12,
),
),
),
),
DragTarget<int>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Container(
height: 20.0,
width: 20.0,
color: Colors.orange,
child: const Center(
child: Text(''),
),
);
},
onAccept: (int data) {
setState(() {
print(data);
});
},
),
],
),
),
),
),
);
}
}
For the arrow, we can use Transform.rotate.
Transform.rotate(
angle: deg2rad(-(180 + 20) * (posX / maxWidth)), // 20 comes from icon size
child: const Icon(
Icons.arrow_forward,
size: 12,
),
),
I'm not sure why onDragUpdate is not updating the UI, you can get current position of drag from that, I store it on posX.
I am using GestureDetector for test case, apply the same logic you will get the result.
Run on dartPad
class SwipeButton extends StatefulWidget {
const SwipeButton({Key? key}) : super(key: key);
#override
_SwipeButtonState createState() => _SwipeButtonState();
}
class _SwipeButtonState extends State<SwipeButton> {
double deg2rad(double deg) => deg * pi / 180;
double posX = 0.0;
#override
Widget build(BuildContext context) {
final maxWidth = MediaQuery.of(context).size.width * 0.9;
return Scaffold(
body: Center(
child: Container(
color: Colors.orange,
width: maxWidth * 0.9,
height: 50,
child: Stack(
alignment: Alignment.center,
children: [
AnimatedPositioned(
duration: const Duration(milliseconds: 100),
left: posX,
key: const ValueKey("item 1"),
child: Container(
height: 20.0,
width: 20.0,
color: Colors.white,
alignment: Alignment.center,
child: Transform.rotate(
angle: deg2rad(-(180 + 20) * (posX / maxWidth)),
child: const Icon(
Icons.arrow_forward,
size: 12,
),
),
),
),
GestureDetector(
onPanEnd: (details) {
setState(() {
posX = 0;
});
},
onPanUpdate: (details) {
setState(() {
posX = details.localPosition.dx;
});
if (posX / maxWidth > .95) {
debugPrint("on success drag");
}
},
)
],
),
),
),
);
}
}
I get this error:
════════ Exception caught by rendering library ═════════════════════════════════
SliverGeometry has a paintOffset that exceeds the remainingPaintExtent from the constraints.
The relevant error-causing widget was
SliverAppBarLayer
It happens every time I scroll it up. The error is not visible on the screen, only in the console which also prevents me to do hot restart/hot reload. What does it mean? Why does it happen? How to fix it, please?
screenshot
my SliverWidget: sliver_app_bar_layer.dart
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class SliverAppBarLayer extends SingleChildRenderObjectWidget {
SliverAppBarLayer({Widget child, Key key}) : super(child: child, key: key);
#override
RenderObject createRenderObject(BuildContext context) {
return RenderSliverAppBarLayer();
}
}
class RenderSliverAppBarLayer extends RenderSliverToBoxAdapter {
RenderSliverAppBarLayer({
RenderBox child,
}) : super(child: child);
#override
void performResize() {}
#override
void performLayout() {
if (child == null) {
geometry = SliverGeometry.zero;
return;
}
final SliverConstraints constraints = this.constraints;
child.layout(constraints.asBoxConstraints(/* crossAxisExtent: double.infinity */), parentUsesSize: true);
double childExtent;
switch (constraints.axis) {
case Axis.horizontal:
childExtent = child.size.width;
break;
case Axis.vertical:
childExtent = child.size.height;
break;
}
assert(childExtent != null);
final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: childExtent);
final double cacheExtent = calculateCacheOffset(constraints, from: 0.0, to: childExtent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = SliverGeometry(
scrollExtent: 0,
paintExtent: childExtent,
paintOrigin: constraints.scrollOffset,
cacheExtent: cacheExtent,
maxPaintExtent: childExtent,
hitTestExtent: paintedChildSize,
);
setChildParentData(child, constraints, geometry);
}
}
main.dart
import 'package:flutter/material.dart';
import 'theme/style_constants.dart';
import 'widgets/sliver_app_bar_layer.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.teal,
canvasColor: Colors.transparent,
),
home: DemoScreen(),
);
}
}
class DemoScreen extends StatelessWidget {
static String id = '/demo';
int numberOfColumns(dynamic context) => ((MediaQuery.of(context).size.width - (2 * kBigBoxPadding)) / kMaxCrossAxisExtent).floor();
// Widget _buildGrid() => GridView.extent(
// maxCrossAxisExtent: kMaxCrossAxisExtent,
// padding: const EdgeInsets.all(4),
// mainAxisSpacing: 4,
// crossAxisSpacing: 4,
// children: _buildGridTileList(500));
List<Container> _buildGridTileList(dynamic context, int count) => List.generate(
count,
(i) => Container(
//NOTE: workaround according to: https://github.com/flutter/flutter/issues/25009
decoration: BoxDecoration(
color: colorBackground, //the color of the main container
border: Border.all(
//apply border to only that side where the line is appearing i.e. top | bottom | right | left.
width: 4, //depends on the width of the unintended line
color: colorBackground,
),
),
child: Container(
decoration: BoxDecoration(
color: colorBackground,
),
child: Center(
child: Text(
'$i / ${numberOfColumns(context)}',
style: TextStyle(color: Colors.grey),
//textAlign: TextAlign.center,
),
),
//margin: EdgeInsets.all(0),
),
));
// List<Widget> tabbarViewItems() {
// List<Widget> items = [];
// for (int i = 0; i < 25; i++) {
// Widget listView = _buildGrid();
// items.add(listView);
// }
// return items;
// }
List<Widget> listViewItems() {
List<Widget> items = [];
for (int i = 0; i < 500; i++) {
Widget widgetItem = Text(
'item $i',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
);
items.add(widgetItem);
}
return items;
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 25,
child: Scaffold(
backgroundColor: colorBackground,
//floatingActionButton: MyTabBar(),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
body: Stack(
children: [
Container(
width: double.infinity,
color: Colors.amber,
child: Image.network(
'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80',
fit: BoxFit.cover,
height: MediaQuery.of(context).size.height * kCoverHeightProportion,
),
//color: Colors.green,
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 40,
width: 300,
color: Colors.red,
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(left: kBigBoxPadding, right: kBigBoxPadding, top: kBigBoxPadding, bottom: kBottomBigBoxPadding),
//width: MediaQuery.of(context).size.width * 0.9,
//margin: EdgeInsets.symmetric(horizontal: kBigBoxPadding),
decoration: BoxDecoration(
//color: Colors.pink,
borderRadius: BorderRadius.all(Radius.circular(30)),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(30)),
child: CustomScrollView(
//physics: FixedExtentScrollPhysics(),
anchor: kCoverHeightProportion *
kCoverHeightProportion *
MediaQuery.of(context).size.height /
(kCoverHeightProportion * (MediaQuery.of(context).size.height - kBigBoxPadding - kBottomBigBoxPadding)),
slivers: [
SliverAppBarLayer(
child: Container(
width: double.infinity,
height: 100,
decoration: BoxDecoration(
color: colorBackground, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))),
child: Center(
child: Text(
'La casa de don Juan',
style: TextStyle(color: colorPrimary1, fontSize: 32, fontWeight: FontWeight.w800),
),
),
),
),
SliverGrid.extent(
maxCrossAxisExtent: kMaxCrossAxisExtent,
childAspectRatio: 1,
mainAxisSpacing: 0,
crossAxisSpacing: 0,
children: _buildGridTileList(context, 250),
),
],
),
),
),
),
],
),
),
);
}
}
style_constants.dart
import 'package:flutter/material.dart';
const Color colorShade1 = Color(0xFFEFF0F2);
const Color colorShade2 = Color(0xFF777777);
const Color colorShade3 = Color(0xFF424242);
const Color colorShade4 = Color(0xFF4B4935);
const Color colorShade5 = Color(0xFF3D2916);
const Color colorShade6 = Color(0xFF1D1C0A);
const Color colorBackground = Color(0xFF101A24);
const Color colorPrimary1 = Color(0xFFCC9757);
const double kTabIconHeight = 28;
const double kCoverHeightProportion = 0.35;
const double kBigBoxPadding = 8;
const double kBottomBigBoxPadding = 60;
const double kMaxCrossAxisExtent = 150;
Just use prepared SliverPersistentHeaderDelegate it works from the box...
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.teal,
canvasColor: Colors.transparent,
),
home: DemoScreen(),
);
}
}
class DemoScreen extends StatelessWidget {
static String id = '/demo';
int numberOfColumns(dynamic context) =>
((MediaQuery.of(context).size.width - (2 * kBigBoxPadding)) /
kMaxCrossAxisExtent)
.floor();
// Widget _buildGrid() => GridView.extent(
// maxCrossAxisExtent: kMaxCrossAxisExtent,
// padding: const EdgeInsets.all(4),
// mainAxisSpacing: 4,
// crossAxisSpacing: 4,
// children: _buildGridTileList(500));
List<Container> _buildGridTileList(dynamic context, int count) =>
List.generate(
count,
(i) => Container(
//NOTE: workaround according to: https://github.com/flutter/flutter/issues/25009
decoration: BoxDecoration(
color: colorBackground, //the color of the main container
border: Border.all(
//apply border to only that side where the line is appearing i.e. top | bottom | right | left.
width: 4, //depends on the width of the unintended line
color: colorBackground,
),
),
child: Container(
decoration: BoxDecoration(
color: colorBackground,
),
child: Center(
child: Text(
'$i / ${numberOfColumns(context)}',
style: TextStyle(color: Colors.grey),
//textAlign: TextAlign.center,
),
),
//margin: EdgeInsets.all(0),
),
));
// List<Widget> tabbarViewItems() {
// List<Widget> items = [];
// for (int i = 0; i < 25; i++) {
// Widget listView = _buildGrid();
// items.add(listView);
// }
// return items;
// }
List<Widget> listViewItems() {
List<Widget> items = [];
for (int i = 0; i < 500; i++) {
Widget widgetItem = Text(
'item $i',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
);
items.add(widgetItem);
}
return items;
}
#override
Widget build(BuildContext context) {
var topPadding = kCoverHeightProportion *
kCoverHeightProportion *
MediaQuery.of(context).size.height /
(kCoverHeightProportion *
(MediaQuery.of(context).size.height -
kBigBoxPadding -
kBottomBigBoxPadding));
return DefaultTabController(
length: 25,
child: Scaffold(
backgroundColor: colorBackground,
//floatingActionButton: MyTabBar(),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
body: Stack(
children: [
Container(
width: double.infinity,
color: Colors.amber,
child: Image.network(
'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80',
fit: BoxFit.cover,
height:
MediaQuery.of(context).size.height * kCoverHeightProportion,
),
//color: Colors.green,
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 40,
width: 300,
color: Colors.red,
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(
left: kBigBoxPadding,
right: kBigBoxPadding,
top: kBigBoxPadding,
bottom: kBottomBigBoxPadding),
//width: MediaQuery.of(context).size.width * 0.9,
//margin: EdgeInsets.symmetric(horizontal: kBigBoxPadding),
decoration: BoxDecoration(
//color: Colors.pink,
borderRadius: BorderRadius.all(Radius.circular(30)),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(30)),
child: CustomScrollView(
//physics: FixedExtentScrollPhysics(),
anchor: topPadding,
slivers: [
SliverPadding(
padding: EdgeInsets.only(
top: topPadding,
),
sliver: SliverPersistentHeader(
pinned: true,
floating: false,
delegate: _SliverPersistentHeaderDelegate(
Container(
width: double.infinity,
height: 100,
decoration: BoxDecoration(
color: colorBackground,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30))),
child: Center(
child: Text(
'La casa de don Juan',
style: TextStyle(
color: colorPrimary1,
fontSize: 32,
fontWeight: FontWeight.w800),
),
),
),
),
),
),
SliverGrid.extent(
maxCrossAxisExtent: kMaxCrossAxisExtent,
childAspectRatio: 1,
mainAxisSpacing: 0,
crossAxisSpacing: 0,
children: _buildGridTileList(context, 250),
),
],
),
),
),
),
],
),
),
);
}
}
const Color colorShade1 = Color(0xFFEFF0F2);
const Color colorShade2 = Color(0xFF777777);
const Color colorShade3 = Color(0xFF424242);
const Color colorShade4 = Color(0xFF4B4935);
const Color colorShade5 = Color(0xFF3D2916);
const Color colorShade6 = Color(0xFF1D1C0A);
const Color colorBackground = Color(0xFF101A24);
const Color colorPrimary1 = Color(0xFFCC9757);
const double kTabIconHeight = 28;
const double kCoverHeightProportion = 0.35;
const double kBigBoxPadding = 8;
const double kBottomBigBoxPadding = 60;
const double kMaxCrossAxisExtent = 150;
class _SliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
_SliverPersistentHeaderDelegate(this.child);
final Widget child;
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return child;
}
#override
double get maxExtent => 100;
#override
double get minExtent => 100;
#override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => false;
}
I am creating a Meme generator application in flutter..i just need to know is there a way that user itself can add text over image and drag that text anywhere in the image area...so that the picture would look funny .I tried dragbox widget but dont know how can i use that for textfield..so that i too can move my text anywhere on the image.I need something like this
class TextOverImage extends StatelessWidget {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Text Over Image Image Example'),
),
body: Center(
child: Container(
height: 300,
width: 300,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.blue,
image: DecorationImage(
image: new NetworkImage(
"https://thumbs.dreamstime.com/b/funny-face-baby-27701492.jpg"),
fit: BoxFit.fill)),
),
HomePage()
],
),
),
),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Offset offset = Offset.zero;
#override
Widget build(BuildContext context) {
return Container(
child: Positioned(
left: offset.dx,
top: offset.dy,
child: GestureDetector(
onPanUpdate: (details) {
setState(() {
offset = Offset(
offset.dx + details.delta.dx, offset.dy + details.delta.dy);
});
},
child: SizedBox(
width: 300,
height: 300,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text("You Think You Are Funny But You Are Not",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 28.0,
color: Colors.red)),
),
),
)),
),
);
}
}