Add: images slider
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -95,6 +95,7 @@ class _MainPageState extends State<MainPage> {
|
||||
}
|
||||
|
||||
void _onLoad() async {
|
||||
if (itemViewCount < filteredData.length) {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
@@ -104,6 +105,7 @@ class _MainPageState extends State<MainPage> {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onSearch() {
|
||||
setState(() {
|
||||
@@ -201,6 +203,7 @@ class _MainPageState extends State<MainPage> {
|
||||
child: LazyLoadScrollView(
|
||||
onEndOfPage: _onLoad,
|
||||
isLoading: isLoading,
|
||||
child: Scrollbar(
|
||||
child: ListView(
|
||||
children: [
|
||||
items.isEmpty
|
||||
@@ -208,7 +211,7 @@ class _MainPageState extends State<MainPage> {
|
||||
: filteredData.isEmpty
|
||||
? const Center(child: Text('Ничего не найдено'))
|
||||
: GridView.builder(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(
|
||||
@@ -222,7 +225,8 @@ class _MainPageState extends State<MainPage> {
|
||||
final product = filteredData[index];
|
||||
return ProductCard(
|
||||
imagePath: Image(
|
||||
image: Image.network(product.images[0].url)
|
||||
image:
|
||||
Image.network(product.images[0].url)
|
||||
.image,
|
||||
width: 50,
|
||||
),
|
||||
@@ -261,7 +265,8 @@ class _MainPageState extends State<MainPage> {
|
||||
: const Text(
|
||||
'Конец списка',
|
||||
style: TextStyle(
|
||||
fontSize: 10, color: Color(0x88000000)),
|
||||
fontSize: 10,
|
||||
color: Color(0x88000000)),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -270,6 +275,7 @@ class _MainPageState extends State<MainPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: SizedBox(
|
||||
|
||||
@@ -40,6 +40,7 @@ dependencies:
|
||||
lazy_load_scrollview: ^1.3.0
|
||||
cupertino_icons: ^1.0.8
|
||||
flutter_svg: ^2.0.10+1
|
||||
carousel_slider: ^4.2.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user