添加水平展示图片组件

pull/1/head
张萌 3 years ago
parent 90429642c2
commit 5ccb68390a

@ -16,8 +16,8 @@ class HallListModel {
final String? accessAddress;
final String? accessAddressDetail;
final int? serviceTime;
final String remarks;
final String voiceUrl;
final String? remarks;
final String? voiceUrl;
final List<ImgModel>? imgList;
final int rewardType;
final int reward;

@ -19,8 +19,8 @@ HallListModel _$HallListModelFromJson(Map<String, dynamic> json) =>
accessAddress: json['accessAddress'] as String?,
accessAddressDetail: json['accessAddressDetail'] as String?,
serviceTime: json['serviceTime'] as int?,
remarks: json['remarks'] as String,
voiceUrl: json['voiceUrl'] as String,
remarks: json['remarks'] as String?,
voiceUrl: json['voiceUrl'] as String?,
imgList: (json['imgList'] as List<dynamic>?)
?.map((e) => ImgModel.fromJson(e as Map<String, dynamic>))
.toList(),

@ -5,7 +5,7 @@ import 'package:aku_new_community/ui/service/task_map.dart';
import 'package:aku_new_community/widget/bee_divider.dart';
import 'package:aku_new_community/widget/buttons/card_bottom_button.dart';
import 'package:aku_new_community/widget/others/user_tool.dart';
import 'package:aku_new_community/widget/views/bee_grid_image_view.dart';
import 'package:aku_new_community/widget/views/bee_hor_image_view.dart';
import 'package:aku_new_community/widget/voice_player.dart';
import 'package:common_utils/common_utils.dart';
import 'package:flutter/cupertino.dart';
@ -141,7 +141,8 @@ class HallCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
model.remarks.text
'${model.remarks ?? ''}'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.65))
.make(),
@ -150,8 +151,14 @@ class HallCard extends StatelessWidget {
url: model.voiceUrl,
),
24.w.heightBox,
BeeGridImageView(
urls: model.imgList?.map((e) => e.url).toList() ?? []),
BeeHorImageView(
maxCount: 4,
onPressed: () {
Get.to(() => HallDetailPage(model: model));
},
imgs: model.imgList ?? [],
imgWidth: 135.w,
imgHeight: 135.w),
],
),
),

@ -38,70 +38,58 @@ class _HallDetailPageState extends State<HallDetailPage> {
title: '',
body: Stack(
children: [
Column(
children: [
Container(
width: double.infinity,
height: 380.w,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFFFB737),
Color(0xFFFFD361),
]),
),
child: Column(
Container(
width: double.infinity,
height: 380.w,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFFFB737),
Color(0xFFFFD361),
]),
),
child: Column(
children: [
150.w.heightBox,
Row(
children: [
150.w.heightBox,
Row(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'未领取'
.text
.size(40.sp)
.color(Colors.black)
.bold
.make(),
'正在等待其他人接单'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
],
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'未领取'
.text
.size(40.sp)
.color(Colors.black)
.bold
.make(),
'正在等待其他人接单'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
],
),
),
Flexible(
child: Container(
width: double.infinity,
color: Color(0xFFE5E5E5),
),
),
],
],
),
),
Positioned(
top: 280.w,
left: 32.w,
right: 32.w,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_content(),
24.w.heightBox,
_taskInfo(),
],
)),
SafeArea(
child: ListView(
padding: EdgeInsets.only(top: 120.w, left: 32.w, right: 32.w),
children: [
_content(),
24.w.heightBox,
_taskInfo(),
],
),
)
],
),
bottomNavi: Container(
@ -263,7 +251,8 @@ class _HallDetailPageState extends State<HallDetailPage> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.model.remarks.text
'${widget.model.remarks ?? ''}'
.text
.size(28.sp)
.color(Colors.black.withOpacity(0.65))
.make(),

@ -5,7 +5,7 @@ import 'package:aku_new_community/ui/service/my_take_task/my_take_task_detail_pa
import 'package:aku_new_community/ui/service/task_map.dart';
import 'package:aku_new_community/widget/bee_divider.dart';
import 'package:aku_new_community/widget/buttons/card_bottom_button.dart';
import 'package:aku_new_community/widget/views/bee_grid_image_view.dart';
import 'package:aku_new_community/widget/views/bee_hor_image_view.dart';
import 'package:aku_new_community/widget/voice_player.dart';
import 'package:common_utils/common_utils.dart';
import 'package:flutter/material.dart';
@ -148,8 +148,14 @@ class MyTakeTaskCard extends StatelessWidget {
url: model.voiceUrl,
),
24.w.heightBox,
BeeGridImageView(
urls: model.imgList?.map((e) => e.url).toList() ?? []),
BeeHorImageView(
maxCount: 4,
onPressed: () {
Get.to(() => MyTakeTaskDetailPage(model: model));
},
imgs: model.imgList ?? [],
imgWidth: 135.w,
imgHeight: 135.w),
],
),
),

