接入圈子列表数据,增加视频播放页
This commit is contained in:
parent
e065158817
commit
f3cf90898e
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.5 KiB |
@ -38,12 +38,6 @@ class Call_outLogic extends GetxController {
|
||||
videoPlayerController?.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
videoPlayerController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
|
||||
@ -5,3 +5,170 @@ class CircleState {
|
||||
///Initialize variables
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Lists {
|
||||
List<Album>? album;
|
||||
Chat? chat;
|
||||
String? content;
|
||||
int? id;
|
||||
bool? isQueen;
|
||||
User? user;
|
||||
|
||||
Lists(
|
||||
{this.album, this.chat, this.content, this.id, this.isQueen, this.user});
|
||||
|
||||
Lists.fromJson(Map<String, dynamic> json) {
|
||||
if (json['album'] != null) {
|
||||
album = <Album>[];
|
||||
json['album'].forEach((v) {
|
||||
album!.add(new Album.fromJson(v));
|
||||
});
|
||||
}
|
||||
chat = json['chat'] != null ? new Chat.fromJson(json['chat']) : null;
|
||||
content = json['content'];
|
||||
id = json['id'];
|
||||
isQueen = json['is_queen'];
|
||||
user = json['user'] != null ? new User.fromJson(json['user']) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
if (this.album != null) {
|
||||
data['album'] = this.album!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
if (this.chat != null) {
|
||||
data['chat'] = this.chat!.toJson();
|
||||
}
|
||||
data['content'] = this.content;
|
||||
data['id'] = this.id;
|
||||
data['is_queen'] = this.isQueen;
|
||||
if (this.user != null) {
|
||||
data['user'] = this.user!.toJson();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Album {
|
||||
int? type;
|
||||
String? url;
|
||||
|
||||
Album({this.type, this.url});
|
||||
|
||||
Album.fromJson(Map<String, dynamic> json) {
|
||||
type = json['type'];
|
||||
url = json['url'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['type'] = this.type;
|
||||
data['url'] = this.url;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Chat {
|
||||
String? accountId;
|
||||
int? count;
|
||||
List<Users>? users;
|
||||
|
||||
Chat({this.accountId, this.count, this.users});
|
||||
|
||||
Chat.fromJson(Map<String, dynamic> json) {
|
||||
accountId = json['account_id'];
|
||||
count = json['count'];
|
||||
if (json['users'] != null) {
|
||||
users = <Users>[];
|
||||
json['users'].forEach((v) {
|
||||
users!.add(new Users.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['account_id'] = this.accountId;
|
||||
data['count'] = this.count;
|
||||
if (this.users != null) {
|
||||
data['users'] = this.users!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Users {
|
||||
String? avatar;
|
||||
int? id;
|
||||
String? nickname;
|
||||
|
||||
Users({this.avatar, this.id, this.nickname});
|
||||
|
||||
Users.fromJson(Map<String, dynamic> json) {
|
||||
avatar = json['avatar'];
|
||||
id = json['id'];
|
||||
nickname = json['nickname'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['avatar'] = this.avatar;
|
||||
data['id'] = this.id;
|
||||
data['nickname'] = this.nickname;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
String? avatar;
|
||||
String? city;
|
||||
int? gender;
|
||||
int? id;
|
||||
double? lat;
|
||||
double? lng;
|
||||
String? nickname;
|
||||
int? orientation;
|
||||
int? role;
|
||||
int? vip;
|
||||
|
||||
User(
|
||||
{this.avatar,
|
||||
this.city,
|
||||
this.gender,
|
||||
this.id,
|
||||
this.lat,
|
||||
this.lng,
|
||||
this.nickname,
|
||||
this.orientation,
|
||||
this.role,
|
||||
this.vip});
|
||||
|
||||
User.fromJson(Map<String, dynamic> json) {
|
||||
avatar = json['avatar'];
|
||||
city = json['city'];
|
||||
gender = json['gender'];
|
||||
id = json['id'];
|
||||
lat = json['lat'] ?? 0.0;
|
||||
lng = json['lng'] ?? 0.0;
|
||||
nickname = json['nickname'];
|
||||
orientation = json['orientation'];
|
||||
role = json['role'];
|
||||
vip = json['vip'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['avatar'] = this.avatar;
|
||||
data['city'] = this.city;
|
||||
data['gender'] = this.gender;
|
||||
data['id'] = this.id;
|
||||
data['lat'] = this.lat;
|
||||
data['lng'] = this.lng;
|
||||
data['nickname'] = this.nickname;
|
||||
data['orientation'] = this.orientation;
|
||||
data['role'] = this.role;
|
||||
data['vip'] = this.vip;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
64
circle_app/lib/app/circle/widgets/list_logic.dart
Normal file
64
circle_app/lib/app/circle/widgets/list_logic.dart
Normal file
@ -0,0 +1,64 @@
|
||||
import 'package:circle_app/app/circle/state.dart';
|
||||
import 'package:circle_app/network/dio_manager.dart';
|
||||
import 'package:circle_app/util/util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class ListLogic extends GetxController {
|
||||
int callOutPage = 1;
|
||||
|
||||
bool isLoad = true;
|
||||
bool callOutMore = true;
|
||||
var _circleId = '';
|
||||
List<Lists> lists = [];
|
||||
final ScrollController scrollController = ScrollController();
|
||||
|
||||
loadCallOutListData(String circleId) async {
|
||||
_circleId = circleId;
|
||||
var data = await DioManager.instance.get(
|
||||
url: "/up-service/interest/$circleId/callouts",
|
||||
params: {"page": callOutPage, "page_size": "20"});
|
||||
if (data["code"] == 200) {
|
||||
List dataList = data["data"]["lists"];
|
||||
if (callOutPage == 1) {
|
||||
if (lists.isNotEmpty) {
|
||||
lists.clear();
|
||||
}
|
||||
}
|
||||
if (dataList.isNotEmpty) {
|
||||
callOutMore = true;
|
||||
for (var element in dataList) {
|
||||
lists.add(Lists.fromJson(element));
|
||||
}
|
||||
callOutPage++;
|
||||
} else {
|
||||
callOutMore = false;
|
||||
}
|
||||
update();
|
||||
} else {
|
||||
showToast(data["msg"]);
|
||||
}
|
||||
}
|
||||
|
||||
void refreshData() {
|
||||
callOutPage = 1;
|
||||
callOutMore = true;
|
||||
loadCallOutListData(_circleId);
|
||||
|
||||
}
|
||||
|
||||
void loadMore() {
|
||||
loadCallOutListData(_circleId);
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
// TODO: implement onInit
|
||||
super.onInit();
|
||||
scrollController.addListener(() {
|
||||
if (scrollController.position.pixels == scrollController.position.maxScrollExtent) {
|
||||
loadMore();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
112
circle_app/lib/app/circle/widgets/play_video_view.dart
Normal file
112
circle_app/lib/app/circle/widgets/play_video_view.dart
Normal file
@ -0,0 +1,112 @@
|
||||
import 'package:circle_app/util/util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class PlayVideoView extends StatefulWidget {
|
||||
String url;
|
||||
PlayVideoView(this.url, {Key? key}) : super(key: key);
|
||||
@override
|
||||
State<PlayVideoView> createState() => _PlayVideoViewState();
|
||||
}
|
||||
|
||||
class _PlayVideoViewState extends State<PlayVideoView> {
|
||||
VideoPlayerController? videoPlayerController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
videoPlayerController = VideoPlayerController.network(widget.url)
|
||||
..initialize().then((_) {
|
||||
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
|
||||
setState(() {});
|
||||
});
|
||||
|
||||
videoPlayerController?.addListener(() async {
|
||||
// value.position == value.duration
|
||||
if (videoPlayerController?.value.position ==
|
||||
videoPlayerController?.value.duration) {
|
||||
// videoPlayerController?.pause();
|
||||
await videoPlayerController?.seekTo(Duration.zero);
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
videoPlayerController?.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
body: Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: Get.width,
|
||||
height: Get.height,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (videoPlayerController!.value.isPlaying) {
|
||||
videoPlayerController!.pause();
|
||||
} else {
|
||||
videoPlayerController!.play();
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: videoPlayerController!.value.aspectRatio,
|
||||
child: VideoPlayer(videoPlayerController!)),
|
||||
Center(
|
||||
child: videoPlayerController!.value.isPlaying
|
||||
? Container()
|
||||
: Image(
|
||||
image: AssetImage(getMineImage("icon_play")),
|
||||
width: 60.sp,
|
||||
height: 60.sp,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
child: SafeArea(
|
||||
child: SizedBox(
|
||||
width: Get.width,
|
||||
height: 10.sp,
|
||||
child: VideoProgressIndicator(videoPlayerController!,
|
||||
allowScrubbing: true,
|
||||
colors: const VideoProgressColors(
|
||||
playedColor: Colors.white,
|
||||
bufferedColor: Colors.white54,
|
||||
backgroundColor: Colors.black)),
|
||||
),
|
||||
)),
|
||||
Positioned(
|
||||
left: 15.sp,
|
||||
top: Get.statusBarHeight,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/images/navigator/back.png',
|
||||
width: 36.sp,
|
||||
height: 36.sp,
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
62
circle_app/lib/app/circle/widgets/video_item.dart
Normal file
62
circle_app/lib/app/circle/widgets/video_item.dart
Normal file
@ -0,0 +1,62 @@
|
||||
|
||||
import 'package:circle_app/app/circle/widgets/play_video_view.dart';
|
||||
import 'package:circle_app/util/util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class VideoItemWidget extends StatefulWidget {
|
||||
String url;
|
||||
VideoItemWidget(this.url,{Key? key}) : super(key: key);
|
||||
@override
|
||||
State<VideoItemWidget> createState() => _VideoItemWidgetState();
|
||||
}
|
||||
|
||||
class _VideoItemWidgetState extends State<VideoItemWidget> {
|
||||
VideoPlayerController? videoPlayerController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
videoPlayerController = VideoPlayerController.network(
|
||||
widget.url)
|
||||
..initialize().then((_) {
|
||||
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
videoPlayerController?.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(PlayVideoView(widget.url));
|
||||
},
|
||||
child: AspectRatio(
|
||||
aspectRatio: videoPlayerController!.value.aspectRatio,
|
||||
child: Stack(
|
||||
children: [
|
||||
VideoPlayer(videoPlayerController!),
|
||||
Center(
|
||||
child: videoPlayerController!.value.isPlaying
|
||||
? Container()
|
||||
: Image(
|
||||
image: AssetImage(getMineImage("icon_play")),
|
||||
width: 30.sp,
|
||||
height: 30.sp,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2,11 +2,11 @@ import 'dart:ui';
|
||||
|
||||
import 'package:circle_app/common/values/values.dart';
|
||||
import 'package:circle_app/router/app_routers.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_state_manager/get_state_manager.dart';
|
||||
|
||||
|
||||
class Util {
|
||||
|
||||
@ -59,6 +59,16 @@ showToast(String msg) {
|
||||
);
|
||||
}
|
||||
|
||||
loaddingWidget(bool isMore) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: isMore ? const CircularProgressIndicator(color: Color(0xFF07FAFB),) : Container(
|
||||
margin:EdgeInsets.only(top: 4.sp,bottom: 4.sp),
|
||||
child: Text('--到底了--',style: TextStyle(color: Colors.white,fontSize: 13.sp),
|
||||
),),
|
||||
);
|
||||
}
|
||||
|
||||
///value: 文本内容;fontSize : 文字的大小;fontWeight:文字权重;maxWidth:文本框的最大宽度;maxLines:文本支持最大多少行
|
||||
double calculateTextHeight(String value, fontSize, FontWeight fontWeight,
|
||||
double maxWidth, int maxLines) {
|
||||
|
||||
@ -76,6 +76,8 @@ dependencies:
|
||||
package_info_plus: ^1.4.3+1
|
||||
#视频播放器
|
||||
video_player: ^2.6.1
|
||||
#图片缓存
|
||||
cached_network_image: ^3.2.3
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user