How to Navigate in Same the Page Master Detail page Flutter - flutter

I am building a master detail based app and I want to show in splitview. Trying to understand how to push data to another page in same view but couldn't. Want to cover details data in second page. How to push data?
It could be either responsive or not. But I don't want to resolve but only using set state and fill the blank in details page
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
widget.title,
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: VerticalSplitView(
left: ListView.builder( itemCount: 12,
itemBuilder: (context, index) {
return Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
//Navigator.push(context, MaterialPageRoute(builder: (context) => new yapiekle()) );
},
child: Container(
child: Padding(
padding: EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
//Center Column contents vertically,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: ListTile(
leading: Image.network("https://picsum.photos/200/300"),
title: Text("Title"),
subtitle: Text("Subtitle")),
),
//Spacer(),
],
),
),
),
),
);
}
),
right: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
),
child: Center(
child: FlutterLogo(
size: 256,
)),
),
),
),
);
}
}
class VerticalSplitView extends StatefulWidget {
final Widget left;
final Widget right;
final double ratio;
const VerticalSplitView(
{Key key, #required this.left, #required this.right, this.ratio = 0.5})
: assert(left != null),
assert(right != null),
assert(ratio >= 0),
assert(ratio <= 1),
super(key: key);
#override
_VerticalSplitViewState createState() => _VerticalSplitViewState();
}
class _VerticalSplitViewState extends State<VerticalSplitView> {
final _dividerWidth = 16.0;
//from 0-1
double _ratio;
double _maxWidth;
get _width1 => _ratio * _maxWidth;
get _width2 => (1 - _ratio) * _maxWidth;
#override
void initState() {
super.initState();
_ratio = widget.ratio;
}
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, BoxConstraints constraints) {
assert(_ratio <= 1);
assert(_ratio >= 0);
if (_maxWidth == null) _maxWidth = constraints.maxWidth - _dividerWidth;
if (_maxWidth != constraints.maxWidth) {
_maxWidth = constraints.maxWidth - _dividerWidth;
}
return SizedBox(
width: constraints.maxWidth,
child: Row(
children: <Widget>[
SizedBox(
width: _width1,
child: widget.left,
),
GestureDetector(
behavior: HitTestBehavior.translucent,
child: SizedBox(
width: _dividerWidth,
height: constraints.maxHeight,
child: RotationTransition(
child: Icon(Icons.drag_handle),
turns: AlwaysStoppedAnimation(0.25),
),
),
onPanUpdate: (DragUpdateDetails details) {
setState(() {
_ratio += details.delta.dx / _maxWidth;
if (_ratio > 1)
_ratio = 1;
else if (_ratio < 0.0) _ratio = 0.0;
});
},
),
SizedBox(
width: _width2,
child: widget.right,
),
],
),
);
});
}
}

I assumed that you want to change the the right page by clicking on the left card widgets. I have been developed something like this. I am using IndexedStack for render on the right side of VerticalSplitView then use provider and consumer for controlling the page to display.
First of all you need to import provider dependency in pubspec.ymal
You can replace this code below for entire of main.dart.
In main.dart you can try to replace this code. The idea is we are going to create IndexedStack that contain the Widget (Page as you prefer). Then we are going to change the index of IndexedStack by using Provider and Consumer.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_indexed_stack/page_data.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) {
var pageData = PageData();
return pageData;
}),
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// Set required page same as list length in left of VerticalSplitView
List<Widget> pages = [Text('Page1'), Text('Page2'), Text('Page3'),
Text('Page4'), Text('Page5'), Text('Page6'), Text('Page7'),
Text('Page8'), Text('Page9'), Text('Page10'), Text('Page11'),
Text('Page12'), ];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
widget.title,
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: VerticalSplitView(
left: ListView.builder( itemCount: 12,
itemBuilder: (context, index) {
return Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
// Set the current page for change page on the right side.
Provider.of<PageData>(context, listen: false).setCurrentTab(index);
},
child: Container(
child: Padding(
padding: EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
//Center Column contents vertically,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: ListTile(
leading: Image.network("https://picsum.photos/200/300"),
title: Text("Title"),
subtitle: Text("Subtitle")),
),
//Spacer(),
],
),
),
),
),
);
}
),
right: Consumer<PageData>(
builder: (context, pageData, child) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
),
child: IndexedStack(
children: pages,
index: pageData.currentPage,
)
);
},
),
),
),
);
}
}
class VerticalSplitView extends StatefulWidget {
final Widget left;
final Widget right;
final double ratio;
const VerticalSplitView(
{Key key, #required this.left, #required this.right, this.ratio = 0.5})
: assert(left != null),
assert(right != null),
assert(ratio >= 0),
assert(ratio <= 1),
super(key: key);
#override
_VerticalSplitViewState createState() => _VerticalSplitViewState();
}
class _VerticalSplitViewState extends State<VerticalSplitView> {
final _dividerWidth = 16.0;
//from 0-1
double _ratio;
double _maxWidth;
get _width1 => _ratio * _maxWidth;
get _width2 => (1 - _ratio) * _maxWidth;
#override
void initState() {
super.initState();
_ratio = widget.ratio;
}
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, BoxConstraints constraints) {
assert(_ratio <= 1);
assert(_ratio >= 0);
if (_maxWidth == null) _maxWidth = constraints.maxWidth - _dividerWidth;
if (_maxWidth != constraints.maxWidth) {
_maxWidth = constraints.maxWidth - _dividerWidth;
}
return SizedBox(
width: constraints.maxWidth,
child: Row(
children: <Widget>[
SizedBox(
width: _width1,
child: widget.left,
),
GestureDetector(
behavior: HitTestBehavior.translucent,
child: SizedBox(
width: _dividerWidth,
height: constraints.maxHeight,
child: RotationTransition(
child: Icon(Icons.drag_handle),
turns: AlwaysStoppedAnimation(0.25),
),
),
onPanUpdate: (DragUpdateDetails details) {
setState(() {
_ratio += details.delta.dx / _maxWidth;
if (_ratio > 1)
_ratio = 1;
else if (_ratio < 0.0) _ratio = 0.0;
});
},
),
SizedBox(
width: _width2,
child: widget.right,
),
],
),
);
});
}
}
You need to create file for Provider and replce the code below.
import 'package:flutter/cupertino.dart';
class PageData extends ChangeNotifier{
PageData();
int _currentPage = 0;
void setCurrentTab(int index){
this._currentPage = index;
notifyListeners();
}
int get currentPage {
return this._currentPage;
}
}
Happy coding :)

if I now want to place a button inside the right widget: "add new post". This new-post-function should create a new post by copying all data from current page to the new post with a new post-ID. In the same function it then should navigate into the new post to edit copy of comment in a copy of current post. Like:
ElevatedButton(
onPressed: () {
addPost();
}
)
addPost() {
String newId = uuid.v1();
var newPost = Entry(
id: newId,
entry: entryProvider.comment,
);
firestoreService.setEntry(newPost);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PostScreen(id: newId)));
}

Related

how to perform drag operation on widget with Gesturedetector flutter

I want to drag and drop my custom widget with gesture detector. It is showing x- direction and y- direction values but not dragging to anywhere on screen.
Here is my code:
layoutpage:
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Stack(
children: _layoutProvider.tables
.map(
(SectionTable sTable) => Positioned(
top: sTable.top,
left: sTable.left,
child: LayoutWidget(
width: sTable.width,
height: sTable.height,
type: sTable.type.index,
name: sTable.name,
left: sTable.left,
top: sTable.top,
rotate: sTable.rotate,
color: sTable.order != null
? Colors.green
: Colors.grey,
seats: sTable.seats,
),
),
)
.toList()),
),
LayoutWidget:
class LayoutWidget extends StatefulWidget {
late double width;
late double height;
late double left;
late double top;
LayoutWidget({
Key? key,
required this.width,
required this.height,
required this.left,
required this.top,
}) : super(key: key);
#override
State<StatefulWidget> createState() => _LayoutWidgetState();
}
class _LayoutWidgetState extends State<LayoutWidget> {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RotationTransition(
turns: widget.type == 0
? const AlwaysStoppedAnimation(0)
: AlwaysStoppedAnimation(rotationValue / 360),
child: GestureDetector(
onPanUpdate: (details) {
widget.top = widget.top+ details.delta.dy;
widget.left = widget.left+ details.delta.dx;
setState(() {
});
},
onTap: () {
setState(() {
showMenu = !showMenu;
});
},
child: myWidget()
}
Can anyone help why i am unable to drag on screen. Thanks.
I hope you you can get Idea from this code. In this code you can drag Container anywhere in the Screen and set it. And also check this Gesture Detector Overview for Gesture Detector detail.
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class GestureDetectorPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.grey[100],
width: double.infinity,
height: double.infinity,
child: MainContent(),
),
);
}
}
class MainContent extends StatefulWidget {
#override
_MainContentState createState() => _MainContentState();
}
class _MainContentState extends State<MainContent> {
GlobalKey key = GlobalKey();
String dragDirection = '';
String startDXPoint = '50';
String startDYPoint = '50';
String dXPoint;
String dYPoint;
String velocity;
#override
Widget build(BuildContext context) {
return GestureDetector(
onHorizontalDragStart: _onHorizontalDragStartHandler,
onVerticalDragStart: _onVerticalDragStartHandler,
onHorizontalDragUpdate: _onDragUpdateHandler,
onVerticalDragUpdate: _onDragUpdateHandler,
onHorizontalDragEnd: _onDragEnd,
onVerticalDragEnd: _onDragEnd,
dragStartBehavior: DragStartBehavior.start, // default
behavior: HitTestBehavior.translucent,
child: Stack(
children: [
Positioned(
left: double.parse(this.startDXPoint),
top: double.parse(this.startDYPoint),
child: Container(
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(100)
),
child: Center(
child: Padding(
padding: const EdgeInsets.all(20),
child: Text('Draggable', style: TextStyle(fontSize: 14, color: Colors.white),),
),
),
)
),
],
),
);
}
void _onHorizontalDragStartHandler(DragStartDetails details) {
setState(() {
this.dragDirection = "HORIZONTAL";
this.startDXPoint = '${details.globalPosition.dx.floorToDouble()}';
this.startDYPoint = '${details.globalPosition.dy.floorToDouble()}';
});
}
/// Track starting point of a vertical gesture
void _onVerticalDragStartHandler(DragStartDetails details) {
setState(() {
this.dragDirection = "VERTICAL";
this.startDXPoint = '${details.globalPosition.dx.floorToDouble()}';
this.startDYPoint = '${details.globalPosition.dy.floorToDouble()}';
});
}
void _onDragUpdateHandler(DragUpdateDetails details) {
setState(() {
this.dragDirection = "UPDATING";
this.startDXPoint = '${details.globalPosition.dx.floorToDouble()}';
this.startDYPoint = '${details.globalPosition.dy.floorToDouble()}';
});
}
/// Track current point of a gesture
void _onHorizontalDragUpdateHandler(DragUpdateDetails details) {
setState(() {
this.dragDirection = "HORIZONTAL UPDATING";
this.dXPoint = '${details.globalPosition.dx.floorToDouble()}';
this.dYPoint = '${details.globalPosition.dy.floorToDouble()}';
this.velocity = '';
});
}
/// Track current point of a gesture
void _onVerticalDragUpdateHandler(DragUpdateDetails details) {
setState(() {
this.dragDirection = "VERTICAL UPDATING";
this.dXPoint = '${details.globalPosition.dx.floorToDouble()}';
this.dYPoint = '${details.globalPosition.dy.floorToDouble()}';
this.velocity = '';
});
}
/// What should be done at the end of the gesture ?
void _onDragEnd(DragEndDetails details) {
double result = details.velocity.pixelsPerSecond.dx.abs().floorToDouble();
setState(() {
this.velocity = '$result';
});
}
}
You can use the Draggable widget instead. Please try this
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int acceptedData = 0;
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Draggable<int>(
// Data is the value this Draggable stores.
data: 10,
feedback: Container(
color: Colors.deepOrange,
height: 100,
width: 100,
child: const Icon(Icons.directions_run),
),
childWhenDragging: Container(
height: 100.0,
width: 100.0,
color: Colors.pinkAccent,
child: const Center(
child: Text('Child When Dragging'),
),
),
child: Container(
height: 100.0,
width: 100.0,
color: Colors.lightGreenAccent,
child: const Center(
child: Text('Draggable'),
),
),
),
DragTarget<int>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Container(
height: 100.0,
width: 100.0,
color: Colors.cyan,
child: Center(
child: Text('Value is updated to: $acceptedData'),
),
);
},
onAccept: (int data) {
setState(() {
acceptedData += data;
});
},
),
],
);
}
}

How can I scroll down and focus to a specific widget in flutter?

I am implementing a tutorial of app using https://pub.dev/packages/tutorial_coach_mark . This marked button of beyond the view. So when I need to target this button, I need to scroll/focus this specific part. But I can not find any solution. Can anyone help me with that please?
One Idea is to , Make one Listview with all your widgets . then
Use this :
scroll_to_index: ^2.1.1
Example:
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scroll To Index Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Scroll To Index Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const maxCount = 100;
static const double maxHeight = 1000;
final random = math.Random();
final scrollDirection = Axis.vertical;
late AutoScrollController controller;
late List<List<int>> randomList;
#override
void initState() {
super.initState();
controller = AutoScrollController(
viewportBoundaryGetter: () =>
Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
axis: scrollDirection);
randomList = List.generate(maxCount,
(index) => <int>[index, (maxHeight * random.nextDouble()).toInt()]);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [
IconButton(
onPressed: () {
setState(() => counter = 0);
_scrollToCounter();
},
icon: Text('First'),
),
IconButton(
onPressed: () {
setState(() => counter = maxCount - 1);
_scrollToCounter();
},
icon: Text('Last'),
)
],
),
body: ListView(
scrollDirection: scrollDirection,
controller: controller,
children: randomList.map<Widget>((data) {
return Padding(
padding: EdgeInsets.all(8),
child: _getRow(data[0], math.max(data[1].toDouble(), 50.0)),
);
}).toList(),
),
floatingActionButton: FloatingActionButton(
onPressed: _nextCounter,
tooltip: 'Increment',
child: Text(counter.toString()),
),
);
}
int counter = -1;
Future _nextCounter() {
setState(() => counter = (counter + 1) % maxCount);
return _scrollToCounter();
}
Future _scrollToCounter() async {
await controller.scrollToIndex(counter,
preferPosition: AutoScrollPosition.begin);
controller.highlight(counter);
}
Widget _getRow(int index, double height) {
return _wrapScrollTag(
index: index,
child: Container(
padding: EdgeInsets.all(8),
alignment: Alignment.topCenter,
height: height,
decoration: BoxDecoration(
border: Border.all(color: Colors.lightBlue, width: 4),
borderRadius: BorderRadius.circular(12)),
child: Text('index: $index, height: $height'),
));
}
Widget _wrapScrollTag({required int index, required Widget child}) =>
AutoScrollTag(
key: ValueKey(index),
controller: controller,
index: index,
child: child,
highlightColor: Colors.black.withOpacity(0.1),
);
}
This will work Perfectly
final dataKey = new GlobalKey();
SingleChildScrollView(
child: Column(
children: [
otherwidgets(),
otherwidgets(),
Container(
key: controller.dataKey,
child: helpPart(context),
),
otherwidgets(),
otherwidgets(),
],
),
on action: Scrollable.ensureVisible(dataKey.currentContext!);
This worked for me!

How can I properly remove an OverlayEntry in flutter?

In my main widget tree, I have a GestureDetector that when tapped, will launch an Overlay as follows:
OverlayState? _overlayState = Overlay.of(context);
_overlayState?.insert(
OverlayEntry(
builder: (BuildContext context) {
return ShowNotificationIcon();
},
)
);
SnowNotificationIcon is actually a StatefulWidget that houses the guts of the Overlay:
class ShowNotificationIcon extends ConsumerStatefulWidget {
const ShowNotificationIcon({Key? key}) : super(key: key);
#override
_ShowNotificationIconState createState() => _ShowNotificationIconState();
}
class _ShowNotificationIconState extends ConsumerState<ShowNotificationIcon> {
void initState(){
super.initState();
}
void dispose(){
super.dispose();
}
Positioned theDropDown(){
return
Positioned(
top: 50.0,
left: 50.0,
child: Material(
color: Colors.transparent,
child:
Column(children: [
Text('Test!'),
],)),
);
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned.fill(
child: GestureDetector(
onTap: () {
/// I WANT TO REMOVE THE OVERLAY HERE
},
child: Container(
color: Colors.transparent,
),
)
),
theDropDown()
],
);
}
}
As I understand it, the overlay must be removed via a .remove() call, but since the overlay is all housed within a StatefulWidget, how can I make a .remove call on the overlay when it was opened outside of the StateWidget?
Am I missing something obvious here?
You can try this example I created for you
OverlayState? _overlayState = Overlay.of(context);
OverlayEntry? _overlayEntry;
_overlayEntry = OverlayEntry(
builder: (BuildContext context) {
return ShowNotificationIcon(entry: _overlayEntry);
},
);
_overlayState?.insert(_overlayEntry);
class ShowNotificationIcon extends ConsumerStatefulWidget {
final OverlayEntry? entry;
const ShowNotificationIcon({Key? key, this.entry}) : super(key: key);
#override
_ShowNotificationIconState createState() => _ShowNotificationIconState();
}
class _ShowNotificationIconState extends ConsumerState<ShowNotificationIcon> {
Positioned theDropDown(){
return
Positioned(
top: 50.0,
left: 50.0,
child: Material(
color: Colors.transparent,
child:
Column(children: [
Text('Test!'),
],)),
);
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned.fill(
child: GestureDetector(
onTap: () {
if (widget.entry != null){
widget.entry.remove();
}
},
child: Container(
color: Colors.transparent,
),
)
),
theDropDown()
],
);
}
}
Here, A sample Toast class. I use close button in overlay. You can use similarly.
import 'package:flutter/material.dart';
class AppDialogs {
static final AppDialogs _instance = AppDialogs.internal();
AppDialogs.internal();
factory AppDialogs() => _instance;
static void appToast(
BuildContext context, {
required Widget title,
Widget? description,
Icon? toastIcon,
Color? toastColor,
double? height,
double? width,
bool dismissibleToast = true,
}) async {
final OverlayState? overlayState = Overlay.of(context);
late OverlayEntry overlayEntry;
overlayEntry = OverlayEntry(
builder: (content) => Positioned(
height: height ?? 80,
width: width ?? 200,
top: 0,
right: 0,
child: Card(
borderOnForeground: true,
elevation: 10,
child: Stack(
children: [
ListTile(
tileColor: toastColor,
title: title,
subtitle: description,
leading: toastIcon,
),
Positioned(
top: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () => closeOverlay(overlayEntry),
child: const Icon(
Icons.close,
size: 14,
),
),
),
),
],
))),
);
overlayState!.insert(overlayEntry);
}
static void closeOverlay(OverlayEntry overlayEntry) {
{
overlayEntry.remove();
}
}
}
class _LoginViewState extends State<LoginView> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
TextButton(
child: Text("Login"),
onPressed: (() {
AppDialogs.appToast(context, title: Text("Toast"));
}),
)
],
),
);
}