@ -81,75 +81,63 @@ class _MyTakeTaskDetailPageState extends State<MyTakeTaskDetailPage> {
title: '',
body: Stack(
children: [
Column(
children: [
Container(
width: double.infinity,
height: 380.w,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: widget.model.status == 9
? [
Colors.white,
Color(0xFFADACAC),
]
: [
Color(0xFFFFB737),
Color(0xFFFFD361),
]),
),
child: Column(
Container(
width: double.infinity,
height: 380.w,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: widget.model.status == 9
? [
Colors.white,
Color(0xFFADACAC),
]
: [
Color(0xFFFFB737),
Color(0xFFFFD361),
]),
),
child: Column(
children: [
150.w.heightBox,
Row(
children: [
150.w.heightBox,
Row(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'${detailStatusToString}'
.text
.size(40.sp)
.color(Colors.black)
.bold
.make(),
'${subStatusString}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
],
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'${detailStatusToString}'
.text
.size(40.sp)
.color(Colors.black)
.bold
.make(),
'${subStatusString}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
],
),
),
Flexible(
child: Container(
width: double.infinity,
color: Color(0xFFE5E5E5),
),
),
],
],
),
),
SafeArea(
child: ListView(
padding: EdgeInsets.only(top: 120.w, left: 32.w, right: 32.w),
children: [
_content(),
24.w.heightBox,
_taskInfo(),
],
),
),
Positioned(
top: 280.w,
left: 32.w,
right: 32.w,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_content(),
24.w.heightBox,
_taskInfo(),
],
)),
],
),
bottomNavi: Container(

@ -3,7 +3,7 @@ import 'package:aku_new_community/models/task/my_task_list_model.dart';
import 'package:aku_new_community/ui/service/my_task/my_task_detail_page.dart';
import 'package:aku_new_community/ui/service/task_map.dart';
import 'package:aku_new_community/widget/buttons/card_bottom_button.dart';
import 'package:aku_new_community/widget/views/bee_grid_image_view.dart';
import 'package:aku_new_community/widget/views/bee_hor_image_view.dart';
import 'package:aku_new_community/widget/voice_player.dart';
import 'package:common_utils/common_utils.dart';
import 'package:flutter/material.dart';
@ -131,8 +131,14 @@ class MyTaskCard extends StatelessWidget {
url: model.voiceUrl,
),
24.w.heightBox,
BeeGridImageView(
urls: model.imgList?.map((e) => e.url).toList() ?? []),
BeeHorImageView(
maxCount: 4,
onPressed: () {
Get.to(() => MyTaskDetailPage(model: model));
},
imgs: model.imgList ?? [],
imgWidth: 135.w,
imgHeight: 135.w),
],
),
),

