Flutter is not clearing rendered widgets, only re-painting - flutter

I am having a Scaffold with a floatingActionButton. Inside I have an inappwebview which displays some webpage. The floatingActionButton is displayed in the front above the webview. Also I show some dialog for a second.
Everything worked fine until yesterday. I upgraded flutter and I suddenly experienced weird behaviour which is why i downgraded flutter again. But I still got the same problem. All the stuff that is rendered above is never cleared and just re-painted all the time, which leads to dark shadows and never disappearing dialog windows.
Here you can see the dark shadow around the floatingActionButton and the bottomBar. Also the "<3 + Karma" badge does not disappear anymore.
The weird thing is, that I did not change anything. On my other machine everything still builds fine. There I use the same code, same package versions in my pubspec.yaml and also the same flutter/dart version.
I am really puzzled here. I can't seem to build a new app version without this bug on my main desktop machine.
This is my currently used flutter version:
Flutter 2.10.2 • channel unknown • unknown source
Framework • revision 097d3313d8 (3 months ago) • 2022-02-18 19:33:08 -0600
Engine • revision a83ed0e5e3
Tools • Dart 2.16.1 • DevTools 2.9.2
flutter doctor tells me, No issues found!
This is my code for reference:
return WillPopScope(
onWillPop: ArticleHandler().backButtonPressed,
child: Scaffold(
floatingActionButton: Visibility(
visible: _fabIsVisible,
child: FloatingActionButton(
onPressed: () {
webView.scrollTo(x: 0, y: 0, animated: true);
},
child: Icon(
Icons.arrow_upward,
color: Colors.white,
),
backgroundColor: Theme.of(context).primaryColor,
)),
floatingActionButtonLocation: MarginEndFloatFABLocation(),
floatingActionButtonAnimator: NoFABAnimation(),
appBar: TopBar(widget.articlePreview.url),
body: Builder(builder: (BuildContext context) {
return Container(
child: Column(
children: <Widget>[
progress < 1.0
? Container(
height: 3,
child: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.white,
valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).primaryColor),
))
: Container(height: 0),
Expanded(
child: InAppWebView(
initialOptions: InAppWebViewGroupOptions(
android: AndroidInAppWebViewOptions(useHybridComposition: true),
crossPlatform: InAppWebViewOptions(
//cacheEnabled: false, // uncomment this line to clean cache on open
)),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
this.progress = progress / 100;
});
},
onOverScrolled: (InAppWebViewController controller, int x, int y, bool clampedX, bool clampedY) {
// maybe show karma badge
},
onScrollChanged: (InAppWebViewController controller, int x, int y) async {
if (y > 0) {
if (!_fabIsVisible) {
setState(() {
_fabIsVisible = true;
});
}
} else {
if (_fabIsVisible) {
setState(() {
_fabIsVisible = false;
});
}
}
})),
BottomTagBar(),
],
));
}),
));

Related

How to take screenshot of entire screen outside of your FLUTTER DESKTOP app(mostly for Windows OS)?

I'm new to flutter. Now I am able to take screenshot for my entire desktop app screen using Screenshot package & storing that image to local storage.
But my requirement is to capture the screenshot of entire screen of the window, like if 2 applications are opened(1 Flutter + 1 any other app e.g. browser) in 1 screen, then we can able to take whole screen's screenshot not only flutter app.
Please help me on how to take entire window's screenshot in Windows OS desktop app?
If it's not possible directly from Flutter, then how to achieve this by implementing some native code with Flutter?
check this completely working as expected
bool _isAccessAllowed = false;
CapturedData? _lastCapturedData;
#override
void initState() {
super.initState();
_init();
}
void _init() async {
_isAccessAllowed = await ScreenCapturer.instance.isAccessAllowed();
}
void _handleClickCapture(CaptureMode mode) async {
Directory directory = await getApplicationDocumentsDirectory();
String imageName =
'Screenshot-${DateTime.now().millisecondsSinceEpoch}.png';
String imagePath =
'${directory.path}/screen_capturer_example/Screenshots/$imageName';
_lastCapturedData = await ScreenCapturer.instance.capture(
mode: mode,
imagePath: imagePath,
silent: true,
);
if (_lastCapturedData != null) {
// ignore: avoid_print
// print(_lastCapturedData!.toJson());
} else {
// ignore: avoid_print
print('User canceled capture');
}
setState(() {});
}
Widget _buildBody(BuildContext context) {
return PreferenceList(
children: <Widget>[
if (Platform.isMacOS)
PreferenceListSection(
children: [
PreferenceListItem(
title: const Text('isAccessAllowed'),
accessoryView: Text('$_isAccessAllowed'),
onTap: () async {
bool allowed =
await ScreenCapturer.instance.isAccessAllowed();
BotToast.showText(text: 'allowed: $allowed');
setState(() {
_isAccessAllowed = allowed;
});
},
),
PreferenceListItem(
title: const Text('requestAccess'),
onTap: () async {
await ScreenCapturer.instance.requestAccess();
},
),
],
),
PreferenceListSection(
title: const Text('METHODS'),
children: [
PreferenceListItem(
title: const Text('capture'),
accessoryView: Row(children: [
CupertinoButton(
child: const Text('region'),
onPressed: () {
_handleClickCapture(CaptureMode.region);
},
),
CupertinoButton(
child: const Text('screen'),
onPressed: () {
_handleClickCapture(CaptureMode.screen);
},
),
CupertinoButton(
child: const Text('window'),
onPressed: () {
_handleClickCapture(CaptureMode.window);
},
),
]),
),
],
),
if (_lastCapturedData != null && _lastCapturedData?.imagePath != null)
Container(
margin: const EdgeInsets.only(top: 20),
width: 400,
height: 400,
child: Image.file(
File(_lastCapturedData!.imagePath!),
),
),
],
);
}
// screen shot taken by the App.
You might try using this package: screen_capturer. It works on Windows, Linux and MacOS.
From the docs:
Example of usage:
import 'package:screen_capturer/screen_capturer.dart';
CapturedData? capturedData = await screenCapturer.capture(
mode: CaptureMode.screen, // screen, window
imagePath: '<path>',
);
CaptureMode.screen is to capture the entire screen.
The screenshot package which you mention is only for taking screenshots for widgets of your app not of whole screen.

