364 lines
11 KiB
Dart
364 lines
11 KiB
Dart
import 'dart:math' as math;
|
|
|
|
import 'package:easy_refresh/easy_refresh.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:wallpaperx/common/components/image_network_widget.dart';
|
|
import 'package:wallpaperx/entity/image_model.dart';
|
|
import 'package:wallpaperx/gen/assets.dart';
|
|
import 'package:wallpaperx/page/search/search_controller.dart';
|
|
|
|
class SearchView extends GetView<CSearchController> {
|
|
const SearchView({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
resizeToAvoidBottomInset: false,
|
|
backgroundColor: Colors.black,
|
|
body: GetBuilder<CSearchController>(
|
|
builder: (controller) => Obx(
|
|
() => Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(
|
|
height: MediaQuery.of(context).padding.top,
|
|
),
|
|
_buildSearchInput(),
|
|
if (controller.searchList.isNotEmpty) ...[
|
|
24.verticalSpace,
|
|
Text(
|
|
"ALL ${controller.total}",
|
|
style: TextStyle(color: Colors.white, fontSize: 20.sp),
|
|
),
|
|
24.verticalSpace,
|
|
_buildMasonryGridView(),
|
|
] else ...[
|
|
Expanded(child: Container()),
|
|
_buildTags(context),
|
|
]
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildMasonryGridView() {
|
|
return Expanded(
|
|
child: EasyRefresh(
|
|
controller: controller.refreshController,
|
|
onLoad: controller.onLoad,
|
|
child: MasonryGridView.count(
|
|
itemCount: controller.searchList.length,
|
|
crossAxisCount: 2,
|
|
mainAxisSpacing: 20.w,
|
|
crossAxisSpacing: 21.w,
|
|
padding: EdgeInsets.zero,
|
|
itemBuilder: (context, index) {
|
|
ImageModel item = controller.searchList[index];
|
|
return GestureDetector(
|
|
onTap: () => controller.onTapItem(index),
|
|
child: ImageNetworkWidget(
|
|
url: item.imageUrl,
|
|
aspectRatio: item.width! / item.height!,
|
|
radius: 14.r,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSearchInput() {
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Container(
|
|
height: 40.w,
|
|
alignment: Alignment.center,
|
|
margin: const EdgeInsets.all(16).w,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(50).r,
|
|
color: const Color(0xff141414),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
10.horizontalSpace,
|
|
Expanded(
|
|
child: TextField(
|
|
onSubmitted: (e) => controller.getImages(),
|
|
focusNode: controller.searchFocusNode,
|
|
onTapOutside: (e) => {controller.searchFocusNode.unfocus()},
|
|
autofocus: false,
|
|
controller: controller.searchController,
|
|
maxLines: 1,
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 14.sp,
|
|
height: 1.4,
|
|
),
|
|
decoration: InputDecoration(
|
|
icon: Image.asset(
|
|
width: 24.w,
|
|
Assets.searchIcon,
|
|
),
|
|
hintText: 'Title',
|
|
hintStyle: TextStyle(
|
|
height: 1.4,
|
|
fontSize: 14.sp,
|
|
color: const Color(0xff47474A)),
|
|
contentPadding: const EdgeInsets.symmetric(
|
|
vertical: -10,
|
|
horizontal: -10,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Get.back(),
|
|
child: Text(
|
|
"Cancel",
|
|
style: TextStyle(color: Colors.white, fontSize: 16.sp),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildTags(context) {
|
|
return Container(
|
|
width: double.infinity,
|
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(10).r,
|
|
border: Border.all(color: Colors.black),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Expanded(
|
|
child: Container(
|
|
margin: EdgeInsets.only(bottom: 12.w),
|
|
child: labelOptionColourItem(
|
|
"Anime Characters",
|
|
Text(
|
|
"Anime Characters",
|
|
style: TextStyle(
|
|
fontSize: 32.sp,
|
|
color: const Color.fromRGBO(255, 255, 255, 0.85),
|
|
),
|
|
),
|
|
angle: 12.0 * (math.pi / 180.0),
|
|
),
|
|
),
|
|
),
|
|
10.horizontalSpace,
|
|
Container(
|
|
child: labelOptionItem(
|
|
"",
|
|
Image.asset(
|
|
width: 40.w,
|
|
Assets.searchTop,
|
|
),
|
|
padding: const EdgeInsets.all(13).w),
|
|
),
|
|
],
|
|
),
|
|
10.verticalSpace,
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
labelOptionItem(
|
|
"",
|
|
SizedBox(
|
|
width: 40.w,
|
|
height: 40.w,
|
|
),
|
|
angle: 0.0 * (math.pi / 180.0),
|
|
padding: const EdgeInsets.all(13).w,
|
|
),
|
|
15.horizontalSpace,
|
|
Expanded(
|
|
child: Container(
|
|
child: labelOptionColourItem(
|
|
"Landscape",
|
|
Text(
|
|
"Landscape",
|
|
style: TextStyle(
|
|
fontSize: 32.sp,
|
|
color: const Color.fromRGBO(255, 255, 255, 0.85),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
10.verticalSpace,
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Expanded(
|
|
child: Container(
|
|
child: labelOptionItem(
|
|
"Fantasy",
|
|
Text(
|
|
"Fantasy",
|
|
style: TextStyle(
|
|
fontSize: 32.sp,
|
|
color: const Color.fromRGBO(255, 255, 255, 0.85),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
25.horizontalSpace,
|
|
labelOptionItem(
|
|
"",
|
|
SizedBox(
|
|
width: 40.w,
|
|
height: 40.w,
|
|
),
|
|
angle: 0.0 * (math.pi / 180.0),
|
|
padding: const EdgeInsets.all(13).w,
|
|
),
|
|
32.horizontalSpace,
|
|
labelOptionItem(
|
|
"",
|
|
SizedBox(
|
|
width: 40.w,
|
|
height: 40.w,
|
|
),
|
|
angle: 0.0 * (math.pi / 180.0),
|
|
padding: const EdgeInsets.all(13).w,
|
|
),
|
|
],
|
|
),
|
|
10.verticalSpace,
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
labelOptionItem(
|
|
"",
|
|
Image.asset(
|
|
width: 40.w,
|
|
Assets.searchBottomRight,
|
|
),
|
|
angle: 0.0 * (math.pi / 180.0),
|
|
padding: const EdgeInsets.all(13).w,
|
|
),
|
|
15.horizontalSpace,
|
|
Expanded(
|
|
child: Container(
|
|
child: labelOptionItem(
|
|
"Anime-style",
|
|
Text(
|
|
"Anime-style",
|
|
style: TextStyle(
|
|
fontSize: 32.sp,
|
|
color: const Color.fromRGBO(255, 255, 255, 0.85),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
10.verticalSpace,
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Expanded(
|
|
child: Container(
|
|
child: labelOptionItem(
|
|
"Illustration",
|
|
Text(
|
|
"Illustration",
|
|
style: TextStyle(
|
|
fontSize: 32.sp,
|
|
color: const Color.fromRGBO(255, 255, 255, 0.85),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
22.horizontalSpace,
|
|
labelOptionItem(
|
|
"",
|
|
Image.asset(
|
|
width: 40.w,
|
|
Assets.searchBottom,
|
|
),
|
|
angle: 0.0 * (math.pi / 180.0),
|
|
padding: const EdgeInsets.all(13).w,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget labelOptionColourItem(tag, tagWidget,
|
|
{double? angle, EdgeInsetsGeometry? padding}) {
|
|
return GestureDetector(
|
|
onTap: () => controller.setSearchText(tag),
|
|
child: Transform.rotate(
|
|
angle: angle ?? 0.0 * (math.pi / 180.0),
|
|
child: Container(
|
|
padding: const EdgeInsets.all(1),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(50).r,
|
|
gradient: const LinearGradient(
|
|
colors: [
|
|
Color(0xffBEEF32),
|
|
Color(0xff2795E5),
|
|
Color(0xff8041FD),
|
|
],
|
|
),
|
|
),
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
padding: padding ?? const EdgeInsets.symmetric(vertical: 10).w,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(50).r,
|
|
color: Colors.black,
|
|
),
|
|
child: tagWidget,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget labelOptionItem(tag, tagWidget,
|
|
{double? angle, EdgeInsetsGeometry? padding}) {
|
|
return GestureDetector(
|
|
onTap: () => controller.setSearchText(tag),
|
|
child: Transform.rotate(
|
|
angle: angle ?? 0.0 * (math.pi / 180.0),
|
|
child: Container(
|
|
alignment: Alignment.center,
|
|
padding: padding ?? const EdgeInsets.symmetric(vertical: 10).w,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(50).r,
|
|
border:
|
|
Border.all(color: const Color.fromRGBO(255, 255, 255, 0.85)),
|
|
),
|
|
child: tagWidget,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|