Text Cursor Handle stays Blue - dart

I tried cursorColor and wrapping the TextField in a Theme where textSelectionHandleColor and textSelectionColor are set to whatever colors, however, the text cursor stays blue.
To be clear, I am talking about the handle. None of the following adjust it for me:
https://github.com/flutter/flutter/issues/14598
https://github.com/flutter/flutter/issues/15571

Sadly, it is currently not possible to change the textSelectionHandleColor of a TextField by modifying its parent Theme. The only Theme that changes the textSelectionHandleColor is the Theme directly inside the MaterialApp (source).
Issue on GitHub: textSelectionHandleColor is not working/changing. #20219
The reason this problem exists is that the handles are rendered inside an Overlay. The Overlay is not a child from the TextField, but instead always a child of the MaterialApp. Here is a failed try from another developer to solve the problem: textSelectionHandleColor taken from parent's context. Fixes #20219
Therefore you can currently only adjust the MaterialApp inside your application:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: Theme.of(context).copyWith(textSelectionHandleColor: Colors.red),
home: Scaffold(
body: Center(
child: TextField(
autofocus: true,
),
),
),
);
}
}

Related

how I can enable when I click in. notch in iOS go top of screen [duplicate]

This question already has an answer here:
Flutter iOS: taps on the status bar can't scroll to top
(1 answer)
Closed 1 year ago.
Generally speaking, it is only available on ios.
When I click on the notch above it takes me to the top of the page
It works on a pre-application for me, but in the current application it does not work, I don't know how to do it or something like that.
Explanation of the location of the notch
may this help:
Scaffold(
body:
Builder(builder: (BuildContext context) =>
CustomScrollView(controller: PrimaryScrollController.of(context))
OR
may be this will help, scrolls_to_top:
#override
Widget build(BuildContext context) {
return ScrollsToTop(
onScrollsToTop: _onScrollsToTop,
scaffold: Scaffold(
appBar: AppBar(title: const Text('Scroll to top')),
body: Container(),
),
);
}
Future<void> _onScrollsToTop(ScrollsToTopEvent event) async {
//TODO: Your code
}
reference: reference

Flutter: AnimatedContainer - children widgets' properties are NOT animating

I've got a simple AnimatedWidget with one child widget.
AnimatedContainer(
duration: Duration(milliseconds: 2000),
curve: Curves.bounceOut,
decoration: BoxDecoration(
color: Colors.purple,
),
child: FlutterLogo(
size: _boxSize,
),
),
where _boxSize is being animated like so:
void _startAnimation() => setState(() {
_boxSize *= 1.7;
});
AnimatedContainer is not working for child widgets, however. You need to change direct properties of AnimatedContainer for the animation to work.
This is in compliance with documentation:
The [AnimatedContainer] will automatically animate between the old
and new values of properties when they change using the provided curve
and duration. Properties that are null are not animated.
Its child and descendants are not animated.
What is the equivalent of AnimatedContainer which is ALSO ABLE to animate its children?
There are few widgets which will animate the child. You can swap the new flutter logo widget with preferred size using AnimatedSwitcher Widget.
AnimatedSwitcher - This widget will swap the child widget with a new widget.
AnimatedPositioned - It'll change the position of the child from the stack widget whenever the given position changes.
AnimatedAlign - Animated version of align which will change the alignment of the child whenever the given alignment changes.
AnimatedCrossFade - It fades between two children and animate itself between their sizes.
There is no magic widget which would simply recursively animate all children. But I think what you want is an implicitly animated widget. ie. you change the constructor parameters of a widget, and as it changes it animates from one value to the next.
The easiest way is probably the ImplicitlyAnimatedWidget with a AnimatedWidgetBaseState. So for your example to animate a boxSize attribute this could look like:
class AnimatedFlutterLogo extends ImplicitlyAnimatedWidget {
const AnimatedFlutterLogo({Key key, #required this.boxSize, #required Duration duration})
: super(key: key, duration: duration);
final double boxSize;
#override
ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget> createState() => _AnimatedFlutterLogoState();
}
class _AnimatedFlutterLogoState extends AnimatedWidgetBaseState<AnimatedFlutterLogo> {
Tween<double> _boxSize;
#override
void forEachTween(visitor) {
_boxSize = visitor(_boxSize, widget.boxSize, (dynamic value) => Tween<double>(begin: value));
}
#override
Widget build(BuildContext context) {
return Container(
child: FlutterLogo(
size: _boxSize?.evaluate(animation),
),
);
}
}
which is imho already pretty concise, the only real boilerplate is basically the forEachTween(visitor) method which has to create Tween objects for all properties you'd like to animate.

Position FloatingActionButton on the left side

How do I position a FloatingActionButton on the left side inside a Scaffold?
Currently the only available options are centerFloat, centerDocked, endFloat and endDocked.
Maybe Material Design does not intend to position the FAB at startFloat or startDocked.
That would be fine if RTL changed endFloat and endDocked to appear on the left side, but that is not the case.
In April 2020, the available options have been expanded and startFloat as well as startDocked are included options now.
Here is the full list of available options (see the FloatingActionButtonLocation documentation):
centerDocked
centerFloat
centerTop
endDocked
endFloat
endTop
miniCenterDocked
miniCenterFloat
miniCenterTop
miniEndDocked
miniEndFloat
miniEndTop
miniStartDocked
miniStartFloat
miniStartTop
startDocked
startFloat
startTop
You can even easily define your own locations using StandardFabLocation.
As of 2020, you can use the following:
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat
A parameter that can be passed to the Scaffold Widget from material.dart
Source: PR 51465
There is also another solution to this problem. Fab button by default is always at the bottom end of the screen. So if we wrap our Scaffoldwith a Directionality and set its text direction to TextDirection.rtl, then the button goes left. but since now the body itself is mirrored, we can wrap the body with another Directionality and set its text direction to TextDirection.ltr
#override
Widget build(BuildContext context) {
return
Directionality(
textDirection: TextDirection.rtl,
child:Scaffold(
appBar: AppBar(
title: const Text('Something),
),
body: Directionality(
textDirection: TextDirection.ltr,
child: Center(child: const Text('Press the button below!'))),
floatingActionButton: FloatingActionButton(
onPressed: () {
},
child: Icon(Icons.navigation),
backgroundColor: Colors.green,
),
)
);
}

Swipe to go back gesture flutter

How do i implement the swipe from the left to go back gesture in flutter? Not sure if it was already implemented automatically for iOS, but I wanted it for Android as well (as things are becoming gesture based).
Use CupertinoPageRoute to make it work on Android;
import 'package:flutter/cupertino.dart';
(as answered on How to implement swipe to previous page in Flutter?)
You could set your Theme.platform to TargetPlatform.ios. This will make use that the swipe back gesture is used on every device.
You can use CupertinoPageRoute() as Tom O'Sullivan said above.
However, if you want to customize it (eg. using custom transition duration) using PageRouteBuilders and get the same swipe to go back gesture, then you can override buildTransitions().
For iOS, the default PageTransitionBuilder is CupertinoPageTransitionsBuilder(). So we can use that in buildTransitions(). This automatically give us the swipe right to go back gesture.
Here's some sample code for the CustomPageRouteBuilder:
class CustomPageRouteBuilder<T> extends PageRoute<T> {
final RoutePageBuilder pageBuilder;
final PageTransitionsBuilder matchingBuilder = const CupertinoPageTransitionsBuilder(); // Default iOS/macOS (to get the swipe right to go back gesture)
// final PageTransitionsBuilder matchingBuilder = const FadeUpwardsPageTransitionsBuilder(); // Default Android/Linux/Windows
CustomPageRouteBuilder({this.pageBuilder});
#override
Color get barrierColor => null;
#override
String get barrierLabel => null;
#override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return pageBuilder(context, animation, secondaryAnimation);
}
#override
bool get maintainState => true;
#override
Duration get transitionDuration => Duration(milliseconds: 900); // Can give custom Duration, unlike in MaterialPageRoute
#override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return matchingBuilder.buildTransitions<T>(this, context, animation, secondaryAnimation, child);
}
}
Then to go to a new page:
GestureDetector(
onTap: () => Navigator.push(
context,
CustomPageRouteBuilder(pageBuilder: (context, animation, secondaryAnimation) => NewScreen()),
),
child: ...,
)
You can set the platform of your theme (and darkTheme) to TargetPlatform.iOS, you can set the pageTransitionsTheme of your themes to,
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
},
),
and you can load the new page using CupertinoPageRoute ... and none of that will work until you make sure to use Navigator.push (instead of Navigator.pushReplacement) to get to that new screen! I hope this helps anyone out there who was working with existing transitions and didn't notice this crucial detail. :)
Use this plugin:
https://pub.dev/packages/cupertino_back_gesture
A Flutter package to set custom width of iOS back swipe gesture area.
For basic use:
import 'package:cupertino_back_gesture/cupertino_back_gesture.dart';
BackGestureWidthTheme(
backGestureWidth: BackGestureWidth.fraction(1 / 2),
child: MaterialApp(
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
//this is default transition
//TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
//You can set iOS transition on Andoroid
TargetPlatform.android: CupertinoPageTransitionsBuilderCustomBackGestureWidth(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilderCustomBackGestureWidth(),
},
),
),
home: MainPage(),
),
)
More details on plugin's page
in my case, the solution turned out to be very simple. I just used context.push('screen') instead of context.go('/screen')
This should not be implemented on Android since it makes interactions inconsistent across the OS.
Swiping from the screens edge to go back is not something that Android wants you to implement, so you should better don't do it.