Flutter Web FilePicker browser crash or close without error on UBUNTU

I want to use flutter file picker on web platform. when i call method "pickFiles" app close without error
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
);
print(result?.files.first.bytes);
if (result?.files.first != null) {
print(result?.files.first.bytes);
} else {
throw "Cancelled File Picker";
}
I think this is happening only on ubuntu.
and flutter doctor:
[✓] Flutter (Channel stable, 3.0.1, on Ubuntu 20.04.3 LTS 5.13.0-44-generic, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc2)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 4.1)
[✓] VS Code
[✓] Connected device (2 available)
[✓] HTTP Host Availability
I have the same problem !
Temporarly i decide to use another package
flutter_dropzone: ^3.0.5
He helps me to put some files in the app.
onTap: () async {
bool fileUploaded = false;
double pourcentageUploaded = 0;
await showDialog(
context: context,
builder: (context) => Dialog(
child: StatefulBuilder(
builder: (context, setstate) => AnimatedContainer(
duration: Duration(seconds: 2),
color: fileUploaded
? Colors.green
: Colors.transparent,
height: 200,
width: 500,
child: Stack(
children: [
DropzoneView(
onDrop: (value) async {
fileUploaded = !fileUploaded;
do {
pourcentageUploaded += 0.0000000004;
print(pourcentageUploaded);
setstate(() {});
} while (pourcentageUploaded < 1);
pourcentageUploaded = 0.4;
setstate(() {});
},
),
Center(
child: Text(fileUploaded
? 'Telechargement...'
: 'Veuillez glisser le document ici'),
),
Container(
child: Container(
decoration: BoxDecoration(
color: Colors.transparent),
height: 50,
width: 500,
child: Center(
child: AnimatedContainer(
duration: Duration(seconds: 1),
color: Colors.yellow[100],
height: 50,
width: pourcentageUploaded * 500,
),
),
),
)
],
),
),
),
));

Flutter Google Map Markers are shown only after hot reload - using with cubit and custom marker

I'm struggling second day on this issue.
I use flutter google map to show about hundred custom markers with network image icons, that can be svg or png (using MarkerGenerator).
After opening the map page, MapCubit start to load items from API. In build i have BlocConsumer, where is listener, that build markers when loaded in that cubit and builder that build GoogleMap.
Problem is, that on first opening of page there are no images in markers, only white circle. When I tried to set one image url to all markers, it was loaded properly. Then, when i go on previous page or hot reload (not always), icons are there. On same page i have legend, that draw images from same urls, where images are set properly in most times. Sometimes it is need to go back and forward more times.
I can load icons after click on item in filter, that calls MapCubit, too.
I dont know, if it means something, but next problem, what i have is, that on release and appbundle build, no map is shown, only grey screen, buttons on side and google logo on bottom left.
I tried many tips on internet, but nothing helped.
Preview of first opening of MapPage
Preview of filter at first opening (has all icons)
Preview of second opening of MapPage
Preview of third opening of MapPage (has all icons)
MapPage (MarkerGenerator is in listener and initState becouse of two different uses that needs it)
class _MapAreaState extends State<MapArea> {
MapCubit _mapCubit;
Set<Marker> markers = {};
List<CustomMarker> markerWidgets = [];
bool markersLoaded = false;
#override
void initState() {
_mapCubit = BlocProvider.of<MapCubit>(context);
markers = {};
MarkerGenerator(
_mapCubit.state.items.map((e) => CustomMarker(type: e.type)).toList(),
(bitmaps) {
setState(() {
bitmaps.asMap().forEach((mid, bmp) {
IMapItem item = _mapCubit.state.items[mid];
markers.add(Marker(
markerId: MarkerId(item.title),
position: item.latLng,
icon: BitmapDescriptor.fromBytes(bmp),
// markerId: MarkerId(item.title),
// position: item.latLng,
onTap: () async {
await _mapCubit.showDetail(item);
}));
});
});
}).generate(context);
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
color: tercialBackgroundColor,
child: BlocConsumer<MapCubit, MapState>(
bloc: _mapCubit,
listener: (context, state) {
if (state.changedItems && state.items.isNotEmpty) {
markerWidgets = _mapCubit.state.items
.map((e) => CustomMarker(type: e.type))
.toList();
markers = {};
MarkerGenerator(markerWidgets, (bitmaps) {
setState(() {
bitmaps.asMap().forEach((mid, bmp) {
log(bmp.toString());
IMapItem item = _mapCubit.state.items[mid];
markers.add(Marker(
markerId: MarkerId(item.title),
position: item.latLng,
icon: BitmapDescriptor.fromBytes(bmp),
// markerId: MarkerId(item.title),
// position: item.latLng,
onTap: () async {
await _mapCubit.showDetail(item);
}));
});
});
}).generate(context);
}
},
builder: (context, state) {
return Stack(
children: [
GoogleMap(
zoomControlsEnabled: false,
compassEnabled: false,
markers: markers,
// markers: Set<Marker>.of(state.markers),
initialCameraPosition: CameraPosition(
target: state.items.length == 1
? state.items[0].latLng
: LatLng(49.07389317899512, 19.30980263713778),
zoom: 8.5,
),
minMaxZoomPreference: MinMaxZoomPreference(8, 22),
cameraTargetBounds: CameraTargetBounds(LatLngBounds(
northeast: LatLng(50.16477808289659, 20.56397637952818),
southwest: LatLng(48.75267922516721, 18.76330228064009),
)),
onMapCreated: (GoogleMapController controller) {
if (!_mapCubit.controller.isCompleted) {
rootBundle
.loadString('assets/googleMapsStyle.json')
.then((string) async {
controller.setMapStyle(string);
});
_mapCubit.controller.complete(controller);
log(_mapCubit.controller.toString());
log(controller.toString());
setState(() {
});
}
},
),
// if(state.items.isEmpty)
// FullScreenLoadingSpinner()
],
);
},
),
);
}
}
CustomMarker class
class CustomMarker extends StatelessWidget {
final ItemType type;
const CustomMarker({Key key, this.type}) : super(key: key);
#override
Widget build(BuildContext context) {
// precachePicture(
// svgPicture.pictureProvider,
// Get.context!,
// );
// if(type.icon is /-
return Stack(
clipBehavior: Clip.none,
children: [
Icon(
Icons.add_location,
color: type.color,
size: 56,
),
Positioned(
left: 16,
top: 10,
child: Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: primaryBackgroundColor,
borderRadius: BorderRadius.circular(10)),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Center(child: type.icon),
),
),
),
],
);
}
}
Icon setting in ItemType factory, that is used in CustomMarker
icon: map['icon'] != null
? (map['icon'] is Image
? map['icon']
: (map['icon'].substring(map['icon'].length - 4) == '.svg'
? WebsafeSvg.network(
map['icon'],
width: 18,
height: 18,
color: Colors.black,
placeholderBuilder: (BuildContext context) => Container(
padding: const EdgeInsets.all(30.0),
child: const CircularProgressIndicator()),
)
: Image.network(map['icon'])))
Lately somewhen this exception is in console
======== Exception caught by image resource service =====================
The following HttpException was thrown resolving an image codec:
, uri = https://www.xxx.sk/images/svgs/culture.png
When the exception was thrown, this was the stack:
Image provider: NetworkImage("https://www.xxx.sk/images/svgs/culture.png", scale: 1.0)
Image key: NetworkImage("https://www.xxx.sk/images/svgs/culture.png", scale: 1.0)
I dont know, what all to send, so far at least this. Thanks.

