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

@@ -10,6 +10,7 @@
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:enableOnBackInvokedCallback="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user

View File

@@ -1,5 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:math';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gymlink_module_web/components/app_bar.dart'; import 'package:gymlink_module_web/components/app_bar.dart';
import 'package:gymlink_module_web/components/heading.dart'; import 'package:gymlink_module_web/components/heading.dart';
@@ -27,6 +29,8 @@ class _DetailPageState extends State<DetailPage> {
bool isInCart = false; bool isInCart = false;
int quantity = 0; int quantity = 0;
GymItem? item; GymItem? item;
final CarouselController _carouselController = CarouselController();
int _currentImage = 0;
@override @override
void initState() { void initState() {
@@ -53,6 +57,11 @@ class _DetailPageState extends State<DetailPage> {
setState(() { setState(() {
item = GymItem.fromJson(jsonDecode(utf8.decode(response.bodyBytes))); 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, mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Image( item!.images.length > 1
image: NetworkImage(item!.images[0].url), ? 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 != '' item!.description != ''
? Padding( ? Padding(
padding: const EdgeInsetsDirectional.all(30), padding: const EdgeInsetsDirectional.all(30),

View File

@@ -95,6 +95,7 @@ class _MainPageState extends State<MainPage> {
} }
void _onLoad() async { void _onLoad() async {
if (itemViewCount < filteredData.length) {
setState(() { setState(() {
isLoading = true; isLoading = true;
}); });
@@ -104,6 +105,7 @@ class _MainPageState extends State<MainPage> {
isLoading = false; isLoading = false;
}); });
} }
}
void _onSearch() { void _onSearch() {
setState(() { setState(() {
@@ -201,6 +203,7 @@ class _MainPageState extends State<MainPage> {
child: LazyLoadScrollView( child: LazyLoadScrollView(
onEndOfPage: _onLoad, onEndOfPage: _onLoad,
isLoading: isLoading, isLoading: isLoading,
child: Scrollbar(
child: ListView( child: ListView(
children: [ children: [
items.isEmpty items.isEmpty
@@ -208,7 +211,7 @@ class _MainPageState extends State<MainPage> {
: filteredData.isEmpty : filteredData.isEmpty
? const Center(child: Text('Ничего не найдено')) ? const Center(child: Text('Ничего не найдено'))
: GridView.builder( : GridView.builder(
physics: const AlwaysScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
gridDelegate: gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount( SliverGridDelegateWithFixedCrossAxisCount(
@@ -222,7 +225,8 @@ class _MainPageState extends State<MainPage> {
final product = filteredData[index]; final product = filteredData[index];
return ProductCard( return ProductCard(
imagePath: Image( imagePath: Image(
image: Image.network(product.images[0].url) image:
Image.network(product.images[0].url)
.image, .image,
width: 50, width: 50,
), ),
@@ -261,7 +265,8 @@ class _MainPageState extends State<MainPage> {
: const Text( : const Text(
'Конец списка', 'Конец списка',
style: TextStyle( style: TextStyle(
fontSize: 10, color: Color(0x88000000)), fontSize: 10,
color: Color(0x88000000)),
), ),
), ),
) )
@@ -270,6 +275,7 @@ class _MainPageState extends State<MainPage> {
), ),
), ),
), ),
),
], ],
), ),
floatingActionButton: SizedBox( floatingActionButton: SizedBox(

View File

@@ -40,6 +40,7 @@ dependencies:
lazy_load_scrollview: ^1.3.0 lazy_load_scrollview: ^1.3.0
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
flutter_svg: ^2.0.10+1 flutter_svg: ^2.0.10+1
carousel_slider: ^4.2.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: