Nếu bạn truy cập vào bài viết này để tìm hiểu cách đưa hình ảnh, phông chữ hoặc các asset khác vào ứng dụng Flutter của mình, thì có thể bạn đã nhầm chỗ. Đùa thôi bạn có thể xem video ở bên dưới nhé! Còn bài viết này mình sẽ hướng dẫn các bạn sử dụng asset trong package (thư viện) của người ta.
1. Bạn nên đặt các asset ở đâu?
Bạn có một hình ảnh, phông chữ hoặc thứ gì đó muốn cung cấp cho các lập trình viên khác sử dụng khi họ dùng package của bạn. Vậy câu hỏi đặt ra là bạn nên đặt nó ở đâu?
Bạn có thể đặt nó vào trong thư mục lib/. Bình thường bạn hay tạo folder assets ở ngoài root project đúng không? Nhưng khi bạn tạo package cho người khác sử dụng thì bạn nên bỏ các assets vào folder lib luôn để họ dễ theo dõi.
Mọi thứ trong thư mục lib/ sẽ được tự động đóng gói với ứng dụng. Những asset đó sẽ có sẵn cho bất kỳ ai sử dụng package của bạn. Với một package developer, bạn thậm chí không cần phải khai báo những asset đó trong pubspec.yaml nếu bạn không sử dụng. Chúng vẫn được đóng gói cùng với package.
Sự lựa chọn khác là tạo một thư mục mới trong dự án chính. Gọi nó là assets hoặc fonts hoặc bất cứ điều gì bạn muốn.
Tuy nhiên, bất kỳ asset nào không có trong thư mục lib/ sẽ không được thêm vào assets bundle của package trừ khi bạn khai báo chúng trong file pubspec.yaml:
flutter:
assets:
- assets/my_image.jpg
fonts:
- family: MyFontFamily
fonts:
- asset: assets/my_font.ttf
Bạn có thể xem một số ví dụ để có thể hiểu cách hoạt động của điều này. Tôi sẽ chỉ cho bạn bốn package Flutter khác nhau trên Pub.dev mà mỗi package thực hiện hơi khác một chút. Bạn sẽ thấy cách mà assets được sử dụng như thế nào từ cả quan điểm của tác giả và người dùng package đó.
2. Ví dụ 1: shrine_images
Package shrine_images không thực sự hữu ích ngoài việc cung cấp image assets cho ứng dụng Shrine, một phần của ứng dụng demo Flutter Gallery . Nhưng nó hữu ích khi chỉ ra cách đưa assets vào package Flutter và có lẽ đó là mục đích chính của nó.
Package developer đặt tất cả các asset trong thư mục lib/ như sau:
shrine_images/lib/
2.0x/
0-0.jpg
1-0.jpg
10-0.jpg
...
3.0x/
0-0.jpg
1-0.jpg
10-0.jpg
...
0-0.jpg
1-0.jpg
10-0.jpg
...
Ba density versions khác nhau của mỗi hình ảnh tồn tại. Không có gì khác trong thư mục lib/ ngoại trừ những hình ảnh này. Nếu bạn nhìn vào tệp pubspec.yaml, không có bất kỳ asset nào được đề cập đến. Chỉ cần đưa chúng vào thư mục lib/ là đủ.
2.1 Các developer sử dụng asset trong package như thế nào
Hơi khó để theo cách ứng dụng Shrine sử dụng package, vì vậy, tôi sẽ tạo một ứng dụng đơn giản sử dụng package shrine_images. Khai báo package đó trong file pubspec.yaml
như sau:
name: flutter_assets
description: A Flutter app.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
shrine_images: ^1.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- packages/shrine_images/10-0.jpg
Lưu ý hai điều:
- Tôi đã thêm
shrine_images: ^1.1.2
như một dependency. - Tôi đã thêm
— packages/shrine_images/10–0.jpg
dưới flutter assets. Bạn bắt đầu vớipackage/
. Sau đó, bạn cho biết tên package (trong trường hợp này làshrine_images
). Sau đó, bạn cung cấp vị trí và tên tệp trong thư mục lib/. Bạn không thêmlib
bởi vì điều đó được giả định. Tôi chỉ sử dụng một hình ảnh trong ứng dụng đơn giản của mình. Nếu tôi sử dụng nhiều hình ảnh hơn, tôi sẽ phải liệt kê chúng riêng lẻ (giống như ứng dụng Shrine). Bạn không thể chỉ định thư mục giống như với local assets.
File main.dart của tôi trông giống như sau:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Center(
child: Image(
image: AssetImage(
'10-0.jpg',
package: 'shrine_images',
),
),
),
),
);
}
}
Lưu ý rằng bạn không cần phải khai báo thư viện shrine_images ở đầu file.Để có được hình ảnh, bạn sử dụng AssetImage
và cung cấp cho nó tên asset và tên package. Dưới đây là code minh hoạ.
AssetImage('10-0.jpg', package: 'shrine_images')
Bạn chạy ứng dụng thì sẽ thấy như thế này
3. Ví dụ 2: font_awesome_flutter
Package font_awesome_flutter cung cấp một bộ phông chữ với rất nhiều icon hữu ích. Các phông chữ được đóng gói sẵn trong package.
Package này đặt các font asset trong một thư mục con của lib/ như thế này:
font_awesome_flutter/lib/
font/
fa-brands-400.ttf
fa-regular-400.ttf
fa-solid-900.ttf
font_awesome_flutter.dart
icon_data.dart
Tuy nhiên, vì lập trình viên đang sử dụng các asset trong logic package, họ cũng khai báo các phông chữ dưới dạng asset trong tệp pubspec.yaml:
flutter:
fonts:
- family: FontAwesomeBrands
fonts:
- asset: lib/fonts/fa-brands-400.ttf
weight: 400
- family: FontAwesomeRegular
fonts:
- asset: lib/fonts/fa-regular-400.ttf
weight: 400
- family: FontAwesomeSolid
fonts:
- asset: lib/fonts/fa-solid-900.ttf
weight: 900
Và đây là một đoạn code của nó được sử dụng trong file icon_data.dart:
class IconDataBrands extends IconData {
const IconDataBrands(int codePoint)
: super(
codePoint,
fontFamily: 'FontAwesomeBrands',
fontPackage: 'font_awesome_flutter',
);
}
Package đã làm sẵn điều này giúp người dùng package cảm thấy dễ dàng hơn rất nhiều khi sử dụng.
3.1 Các developer sử dụng asset trong package như thế nào
Lập trình viên ứng dụng chỉ cần thêm font_awesome_flutter vào file pubspec.yaml của ứng dụng.
dependencies:
font_awesome_flutter: ^8.5.0
Không cần phải khai báo bất kỳ font asset nào. Lập trình viên ứng dụng thậm chí không cần biết tên của các tệp phông chữ.
Bạn chỉ cần import package và sử dụng trực tiếp. Đây là file main.dart cho một bản demo đơn giản:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Center(
child: IconButton(
icon: Icon(FontAwesomeIcons.wordpress),
iconSize: 100,
onPressed: (){},
),
),
),
);
}
}
Bạn chỉ cần truyền dữ liệu FontAwesomeIcons.wordpress
vào một Icon widget. Điều này giúp cho công việc của lập trình viên ứng dụng trở nên cực kỳ dễ dàng. Chạy ứng dụng ngay bây giờ, bạn sẽ thấy:
4. Ví dụ 3: crypto_font_icons
Package crypto_font_icons tương tự như font_awesome_flutter ở chỗ nó cung cấp một phông chữ tùy chỉnh cho các lập trình viên ứng dụng sử dụng. Lý do tôi đề cập đến nó là package developer đã sử dụng một cấu trúc thư mục khác.
Thay vì đặt font vào thư mục lib/, package developer đã tạo một thư mục fonts trong thư mục package chính như thế này:
cryptofont-flutter/
font/
cryptofont-webfont.ttf
lib/
crypto_font_icon_data.dart
crypto_font_icons.dart
Sau đó, pubspec.yaml trông như thế này:
flutter:
fonts:
- family: CryptoFont
fonts:
- asset: font/cryptofont-webfont.ttf
Bằng cách liệt kê phông chữ dưới dạng asset trong pubspec.yaml, nó vẫn được đưa vào gói asset và do đó sẽ có sẵn cho các lập trình viên ứng dụng sử dụng package này.
4.1 Các developer sử dụng asset trong package như thế nào
Từ quan điểm của lập trình viên ứng dụng, không có vấn đề gì khi package developer không đặt asset vào thư mục lib/. Đó là tất cả những gì được package giấu đi. Chỉ cần phụ thuộc vào nó
dependencies:
crypto_font_icons: ^0.1.0+1
Và sử dụng nó giống như chúng ta đã làm trong ví dụ font_awesome_flutter ở trên.
import 'package:crypto_font_icons/crypto_font_icons.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Center(
child: IconButton(
icon: Icon(CryptoFontIcons.BTC),
iconSize: 100,
onPressed: (){},
),
),
),
);
}
}
Điều này cho ra:
5. Ví dụ 4: mongol
Trong phiên bản gốc của bài viết này, tôi chỉ có ba ví dụ. Trình bày những ví dụ này giúp tôi học cách tự làm điều đó. Tuy nhiên, tôi đã phát hiện ra khi làm việc trên package rằng các ví dụ trên không đề cập đến cách cung cấp phông chữ. Ví dụ 1 sử dụng widget AssetImage
để chỉ định package và ví dụ 2 và 3 sử dụng widget IconData
để chỉ định package. Nhưng tôi muốn chia sẻ toàn bộ một phông chữ.
Package của tôi được gọi là mongol. Bạn sẽ không bao giờ sử dụng nó trừ khi bạn là một trong số ít lập trình viên Flutter tạo ứng dụng cho vertical Mongolian text. Tuy nhiên, vì source code nằm trên GitHub, bạn có thể thấy cách tôi cung cấp tệp phông chữ (không chỉ icon data) cho người dùng package.
Tôi đã đưa tệp phông chữ Mongolian (Mông Cổ) vào thư mục lib như thế này:
mongol
lib/
fonts/
MQG8F02.ttf
Vì nó nằm trong thư mục lib/ nên nó sẽ tự động được đưa vào gói package. Nhưng vì tôi đang sử dụng nó trong package code để đặt làm phông chữ mặc định cho widget MongolText
, tôi cũng đã khai báo nó trong pubspec.yaml:
flutter:
fonts:
- family: MenksoftQagan
fonts:
- asset: lib/fonts/MQG8F02.ttf
MenksoftQagan
là tên mô tả. Tôi có thể đã gọi font family là HappyHippos
nếu tôi muốn Mẹo tiếp theo là làm thế nào để cung cấp quyền truy cập vào phông chữ đó. Sử dụng MenksoftQagan
là không đủ vì không chứa thông tin package. Cách giải quyết là sử dụng string pattern sau khi font family cần thiết:
'packages/<package_name>/<font_family_name>'
Đối với package của tôi, điều này được dịch sang
'packages/mongol/MenksoftQagan'
Trong package code, tôi đã tạo một class cho điều này:
class MongolFont {
static const String qagan = 'packages/mongol/MenksoftQagan'; }
5.1 Các developer sử dụng asset trong package như thế nào
Vì package sử dụng string 'packages/mongol/MenksoftQagan' trong nội bộ, người dùng package hoàn toàn không cần biết về nó.
Khai báo thư viện trong file pubspec.yaml:
dependencies:
mongol: ^0.3.0
main.dart:
import 'package:flutter/material.dart';
import 'package:mongol/mongol_text.dart';
void main() => runApp(DemoApp());
class DemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('My App')),
body: Stack(
children: <Widget>[
Center(
child: MongolText(
'ᠮᠣᠩᠭᠣᠯ',
style: TextStyle(fontSize: 100),
),
),
],
),
),
);
}
}
Chạy ứng dụng mang lại điều này
Tuy nhiên, nếu người dùng ứng dụng muốn sử dụng trực tiếp tệp phông chữ, họ có thể sử dụng string 'packages/mongol/MenksoftQagan'
để truy cập nó. Ví dụ: thay thế widget MongolFont
bằng widget Text
chuẩn:
Text(
'ᠮᠣᠩᠭᠣᠯ',
style: TextStyle(
fontFamily: 'packages/mongol/MenksoftQagan',
fontSize: 100,
),
),
Nó cho ra:
Để được trợ giúp khi truy cập các loại tệp khác, hãy xem phần Hỏi và Đáp về Stack Overflow này.
Tóm lại:
Thật tuyệt khi các package Pub là open source để chúng ta có thể học hỏi bằng cách xem người khác giải quyết vấn đề tương tự như thế nào. Nếu bạn có cách để cải thiện quy trình thêm asset vào một package, trước tiên hãy kiểm tra vấn đề GitHub này. Và nếu có bất kỳ cải tiến hoặc thông tin nào có thể thêm vào bài viết này, vui lòng cho 200Lab biết nhé.
Bài viết được dịch từ đây.
Kieu Hoa
Khi mình yêu cuộc đời, cuộc đời cũng sẽ yêu mình đắm say