I've created a UI in which a Staggered Masonry layout sets its item at any random position with the vertical auto-scrolling from the bottom to the top of the screen infinitely. Program is - The balloons will move from the bottom to the top and when the user taps on the balloon it will disappear. For this, I used flutter_staggered_grid_view: ^0.7.0 dependency.
This code exactly works as I want. But-
- Whenever I click on any item, the layout pauses for a moment and onTap isn't working.
- If I use NeverScrollable physics property, but it prevents me from tapping on the item
In short, I want an infinite auto-scrolling feature so the user cannot scroll up or scroll down automatically and balloons will be clickable. Please suggest changes to this code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:infinite_scroll/balloon_paint.dart';
import 'package:infinite_scroll/navigs.dart';
import 'new_balloon.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: HomeScreen());
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final List<String> items = [
'Item 1',
'Item 2',
'Item 3',
'Item 4',
'Item 5',
'Item 6',
'Item 7',
'Item 8',
'Item 9',
'Item 10',
'Item 11',
'Item 12',
'Item 13',
'Item 14',
'Item 15',
'Item 16',
'Item 17',
'Item 18',
'Item 19',
'Item 20'
];
final ScrollController _scrollController = ScrollController();
final double itemExtent = 100.0;
Timer? _scrollTimer;
@override
void initState() {
super.initState();
_startAutoScroll();
}
void _startAutoScroll() {
_scrollTimer = Timer.periodic(const Duration(milliseconds: 1000), (timer) {
if (_scrollController.hasClients) {
final double maxScrollExtent = _scrollController.position.maxScrollExtent;
final double currentOffset = _scrollController.offset;
double newOffset = currentOffset + itemExtent;
if (newOffset > maxScrollExtent) {
newOffset = 0; // Reset to the beginning
}
_scrollController.animateTo(
newOffset,
duration: const Duration(milliseconds: 1000),
curve: Curves.linear,
);
}
});
}
@override
Widget build(BuildContext context) {
int ind = 0;
return Scaffold(
appBar: AppBar(
title: const Text('Vertical Auto Scroll'),
),
body: MasonryGridView.count(
controller: _scrollController,
// physics: const MyCustomScrollPhysics(),
crossAxisCount: 4,
mainAxisSpacing: 10,
crossAxisSpacing: 50,
itemCount: items.length * 30,
itemBuilder: (context, index) {
final int normalizedIndex = index % items.length;
ind = index;
return Tile(
index: normalizedIndex,
extent: (normalizedIndex % 3 + 1) * 100,
);
},
),
);
}
@override
void dispose() {
_scrollTimer?.cancel();
_scrollController.dispose();
super.dispose();
}
}
class Tile extends StatelessWidget {
final int index;
final double extent;
const Tile({super.key, required this.index, required this.extent});
@override
Widget build(BuildContext context) {
return SizedBox(
// You can customize the tile's appearance
width: extent,
height: extent,
child: Center(
child: Material(
child: InkWell(
onTap: () {
debugPrint('Tapped On: $index');
},
child: Container(
width: 100,
height: 100,
color: Colors.red[100],
child: Center(
child: Text(
'${index + 1}', // Display the normalized index
),
),
),
),
),
),
);
}
}