@ -82,75 +82,63 @@ class _MyTaskDetailPageState extends State<MyTaskDetailPage> {
title: '',
body: Stack(
children: [
Column(
children: [
Container(
width: double.infinity,
height: 380.w,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: widget.model.status == 9
? [
Colors.white,
Color(0xFFADACAC),
]
: [
Color(0xFFFFB737),
Color(0xFFFFD361),
]),
),
child: Column(
Container(
width: double.infinity,
height: 380.w,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: widget.model.status == 9
? [
Colors.white,
Color(0xFFADACAC),
]
: [
Color(0xFFFFB737),
Color(0xFFFFD361),
]),
),
child: Column(
children: [
150.w.heightBox,
Row(
children: [
150.w.heightBox,
Row(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'${detailStatusToString}'
.text
.size(40.sp)
.color(Colors.black)
.bold
.make(),
'${subStatusString}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
],
Padding(
padding: EdgeInsets.symmetric(horizontal: 32.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'${detailStatusToString}'
.text
.size(40.sp)
.color(Colors.black)
.bold
.make(),
'${subStatusString}'
.text
.size(24.sp)
.color(Colors.black.withOpacity(0.45))
.make(),
],
),
),
Spacer(),
],
),
),
Flexible(
child: Container(
width: double.infinity,
color: Color(0xFFE5E5E5),
),
),
],
],
),
),
SafeArea(
child: ListView(
padding: EdgeInsets.only(top: 120.w, left: 32.w, right: 32.w),
children: [
_content(),
24.w.heightBox,
_taskInfo(),
],
),
),
Positioned(
top: 280.w,
left: 32.w,
right: 32.w,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_content(),
24.w.heightBox,
_taskInfo(),
],
)),
],
),
bottomNavi: Container(

@ -926,6 +926,7 @@ class _PublishTaskPageState extends State<PublishTaskPage> {
borderRadius: BorderRadius.circular(16.w),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [

@ -16,7 +16,7 @@ class TaskFunc {
required String? serviceAddress,
required String? serviceAddressDetail,
required String? remarks,
required String voiceUrl,
required String? voiceUrl,
required List<String> imgUrls,
required int rewardType,
required String reward,

@ -1,5 +1,5 @@
import 'package:aku_new_community/const/resource.dart';
import 'package:aku_new_community/constants/sars_api.dart';
import 'package:aku_new_community/gen/assets.gen.dart';
import 'package:aku_new_community/model/common/img_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
@ -24,11 +24,13 @@ class BeeImageNetwork extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FadeInImage.assetNetwork(
placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
image: SARSAPI.image(ImgModel.first(imgs)),
placeholder: Assets.images.placeholder.path,
image: imgs == null
? SARSAPI.image(urls!.isEmpty ? '' : urls!.first)
: SARSAPI.image(ImgModel.first(imgs)),
imageErrorBuilder: (context, obj, stackTrace) {
return Image.asset(
R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
Assets.images.placeholder.path,
width: width ?? 160.w,
height: height ?? 160.w,
fit: BoxFit.fill,

@ -1,13 +1,10 @@
import 'dart:io';
import 'package:aku_new_community/constants/sars_api.dart';
import 'package:aku_new_community/gen/assets.gen.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:aku_new_community/const/resource.dart';
import 'package:aku_new_community/constants/api.dart';
import 'package:aku_new_community/constants/sars_api.dart';
///
class BeeImagePreview extends StatefulWidget {
static Future<T?> toFile<T>({required File file, String? tag}) async {
@ -68,8 +65,14 @@ class _BeeImagePreviewState extends State<BeeImagePreview> {
return Hero(
tag: widget.tag ?? widget.path!,
child: FadeInImage.assetNetwork(
placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
placeholder: Assets.images.placeholder.path,
image: SARSAPI.image(widget.path),
imageErrorBuilder: (context, obj, stackTrace) {
return Image.asset(
Assets.images.placeholder.path,
fit: BoxFit.fill,
);
},
),
);
else

@ -1,7 +1,6 @@
// Dart imports:
import 'dart:io';
import 'package:aku_new_community/extensions/widget_list_ext.dart';
import 'package:aku_new_community/gen/assets.gen.dart';
import 'package:aku_new_community/widget/picker/bee_image_picker.dart';
// Package imports:
@ -29,7 +28,11 @@ class _BeePickImageWidgetState extends State<BeePickImageWidget> {
@override
Widget build(BuildContext context) {
return Row(
return Wrap(
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
spacing: 10.w,
runSpacing: 10.w,
children: [
..._files.map((e) => showImage(e)).toList(),
GestureDetector(
@ -75,7 +78,7 @@ class _BeePickImageWidgetState extends State<BeePickImageWidget> {
),
).material(color: Colors.transparent),
)
].sepWidget(separate: 10.w.widthBox),
],
);
}

@ -0,0 +1,117 @@
import 'package:aku_new_community/extensions/num_ext.dart';
import 'package:aku_new_community/extensions/widget_list_ext.dart';
import 'package:aku_new_community/model/common/img_model.dart';
import 'package:aku_new_community/widget/beeImageNetwork.dart';
import 'package:aku_new_community/widget/picker/bee_image_preview.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:velocity_x/src/extensions/string_ext.dart';
class BeeHorImageView extends StatefulWidget {
final EdgeInsets? padding;
final int maxCount;
final List<ImgModel> imgs;
final double imgWidth;
final double imgHeight;
final BorderRadiusGeometry? borderRadius;
final int? spacing;
final VoidCallback? onPressed;
const BeeHorImageView(
{Key? key,
this.padding = EdgeInsets.zero,
required this.maxCount,
required this.imgs,
required this.imgWidth,
required this.imgHeight,
this.borderRadius,
this.spacing,
this.onPressed})
: super(key: key);
@override
_BeeHorImageViewState createState() => _BeeHorImageViewState();
}
class _BeeHorImageViewState extends State<BeeHorImageView> {
bool get overFlow => widget.imgs.length > widget.maxCount;
int get overCount => overFlow ? (widget.imgs.length - widget.maxCount) : 0;
@override
Widget build(BuildContext context) {
return Container(
padding: widget.padding,
child: Row(
children: List.generate(widget.imgs.length - overCount, (index) {
if (overFlow && (index == widget.maxCount - 1)) {
return _overFlowWidget(widget.imgs[index]);
} else {
return _imageView(widget.imgs[index]);
}
}).sepWidget(separate: (widget.spacing ?? 10).wb),
),
);
}
Widget _overFlowWidget(ImgModel img) {
return Stack(
children: [
Container(
clipBehavior: Clip.antiAliasWithSaveLayer,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: widget.borderRadius ?? BorderRadius.circular(16.w)),
child: BeeImageNetwork(
width: widget.imgWidth,
height: widget.imgHeight,
imgs: [img],
),
),
GestureDetector(
onTap: widget.onPressed,
child: Container(
width: widget.imgWidth,
height: widget.imgHeight,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
borderRadius: widget.borderRadius ?? BorderRadius.circular(16.w),
),
alignment: Alignment.center,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.image,
size: 24.w,
color: Colors.white,
),
8.wb,
'${overCount + 1}'.text.size(28.sp).color(Colors.white).make(),
],
),
),
)
],
);
}
Widget _imageView(ImgModel img) {
return GestureDetector(
onTap: () {
BeeImagePreview.toPath(path: img.url);
},
child: Container(
clipBehavior: Clip.antiAliasWithSaveLayer,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: widget.borderRadius ?? BorderRadius.circular(16.w)),
child: BeeImageNetwork(
width: widget.imgWidth,
height: widget.imgHeight,
imgs: [img],
),
),
);
}
}

@ -16,8 +16,7 @@ class VoicePlayer extends StatefulWidget {
const VoicePlayer(
{Key? key, this.url, this.onDelete, this.showXmark = false, this.path})
: assert(url != null || path != null),
super(key: key);
: super(key: key);
@override
_VoicePlayerState createState() => _VoicePlayerState();
@ -25,6 +24,7 @@ class VoicePlayer extends StatefulWidget {
class _VoicePlayerState extends State<VoicePlayer>
with SingleTickerProviderStateMixin {
bool get nullVoice => widget.url == null && widget.path == null;
final double width = 150.w;
final double height = 45.w;
late Animation<int> animation;
@ -64,6 +64,9 @@ class _VoicePlayerState extends State<VoicePlayer>
}
Future initVoice() async {
if (nullVoice) {
return;
}
if (widget.url != null) {
await player.setUrl(SARSAPI.image(widget.url));
} else {
@ -78,6 +81,9 @@ class _VoicePlayerState extends State<VoicePlayer>
}
Future resetPlay() async {
if (nullVoice) {
return;
}
_timer?.cancel();
_timer = null;
controller.stop();
@ -135,53 +141,56 @@ class _VoicePlayerState extends State<VoicePlayer>
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (player.playing) {
stopPlay();
} else {
startPlay();
}
},
child: Material(
color: Colors.transparent,
child: Stack(
fit: StackFit.passthrough,
clipBehavior: Clip.none,
children: [
Container(
width: width,
// height: height,
padding: EdgeInsets.symmetric(vertical: 14.w, horizontal: 20.w),
decoration: BoxDecoration(
color: Color(0xFFFFE7BA),
borderRadius: BorderRadius.circular(8.w)),
child: Row(
return nullVoice
? SizedBox.shrink()
: GestureDetector(
onTap: () {
if (player.playing) {
stopPlay();
} else {
startPlay();
}
},
child: Material(
color: Colors.transparent,
child: Stack(
fit: StackFit.passthrough,
clipBehavior: Clip.none,
children: [
CustomPaint(
painter:
VoicePlayerPainter(inAnimate ? animation.value : 3),
Container(
width: width,
// height: height,
padding:
EdgeInsets.symmetric(vertical: 14.w, horizontal: 20.w),
decoration: BoxDecoration(
color: Color(0xFFFFE7BA),
borderRadius: BorderRadius.circular(8.w)),
child: Row(
children: [
CustomPaint(
painter: VoicePlayerPainter(
inAnimate ? animation.value : 3),
),
40.wb,
Text('${_currentLength}\"'),
],
),
),
40.wb,
Text('${_currentLength}\"'),
if (widget.showXmark)
Positioned(
top: -10.w,
right: -10.w,
child: GestureDetector(
onTap: widget.onDelete,
child: Icon(
CupertinoIcons.xmark_circle_fill,
size: 30.w,
),
))
],
),
),
if (widget.showXmark)
Positioned(
top: -10.w,
right: -10.w,
child: GestureDetector(
onTap: widget.onDelete,
child: Icon(
CupertinoIcons.xmark_circle_fill,
size: 30.w,
),
))
],
),
),
);
);
}
}

Loading…
Cancel
Save