您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
Flutter for iOS 开发者(视频播放详情页)
发布时间:2026-07-25 00:33:33编辑:雪饮阅读()
-
官方文档是这个
https://docs.flutter.dev/flutter-for/swiftui-devs
swift即是ios使用的开发语言
主要说的就是在swift中的一些实现,对应在flutter中具体怎么实现的。
那么今天这里就忽略了,可以直接去看文档。
现在完成下上次没有完成的播放视频部分。
这次最大的麻烦依旧是与翻墙相关,其实有的依赖,尤其是AGP底层是硬编码,所以无法使用国内镜像。
首先要引入播放器
D:\flutterDemo\flutterDemo1\flutter_application_1\pubspec.yaml:
name: flutter_application_1
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: ^3.12.2
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
http: ^1.2.0
video_player: ^2.9.3
chewie: ^1.10.0
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^6.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/to/asset-from-package
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/to/font-from-package
然后之前的搜索结果页要引入详情页组件
D:\flutterDemo\flutterDemo1\flutter_application_1\lib\search_result_table.dart:
import 'detail_page.dart';
然后之前的“详情”按钮要点击后跳转到播放页
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(
id: id,
type: type,
title: title,
auth: authorizationController.text,
imageBytes: _imageDataUris[index],
),
),
);
},
child: const Text('详情'),然后接下来就是详情页detail_page.dart:
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';
class DetailPage extends StatefulWidget {
final String id;
final int type;
final String title;
final String auth;
final Uint8List? imageBytes;
const DetailPage({
super.key,
required this.id,
required this.type,
required this.title,
required this.auth,
this.imageBytes,
});
@override
State<DetailPage> createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
VideoPlayerController? _videoController;
ChewieController? _chewieController;
String? _errorMessage;
bool _isLoading = true;
@override
void initState() {
super.initState();
_fetchDetail();
}
@override
void dispose() {
_videoController?.dispose();
_chewieController?.dispose();
super.dispose();
}
Future<void> _fetchDetail() async {
final url = Uri.parse('https://social-server.6wlua.com/Social/Trend/Read');
try {
final response = await http.post(
url,
headers: {
'Content-Type': 'application/json',
'Authorization': widget.auth,
'x-bundle-info': '1, com.xingba.web.online',
},
body: jsonEncode({'for_id': widget.id, 'type': 1}),
);
debugPrint('详情页响应状态码: ${response.statusCode}');
debugPrint('详情页响应数据: ${response.body}');
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
final link = data['msg']['videos'][0]['link'];
final videoUrl = '${link['domain']}${link['path']}';
debugPrint('视频播放链接: $videoUrl');
_videoController = VideoPlayerController.networkUrl(
Uri.parse(videoUrl),
);
await _videoController!.initialize();
_chewieController = ChewieController(
videoPlayerController: _videoController!,
autoPlay: true,
looping: false,
allowFullScreen: true,
);
if (mounted) {
setState(() {
_isLoading = false;
});
}
} else {
setState(() {
_isLoading = false;
_errorMessage = '请求失败,状态码: ${response.statusCode}';
});
}
} catch (e) {
debugPrint('详情页请求失败: $e');
if (mounted) {
setState(() {
_isLoading = false;
_errorMessage = '请求失败: $e';
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Column(
children: [
if (widget.imageBytes != null)
Image.memory(widget.imageBytes!, fit: BoxFit.contain, height: 200),
Expanded(child: _buildBody()),
],
),
);
}
Widget _buildBody() {
if (_isLoading) {
return const Center(child: CircularProgressIndicator());
}
if (_errorMessage != null) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(_errorMessage!, textAlign: TextAlign.center),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
setState(() {
_isLoading = true;
_errorMessage = null;
});
_fetchDetail();
},
child: const Text('重试'),
),
],
),
);
}
if (_chewieController != null) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Chewie(controller: _chewieController!),
);
}
return const Center(child: Text('暂无视频资源'));
}
}由于详情页引入了播放器组件所以相关依赖要调整下,仅支持AGP9之前的版本
D:\flutterDemo\flutterDemo1\flutter_application_1\android\settings.gradle.kts:
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
maven { url = uri("https://maven.aliyun.com/repository/google") }
maven { url = uri("https://maven.aliyun.com/repository/central") }
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
maven { url = uri("https://maven.aliyun.com/repository/public") }
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.0" apply false
id("org.jetbrains.kotlin.android") version "2.2.0" apply false
}
include(":app")以及D:\flutterDemo\flutterDemo1\flutter_application_1\android\build.gradle.kts:
allprojects {
repositories {
mavenLocal()
maven { url = uri("https://maven.aliyun.com/repository/google") }
maven { url = uri("https://maven.aliyun.com/repository/central") }
maven { url = uri("https://maven.aliyun.com/repository/public") }
}
}
val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}以及gradle要降低版本,并为了优化每次从网络拉取耗费时间,所以修改为本地直接取(提前下载好)D:\flutterDemo\flutterDemo1\flutter_application_1\android\gradle\wrapper\gradle-wrapper.properties:
distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=file\:///D:/software/gradle/gradle-8.9-all.zip然后是D:\flutterDemo\flutterDemo1\flutter_application_1\android\app\build.gradle.kts:
plugins {
id("com.android.application")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.example.flutter_application_1"
compileSdk = flutter.compileSdkVersion
ndkVersion = "30.0.15729638"
buildToolsVersion = "36.0.0"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.flutter_application_1"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
android {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
}
flutter {
source = "../.."
}
因为暂时没有mac实体机,所以搭建vmware的mac13.5虚拟机,具体可以参考
https://www.gaojiupan.cn/manshenghuo/chengxurensheng/5540.html
但文中使用了vmware16 pro的,我发现我用vmware17(VMware® Workstation 17 Pro)就默认支持,不用解锁
然后安装xcode15
可以参考
https://www.gaojiupan.cn/manshenghuo/chengxurensheng/5543.html
然后刚打开发现默认居然没有可以运行的ios模拟器,我下载了ios17,但下载了好几次看到都失败了,我家里网络慢,有次下载的时候我一边玩游戏去了,那次应该是最长的最后游戏完毕后回来发现还是失败

但后面发现我运行iPhone15模拟器显示的是ios17(就奇怪,实际下载成功了?暂时没有纠结了),接下来在mac的终端中安装git
xy@xydeMac ~ % xcode-select --install
xcode-select: note: install requested for command line developer tools
这里提示要先安装命令行开发工具,于是回到mac中会看到有个提示,问你是否要安装,点击确定后开始安装

也是够久的。
终于下载完成,再次安装git又报错误
xy@xydeMac ~ % xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" in System Settings to install updates

大概意思是要更新这个,不过最好先做下快照,这种系统级别的更新有点可怕。
尤其是在虚拟机环境下。

又是漫长的更新。我的mini主机,散热不太好的原因吧,更新到大概80-90%的时候显示器不亮了,把主机关机让其冷却后,重新开机,现在又开始再次更新了。

这里后面又卡死了,最后重启后再次开机又更新了一个什么,结果物理机又出现了显示器上面一堆错误代码。
看来这东西需要真实mac物理机,我这里没有,暂且就先这样了。
关键字词:flutter,ios,开发者,视频播放