how to make a container draggable in horizontal direction in flutter - flutter

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

Related

Position widgets in orbit around another widget in Flutter

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

how to display a dragged container inside another container when dragged into it in flutter

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 can make listview builder to a reorderable listview in flutter (a priority task app (todo app))

how can i convert listview to reorderedableListview to make a priority task app
this is my application design output
i see many solutions but in most of them i found error
Here is initstate code
class _TodoListScreenState extends State<TodoListScreen> {
late List<Task> taskList = [];
#override
void initState() {
super.initState();
_updateTaskList();
}
_updateTaskList() async {
print('--------->update');
this.taskList = await DatabaseHelper.instance.getTaskList();
print(taskList);
setState(() {});
}
this is method where listtile created
Widget _buildTask(Task task) {
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: ListTile(
title: Text(
task.title!,
style: TextStyle(
fontSize: 18.0,
decoration: task.status == 0
? TextDecoration.none
: TextDecoration.lineThrough,
),
),
subtitle: Text(
'${DateFormat.yMMMEd().format(task.date!)} • ${task.priority}',
style: TextStyle(
fontSize: 18.0,
decoration: task.status == 0
? TextDecoration.none
: TextDecoration.lineThrough,
),
),
trailing: Checkbox(
onChanged: (value) {
task.status = value! ? 1 : 0;
DatabaseHelper.instance.updateTask(task);
_updateTaskList();
},
value: task.status == 1 ? true : false,
activeColor: Theme.of(context).primaryColor,
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddTask(
task: task,
updateTaskList: () {
_updateTaskList();
},
),
),
),
),
),
Divider(),
],
);
}
this is method build
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
backgroundColor: Theme.of(context).primaryColor,
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddTask(updateTaskList: _updateTaskList),
),
),
),
in this body tag i want to create reorderable listview
body: ListView.builder(
padding: EdgeInsets.symmetric(vertical: 80.0),
itemCount: taskList.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"My Tasks",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 40.0,
color: Colors.black),
),
SizedBox(height: 15.0),
Text(
'${taskList.length} of ${taskList.where((Task task) => task.status == 1).toList().length} task complete ',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 20.0,
color: Colors.grey,
),
),
],
),
);
} else {
return _buildTask(taskList[index - 1]);
}
},
),
);
}
}
this is whole code i want to change
There is a widget like ReorderableListView and library like Reorderables are available that you can use.
Updated
Sample Code:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:reorderables/reorderables.dart';
class ReorderablesImagesPage extends StatefulWidget {
ReorderablesImagesPage({
Key key,
this.title,
#required this.size,
}) : super(key: key);
final String title;
final double size;
#override
State<StatefulWidget> createState() => _ReorderablesImagesPageState();
}
class _ReorderablesImagesPageState extends State<ReorderablesImagesPage> {
List<Widget> _tiles;
int maxImageCount = 30;
double iconSize;
final int itemCount = 3;
final double spacing = 8.0;
final double runSpacing = 8.0;
final double padding = 8.0;
#override
void initState() {
super.initState();
iconSize = ((widget.size - (itemCount - 1) * spacing - 2 * padding) / 3)
.floor()
.toDouble();
_tiles = <Widget>[
Container(
child: Image.network('https://picsum.photos/250?random=1'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=2'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=3'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=4'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=5'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=6'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=7'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=8'),
width: iconSize,
height: iconSize,
),
Container(
child: Image.network('https://picsum.photos/250?random=9'),
width: iconSize,
height: iconSize,
),
];
}
#override
Widget build(BuildContext context) {
void _onReorder(int oldIndex, int newIndex) {
setState(() {
Widget row = _tiles.removeAt(oldIndex);
_tiles.insert(newIndex, row);
});
}
var wrap = ReorderableWrap(
minMainAxisCount: itemCount,
maxMainAxisCount: itemCount,
spacing: spacing,
runSpacing: runSpacing,
padding: EdgeInsets.all(padding),
children: _tiles,
onReorder: _onReorder,
onNoReorder: (int index) {
//this callback is optional
debugPrint(
'${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index');
},
onReorderStarted: (int index) {
//this callback is optional
debugPrint(
'${DateTime.now().toString().substring(5, 22)} reorder started: index:$index');
});
var column = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: SingleChildScrollView(
child: wrap,
),
),
ButtonBar(
buttonPadding: EdgeInsets.all(16),
alignment: MainAxisAlignment.end,
children: <Widget>[
if (_tiles.length > 0)
IconButton(
iconSize: 50,
icon: Icon(Icons.remove_circle),
color: Colors.teal,
padding: const EdgeInsets.all(0.0),
onPressed: () {
setState(() {
_tiles.removeAt(0);
});
},
),
if (_tiles.length < maxImageCount)
IconButton(
iconSize: 50,
icon: Icon(Icons.add_circle),
color: Colors.deepOrange,
padding: const EdgeInsets.all(0.0),
onPressed: () {
var rand = Random();
var newTile = Container(
child: Image.network(
'https://picsum.photos/250?random=${rand.nextInt(100)}'),
width: iconSize,
height: iconSize,
);
setState(() {
_tiles.add(newTile);
});
},
),
],
),
],
);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: column,
);
}
}

