Having a shopping cart icon on the right side of the AppBar on Flutter it’s not that hard, you can use basically a stack widget and inside the stack get IconButton and Positioned widgets.
Here is the code and screenshot
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(appBarTitle),
actions: [
Stack(
children: [
IconButton(
onPressed: () {},
icon: const Icon(
Icons.shopping_cart_rounded,
size: 30,
),
),
Positioned(
top: 4,
right: 6,
child: Container(
height: 22,
width: 22,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.purple,
),
child: const Center(
child: Text(
"2",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
),
)),
),
),
],
),
],
)
Downloading PDF file in the user download directory on Android is a very common feature, a lot of app uses PDF viewing and downloading feature.
I hoped that flutter plugins could solve my problem but they didn’t. Fortunately, it was working great on iOS but it was not on android. So I decided to use my old java code in Flutter using Method Channel.
First I tried two Flutter plugins one for permission and one for creating a directory.
Request permission was very easy and it worked on both iOS and Android
Future<bool> _requestWritePermission() async {
await Permission.storage.request();
var r = await Permission.storage.request();
return r.isGranted;
}
Since it was working on iOS, I decided to leave that code and separate platform code by importing ‘dart:io’ show Platform. Use this code on your onTap action.
static const channel = MethodChannel('com.flutterframework/test');
bool hasPermission = await _requestWritePermission();
if (hasPermission) {
if (Platform.isAndroid) {
final int downloader = await channel.invokeMethod(
'download',
<String, String>{'title': title, 'pdf': pdf},
);
print(downloader);
}
if (Platform.isIOS) {
var dir = await getApplicationDocumentsDirectory();
if (dir != null) {
String saveName = "$title.pdf";
String savePath = "${dir.path}/$saveName";
print(savePath);
try {
await Dio().download(pdf, savePath,
onReceiveProgress: (received, total) {
if (total != -1) {
var percentage = (received / total * 100);
print(percentage);
if (percentage >= 100.0) {
ScaffoldMessenger.of(context).showSnackBar(
snackMessage(
'Download completed, please open Files app.'));
}
}
});
print("File is saved to download folder.");
} on DioError catch (e) {
ScaffoldMessenger.of(context).showSnackBar("Download error");
}
}
}
} else {
ScaffoldMessenger.of(context).showSnackBar(filePermissionError);
}
Finally, the Java code, create a Java class in your main directory.
package your_package;
import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
public class DownloadHelper {
public static void downloadPDF(Context context, String title, String pdfUrl) {
try {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(pdfUrl));
request.setDescription("MyApp");
request.setTitle(title);
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
if (Build.VERSION.SDK_INT <= 17) {
request.setDestinationInExternalFilesDir(context, "Documents", "MyFolder/" + title + ".pdf");
} else {
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "MyFolder/" + title + ".pdf");
}
// get download service and enqueue file
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
Call that Java code from MainActivity, my MainActivity in Kotlin
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.flutterframework/test";
private lateinit var channel: MethodChannel
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
channel.setMethodCallHandler { call, result ->
if (call.method == "download") {
val pdfTitle = call.argument<String>("title")
val pdfUrl = call.argument<String>("pdf")
Log.d("TAG", pdfTitle.toString());
Log.d("TAG", pdfUrl.toString());
DownloadHelper.downloadPDF(this, pdfTitle, pdfUrl);
}
}
}
}
As a flutter developer, there are not many things you can do on Xcode since Flutter itself builds everything for you but why not learn some app development with Swift and Xcode.
Swift is a deep and large language and I find it complex, when I learned Objective-C back in 2010 with Xcode 3.x that was very hard to start but later it became easy for me.
Today there is no reason to start learning Objective-C over Swift unless you have a specific interest.
For Flutter developers, if flutter is your first mobile framework and dart is the first language you may find Swift is complex and hard to start but the idea behind all the languages is the same you just have to learn the syntax. Of course, some languages have specific features for some reasons.
I have a series of videos for Flutter developers who want to learn Swift App Development with Xcode. For running Xcode you just need a Mac computer. Running Xcode on any Mac will work, most of the time you don’t need a very powerful Mac.
I’m very new to making videos and teaching programming to others, if you find anything wrong, just let me know in the comments. Also if you can subscribe to my channel and like the video, I’m gonna appreciate that.
So this is the first video, there going to be a few more videos. We are going to make an app with a login page and list page. We also going to use some APIs which also we are going to make ourselves in PHP.