How to add watermark over all screens in flutter app

Most search results showed adding watermarks to images .. what i need is to add text watermark to the whole app that covers all screens or pages of the app.. such as (beta version) or (student version) so as to avoid screenshots of not yet ready version of the app.
You can use this class:
class Watarmark extends StatelessWidget {
final int rowCount;
final int columnCount;
final String text;
const Watarmark(
{Key key,
#required this.rowCount,
#required this.columnCount,
#required this.text})
: super(key: key);
#override
Widget build(BuildContext context) {
return IgnorePointer(
child: Container(
child: Column(
children: creatColumnWidgets(),
)),
);
}
List<Widget> creatRowWdiges() {
List<Widget> list = [];
for (var i = 0; i < rowCount; i++) {
final widget = Expanded(
child: Center(
child: Transform.rotate(
angle: pi / 10,
child: Text(
text,
style: TextStyle(
color: Color(0x08000000),
fontSize: 18,
decoration: TextDecoration.none),
),
)));
list.add(widget);
}
return list;
}
List<Widget> creatColumnWidgets() {
List<Widget> list = [];
for (var i = 0; i < columnCount; i++) {
final widget = Expanded(
child: Row(
children: creatRowWdiges(),
));
list.add(widget);
}
return list;
}
}
and use by this as a widget:
OverlayEntry _overlayEntry;
void addWatermark(BuildContext context, String watermark,
{int rowCount = 3, int columnCount = 10}) async {
if (_overlayEntry != null) {
_overlayEntry.remove();
}
OverlayState overlayState = Overlay.of(context);
_overlayEntry = OverlayEntry(
builder: (context) => Watarmark(
rowCount: rowCount,
columnCount: columnCount,
text: watermark,
));
overlayState.insert(_overlayEntry);
// return await _methodChannel.invokeMethod<void>("addWatermark", ['I am a watermark']);
}
Here's an example of how you can use Overlay to add something on top of you whole flutter app
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _navigatorKey = GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: WillPopScope(
onWillPop: () async => !await _navigatorKey.currentState.maybePop(),
child: LayoutBuilder(
builder: (context, constraints) {
WidgetsBinding.instance.addPostFrameCallback((_) => _insertOverlay(context));
return Navigator(
key: _navigatorKey,
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/page2':
return MaterialPageRoute(builder: (_) => Page2());
default:
return MaterialPageRoute(builder: (_) => Page1(_navigatorKey));
}
},
);
},
),
),
);
}
void _insertOverlay(BuildContext context) {
return Overlay.of(context).insert(
OverlayEntry(builder: (context) {
final size = MediaQuery.of(context).size;
return Positioned(
width: 130,
height: 50,
top: size.height - 200,
left: size.width - 200,
child: Material(
color: Colors.transparent,
child: GestureDetector(
onTap: () => print('ON TAP OVERLAY!'),
child: Center (child: Container(
decoration: BoxDecoration(color: Colors.redAccent),
child: Text('BETA VERSION')
),)
),
),
);
}),
);
}
}
class Page1 extends StatelessWidget {
final GlobalKey<NavigatorState> navigatorKey;
Page1(this.navigatorKey);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.green[200],
appBar: AppBar(title: Text('Page1')),
body: Container(
alignment: Alignment.center,
child: TextButton(
child: Text('go to Page2'),
onPressed: () => navigatorKey.currentState.pushNamed('/page2'),
),
),
);
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.yellow[200],
appBar: AppBar(title: Text('back to Page1')),
body: Container(
alignment: Alignment.center,
child: Text('Page 2'),
),
);
}
}
class WatermarkLogo extends StatelessWidget {
const WatermarkLogo({super.key, required this.child});
final Widget child;
#override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
Positioned.fill(child: child),
IgnorePointer(
child: Center(
child: Opacity(
opacity: 0.025,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 50,
),
child: Image.asset('assets/logo.png')),
)))
],
);
}
}

