Related
I'm new to flutter, and I'm trying to divide the screen into three parts, here's my attempt:
class Homepage extends Statelesswidget {
const HomePage({Key? key}): super (key: key);
#override
Widget build(BuildContext context) {
return Row(children: [
const Expanded(
flex: 1,
child: Scaffold(
body: Center(child: Text("Left")),
), // Scaffold
), // Expanded
Expanded(
flex: 2,
child: Scaffold(
appBar: AppBar(),
body: const Center(child: Text("Middle")),
), // Scaffold
), // Expanded
const Expanded(
flex: 1,
child: Scaffold(
body: Center(child: Text("Right")),
), // Scaffold
) // Expanded
]);
}
}
and main.dart looks like:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomePage(),
debugShowCheckedModeBanner: false,
);
}
}
Here's the result:
I got these vertical lines out of nowhere, how can I get rid of them?
Welcome to Flutter 💙
These lines are the boarders of the Scaffold widget which you are using inside each Expanded widget in the row.
Now intead of looking for a way to remove these border lines, I suggest you to learn more about the Scaffold widget in Flutter
Since you are new to Flutter, you have to be aware with the goal of using Scaffold widget, which is stated in the official docs as the following:
Implements the basic material design visual layout structure.
This class provides APIs for showing drawers and bottom sheets.
So in other words, we use the Scaffold Widget as a basic canvas for the screen with some properties to implement popular layout designs, such as AppBar, BottomNavigationBar, FloatingActionButton, etc...
Then, we use it once in the screen to set the basic layout, and does not required to be used multiple times for each sub part of the screen
Then your HomePage code should be something like:
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(children: [
const Expanded(
flex: 1,
child: Center(child: Text("Left")),
), // Expanded
Expanded(
flex: 2,
child: Column(
children: [
AppBar(),
const Expanded(
child: Center(child: Text("Middle")),
),
],
),
),
const Expanded(
flex: 1,
child: Center(child: Text("Right")),
)
]),
);
}
}
I created an app with image picker and I want to embed a text or image to that selected picture and saved it to gallery.
👇 My App
👇 I tried to create this
This is the code I used for image picker
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Watermark',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
File _pickedImage;
Future pickAnImage() async {
final pickedFile =
await ImagePicker().getImage(source: ImageSource.gallery);
setState(() {
_pickedImage = File(pickedFile.path);
});
}
_saveImage() {
//TODO: Save image to gallery
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text("Flutter Watermark"),
),
body: SingleChildScrollView(
child: Center(
child: Column(
children: <Widget>[
_pickedImage == null
? TextButton(
child: Text("Pick an Image"),
onPressed: pickAnImage,
)
: Column(
children: [
Image.file(_pickedImage),
SizedBox(
height: 50.0,
),
TextButton(
onPressed: _saveImage, child: Text("Save Image"))
],
),
],
),
),
),
),
);
}
}
I followed the below tutorial but it is freeze the app and I couldn't implement it.
Tutorial
https://medium.com/flutter-community/add-watermark-over-image-in-flutter-e7353e3cf603
Can anyone help me please?
You can try using this dependency:
As suggested by the author, this example is similar to your query
import 'dart:io';
import 'package:image/image.dart';
void main() {
// Create an image
Image image = Image(320, 240);
// Draw some text using 24pt arial font
drawString(image, arial_24, 0, 0, 'Hello World');
// Save the image to disk as a PNG
File('test.png').writeAsBytesSync(encodePng(image));
}
Image downloaded from this link.
// I want to use a background image for every page in my Flutter app. For the moment, I'm using a
// separate class BaseLayout to set up the background image. However, flutter does not reflect the
// described the background image on the device.
// Is there a better way to reflect the background image?
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter_svg/flutter_svg.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: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
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> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: CarouselSlider(
options: CarouselOptions(height: 240.0),
items: [1, 2, 3, 4, 5].map((i) {
return Builder(
builder: (BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(color: Colors.amber),
child: Text(
'text $i',
style: TextStyle(fontSize: 16.0),
));
},
);
}).toList(),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class BaseLayout extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/logo1.svg"), fit: BoxFit.cover),
),
child: Center(child: FlutterLogo(size: 300)),
);
}
}````
You have to make your scaffold background transparent, If you are going to use a Base Layout as a parent to all your pages.
You can use scaffoldBackgroundColor property of Scaffold widget to make it transparent.
Or better you can define it your Theme data while you declare your MaterialApp.
Sample Code:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
scaffoldBackgroundColor: Colors.transparent, // To Make scaffold background Transparent
appBarTheme: AppBarTheme(color:Colors.transparent // To Make appbar background transparent.
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
Then on your BaseLayout class:
class BaseLayout extends StatelessWidget {
const BaseLayout({this.child});
final Widget child;
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/logo1.svg"), fit: BoxFit.cover),
),
child: Center(child: child),
);
}
}
Now you can wrap any Scaffold widget of your app with this BaseLayout class you just created and it's background image will be same across whole application.
I tried to wrap it in a Hero widget, as that should achieve what I want. This works with BottomNavigationBar, but not with BottomAppBar, which gives this error: Scaffold.geometryOf() called with a context that does not contain a Scaffold. I tried to give it a context by using Builder, but that did not work either. Here is a sample app to showcase the behaviour:
void main() {
runApp(
MaterialApp(
home: PageOne(),
),
);
}
Widget _bottomNavigationBar() {
return BottomNavigationBar(items: [
BottomNavigationBarItem(icon: Icon(Icons.menu), title: Text('menu')),
BottomNavigationBarItem(icon: Icon(Icons.arrow_back), title: Text('back')),
]);
}
Widget _bottomAppBar() {
return BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(icon: Icon(Icons.menu), onPressed: null),
IconButton(icon: Icon(Icons.arrow_back), onPressed: null),
],
),
);
}
class PageOne extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Hero(
tag: 'bottomNavigationBar',
child: _bottomAppBar(),
),
body: Center(
child: IconButton(
iconSize: 200,
icon: Icon(Icons.looks_two),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageTwo()),
),
),
),
);
}
}
class PageTwo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Hero(
tag: 'bottomNavigationBar',
child: _bottomAppBar(),
),
body: Center(
child: IconButton(
iconSize: 200,
icon: Icon(Icons.looks_one),
onPressed: () => Navigator.pop(context),
),
),
);
}
}
The problem seems to be the animation that is used with the Navigation stack. Therefore, getting rid of the animation during the page load will stop this animation. I added the PageRouteBuilder to the PageOne class in your example to get rid of the Navigation stack animation. Use the code below to replace the PageOne class from your example.
class PageOne extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _bottomAppBar(),
body: Center(
child: IconButton(
iconSize: 200,
icon: Icon(Icons.looks_two),
onPressed: () => Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, anim1, anim2) => PageTwo(),
transitionsBuilder: (context, anim1, anim2, child) =>
Container(child: child),
),
),
),
),
);
}
}
There are additional ways to control the animation for Navigation here
(Oh, and I got rid of the Hero() widget)
I have solved this by wrapping the Row with a Hero widget in BottomAppBar. This still allows page transitions, and does not animate the BottomAppBar as intended.
BottomAppBar(
child: Hero(
tag: 'bottomAppBar',
child: Material(
child: Row(
...
),
),
),
);
However, this has laggy animations when using a CircularNotchedRectangle.
Hamburger icon color of navigation drawer is not changing. Its black by default. I want to change the this icon color in flutter, I am stuck, help me to change this icon color. here is my code.
class Test extends StatefulWidget {
#override
_TestState createState() => new _TestState();
}
class _TestState extends State<Test> {
#override
Widget build(BuildContext context) {
return new Scaffold(
drawer: new Drawer(),
appBar: new AppBar(
title: new Text("Navigation Drawer")
),
),
);
}
}
Add iconTheme to your AppBar
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(),
appBar: AppBar(
title: Text("Navigation Drawer"),
iconTheme: IconThemeData(color: Colors.green),
),
);
}
You can also check other solutions here.
You can also use following in Theme's data property
Theme(
data: ThemeData(primaryIconTheme: IconThemeData(color: Colors.red)), // use this
child: Scaffold(),
)
Or
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.menu, color: Colors.red), // set your color here
onPressed: () {},
),
),
To change color of your icon use this
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: AppBar(title: new Text('List view example'),
leading: new Icon(Icons.menu,color: Colors.green,),
),
),
);
}
Icon(Icons.menu,color: Colors.green,) define color inside Icon
Use iconTheme in Appbar like this:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("App Bar"),
iconTheme: IconThemeData(color: Colors.black),
),
drawer: Drawer(),
);
}
This is the only solution to make the button clickable otherwise you need to openDrawer onTap.
AppBar(
iconTheme: const IconThemeData(
size: 40, //change size on your need
color: Colors.black, //change color on your need
),
),
Using The iconTheme for Appbar is not currently working with useMaterial3 = true, And all these answers defined a leading icon for the Appbar without telling how to implement it's onPress behavior, So the best way to change the Drawers icon or it's color is this :
Declare the key for Scaffold :
final scaffoldKey = GlobalKey<ScaffoldState>();
And apply it to Scaffold:
Scaffold(
key: scaffoldKey,
drawer: Drawer()
)
Then , Apply the drawer icon like below with click action:
AppBar(
title: Text("My AppBar"),
leading: IconButton(
icon: Icon(Icons.person),
onPressed: (){
if(scaffoldKey.currentState!.isDrawerOpen){
scaffoldKey.currentState!.closeDrawer();
//close drawer, if drawer is open
}else{
scaffoldKey.currentState!.openDrawer();
//open drawer, if drawer is closed
}
},
),
)
You can change it from main.dart easily this way-
return MaterialApp(
title: 'XYZ',
debugShowCheckedModeBanner: false,
theme: ThemeData(
appBarTheme: AppBarTheme(
iconTheme: IconThemeData(color: Colors.black),
actionsIconTheme: IconThemeData(color: Colors.blue),
backgroundColor: theme.backgroundColor,
elevation: 0,
),
),