How can I add rotation attributes to an Icon? - flutter

I want to rotate an image based on the heading/direction of my device, This class produces the MarkerIcon widget
import 'package:location/location.dart';
class MarkerOption {
final MarkerIcon? defaultMarker;
final MarkerIcon? advancedPickerMarker;
MarkerOption({
this.defaultMarker,
this.advancedPickerMarker,
});
MarkerOption copyWith({
MarkerIcon? defaultMarker,
MarkerIcon? advancedPickerMarker,
}) {
return MarkerOption(
defaultMarker: defaultMarker ?? this.defaultMarker,
advancedPickerMarker:
advancedPickerMarker ?? this.advancedPickerMarker);
}
}
class MarkerIcon extends StatelessWidget {
final Icon? icon;
final AssetImage? image;
MarkerIcon({
this.icon,
this.image,
Key? key,
}) : assert(icon != null || image != null),
super(key: key);
#override
Widget build(BuildContext context) {
Widget? child = SizedBox.shrink();
if (icon != null) {
child = icon;
} else if (image != null)
child = Image(
image: image!,
);
return child!;
}
}
I am using the Location Plugin that allows you to add the rotation attributes to the widget like this
MarkerIcon( rotation: currentLocation.heading )This way the image will point to which ever direction my device is pointing.But I don't know how to use it in this class. How can I add these attributes to the class such that I can call it like this?
markerIcon: MarkerIcon(
image: AssetImage(
"images/images/arrow.png",
rotation: position.heading,
),
)

Related

How to create custom types of widgets in Flutter?

I am trying to create a couple of widgets A that all should belong to another type of widget B, so that in the end all of them could be passed to a constructor that accepts only widgets of type B, but not other custom widgets like Container, Text, etc.
I tried something like this:
Parent class:
class ProDynamicWidget {
const ProDynamicWidget({
required this.height
});
final double height;
}
Child classes:
class ProDynamicTitle extends ProDynamicWidget {
final String title;
ProDynamicTitle({
required this.title
}) : super(height: 50.0);
// Here should be a build method for the title
}
############################################################
class ProDynamicImage extends ProDynamicWidget {
final String imageUrl;
ProDynamicImage({
required this.imageUrl
}) : super(height: 70.0);
// Here should be a build method for the image
}
I then wanted to create a widget that only accept widgets of type ProDynamicWidget:
class TestOneWidget extends StatelessWidget {
const TestOneWidget({
Key? key,
required this.widget
}) : super(key: key);
final ProDynamicWidget widget;
#override
Widget build(BuildContext context) {
return Container();
}
}
I do not really get how can now end up with child widgets that have separate build methods and a way the constructur at the end only accepts these child widgets instead of every type of widget.
Make ProDynamicWidget abstract and let it extend StatelessWidget:
abstract class ProDynamicWidget extends StatelessWidget{
const ProDynamicWidget({
required this.height
});
final double height;
}
Next, ProDynamicTitle and ProDynamicImage simply extend ProDynamicWidget and will thus have to define the build method:
class ProDynamicTitle extends ProDynamicWidget {
final String title;
const ProDynamicTitle({
required this.title
}) : super(height: 50.0);
#override
Widget build(BuildContext context) {
return Text(title);
}
}
class ProDynamicImage extends ProDynamicWidget {
final String imageUrl;
const ProDynamicImage({
required this.imageUrl
}) : super(height: 70.0);
#override
Widget build(BuildContext context) {
return Image(image: NetworkImage(imageUrl));
}
}
You can keep TestOneWidget as is. It will only accept descendants of ProDynamicWidget.

How can I rotate a Asset image based on obtained degrees

I can get the heading of my position i.e 90 (east),82,77, 180(south) etc, I have an asset image so before I show it in the screen i want to rotate it based on the heading.
For example
rat = position.heading;
//here rat is 270 degrees
RotateImageFunction(
MarkerIcon(
image: AssetImage(
//rotate this image 270 deg
"images/images/arrow.png",
),
), )
The RotateImageFunction class
class RotateImageFunction{
final String id;
final MarkerIcon? markerIcon;
final List<GeoPoint>? geoPoints;
RotateImageFunction(
this.id,
this.markerIcon,
this.geoPoints,
);
}
The MarkerIcon class
class MarkerIcon extends StatelessWidget {
final Icon? icon;
final AssetImage? image;
MarkerIcon({
this.icon,
this.image,
Key? key,
}) : assert(icon != null || image != null),
super(key: key);
#override
Widget build(BuildContext context) {
Widget? child = SizedBox.shrink();
if (icon != null) {
child = icon;
} else if (image != null) child = Image(image: image!);
return child!;
}
}
You can achieve it by wrapping it with Transform.rotate and easily use angle to rotate it
If you know that it will only be rotated in increments of 90 degrees, you can use RotatedBox:
RotatedBox(
quarterTurns: 1,
child: AssetImage( ... ),
)
If you want to be able to rotate it by any amount, you can use Transform.rotate(). However, you will then have to think about how the shape of your widget changes when not rotated by a multiple of 90 degrees:
Transform.rotate(
angle: 0.5 * pi, // radians
child: AssetImage( ... ),
)

