老鐵記得 轉發 ,貓哥會呈現更多 Flutter 好文~~~~
微信群 ducafecat
b 站 https://space.bilibili.com/40...
原文
https://medium.com/geekcultur...
程式碼
https://github.com/jagrut-18/...
參考
- https://pub.dev/packages/camera
正文
在許多應用程式中,我們需要使用者透過點選圖片上傳圖片。為此,我們可以使用裝置的預設攝像頭應用程式,但如果我們需要整合一個應用程式內的攝像頭呢?那麼,這也是可能的 Flutter 。小組已經開發了一個叫做攝像頭的 https://pub.dev/packages/camera ,它可以讓我們做到這一點。
建立專案
首先,透過在 pubspec.yaml 檔案中新增以下行,將 camera 包安裝到專案中。
camera: ^0.8.1+3
- IOS 設定
這個外掛需要 IOS 10.0 或更高版本。在 Info.plist 檔案中新增以下行來設定內容。
<key>NSCameraUsageDescription</key>
<string>Can I use the camera please?</string>
<key>NSMicrophoneUsageDescription</key>
<string>Can I use the mic please?</string>
- Android Setup
在 Android/app/build.gradle 檔案中將 Android sdk 最小版本更改為 21(或更高版本)。
minSdkVersion 21
現在我們的專案設定完成了,我們可以開始編寫應用程式了。
我們將在應用程式中建立兩個螢幕。
1.CameraScreen ー此螢幕將顯示相機輸出並拍攝圖片
2.GalleryScreen ー這個螢幕將在網格檢視中顯示捕獲的圖片。
裝載攝像頭
為了顯示相機預覽,我們需要首先載入相機。為此,轉到 main.dart 檔案中的 main 函式和 runApp 上面的這些行。
WidgetsFlutterBinding.ensureInitialized(); //Ensure plugin services are initializedfinal cameras = await availableCameras(); //Get list of available cameras
現在我們有了相機列表,我們需要把它們傳遞給我們的相機/螢幕。
所以,攝像機會像這樣透過
經過這一切之後,這就是 main.dart 的樣子。
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'camera_screen.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
runApp(MyApp(cameras: cameras));
}
class MyApp extends StatelessWidget {
final List<CameraDescription> cameras;
const MyApp({Key? key, required this.cameras}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Camera App',
home: CameraScreen(cameras: cameras),
);
}
}
CameraScreen
這個螢幕的佈局很簡單。在頂部我們將顯示實時相機預覽和在底部將有三個按鈕(交換相機,捕獲和顯示畫廊)。
建立一個有狀態小部件 CameraScreen。
我們將建立四個變數,
我們必須設定 selectedCamera = 0,從後置攝像頭開始。如果裝置有多於 1 個攝像頭,我們可以透過更改這個索引切換到它。
現在讓我們建立一個方法來初始化選定的相機。
在此方法中,我們將傳遞要初始化的攝像機索引。使用透過的攝像機列表,我們將載入具體的相機與解析度的選擇。
使用這個方法,我們將初始化 initState 中的後置攝像頭。
別忘了丟掉相機控制器。
- 現在讓我們構建 UI。
為了顯示 CameraPreview,我們將使用以下程式碼。
FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
),
好了,現在我們要連續顯示三個按鈕。
開關/攝像頭按鈕
首先是開關攝像頭圖示按鈕。點選這個按鈕,攝像頭應該在前後之間切換。
為此,我們將使用相同的 initializeCamera 方法,但這一次 cameraIndex 將是動態的。cameraIndex 後置攝像頭為 0,前置攝像頭為 1(如果有前置攝像頭的話)。
在點選,我們將檢查裝置是否有多個攝像頭,如果沒有,我們將顯示一個帶有訊息的 snackbar。
IconButton(
onPressed: () {
if (widget.cameras.length > 1) {
setState(() {
selectedCamera = selectedCamera == 0 ? 1 : 0;//Switch camera
initializeCamera(selectedCamera);
});
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('No secondary camera found'),
duration: const Duration(seconds: 2),
));
}
},
icon: Icon(Icons.switch_camera_rounded, color: Colors.white),
),
捕捉按鈕
為了顯示捕獲按鈕,我使用了一個半徑為 60 的簡單白色圓圈。點選後,我們將使用相機控制器拍攝一張照片並將其新增到 captureImages 陣列中。
GestureDetector(
onTap: () async {
await _initializeControllerFuture; //To make sure camera is initialized
var xFile = await _controller.takePicture();
setState(() {
capturedImages.add(File(xFile.path));
});
},
child: Container(
height: 60,
width: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
),
),
顯示畫廊按鈕
這個按鈕非常簡單,我們將顯示從 capturedmages 陣列拍攝的最後一張圖片,當單擊時,它將導航到 GalleryScreen。
GestureDetector(
onTap: () {
if (capturedImages.isEmpty) return; //Return if no image
Navigator.push(context,
MaterialPageRoute(
builder: (context) => GalleryScreen(
images: capturedImages.reversed.toList())));
},
child: Container(
height: 60,
width: 60,
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
image: capturedImages.isNotEmpty
? DecorationImage(image: FileImage(capturedImages.last), fit: BoxFit.cover)
: null,
),
),
),
如您所見,GalleryScreen 接受捕獲的影像列表,因此我們可以在 gridview 中顯示它們。讓我們完成這一部分來看看應用程式的執行情況。
GalleryScreen
這是非常直接的螢幕。獲取影像列表並在 GridView 中顯示它們。
import 'dart:io';
import 'package:flutter/material.dart';
class GalleryScreen extends StatelessWidget {
final List<File> images;
const GalleryScreen({Key? key, required this.images}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Gallery'),
),
body: GridView.count(
crossAxisCount: 3,
mainAxisSpacing: 2,
crossAxisSpacing: 2,
children: images
.map((image) => Image.file(image, fit: BoxFit.cover))
.toList(),
),
);
}
}
Final Product
在構建應用程式之後,這是最終的結果。
攝像頭包也可以捕捉影片,你可以使用 startVideoRecording,pauseVideoRecording 和 stopVideoRecording 方法來捕捉 https://pub.dev/packages/Camera。
這是這個專案的 Github 連結,希望對你有所幫助。
https://github.com/jagrut-18/...
這個就到此為止,希望你喜歡。
© 貓哥
https://ducafecat.tech/
https://github.com/ducafecat
往期
開源
GetX Quick Start
https://github.com/ducafecat/...
新聞客戶端
https://github.com/ducafecat/...
strapi 手冊譯文
https://getstrapi.cn
微信討論群 ducafecat
系列集合
譯文
https://ducafecat.tech/catego...
開源專案
https://ducafecat.tech/catego...
Dart 程式語言基礎
https://space.bilibili.com/40...
Flutter 零基礎入門
https://space.bilibili.com/40...
Flutter 實戰從零開始 新聞客戶端
https://space.bilibili.com/40...
Flutter 元件開發
https://space.bilibili.com/40...
Flutter Bloc
https://space.bilibili.com/40...
Flutter Getx4
https://space.bilibili.com/40...
Docker Yapi
https://space.bilibili.com/40...