I'm trying to make a 'custom button' for my app.
I have an image of egg with transparent backgroung and I need this image to be a button that ignore tapping on the transparent part.
Right now , I use gesturedetcetor , I also tried inkwell ,they are both detect tapping all the whole image, include the transparent back.
Align(
alignment: Alignment(0, 0.75),
child: Container(
width: swidth * 0.75,
height: sheight * 0.6,
child: GestureDetector(
onTap: () {
setState(() {
pushes--;
});
},
child: Image.asset(
'images/egg.png',
fit: BoxFit.fill,
)),
))
Welcome maor ts in Stackoverflow and Flutter dev.
I was very interesting with your question and your problem, so I decided to solve it with a new package you can use.
This package is transparent_image_button which I recently coded it.
You can use it as this example
TransparentImageButton.assets( "assets/images/egg.png",
width: 200,
onTapInside: () => print("You tapped the image."),
onTapOutside: () => print("You tapped outside the image."),
)
As you can see, you can set function when you tapped on image and another function when you tapped outside the image.
I hope other people can benefit from it also. Thanks for giving me the idea with your question.
In the way, you are implementing it will detect the tap on all over the image.
I will suggest you add the transparent view on the image in the fill area and then add GestureDetector on that view. In this way, you can avoid the click on the transparent area.
Try this code may solved your issue
Row(children: <Widget>[
GestureDetector(child: Container(
width: swidth * 0.75,
height: sheight * 0.6,
),onTap: (){
setState(() {
pushes--;
});
},),
Image.asset(
'images/egg.png',
fit: BoxFit.fill,
)
],)
Related
I am using the package flutter_map to build a map in my app, where there are circles around points. I am trying to turn this layer on/off dynamically, in accordance to the zoom level.
Such as the following, where I'm trying to only show the CircleLayerOptions layer if the map zoom level is >14 (zoomed in).
FlutterMap(
mapController: _mapController,
options: MapOptions(
center: LatLng(startLat, startLon),
zoom: 14,
plugins: [MarkerClusterPlugin()],
onTap: (_, __) => _popupController.hideAllPopups(),
),
layers: [
TileLayerOptions(
minZoom: 1,
maxZoom: 20,
backgroundColor: Colors.white,
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
),
// HERE (show circles around the points if zoomed in enough) <---------------------
(_mapController.zoom > 14) ? CircleLayerOptions(circles: myCircles)
: Container(),
]
);
The issue with this is that pinch zoom specifically doesn't reload the map at all.
Any idea how I can reload the state of the map automatically when the
user pinch zooms in or out?
(In case anyone asks, I am not using google maps as I'm trying to keep my app open source)
SOLUTION:
Courtesy of pskink (see above)
The MapController has an event listener that allows me to capture when pinch zoom is being done (called Drag as the event name). I can then call setState(() {}) to reload the map as I please. See below.
_mapController.mapEventStream.listen((event) {
if (_mapController.zoom >= 12) {
setState(() {});
}
});
return FlutterMap(
mapController: _mapController,
... etc ...
);
I want to calculate percent of double type data in text widget.
Padding(
padding: EdgeInsets.fromLTRB(5, 1, 5, 10),
child: Text( data[numberdata].toString(), //I want to calculate 5 percent of this numberdata
style: GoogleFonts.montserrat(color: Colors.black87, fontSize: 18 , textStyle:
TextStyle(fontWeight: FontWeight.w400)),
textAlign: TextAlign.center,
),
),
A bit tricky to be sure what you are after. But my best guess is:
Text((data[numberdata]*0.05).toString()),
...
child: Text(double.tryParse(data[numberdata].toString())*(5/100).toString()),
or
child: Text((double.tryParse(data[numberdata].toString())*0.5).toString()),
You just need to multiple it by the percent
For example in your text widget replace the code with
${data[numberdata] * 0.05}
This will show 5 percent of the value.
// let us say your number was 100 :
if you want to add a increment + %5 to your number use this :
Text((data[numberdata]*1.05).toString()),
// this will give you 105 .
if you want to add a decrement - %5 to your number use this :
Text((data[numberdata]*0.95).toString()),
// this will give you 95 .
I'm trying to increase the speed of my change in text by pressing a button. So my text is a number.toString() and is increasing by 1 (++) every time I click my GestureDetector that I've created. But I'm trying to use the property onLongPress to increase the speed by which my text increases when I hold the button down. But nothing I've tried has worked successfully!
I've scoured the internet for info and all I found was how to slow it down one by one, which is not only the opposite of what I need but also it doesn't continue decreasing in count when I hold down the button, it only decreases the speed at which the button is pressed per number. The code I used was:
import 'package:flutter/scheduler.dart' show timeDilation;
...
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(onTap: () => age >= 100 ? null : setState(() {
age++; }),
child: Icon(Icons.add_circle_outline, size: 40.0, color:
Colors.white,),
onLongPress: () { setState(() {
timeDilation = 10.0;
weight++;
});
},
), //GestureDetector
I expected the animation time to decrease, but I didn't expect to have to repeat tapping the button each time to allow for this decrease. I really want to increase the animation time and keep it increasing without having to constantly repeat pressing the button.
Although onLongPress in the GestureDetector is used for longer taps, it's still designed for a single press, not for contnual presses. What you're looking for though can be accomplished with the Listener widget, using onPointerDown, which would allow you to continuously process a tap down. There's a simple example here.
The purpose of this question is to find the best way to display a lot of images (20 or more) from the gallery.
I need to display all the photos on the on the device. As you can see there could be a lot of images to be displayed, and when I try to display them all using different Image.file() widget, My phone (LG G2) gets slow and then the app completely crashes.
I think the Problem Is that I am Loading a lot of 4K Images (More Than 100) on a 5 years old Device. The Images actually displayed on the Screen at the same time are actually around 15, but I need to have something like a gallery, so all the images in a GridView.
So, I don't think it's the best option, maybe there is a function to downscale the image to like 100x100 px. But looking online I couldn't find anything. So, Is there a better way?
I get all the Image Paths and their folder using a Platform Channel to Android.
I get them all in a list like this:
[["Camera", "storage/emulated/0/downloads/1.png"], etc]
This is The UI I got: (Sorry For the Awful design)
There Are three Main components on the Screen, The IconButton With The Two Arrows:
The DropDownMenu and The GridView.
The IconButton requeries all the paths from android. in the List as stated above.
The DropDown Menu has a function on onChanged which creates all the Cards in the List used by gridView.
This is The Funciton:
void _onChanged(String value) {
setState(() {
_currFolder = value;
_photoCards = calculatePhotoCards();
});
}
And the calculatePhotoCards is this:
List<Widget> calculatePhotoCards() {
List<Widget> list = new List();
for (int v = 0; v < _foldersAndPaths.length; v++) {
if (_foldersAndPaths[v][0] == _currFolder) {
list.add(Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: new ClipRRect(
borderRadius: new BorderRadius.circular(8.0),
child: Image.file(
File(_foldersAndPaths[v][1]),
fit: BoxFit.cover,
),
),
),
));
}
}
print(list);
return list;
}
Where _foldersAndPaths is the List containing all the paths which their respective folders (as stated above), while _currFolder is the Selected Folder in DropDownMenu.
You need to add cacheWidth and cacheHeight
example:
Image.network(
shop.shopPic,
width: 46,
height: 46,
cacheWidth: 46,
cacheHeight: 46,
)
I decided to implement this to see if it was something to do with image sizing etc, as there have been a few questions about that in the past for remote images.
When I implemented it, I ran into the exact same problem as you. I thought that flutter did caching of images scaled to a reasonable size but that doesn't seem to be the case. It's actually loading up each image into memory, which is why you're getting a crash. It doesn't take that many images to run out of memory as by the time they're decoded into pixels they're pretty huge.
Here and here are bugs about this (I raised one myself) against flutter.
So unfortunately, I don't think there's a pure flutter way of doing this at the moment. There is a image package on pub that can scale down images but it does it directly in dart code so isn't all that performant.
Until those bugs have been fixed, you may have to look for an android-specific (and iOS-specific if you're interested in that) solution to this. That would entail using the android thumbnail creator to create a bitmap, then either saving that bitmap and passing it's URL back to flutter, or passing the bitmap's bytes directly.
Sorry I don't have a better answer than that!
I'm using CachedNetworkImage and I had an issue with loading multiple Images and the app got to over 3GB ram because of it the solution was
CachedNetworkImage(
height: height,
width: width,
memCacheHeight: height, //add this line
memCacheWidth: width, //add this line
imageUrl: imageUrl,
),
It reduced the memory usage from3GB to 60MB
I'm back with tales of frustrating adventures. This time concerning images on the android side of titanium.
Long story short, I can't get any images to show up for android whatsoever, whether it be a background image or a plain image in an imageView object.
I will provide code I'm trying and keep it extremely small and simple so that it can be easily replicated for all of our testing purposes.
The Code:
Attempt #1 programatically creating view and image:
index.js
var header = Ti.UI.createImageView({
width: 300,
image: '/images/header.png',
width: 300
});
var win = Ti.UI.createWindow({
backgroundColor: 'white',
height: Ti.UI.FILL,
title: 'test',
width: Ti.UI.FILL
});
win.add(header);
win.open();
Attempt #2 plain jane .xml and .tss styling:
index.js:
$.index.open();
index.xml:
<Alloy>
<Window class="container">
<Label id="label">Hello World!!</Label>
<ImageView id='img1'></ImageView>
</Window>
</Alloy>
index.tss:
".container": {
backgroundColor: 'white'
}
"#img1": {
width: 300,
image: '/header.png',
width: 300,
top: 0,
left: 0
}
file locations (i copied the same image to 3 different locations to try and get something):
app/assets/header.png
app/assets/android/header.png
app/assets/android/images/header.png
IMPORTANT, What I have tried:
using "/images/header.png
using "images/header.png"
using "header.png"
using "/header.png"
First thing, in the ImageView property you have mentioned the width twice, so you can remove one declaration and put the height of the image, like 300 (you can put Ti.UI.SIZE to maintain the aspect ratio)
Second, put the images inside app/asset/android/images/res-<density> respectively. Replace <density> with for example mdpi / hdpi / xhdpi. (you can put this in res-hdpi for testing)
Do a clean build and then check if it is getting reflected or not.
Very Simple!
Alloy example:
Put your image at app/assets/images for example app/assets/images/header.png .
Now your code is
<ImageView id='img1' image='/images/header.png' ></ImageView>
Or in .tss file
"#img1": {
width: 300,
image: '/images/header.png',
width: 300,
top: 0,
left: 0
}
End !
put your image :
app/assets/images/header.png
then access it with
<ImageView id='img1' image="/images/header.png"></ImageView>
important : try to clean your project first for every changes you made at assets folder before you run the app!