Dart/Flutter widget with optional parameters but at least one required

I'm trying to create a Flutter widget that can be initialized by various parameters, something like this
class MyWidget extends StatefulWidget {
final int? id;
final String? username;
MyWidget({this.id, this.username});
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
#override
void initState() {
super.initState();
if (widget.id != null) {
// init based on id
} else if (widget.username != null) {
// init based on username
} else {
// this should never happen
}
}
#override
Widget build(BuildContext context) {
return Container(); // build some widget
}
}
As you can see, neither of id and username are required, but I would need that at least one of them present. What would be a good way to approach this?
You can declare the constructor as anyone of these
MyWidget(this.id,{this.username});//ID is required. Usage will be MyWidget(1,usename:'test');
MyWidget(this.username,{this.id});//username is required Usage will be MyWidget('test',id:1);
MyWidget({required this.id, this.username}); //id required
MyWidget({this.id, required this.username});//username required
MyWidget({requried this.id, required this.username});//both required
And you can also use Assert Statement to check values at runtime have a look
MyWidget({this.id, this.username}):assert(id != null && username != null,'Both parameters cannot be null');
class TestWidget extends StatelessWidget {
final String id;
final String name;
const TestWidget.name({this.id, #required this.name});
const TestWidget.id({#required this.id, this.name});
#override
Widget build(BuildContext context) {
return Container(
child: Text(id ?? name),
);
}
}

I am getting this error styling my portfolio in flutter

import 'package:flutter/material.dart';
class ThemeSwitcher extends InheritedWidget {
final _ThemeSwitcherWidgetState data; // We'll use ThemeSwitcher to get access to the current state of ThemeSwitcherWidget
const ThemeSwitcher({
Key key,
#required this.data,
#required Widget child,
}) : assert(child != null),
super(key: key, child: child);
static _ThemeSwitcherWidgetState of(BuildContext context) { //This method returns the current state of the ThemeSwitcherWidget. This will be used down the tree
return (context.dependOnInheritedWidgetOfExactType(ThemeSwitcher)
as ThemeSwitcher)
.data;
}
#override
bool updateShouldNotify(ThemeSwitcher old) {
return this != old;
}
}
class ThemeSwitcherWidget extends StatefulWidget {
final bool initialDarkModeOn; // this is the initial state of the variable
final Widget child; // child to which this boolean variable should be propagated upon change. This will be our app in this case
ThemeSwitcherWidget({Key key, this.initialDarkModeOn, this.child})
: assert(initialDarkModeOn != null),
assert(child != null),
super(key: key);
#override
_ThemeSwitcherWidgetState createState() => _ThemeSwitcherWidgetState();
}
class _ThemeSwitcherWidgetState extends State<ThemeSwitcherWidget> {
bool isDarkModeOn;
void switchDarkMode() { //method used to toggle dark mode during the runtime of the app
setState(() {
isDarkModeOn = !isDarkModeOn;
});
}
#override
Widget build(BuildContext context) {
isDarkModeOn = isDarkModeOn ?? widget.initialDarkModeOn; // this is the build method which would build the widget tree with the above info
return ThemeSwitcher(
data: this,
child: widget.child,
);
}
}
Too many positional arguments: 0 expected, but 1 found.
Try removing the extra positional arguments, or specifying the name for named arguments.
This is the Error I am continuously facing the issue after trying many methods.
I would like to know how would this problem can be solved as I am not getting any good solution from searches.
Return the following statement in _ThemeSwitcherWidgetState of(BuildContext context) method of your code:
return (context.dependOnInheritedWidgetOfExactType<ThemeSwitcher>()).data;

How to set icon size for childs on parent widget

I'm creating a widget where I want to set the the size of the icons used in the sub-widgets globally.
class ItemsContainer extends StatefulWidget {
final List<Item> items;
final double iconSize; //global default
const ItemsContainer({
#required this.items,
this.iconSize = 56.0,
});
}
class Item {
final Icon icon;
const Item ({
#required this.icon,
});
}
What I'd like to do is this:
for (var item in items) {
if (item.size == null)
item.size = iconSize;
}
The problem I face is, that I can't set the size due to the fact, that I have a const constructor.
I could clone an existing Icon and change the original size, but is there a better way to do it?
Icon _getSizedIcon(Icon icon, double size) {
return icon.size != null ? icon :
Icon(icon.icon,
size: size,
color: icon.color,
key: icon.key,
semanticLabel: icon.semanticLabel,
textDirection: icon.textDirection,
);
}
The IconTheme widget is what you probably want:
https://api.flutter.dev/flutter/widgets/IconTheme-class.html