Not full display of SVG in singleChildScrollView - flutter

I need to place a large svg file on the flutter application page so that it scrolls like a normal layout page, I created a simple code structure that basically works as I need, but there was a problem, some images from the file were replaced with white squares, why is this happening and how fix this, help if anyone has come across a similar one and solved it already. here is the code:
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
void main() {
const app = App();
runApp(app);
}
class App extends StatelessWidget {
const App({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'TitleText',
debugShowCheckedModeBanner: false,
home: Screen());
}
}
class Screen extends StatefulWidget {
const Screen({super.key});
#override
State<Screen> createState() => _ScreenState();
}
class _ScreenState extends State<Screen> {
#override
Widget build(BuildContext context) {
// final size = MediaQuery.of(context).size;
const String assetName = 'assets/images/gyber.svg';
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: SingleChildScrollView(
child: SvgPicture.asset(assetName),
),
));
}
}
here is an example of replacing a fragment with a white block:
the debug console gives a bunch of errors, as I understand it, related to svg :
Another exception was thrown: Failed to find definition for url(#pattern13) Another exception was thrown: Failed to find definition for url(#pattern14) unhandled element filter; Picture key: AssetBundlePictureKey(bundle: PlatformAssetBundle#1926e(), name: "assets/images/gyber.svg", colorFilter: null, theme: SvgTheme(currentColor: Color(0xff000000), fontSize: 14, xHeight: 7)) unhandled element pattern; Picture key: AssetBundlePictureKey(bundle: PlatformAssetBundle#1926e(), name: "assets/images/gyber.svg", colorFilter: null, theme: SvgTheme(currentColor: Color(0xff000000), fontSize: 14, xHeight: 7))

Related

Is there a way to stop the image darkening that intro_slider does to backgroundImage?

I'm currently making a 3-slides long Intro Slider for my application, using the Flutter package intro_slider.
Everything works flawlessly and looks perfect, but since I decided to use a custom png image as my backgroundImage, it seems that the package shows the image with extremely darker colors.
In the image I've attached I'm showing the effective problem. The one on top (using centerWidget to show it) is the expected image that should show with the exact same colors.
On the back there is the backgroundImage, darkened automatically.
I couldn't find anyone else talking about this issue and hope someone found a way to "solve" it.
Is there a way to stop the darkening of the image?
Thanks in advance.
I have currently tried:
Changing image extensions and trying again.
Remove everything but the backgroundImage (I thought that the image was darkened because of the items on top of it)
Here is the code I wrote for the slides:
Main
void main() {
runApp(const MyApp());
}
// Main
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Goals App',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: IntroScreen(),
);
}
}
IntroScreen
class IntroScreen extends StatefulWidget {
const IntroScreen({Key? key}) : super(key: key);
#override
IntroScreenState createState() => IntroScreenState();
}
class IntroScreenState extends State<IntroScreen> {
List<Slide> slides = [];
#override
void initState() {
super.initState();
slides.add(Slide(
backgroundImage: 'assets/images/intro_first_slide.png',
centerWidget:
Image(image: AssetImage('assets/images/intro_first_slide.png')),
));
}
Widget renderNextBtn() {
return const Icon(
Icons.navigate_next,
color: Colors.white,
size: 35.0,
);
}
Widget renderDoneBtn() {
return const Icon(
Icons.done,
color: Colors.white,
size: 35.0,
);
}
Widget renderSkipBtn() {
return const Icon(
Icons.skip_next,
color: Colors.white,
size: 35.0,
);
}
#override
Widget build(BuildContext context) {
return IntroSlider(
// List Slides
slides: slides,
// Skip button
// renderSkipBtn: renderSkipBtn(),
// Next button
renderNextBtn: renderNextBtn(),
// Done button
renderDoneBtn: renderDoneBtn(),
// Dot indicator
colorDot: Colors.white,
colorActiveDot: Colors.grey[300],
sizeDot: 13.0,
// show/hide status bar
hideStatusBar: true,
backgroundColorAllSlides: Colors.grey,
// Scrollbar
verticalScrollbarBehavior: scrollbarBehavior.HIDE,
);
}
}
Maybe this is what you are looking for?
https://pub.dev/packages/intro_slider#slide-object-properties all the way down at the bottom of the properties list:
backgroundBlendMode BlendMode? BlendMode.darken Background tab image filter blend mode
probably like so
slides.add(
Slide(
backgroundImage: 'assets/images/intro_first_slide.png',
centerWidget: Image(
image: AssetImage('assets/images/intro_first_slide.png'),
),
backgroundBlendMode: BlendMode.srcOver // <- try this
),);

I'm trying to make a simple app that randomly changes the color of the body's background but all I'm getting on the emulator is a blank