Flutter InAppWebView does not allow non english content in textfield

I'm having a weird issue with the Flutter InAppWebView plugin version 4.0.0+4 here https://pub.dev/packages/flutter_inappwebview where I try to load the simple contact us form into the plugin and realize that I can't enter the content into html input text field if I use non English keyboard, in my case I use Vietnamese keyboard. If I switch the keyboard to English one then its working. I double checked the contact us form and made sure its working 100% on Chrome browser outside of the Flutter app using even non English keyboard. I don't use any special code or settings for the plugin, just same as the one mentioned in the pub.dev. I'm using Flutter channel stable v. 1.22.6
This is my code in case you need it:
class WebViewerWidget extends StatefulWidget {
final Map<String, String> metaData;
WebViewerWidget({this.metaData});
#override
_WebViewerWidgetState createState() => _WebViewerWidgetState();
}
class _WebViewerWidgetState extends State<WebViewerWidget> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
InAppWebViewController _webviewCtrl;
double progressIndicator = 0;
return Scaffold(
backgroundColor: ColorPalette.white,
appBar: PreferredSize(
child: TopNavWidget(
title: widget.metaData['title'] ?? '',
),
preferredSize: Size.fromHeight(50.0),
),
body: Builder(
builder: (BuildContext context) {
return Container(
child: Column(
children: [
Container(
child: progressIndicator < 1
? LinearProgressIndicator(
value: progressIndicator,
backgroundColor: Colors.black12,
valueColor:
AlwaysStoppedAnimation<Color>(Colors.blue),
)
: Container()),
Expanded(
child: InAppWebView(
initialUrl: widget.metaData['url'] ?? 'about:blank',
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
javaScriptEnabled: true,
useShouldInterceptAjaxRequest: true,
useShouldInterceptFetchRequest: true,
),
ios: IOSInAppWebViewOptions(),
android: AndroidInAppWebViewOptions(),
),
onWebViewCreated:
(InAppWebViewController webviewController) {
_webviewCtrl = webviewController;
},
onProgressChanged:
(InAppWebViewController controller, int progress) {
setState(() {
progressIndicator = progress / 100;
});
},
),
),
],
),
);
},
));
}
}
Thanks.
Ok, after spending a couple days fixing the issue, I had to give up on this one. Its definitely a bug from the plugin, found someone had the similar issue here https://github.com/pichillilorenzo/flutter_inappwebview/issues/560. I then tried another plugin called WebView https://pub.dev/packages/webview_flutter and it worked perfectly.
This has been fixed with new version 5.0.0 (the latest version now is 5.0.5+3): use useHybridComposition: true Android-specific webview option, all the issues related to the Android keyboard are fixed.

why the SmartRefresher does not work in flutter

Now I am using SmartRefresher to refresh my app when pull down article list, I add pull_to_refresh dependencies in pubspec.yaml like this:
pull_to_refresh: 1.6.3
and this is my code:
child: CupertinoScrollbar(
child: SmartRefresher(
onRefresh: _onRefresh,
enablePullUp: true,
enablePullDown: true,
header: WaterDropMaterialHeader(),
controller: _refreshController,
onLoading: _loadingMoreArticle,
footer: CustomFooter(
builder: (BuildContext context, LoadStatus mode) {
Widget body;
if (mode == LoadStatus.idle) {
body = Text("上拉加载更多");
} else if (mode == LoadStatus.loading) {
body = CupertinoActivityIndicator();
} else if (mode == LoadStatus.failed) {
body = Text("加载失败!点击重试!");
} else if (mode == LoadStatus.canLoading) {
body = Text("release to load more");
} else {
body = Text("No more Data");
}
return Container(
height: 55.0,
child: Center(child: body),
);
},
),
child: CupertinoScrollbar(
child: CustomScrollView(
controller: scrollController,
slivers: <Widget>[
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context,
),
),
if (state.articleListState.articleIds != null && state.articleListState.articleIds.length > 0)
SliverPadding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
sliver: viewService.buildComponent("articlelist"),
)
],
)))));
but the UI does not contain any effect of SmartRefresher, the header shows nothing when pull, and the footer shows nothing when push up, am I missing something? what should I do to fix it? Now I am using macOS Catalina 10.15.7 and Android Studio 4.1.2.
$ dart --version
Dart SDK version: 2.10.2 (stable) (Tue Oct 13 15:50:27 2020 +0200) on "macos_x64"
(base)
$ ~/apps/flutter/bin/flutter --version
Flutter 1.22.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7891006299 (7 weeks ago) • 2020-12-10 11:54:40 -0800
Engine • revision ae90085a84
Tools • Dart 2.10.4
(base)
this is the header shows when pull down:
The SmartRefresher needs to be higher up the widget tree than other scrolling widgets which will conflict/override the pull up/pull down action for the refresher. You can wrap your entire widget tree in a container(full width and height of the screen) and apply the SmartRefresher to that with everything else a child, or test out moving the refresher further up the widget tree.