class AddResultPage extends StatelessWidget {
const AddResultPage({
Key? key,
required this.faceImage,
required this.faceName,
}) : super(key: key);
final File? faceImage;
final String faceName;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
faceImage == null ? Container() : Image.file(faceImage!),
// ignore: prefer_const_constructors
CircleAvatar(
radius: 50,
foregroundImage: ,
),
Text(faceName),
how insert image in CircleAvatar?
i don't know why it is wrong.......
foregroundImage: faceImage,
i don't know how to use CircleAvatar, file path....
please help....
You can't insert a file as an Image, what you can do though is to use
FileImageCircleAvatar(
..
foregroundImage: FileImage(widget.faceImage),
),
You are trying to assign the file into the foregroundImage which expects an Image Provider. Since you are trying to display the image from file, you should use FileImage(imageFIle)
CircleAvatar(
radius: 50,
foregroundImage: FileImage(faceImage),
backgroundColor: Colors.transparent,
)
I solved it!!
const SizedBox(height: bigSpace),
Center(
child: CircleAvatar(
radius: 80,
foregroundImage: FileImage(faceImage!)
//faceImage == null ? Container() : Image.file(faceImage!),
),
),
Related
Hello everybody working on a project and get this code from a repo and have some types errors and I cant understand them because I cant have the knowledge to solve and I didnt find nothing on google about these errors.
The problem is the #require this.#property and error as null value. I cant understand the problem, can explain me the problem?
Home Widget
class Home extends StatelessWidget {
const Home({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
AppColors.backgroundFadedColor,
AppColors.backgroundColor,
],
stops: [0.0, 1],
),
),
),
SafeArea(
child: _TodoListContent(
todos: fakeData,
),
),
const Align(
alignment: Alignment.bottomRight,
child: AddTodoButton(),
)
],
),
);
}
}
class _TodoListContent extends StatelessWidget {
const _TodoListContent({
Key? key,
#required this.todos,
}) : super(key: key);
final List<Todo> todos;
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: todos.length,
padding: const EdgeInsets.all(16),
itemBuilder: (context, index) {
final _todo = todos[index];
return _TodoCard(todo: _todo);
},
);
}
}
class _TodoCard extends StatelessWidget {
const _TodoCard({
Key? key,
#required this.todo,
}) : super(key: key);
final Todo todo;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
HeroDialogRoute(
builder: (context) => Center(
child: _TodoPopupCard(todo: todo),
),
),
);
},
child: Hero(
tag: todo.id,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Material(
color: AppColors.cardColor,
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
_TodoTitle(title: todo.description),
const SizedBox(
height: 8,
),
if (todo.items.length != 0) ...[
const Divider(),
_TodoItemsBox(items: todo.items),
]
],
),
),
),
),
),
);
}
}
class _TodoTitle extends StatelessWidget {
const _TodoTitle({
Key? key,
#required this.title,
}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
);
}
}
class _TodoPopupCard extends StatelessWidget {
const _TodoPopupCard({Key key, this.todo}) : super(key: key);
final Todo todo;
#override
Widget build(BuildContext context) {
return Hero(
tag: todo.id,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Material(
borderRadius: BorderRadius.circular(16),
color: AppColors.cardColor,
child: SizedBox(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_TodoTitle(title: todo.description),
const SizedBox(
height: 8,
),
if (todo.items.length != 0) ...[
const Divider(),
_TodoItemsBox(items: todo.items),
],
Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.black12,
borderRadius: BorderRadius.circular(8),
),
child: const TextField(
maxLines: 8,
cursorColor: Colors.white,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
hintText: 'Write a note...',
border: InputBorder.none),
),
),
],
),
),
),
),
),
),
);
}
}
class _TodoItemsBox extends StatelessWidget {
const _TodoItemsBox({
Key? key,
#required this.items,
}) : super(key: key);
final List<Item> items;
#override
Widget build(BuildContext context) {
return Column(
children: [
for (final item in items) _TodoItemTile(item: item),
],
);
}
}
class _TodoItemTile extends StatefulWidget {
const _TodoItemTile({
Key? key,
#required this.item,
}) : super(key: key);
final Item item;
#override
_TodoItemTileState createState() => _TodoItemTileState();
}
class _TodoItemTileState extends State<_TodoItemTile> {
void _onChanged(bool val) {
setState(() {
widget.item.completed = val;
});
}
#override
Widget build(BuildContext context) {
return ListTile(
leading: Checkbox(
onChanged: _onChanged,
value: widget.item.completed,
),
title: Text(widget.item.description),
);
}
}
On classes properties #required this.# error: The parameter '#' can't have a value of 'null' because of its type, but the implicit default value is 'null'. Try adding either an explicit non-'null' default value or the 'required' modifier.
Models file
import 'package:meta/meta.dart';
class Todo {
const Todo({
#required this.id,
#required this.description,
this.items,
});
final String id;
final String description;
final List<Item> items;
}
class Item {
Item({
#required this.id,
this.description = '',
this.completed = false,
});
final String id;
final String description;
bool completed;
}
On code
Todo
#required this.id,
#required this.description,
this.items,
and
Item
#required this.id,
error: The parameter '#' can't have a value of 'null' because of its type, but the implicit default value is 'null'. Try adding either an explicit non-'null' default value or the 'required' modifier.
TLDR: change #required => required
You are working with "null safety" enabled. This is a good thing, and helps avoid bugs by catching them at compile time.
In Todo, you have a field final String id;. With null safety enabled, null is not a valid value for a String (i.e. String id = null; is a compile time error).
This means that you can safely call methods on id without worrying about it being null, but it also means you must give it a value.
Consider:
final todo = Todo();
print(todo.id); // what happens here?
If the compiler allowed your code, this would print "null". But id is a String, not a String? (a nullable string), so this can't be allowed.
The main issue you are facing is the use of #required rather than just required. #required is a metadata annotation, that allows development tools (e.g. your IDE) to give helpful warnings.
On the other hand, required is a language keyword (when null safety is enabled). If you have a non-null named parameter, you must either:
mark it as required so it is a compile time error if you fail to provide it
give it a default value, so it will be non-null even if you don't provide it.
I'm new to Flutter, I have a requirement where I need to place a RaisedButton at the edge of an image as shown in the below screenshot(because of privacy, I covered the content on the mockup)
I tried by changing the padding but it's not working with all the devices in iOS and Android. Please help me out to achieve this for all kind of devices present in iOS and Android.
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.orange.shade200,
body: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.asset('assets/images/pngs/cake.png'),
SizedBox(
height: 25,
)
],
),
RaisedButton(
onPressed: () {},
child: Text("sample button"),
),
],
),
);
}
}
gives
EDIT: One of the non-hacky ways to do this.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
final sm = 100.0, lg = 200.0;
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
width: lg,
height: lg,
alignment: FractionalOffset.bottomCenter +
FractionalOffset.fromOffsetAndSize(
Offset(0, sm / 2),
Size(sm, sm),
),
child: Container(
color: Colors.blue,
width: sm,
height: sm,
),
);
}
}
Did you try Stack in Flutter ?
I new to flutter and i have a counter button that i want to prevent it from multiple touch.
The Tap Function is defined under Inkwell component (onTap: () => counterBloc.doCount(context)).
if i run this apps and doing multi touch, counter will go up quickly, but i dont want it happen. any idea ?
below are my code :
Expanded(
child: Container(
padding: EdgeInsets.only(right: 16),
alignment: Alignment.centerRight,
child: InkWell(
onTap: () => counterBloc.doCount(context),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Image.asset("assets/images/home/tap.png", scale: 11,),
StreamBuilder(
initialData: 0,
stream: counterBloc.counterStream,
builder: (BuildContext ctx, AsyncSnapshot<int> snapshot){
return Text("${snapshot.data}",style: TextStyle(color: Colors.white, fontSize: 120),);
},
),
],
)
)
)
)
you can use an AbsorbPointer
AbsorbPointer(
absorbing: !enabled,
child: InkWell(
onTap: (){
print('buttonClicked');
setState(() {
enabled = false;
});
},
child: Container(
width: 50.0,
height: 50.0,
color: Colors.red,
),
),
),
and when you want to enable the button again, set the enabled to true, don't forget to wrap it with a setState
Try this? It should solve your problem.
class SafeOnTap extends StatefulWidget {
SafeOnTap({
Key? key,
required this.child,
required this.onSafeTap,
this.intervalMs = 500,
}) : super(key: key);
final Widget child;
final GestureTapCallback onSafeTap;
final int intervalMs;
#override
_SafeOnTapState createState() => _SafeOnTapState();
}
class _SafeOnTapState extends State<SafeOnTap> {
int lastTimeClicked = 0;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
final now = DateTime.now().millisecondsSinceEpoch;
if (now - lastTimeClicked < widget.intervalMs) {
return;
}
lastTimeClicked = now;
widget.onSafeTap();
},
child: widget.child,
);
}
}
You can wrap any kind of widget if you want.
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
// every click need to wait for 500ms
SafeOnTap(
onSafeTap: () => log('500ms'),
child: Container(
width: double.infinity,
height: 200,
child: Center(child: Text('500ms click me')),
),
),
// every click need to wait for 2000ms
SafeOnTap(
intervalMs: 2000,
onSafeTap: () => log('2000ms'),
child: Container(
width: double.infinity,
height: 200,
child: Center(child: Text('2000ms click me')),
),
),
],
),
),
),
);
}
}
Another option is to use debouncing to prevent this kind of behaviour ie with easy_debounce, or implementing your own debounce.
You can also use IgnorePointer
IgnorePointer(
ignoring: !isEnabled
child: yourChildWidget
)
And when you disable the component, it starts ignoring the touches within the boundary of the widget.
I personally wouldn't rely on setState, I'd go with a simple solution like this:
Widget createMultiClickPreventedButton(String text, VoidCallback clickHandler) {
var clicked = false;
return ElevatedButton(
child: Text(text),
onPressed: () {
if (!clicked) {
clicked = true;
clickHandler.call();
}
});
}
You can also use a Stream to make counter to count only on debounced taps.
final BehaviourSubject onTapStream = BehaviourSubject()
#override
void initState() {
super.initState();
// Debounce your taps here
onTapStream.debounceTime(const Duration(milliseconds: 300)).listen((_) {
// Do something on tap
print(1);
});
}
I'm building a Flutter app, mainly for iOS.
One of my views has a text field, and iOS keyboard appears when you tap on it. The problem is - layout does not change smoothly like it does in native iOS apps. Instead, it instantly jumps to the final available screen height even before keyboard opening animation finishes.
I tried wrapping my SafeArea element in AnimatedSize and AnimatedContainer - it didn't help.
My layout code:
SafeArea(child:
Column(children:[
TextField(...)
])
)
How can I make the layout resize smoothly when the keyboard appears?
Expected:
Actual
I use something like that:
AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
duration: const Duration(milliseconds: 100),
curve: Curves.decelerate,
child: ....
)
This animates the padding based on the viewInsets(software keyboard height).
The desired output can be achieved using AnimatedPadding Widget, though this is not perfect, but better than nothing :d
Open issue as of 15/03/21, for reference
import 'dart:math';
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
bottom: false,
child: Scaffold(
// !!! Important part > to disable default scaffold insets
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text("Appbar Title"),
),
body: Stack(
children: [
Scrollbar(
child: ListView.builder(
padding: EdgeInsets.all(0.0),
itemCount: 30,
itemBuilder: (context, i) {
return Container(
height: 100,
width: double.infinity,
color: Colors
.primaries[Random().nextInt(Colors.primaries.length)],
);
},
),
),
Align(
alignment: Alignment.bottomLeft,
child: AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
// You can change the duration and curve as per your requirement:
duration: const Duration(milliseconds: 200),
curve: Curves.decelerate,
child: InputField()),
)
],
)),
);
}
}
class InputField extends StatefulWidget {
InputField({Key key}) : super(key: key);
#override
_InputFieldState createState() => _InputFieldState();
}
class _InputFieldState extends State<InputField> {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[100],
padding: const EdgeInsets.symmetric(vertical: 6),
child: Row(
children: [
SizedBox(
width: 60,
child: Icon(Icons.add_a_photo),
),
Flexible(
child: TextField(
style: Theme.of(context).textTheme.bodyText1,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Enter text...',
),
),
),
SizedBox(
width: 60,
child: Icon(Icons.send),
),
],
),
);
}
}
Output ->
You can use this package keyboard_visibility and listen to keyboard visibility. Then you can give your logic to implement your feature like you can shorten the home container height. That's not perfect . But I think it's the only way right now.
You need to use keyboard_visibility package and use it to trigger your AnimatedContainer or AnimatedPadding
bool _isKeyboardActive = false;
#override
void initState() {
super.initState();
//add keyboard visibility Listener
KeyboardVisibility.onChange.listen((event) {
setState(() {
_isKeyboardActive = event;
});
});
}
Widget build(BuildContext context){
return AnimatedContainer(
width: _isKeyboardActive ? 200 : MediaQuery.of(context).size.width,
height: 60,
color: Colors.red,
duration: Duration(milliseconds: 600)
)
}
use this as a basis.
You should try setting resizeToAvoidBottomPadding: false like so:
return Scaffold(
key: _scaffoldKey,
resizeToAvoidBottomPadding: false,
i have a listview builder in flutter which is used to load a images when i remove a item i want to set listener for my listview that data has changed.
this is complete code this class is used for create a image style.
How can i solve hwn i click iconbutton i want to remove a item from list,
onw this is its removing when i press another button or something else
class Users extends StatefulWidget
{
final List image;
final File imageURL;
const Users ({Key key, this.imageURL,this.image}) : super(key: key);
#override
UserWidgets createState() => UserWidgets();
}
class UserWidgets extends State<Users>
{
#override
Widget build(BuildContext context)
{
VideoPlayerController playerController;
VoidCallback listener;
Widget play=new Icon(Icons.play_arrow);
Widget pause=new Icon(Icons.pause);
return new Container(
height: 200.0,
child: Stack(
children: <Widget>[
widget.imageURL.toString().contains(".jpg") ||widget.imageURL.toString().contains(".png") ||
widget.imageURL.toString().contains(".jpeg") ?
new Container(
child: new Card(
child: new Column(
children: <Widget>[
new GestureDetector(
onTap: ()
{
Navigator.push(context, MaterialPageRoute(builder: (context) => VideoApp(file: widget.imageURL,)
),
);
},
child:
new Image.file(widget.imageURL
,fit: BoxFit.cover,
height: 200.0,
width: 150.0,
),
)
],
)
),
): widget.imageURL.toString().contains(".mp4") ||widget.imageURL.toString().contains(".3gp") ?
new Container(
height: 100.0,
child: AspectRatio(aspectRatio: 10/6,
child: GestureDetector(
onTap: ()
{
Navigator.push(context, MaterialPageRoute(builder: (context) => VideoApp(file: widget.imageURL,)
),
);
},
child:
VideoPlayer(playerController = VideoPlayerController.file (widget.imageURL)
..addListener(listener)
..setVolume(1.0)
..initialize()
,
)
)
)
): new
Container(),
new Positioned(
child:
IconButton(icon: Icon(Icons.remove_circle),
color: Colors.black,
onPressed : ()
{
setState(() {
widget.image.remove(widget.imageURL);
print("helo");
});
}
)
,
top: 0.0,
right: 0.0,
)
],
),
);
}
}
now i need to know that what is equivalent to notifdatasetchanged().