Add: images slider

This commit is contained in:
2024-05-31 14:55:24 +03:00
parent 3b593ad733
commit 1eeff4209e
4 changed files with 146 additions and 74 deletions

View File

@@ -1,5 +1,7 @@
import 'dart:convert';
import 'dart:math';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:gymlink_module_web/components/app_bar.dart';
import 'package:gymlink_module_web/components/heading.dart';
@@ -27,6 +29,8 @@ class _DetailPageState extends State<DetailPage> {
bool isInCart = false;
int quantity = 0;
GymItem? item;
final CarouselController _carouselController = CarouselController();
int _currentImage = 0;
@override
void initState() {
@@ -53,6 +57,11 @@ class _DetailPageState extends State<DetailPage> {
setState(() {
item = GymItem.fromJson(jsonDecode(utf8.decode(response.bodyBytes)));
});
WidgetsBinding.instance.addPostFrameCallback((_) {
for (var element in item!.images) {
precacheImage(NetworkImage(element.url), context);
}
});
}
}
@@ -173,9 +182,64 @@ class _DetailPageState extends State<DetailPage> {
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image(
image: NetworkImage(item!.images[0].url),
),
item!.images.length > 1
? Column(children: [
CarouselSlider.builder(
itemCount: item!.images.length,
itemBuilder: (context, index, realIdx) {
return Center(
child: Image.network(
item!.images[realIdx].url,
width: min(
800,
MediaQuery.sizeOf(context)
.width)),
);
},
carouselController: _carouselController,
options: CarouselOptions(
enlargeCenterPage: true,
aspectRatio: 1,
enableInfiniteScroll: false,
onPageChanged: (index, reason) {
setState(() {
_currentImage = index;
});
}),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: item!.images
.asMap()
.entries
.map((entry) {
return GestureDetector(
onTap: () => _carouselController
.animateToPage(entry.key),
child: Container(
width: 12.0,
height: 12.0,
margin: const EdgeInsets.symmetric(
vertical: 8.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: (Theme.of(context)
.brightness ==
Brightness.dark
? Colors.white
: Colors.black)
.withOpacity(
_currentImage == entry.key
? 0.9
: 0.4)),
),
);
}).toList(),
),
])
: Image.network(item!.images[0].url,
width: min(
800, MediaQuery.sizeOf(context).width)),
item!.description != ''
? Padding(
padding: const EdgeInsetsDirectional.all(30),

View File

@@ -95,14 +95,16 @@ class _MainPageState extends State<MainPage> {
}
void _onLoad() async {
setState(() {
isLoading = true;
});
await Future.delayed(const Duration(seconds: 1));
setState(() {
itemViewCount = min(filteredData.length, itemViewCount + 5);
isLoading = false;
});
if (itemViewCount < filteredData.length) {
setState(() {
isLoading = true;
});
await Future.delayed(const Duration(seconds: 1));
setState(() {
itemViewCount = min(filteredData.length, itemViewCount + 5);
isLoading = false;
});
}
}
void _onSearch() {
@@ -201,72 +203,76 @@ class _MainPageState extends State<MainPage> {
child: LazyLoadScrollView(
onEndOfPage: _onLoad,
isLoading: isLoading,
child: ListView(
children: [
items.isEmpty
? const Center(child: CircularProgressIndicator())
: filteredData.isEmpty
? const Center(child: Text('Ничего не найдено'))
: GridView.builder(
physics: const AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: min(
(MediaQuery.sizeOf(context).width ~/ 200)
.toInt(),
8),
),
itemCount: itemViewCount,
itemBuilder: (context, index) {
final product = filteredData[index];
return ProductCard(
imagePath: Image(
image: Image.network(product.images[0].url)
.image,
width: 50,
),
name: product.title,
price: product.price.toString(),
onTap: () => Navigator.of(context).push(
CustomPageRoute(
builder: (context) => DetailPage(
id: product.id,
child: Scrollbar(
child: ListView(
children: [
items.isEmpty
? const Center(child: CircularProgressIndicator())
: filteredData.isEmpty
? const Center(child: Text('Ничего не найдено'))
: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: min(
(MediaQuery.sizeOf(context).width ~/ 200)
.toInt(),
8),
),
itemCount: itemViewCount,
itemBuilder: (context, index) {
final product = filteredData[index];
return ProductCard(
imagePath: Image(
image:
Image.network(product.images[0].url)
.image,
width: 50,
),
name: product.title,
price: product.price.toString(),
onTap: () => Navigator.of(context).push(
CustomPageRoute(
builder: (context) => DetailPage(
id: product.id,
),
),
),
),
);
},
),
itemViewCount > 0
? Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Center(
child: itemViewCount < filteredData.length
? !isLoading
? ElevatedButton(
onPressed: _onLoad,
style: ElevatedButton.styleFrom(
backgroundColor:
Theme.of(context).primaryColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(50)),
);
},
),
itemViewCount > 0
? Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Center(
child: itemViewCount < filteredData.length
? !isLoading
? ElevatedButton(
onPressed: _onLoad,
style: ElevatedButton.styleFrom(
backgroundColor:
Theme.of(context).primaryColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(50)),
),
foregroundColor: Colors.white,
),
foregroundColor: Colors.white,
),
child: const Text('Загрузить ещё'),
)
: const CircularProgressIndicator()
: const Text(
'Конец списка',
style: TextStyle(
fontSize: 10, color: Color(0x88000000)),
),
),
)
: const SizedBox.shrink(),
],
child: const Text('Загрузить ещё'),
)
: const CircularProgressIndicator()
: const Text(
'Конец списка',
style: TextStyle(
fontSize: 10,
color: Color(0x88000000)),
),
),
)
: const SizedBox.shrink(),
],
),
),
),
),