I don't get any errors upon running, I just get a blank page. I guess it has to do with the layout arrangement, but that's just a guess.
I switched the class to statful in the scaffold body, so I can use setState(){} under the flatButton. I don't know why nothing is showing on the screen though, because I would assume at least the AppBar would be on the screen. Can the body extend over the AppBar?
import 'package:flutter/material.dart';
import 'dart:math';
int colorNumber = 1;
void main()=> runApp(StructureBuild());
class StructureBuild extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Random Color Generator',
style: TextStyle(color: Colors.white)),
backgroundColor: Colors.blue,
),
body: BodyBuild()
));
}
}
class BodyBuild extends StatefulWidget {
#override
_BodyBuildState createState() => _BodyBuildState();
}
class _BodyBuildState extends State<BodyBuild> {
int changeColor(int colorNumber) {
return colorNumber = Random().nextInt(245) + 1;
}
#override
Widget build(BuildContext context) {
return Expanded(child:
FlatButton(color: Color(colorNumber),
onPressed: () {
setState(() {
changeColor(1);
});
}, child: Text('press anywhere'),));
}
}
First of all, I recommend checking the documentation of Flutter for using color const. Color const has color from the lower 32 bits of an int. 1-255 values are very rare values for Color. I suggest you find a hexadecimal value by examining the link I gave. https://api.flutter.dev/flutter/dart-ui/Color-class.html .
Also, you can give an integer value. But it should be a huge number to change the color of the Flatbutton. For Example, 4123423412341242342 would change to color kind of turquoise blue.

Flutter exception Builder keeps being called

I am using a flutter Image.file() to show an Image in my app. I am also using the errorBuilder to handle any crashes and show a message to the user.
I encounter a problem when i do these steps.
Load a good image that works
Load a corrupt image into the same Image.File() widget
Load the original good image back into the same Image.File() widget
It seems every file change after the corrupt photo is passed in (step 2) will result in the error builder being shown and not the new good image.
If i don't pass in the corrupt photo in step 2, the photo changes like it should. Is this a bug with the flutter Image() or should I be doing something after it goes into the errorBuilder.
Here is my current setup.
Image.file(
file,
fit: BoxFit.cover,
errorBuilder: (BuildContext context, Object exception, StackTrace stackTrace) {
print("Failed to initialise the file");
print(stackTrace);
// Once an error occurs it always goes in here
return Text("an error occurred");
},
);
The actual error I receive on all file changes when/after the corrupt file is passed in is
Could not instantiate image codec.
UPDATE
I have wrote a dartpad that shows the problem i am experiencing.
https://dartpad.dev/98c2dacb481c088dfd2e5bee490f45ed
If you click
Good Image
Good Image 2
Good Image
Good Image 2
The images cycle correctly... which works.
if you then click "Corrupt Image" which will attempt to load a corrupt jpeg file the error builder will fire.
If you then click "Good Image" or "Good Image 2" they no longer build and the Image is stuck loading the error builder everytime... How can I get it to then load one of the good images again?
Please let me know if I haven't been clear and I will add more information :)
Thanks a lot
You can copy paste run full code below
This error can be fixed with add key: UniqueKey(),
I have test it with DardPad works fine
code snippet
Image.network(
_selectedImageURL,
key: UniqueKey(),
working demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
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> {
String _goodImageOne =
"https://upload.wikimedia.org/wikipedia/commons/6/69/June_odd-eyed-cat_cropped.jpg";
String _corruptImage =
"https://srv-file16.gofile.io/download/hwTzLI/cat_corrupt.jpg";
String _goodImageTwo =
"https://upload.wikimedia.org/wikipedia/commons/c/c7/Tabby_cat_with_blue_eyes-3336579.jpg";
String _selectedImageURL;
#override
void initState() {
super.initState();
_selectedImageURL = _goodImageOne;
}
void _changeFile(String newUrl) {
setState(() {
_selectedImageURL = newUrl;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
_selectedImageURL,
key: UniqueKey(),
height: 300,
width: 200,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
));
},
errorBuilder: (BuildContext context, Object exception,
StackTrace stackTrace) {
return Text("Cannot display url");
},
),
Expanded(child: Container()),
RaisedButton(
onPressed: () => _changeFile(_goodImageOne),
child: Text("Good Image"),
),
RaisedButton(
onPressed: () => _changeFile(_corruptImage),
child: Text("Corrupt Image"),
),
RaisedButton(
onPressed: () => _changeFile(_goodImageTwo),
child: Text("Good Image 2"),
),
],
),
),
);
}
}

How do I make a specific part of a transparent image clickable?