setState() or markNeedsBuild() called during build. when call native ad

import 'package:facebook_audience_network/ad/ad_native.dart';
import 'package:facebook_audience_network/facebook_audience_network.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:social_share/social_share.dart';
import 'package:clipboard_manager/clipboard_manager.dart';
// ignore: camel_case_types
class listview extends StatefulWidget {
const listview({
Key key,
#required this.records,
}) : super(key: key);
final List records;
#override
_listviewState createState() => _listviewState();
}
// ignore: camel_case_types
class _listviewState extends State<listview> {
#override
void initState() {
super.initState();
FacebookAudienceNetwork.init(
testingId: "35e92a63-8102-46a4-b0f5-4fd269e6a13c",
);
// _loadInterstitialAd();
// _loadRewardedVideoAd();
}
// ignore: unused_field
Widget _currentAd = SizedBox(
width: 0.0,
height: 0.0,
);
Widget createNativeAd() {
_showNativeAd() {
_currentAd = FacebookNativeAd(
adType: NativeAdType.NATIVE_AD,
backgroundColor: Colors.blue,
buttonBorderColor: Colors.white,
buttonColor: Colors.deepPurple,
buttonTitleColor: Colors.white,
descriptionColor: Colors.white,
width: double.infinity,
height: 300,
titleColor: Colors.white,
listener: (result, value) {
print("Native Ad: $result --> $value");
},
);
}
return Container(
width: double.infinity,
height: 300,
child: _showNativeAd(),
);
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: this.widget.records.length,
itemBuilder: (BuildContext context, int index) {
var card = Container(
child: Card(
margin: EdgeInsets.only(bottom: 10),
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(1.0),
),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
print(this.widget.records);
},
child: Image.asset(
"assets/icons/avatar.png",
height: 45,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
(this
.widget
.records[index]['fields']['Publisher Name']
.toString()),
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
(this
.widget
.records[index]['fields']['Date']
.toString()),
style: TextStyle(
fontSize: 12,
),
),
],
),
)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.90,
// height: MediaQuery.of(context).size.height * 0.20,
decoration: BoxDecoration(
border: Border.all(
color: Colors.purple,
width: 3.0,
),
),
child: Center(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Text(
(this
.widget
.records[index]['fields']['Shayari']
.toString()),
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
GestureDetector(
onTap: () {
ClipboardManager.copyToClipBoard(this
.widget
.records[index]['fields']['Shayari']
.toString())
.then((result) {
final snackBar = SnackBar(
content: Text('Copied to Clipboard'),
);
Scaffold.of(context).showSnackBar(snackBar);
});
print(this
.widget
.records[index]['fields']['Shayari']
.toString());
},
child: Image.asset(
"assets/icons/copy.png",
height: 25,
),
),
GestureDetector(
onTap: () async {
SocialShare.checkInstalledAppsForShare().then(
(data) {
print(data.toString());
},
);
},
child: Image.asset(
"assets/icons/whatsapp.png",
height: 35,
),
),
GestureDetector(
onTap: () async {
Share.share("Please Share https://google.com");
},
child: Image.asset(
"assets/icons/share.png",
height: 25,
),
),
],
),
SizedBox(
height: 5,
),
],
),
),
);
return Column(
children: [
card,
index != 0 && index % 5 == 0
? /* Its Show When Value True*/ createNativeAd()
: /* Its Show When Value false*/ Container()
],
);
},
);
}
}
I Am Having This Error setState() or markNeedsBuild() called during build.
I Try To Call Facebook Native Ads Between My Dynamic List View But Showing this error when I call native ad createNativeAd This is My Widget Where I set Native ad
This is code where I call ad
** return Column(
children: [
card,
index != 0 && index % 5 == 0
? /* Its Show When Value True*/ createNativeAd()
: /* Its Show When Value false*/ Container()
],
);
},
);**

how to overlap items on Appbar flutter

I want to achieve have a round icon for the profile image like in this example:
But is not working for me, this is what I achieved so far:
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: _AppBarProfileClipper(childHeight),
child: Container(
padding: const EdgeInsets.only(top: 48.0),
color: TheBaseColors.lightBlue,
height: height,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
leading,
FlatButton(
onPressed: null,
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18.0,
color: Colors.white,
),
),
),
trailing,
],
),
),
),
Positioned(
bottom: childHeight / 2, //50
left: 0,
right: 0,
child: Align(
alignment: Alignment.bottomCenter,
child: child,
),
),
],
);
}
}
All the parameters are represented in the constructor and used in the code. But I cant figure out how to make that nice effect with the rounded icon.
Someone knows why is not working?
You can achieve given example like this:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final double appBarHeight = 100.0;
final double spaceAroundRoundButton = 4.0;
final double roundedButtonSize = 64.0;
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return SafeArea(
child: Stack(
children: <Widget>[
Scaffold(
backgroundColor: Colors.white,
appBar: PreferredSize(
preferredSize:
Size(MediaQuery.of(context).size.width, appBarHeight),
child: ClipPath(
clipper: BottomClipper(),
child: Container(
alignment: Alignment.topLeft,
height: appBarHeight,
color: Colors.black,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
),
onPressed: () {}),
Text(
'User Profile',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {})
],
),
),
)),
body: Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(
top:
roundedButtonSize * 0.75 + spaceAroundRoundButton + 16.0),
child: Text('Body'),
),
),
Positioned(
child: Container(
padding: EdgeInsets.all(spaceAroundRoundButton),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: RawMaterialButton(
elevation: 0,
constraints: BoxConstraints.tightFor(
width: roundedButtonSize, height: roundedButtonSize),
shape: StadiumBorder(
side: BorderSide(width: 4, color: Colors.grey)),
child: Icon(Icons.person),
onPressed: () {},
fillColor: Colors.white,
),
),
left: (size.width / 2) -
(roundedButtonSize / 2) -
spaceAroundRoundButton,
top: appBarHeight -
(roundedButtonSize * 0.25) -
spaceAroundRoundButton,
)
],
),
);
}
}
class BottomClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.lineTo(0.0, size.height * 0.75);
var firstControlPoint = Offset(size.width * 0.25, size.height);
var firstEndPoint = Offset(size.width * 0.5, size.height);
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstEndPoint.dx, firstEndPoint.dy);
var secondControlPoint = Offset(size.width * 0.75, size.height);
var secondEndPoint = Offset(size.width, size.height * 0.75);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondEndPoint.dx, secondEndPoint.dy);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Screenshot: