diff --git a/lib/api/article_parts.dart b/lib/api/article_parts.dart index ff1b82ba..b2769e63 100644 --- a/lib/api/article_parts.dart +++ b/lib/api/article_parts.dart @@ -21,6 +21,7 @@ import 'package:boxbox/Screens/article.dart'; import 'package:boxbox/Screens/free_practice_screen.dart'; import 'package:boxbox/Screens/race_details.dart'; import 'package:boxbox/api/news.dart'; +import 'package:boxbox/helpers/custom_physics.dart'; import 'package:boxbox/helpers/news_feed_widget.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; @@ -1151,8 +1152,7 @@ class WidgetsList extends StatelessWidget { child: Padding( padding: const EdgeInsets - .all( - 10), + .all(10), child: Text( element['fields'] [ @@ -1180,7 +1180,8 @@ class WidgetsList extends StatelessWidget { [ 'tableContent']) Row( - children: [ + children: < + Widget>[ for (Map driverDetails in driverItem) Container( @@ -1461,7 +1462,7 @@ class WidgetsList extends StatelessWidget { // related articles - kIsWeb + kIsWeb && false ? Stack( alignment: Alignment.center, children: [ @@ -1550,36 +1551,41 @@ class WidgetsList extends StatelessWidget { ), ], ) - : SingleChildScrollView( - scrollDirection: Axis.horizontal, - controller: scrollController, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - for (var article in article.relatedArticles) - NewsItem( - News( - article['id'], - article['articleType'], - article['slug'], - article['title'], - article['metaDescription'] ?? ' ', - DateTime.parse(article['updatedAt']), - article['thumbnail'] != null - ? useDataSaverMode - ? article['thumbnail']['image'] - ['renditions'] != - null - ? article['thumbnail']['image'] - ['renditions']['2col'] - : article['thumbnail']['image']['url'] + - '.transform/2col-retina/image.jpg' - : article['thumbnail']['image']['url'] - : '', - ), - true, - ), - ], + : SizedBox( + height: 275, + child: ListView.builder( + scrollDirection: Axis.horizontal, + controller: scrollController, + physics: PagingScrollPhysics( + itemDimension: 300, + ), + itemCount: article.relatedArticles.length, + itemBuilder: (context, index) => NewsItem( + News( + article.relatedArticles[index]['id'], + article.relatedArticles[index]['articleType'], + article.relatedArticles[index]['slug'], + article.relatedArticles[index]['title'], + article.relatedArticles[index]['metaDescription'] ?? ' ', + DateTime.parse( + article.relatedArticles[index]['updatedAt']), + article.relatedArticles[index]['thumbnail'] != null + ? useDataSaverMode + ? article.relatedArticles[index]['thumbnail'] + ['image']['renditions'] != + null + ? article.relatedArticles[index]['thumbnail'] + ['image']['renditions']['2col'] + : article.relatedArticles[index]['thumbnail'] + ['image']['url'] + + '.transform/2col-retina/image.jpg' + : article.relatedArticles[index]['thumbnail'] + ['image']['url'] + : '', + ), + true, + width: 300, + ), ), ), ], diff --git a/lib/api/news.dart b/lib/api/news.dart index 0a0f0cd6..d17c7402 100644 --- a/lib/api/news.dart +++ b/lib/api/news.dart @@ -246,6 +246,7 @@ class NewsItem extends StatefulWidget { final News item; final bool inRelated; final bool? showSmallDescription; + final double? width; final int itemPerRow; const NewsItem( @@ -253,6 +254,7 @@ class NewsItem extends StatefulWidget { this.inRelated, { Key? key, this.showSmallDescription, + this.width, this.itemPerRow = 1, }) : super(key: key); @override @@ -396,6 +398,7 @@ class _NewsItemState extends State with TickerProviderStateMixin { color: Colors.transparent, elevation: isHovered ? 16 : 0, child: Column( + mainAxisSize: MainAxisSize.min, children: [ ClipRRect( borderRadius: const BorderRadius.only( @@ -458,6 +461,7 @@ class _NewsItemState extends State with TickerProviderStateMixin { ), ) : Column( + mainAxisSize: MainAxisSize.min, children: [ ClipRRect( borderRadius: const BorderRadius.only( diff --git a/lib/helpers/custom_physics.dart b/lib/helpers/custom_physics.dart new file mode 100644 index 00000000..b1a2eaa0 --- /dev/null +++ b/lib/helpers/custom_physics.dart @@ -0,0 +1,95 @@ +/* + * This file is part of BoxBox (https://github.com/BrightDV/BoxBox). + * + * BoxBox is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BoxBox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with BoxBox. If not, see . + * + * Copyright (c) 2022-2023, BrightDV + */ + +import 'package:flutter/material.dart'; + +// Originally form https://github.com/Sangwan5688/BlackHole/blob/main/lib/CustomWidgets/custom_physics.dart + +class PagingScrollPhysics extends ScrollPhysics { + final double itemDimension; + + const PagingScrollPhysics({required this.itemDimension, super.parent}); + + @override + PagingScrollPhysics applyTo(ScrollPhysics? ancestor) { + return PagingScrollPhysics( + itemDimension: itemDimension, + parent: buildParent(ancestor), + ); + } + + Tolerance toleranceFor(ScrollMetrics metrics) { + double devicePixelRatio = + MediaQueryData.fromWindow(WidgetsBinding.instance.window) + .devicePixelRatio / + WidgetsBinding.instance.window.physicalSize.height; + return Tolerance( + velocity: 1.0 / (50 * devicePixelRatio), // logical pixels per second + distance: 1.0 / devicePixelRatio, // logical pixels + ); + } + + double _getPage(ScrollMetrics position) { + return position.pixels / itemDimension; + } + + double _getPixels(double page) { + return page * itemDimension; + } + + double _getTargetPixels( + ScrollMetrics position, + Tolerance tolerance, + double velocity, + ) { + double page = _getPage(position); + if (velocity < -tolerance.velocity) { + page -= 0.5; + } else if (velocity > tolerance.velocity) { + page += 0.5; + } + return _getPixels(page.roundToDouble()); + } + + @override + Simulation? createBallisticSimulation( + ScrollMetrics position, + double velocity, + ) { + if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) || + (velocity >= 0.0 && position.pixels >= position.maxScrollExtent)) { + return super.createBallisticSimulation(position, velocity); + } + final Tolerance tolerance = toleranceFor(position); + final double target = _getTargetPixels(position, tolerance, velocity); + if (target != position.pixels) { + return ScrollSpringSimulation( + spring, + position.pixels, + target, + velocity, + tolerance: tolerance, + ); + } + return null; + } + + @override + bool get allowImplicitScrolling => false; +}