How to display an animated picture in Flutter?

I want to display an animated picture, whatever its format, in Flutter. The fact is that currently there seems to be only one solution available, video_loader. This works only on full screen, but it doesn't fit my use case.
Any idea on how I could sort this out?
Now, Image widget Supports GIF. (April 18)
For Ex.
new Image(image: new AssetImage("assets/ajax-loader.gif"))
You can split the frames into separate images using https://ezgif.com/split and add them as assets in your pubspec.yaml.
Then use an Animation<int> to select the correct frame to display. Make sure to set gaplessPlayback: true to avoid flickering.
For example, the following code displays the frames of an animated GIF that was created by Guillaume Kurkdjian.
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData.dark(),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
AnimationController _controller;
Animation<int> _animation;
#override
void initState() {
_controller = new AnimationController(vsync: this, duration: const Duration(seconds: 5))
..repeat();
_animation = new IntTween(begin: 0, end: 116).animate(_controller);
}
Widget build(BuildContext context) {
return new Scaffold(
body: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new AnimatedBuilder(
animation: _animation,
builder: (BuildContext context, Widget child) {
String frame = _animation.value.toString().padLeft(3, '0');
return new Image.asset(
'assets/frame_${frame}_delay-0.04s.png',
gaplessPlayback: true,
);
},
),
new Text('Image: Guillaume Kurkdjian', style: new TextStyle(fontStyle: FontStyle.italic)),
],
),
);
}
}
2021 Update
As of now flutter does supports playing gif files using the Image widget.
Image.asset('assets/logo.gif')
But there's a problem with current way of loading gif in flutter. The gif plays in a loop and you can't stop the gif after playing it once. There are other ways of showing animated pictures using Rive and Lottie and both of them comes with a pretty well maintained flutter package that gives lots of features out of the box.
Workaround :
Convert your gif to mp4 (Gif to mp4)
Convert mp4 to Lottie json (Mp4 to Json)
Upload your Lottie json to lottiefiles.com or add to your assets folder
Use Lottie package to load your animation
Example from Lottie package docs :
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView(
children: [
// Load a Lottie file from your assets
Lottie.asset('assets/LottieLogo1.json'),
// Load a Lottie file from a remote url
Lottie.network(
'https://raw.githubusercontent.com/xvrh/lottie-flutter/master/example/assets/Mobilo/A.json'),
// Load an animation and its images from a zip file
Lottie.asset('assets/lottiefiles/angel.zip'),
],
),
),
);
}
}
For sure this is not the most ideal way of loading a gif as this is just a workaround. You can simply use an Image widget if you're not doing much with your gif. But if you will use Lottie then you get lots of things that you can do with your gif with much more control.
In order to run gif animation only once, there are 2 solutions.
First solution.
List<int> listGifDuration = [0,0,22,26,31,27,30,29,29,23,29,24,25,27,33,33,29,29];
List<int> listGifDurationDs = [0,0,1,0,0,0,0,0,0,0,0,0,0,0,5,2,5,0];
List<double> listGifFrames = [0,0,315,389,310,294,435,423,425,331,425,360,365,395,309,384,426,435];
strgif = "assets/gif/motion-all.gif"
fetchGif(AssetImage(strgif)).then((value) {
controller= GifController(vsync: this,duration: Duration(seconds: listGifDuration[widget.storyid]));
controller.addListener(() => setState(() {}));
TickerFuture tickerFuture = controller.repeat(min:0,max:listGifFrames[widget.storyid],period:Duration(seconds: listGifDuration[widget.storyid]));
tickerFuture.timeout(Duration(seconds: listGifDuration[widget.storyid]), onTimeout: () {
controller.forward(from: 0);
controller.stop(canceled: true);
});
});
2nd solution.
Convert the property of the gif file from the infinite loop to 1 loop.
Please use following link to convert gif file looping count.
https://ezgif.com/loop-count
and then
child: new Image.asset(strgif),
We can use Image widget to load any type of image whether it is a normal image or the gif.
We can load them from our asset as well as from network with the help of Image widget
Image.asset('name');
Image.file(file);
Image.memory(bytes);
Image.network('src');
There are some dependency for load the gif also

Resources