How change the Icon of an IconButton when it is pressed

I want to know how I can change the Icon of an IconButton when it is pressed. (Favorite_border to Favorite). I tried somethings but it doesn't works.
Maybe it is easy but I am a beginner and I don't understand very well how it is works.
Update
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../recyclerview/data.dart';
import 'package:watch/constants.dart';
int itemCount = item.length;
List<bool> selected = new List<bool>();
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
initState() {
for (var i = 0; i < itemCount; i++) {
selected.add(false);
}
super.initState();
}
Icon notFavorite = Icon(Icons.favorite_border, size: 25,);
Icon inFavorite = Icon(Icons.favorite, size: 25,);
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Accueil', style: kAppBarStyle,),
//backgroundColor: Colors.white,
elevation: 0,
),
body: ListView.builder(
itemCount: itemCount,
itemBuilder: (BuildContext context, int index) {
return Container(
child: new Row(
children: <Widget>[
//Image
new Container(
margin: new EdgeInsets.all(5.0),
child: new CachedNetworkImage(
imageUrl: item[index].imageURL,
height: MediaQuery.of(context).size.width / 4,
width: MediaQuery.of(context).size.width / 2,
fit: BoxFit.cover,
),
),
//Text
Expanded(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Spacer(),
//Titre
Container(
padding: const EdgeInsets.only(bottom: 75.0, top: 10.0 ),
child: Text(
item[index].title,
style: kItemTitle,
),
),
//Decription
Container(
padding: const EdgeInsets.only(left: 10.0, top: 10.0),
child:Text(
item[index].description,
style: kItemDescription,
),
),
//Favoris
Spacer(),
GestureDetector(
child: Container(
padding: const EdgeInsets.only(right: 10.0, top: 3.0),
child: selected.elementAt(index) ? inFavorite : notFavorite,
),
onTap: () {
setState(() {
selected[index] = !selected.elementAt(index);
});
},
),
],
),
),
],
),
);
}
)
);
}
}
It is a ListView with Images, Texts and the Favorite Button and it works fine.
First you need a boolean variable.
bool toggle = false;
After that you can use IconButton like this:
IconButton(
icon: toggle
? Icon(Icons.favorite_border)
: Icon(
Icons.favorite,
),
onPressed: () {
setState(() {
// Here we changing the icon.
toggle = !toggle;
});
}),
custom radio button (some IconButton in ListView that change their icons):
main.dart file :
import 'package:flutter/material.dart';
import 'my_home_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
my_home_page.dart file:
import 'package:flutter/material.dart';
int itemCount = 5;
List<bool> selected = new List<bool>();
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
initState() {
for (var i = 0; i < itemCount; i++) {
selected.add(false);
}
super.initState();
}
Icon firstIcon = Icon(
Icons.radio_button_on, // Icons.favorite
color: Colors.blueAccent, // Colors.red
size: 35,
);
Icon secondIcon = Icon(
Icons.radio_button_unchecked, // Icons.favorite_border
color: Colors.grey,
size: 35,
);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ListView.builder(
itemCount: itemCount,
itemBuilder: (BuildContext context, int index) {
return IconButton(
icon: selected.elementAt(index) ? firstIcon : secondIcon,
onPressed: () {
try {
// your code that you want this IconButton do
setState(() {
selected[index] = !selected.elementAt(index);
});
print('tap on ${index + 1}th IconButton ( change to : ');
print(selected[index] ? 'active' : 'deactive' + ' )');
} catch (e) {
print(e);
}
},
);
}),
),
);
}
}
Copy paste the code and it will work :)
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: HomeApp(),
);
}
}
class HomeApp extends StatefulWidget {
#override
_HomeAppState createState() => _HomeAppState();
}
class _HomeAppState extends State<HomeApp> {
// Using a Bool
bool addFavorite = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter App :)"),
),
body: Center(
child: IconButton(
icon: Icon(addFavorite ? Icons.favorite : Icons.favorite_border),
onPressed: () {
// Setting the state
setState(() {
addFavorite = !addFavorite;
});
}),
),
);
}
}
Updating the Code for ListView
class _HomeAppState extends State<HomeApp> {
// Using a Bool List for list view builder
List<bool> addFavorite = List<bool>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter App :)"),
),
body: ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
// Setting a bool initially
addFavorite.add(false);
return IconButton(
icon: Icon(addFavorite.elementAt(index)
? Icons.favorite
: Icons.favorite_border),
onPressed: () {
// Setting the state
setState(() {
// Changing icon of specific index
addFavorite[index] =
addFavorite[index] == false ? true : false;
});
});
}),
);
}
}
the IconButton must be in StatefulWidget and use a flag for unselected icon and selected icon:
.
.
.
bool selected = false;
Icon first_icon = Icon(...);
Icon second_icon = Icon(...);
.
.
.
IconButton(
icon: selected
? first_icon
: second_icon,
onPressed: () {
try {
// your code that you want this IconButton do
setState(() {
selected = !selected;
});
} catch(e) {
print(e);
}
}),
for use in ListView:
.
.
.
List<bool> selected = new List<bool>();
Icon first_icon = Icon(...);
Icon second_icon = Icon(...);
.
.
.
ListView.builder(
controller: scrollController,
primary: true,
...
itemCount: _yourListViewLength,
itemBuilder: (BuildContext context, int i) {
selected.add(false);
IconButton(
icon: selected.elementAt(i)
? first_icon
: second_icon,
onPressed: () {
try {
// your code that you want this IconButton do
setState(() {
selected.elementAt(i) = !selected.elementAt(i);
});
} catch(e) {
print(e);
}
}),
},
)
i hope this help you
My code if you want : home_screen.dart
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../recyclerview/data.dart';
import 'package:watch/constants.dart';
class ListViewExample extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new ListViewExampleState();
}
}
class ListViewExampleState extends State<ListViewExample>{
bool addFavorite = false;
Icon notFavorite = Icon(Icons.favorite_border, size: 25,);
Icon inFavorite = Icon(Icons.favorite, size: 25,);
List<Container> _buildListItemsFromItems(){
return item.map((item){
var container = Container(
child: new Row(
children: <Widget>[
//Image
new Container(
margin: new EdgeInsets.all(5.0),
child: new CachedNetworkImage(
imageUrl: item.imageURL,
height: MediaQuery.of(context).size.width / 4,
width: MediaQuery.of(context).size.width / 2,
fit: BoxFit.cover,
),
),
//Text
Expanded(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Spacer(),
//Titre
Container(
padding: const EdgeInsets.only(bottom: 75.0, top: 5.0 ),
child: Text(
item.title,
style: kItemTitle,
),
),
//Decription
Container(
padding: const EdgeInsets.only(left: 10.0, top: 5.0),
child:Text(
item.description,
style: kItemDescription,
),
),
//Favoris
Spacer(),
GestureDetector(
child: Container(
padding: const EdgeInsets.only(right: 10.0, top: 1.0),
child: addFavorite ? inFavorite : notFavorite,
),
onTap: () {
setState(() {
addFavorite = !addFavorite;
});
},
),
],
),
),
],
),
);
return container;
}).toList();
}
//Scaffold Global
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Accueil', style: kAppBarStyle,),
//backgroundColor: Colors.white,
elevation: 0,
),
body: ListView(
children: _buildListItemsFromItems(),
),
);
}
}
It is not an IconButton but just an Icon but it is working.