I have a stack in a Flutter app, that stacks multiple images on top of each other. They are all of the same width and height, and have transparent backgrounds.
Individually, they look like this:
When they overlap, they look like this:
I need to make the visible part of each picture clickable. I do not want any interaction with the transparent part of any image. I've tried using GestureDetector, but since all the images are of the same size, it isn't working too well. How do I achieve this?
Circle the borders of the picture in any vector graphics editor, I used figma.com, it's free.
Save it as svg file, open it and copy path from svg.
Convert svg paths to Flutter Paths, I've used the path_drawing package.
Use custom clipper to clip image by path.
Unfortunately, path_drawing package ignores the beginning of the path. So you need to add it, by adding offset.
Add GestureDetector.
import 'package:flutter/material.dart';
import 'package:path_drawing/path_drawing.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String clicked = '';
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
_getClippedImage(
clipper: _Clipper(
svgPath: svgCarPath,
offset: Offset(66, 157),
),
image: 'assets/image.png',
onClick: _handleClick('car'),
),
_getClippedImage(
clipper: _Clipper(
svgPath: svgManPath,
offset: Offset(115, 53),
),
image: 'assets/image.png',
onClick: _handleClick('man'),
),
Positioned(
child: Text(
clicked,
style: TextStyle(fontSize: 30),
),
bottom: 0,
),
],
);
}
void Function() _handleClick(String clickedImage) {
return () => setState(() {
clicked = clickedImage;
});
}
Widget _getClippedImage({
_Clipper clipper,
String image,
void Function() onClick,
}) {
return ClipPath(
clipper: clipper,
child: GestureDetector(
onTap: onClick,
child: Image.asset('assets/image.png'),
),
);
}
}
class _Clipper extends CustomClipper<Path> {
_Clipper({this.svgPath, this.offset = Offset.zero});
String svgPath;
Offset offset;
#override
Path getClip(Size size) {
var path = parseSvgPathData(svgPath);
return path.shift(offset);
}
#override
bool shouldReclip(CustomClipper oldClipper) {
return false;
}
}
const svgCarPath =
'M35 13.7742L46.9628 1.52606L58.8398 5.97996V17.1147L111.544 13.7742L117.111 50.8899L109.688 55.715C108.575 61.2823 103.75 72.417 93.3574 72.417C82.965 72.417 80.4751 64.3753 80.4751 59.4266C68.1032 55.5913 53.5355 53.8592 39.5397 57.5708C35.0128 76.8252 14.4397 76.0591 12.0741 55.715H0.939362V26.7647L12.0741 17.1147L35.8281 13.7742Z';
const svgManPath =
'M50.2647 19.9617C50.6461 5.85163 47.5952 0.703364 38.2521 0.703369C32.0776 2.87051 31.0217 6.36354 30.625 14.0016C30.625 14.0016 27.9555 28.1424 30.625 32.8584C33.2945 37.5744 42.1784 35.788 39.3961 40.7456C36.6138 45.7032 27.9555 63.6268 27.9555 63.6268H22.6165C14.7864 70.572 19.1843 79.9011 12.1293 88.7962C3.01255 100.291 -0.77319 103.733 0.879345 106.911L8.12508 109.199L19.1844 96.8046L12.1293 120.258L15.9428 123.499L22.6165 121.402L32.7224 97.9487L39.3961 104.622C36.5995 110.597 32.2267 122.088 37.108 120.258C43.2097 117.97 54.2865 120.258 66.0909 113.394C75.3267 28.4915 49.8834 34.0719 50.2647 19.9617Z';

How can I read text from files and display them as list using widget/s in Flutter?

may I ask a way how to make this work.
I have a text file named questions.txt.
This file contains the following questions:
How old are you?
Where do you live?
What is your age?
I want to load these questions from the file, and render them as a list in Flutter.
questionnaires.dart
import 'package:flutter/material.dart';
class Questionnaires extends StatefulWidget {
#override
_QuestionnairesState createState() => _QuestionnairesState();
}
class _QuestionnairesState extends State<Questionnaires> {
String q1 = "";
String q2 = "";
String q3 = "";
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Center(
child: Column(
children: <Widget>[
Text(q1),
Text(q2),
Text(q3)
],
),
),
),
);
}
}
You can start with the most basic way of retrieving the questions from a .txt file using rootBundle.loadString, then display it using a ListView widget.
main.dart
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Questions',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyAppScreen(),
);
}
}
class MyAppScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyAppScreenState();
}
}
class MyAppScreenState extends State<MyAppScreen> {
List<String> _questions = [];
Future<List<String>> _loadQuestions() async {
List<String> questions = [];
await rootBundle.loadString('path/to/questions.txt').then((q) {
for (String i in LineSplitter().convert(q)) {
questions.add(i);
}
});
return questions;
}
#override
void initState() {
_setup();
super.initState();
}
_setup() async {
// Retrieve the questions (Processed in the background)
List<String> questions = await _loadQuestions();
// Notify the UI and display the questions
setState(() {
_questions = questions;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Flutter Questions")),
body: Center(
child: Container(
child: ListView.builder(
itemCount: _questions.length,
itemBuilder: (context, index) {
return Text(_questions[index]);
},
),
),
),
);
}
}
And here are the sample list of questions.
questions.txt
"How old are you?"
"Where do you live?"
"What is your age?"
In the example code above, you are parsing the text file line by line, please see LineSplitter. This is good for small and sample projects while you're testing out Flutter. But you should be able to update this implementation by following the official docs of Flutter, on how you can read from and write on files.
Furthermore, if you want to go big with your Flutter project, you should look into ways on how you can host your questions online, eg. served via REST APIs, then retrieve it using the http plugin for Flutter.
More on:
https://flutter.dev/docs/cookbook/networking/fetch-data
https://flutter.dev/docs/cookbook/persistence/reading-writing-files
https://pub.dev/packages/path_provider
Output: