Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doesn't work with Sliver in CustomScrollView #5

Closed
Foodnet24App opened this issue Dec 28, 2021 · 13 comments
Closed

doesn't work with Sliver in CustomScrollView #5

Foodnet24App opened this issue Dec 28, 2021 · 13 comments

Comments

@Foodnet24App
Copy link

I was trying to implement this module into Sliver in CustomScrollView
everything works fine but VerticalScrollableTabView.
it wasn't scrolled with Sliver
VerticalScrollableTabView only scroll with itself
is there any way to scroll in sliver in customScrollView??

@aytunch
Copy link

aytunch commented Jan 1, 2022

I have the exact same problem
Wrapping the TabBar and VerticalScrollableTabView in to a SliverToBoxAdapter does not work either.
@wayne900204 can you support slivers with this package please?

@wayne900204
Copy link
Owner

I am trying to fix it.

@aytunch
Copy link

aytunch commented Jan 3, 2022

The problem might be caused by the fact that when a NestedScrollView or CustomScrollView is used, platform does not want us to set a ScrollController to the inner scrolling widget (vertical_scrollable_tabview)

I might be wrong and I hope that there is an easy solution for using this package in Slivers because I just love it :D

@aytunch
Copy link

aytunch commented Jan 3, 2022

Some resources for my above comment:
NestedScrollView class

Screen Shot 2022-01-03 at 23 19 37

@wayne900204
Copy link
Owner

wayne900204 commented Jan 4, 2022

@aytunch Can you provide some sample code about your problem?

@wayne900204
Copy link
Owner

@Foodnet24App Can you provide some sample code about your problem?

@Foodnet24App
Copy link
Author

@Foodnet24App Can you provide some sample code about your problem?

this is sample code

you can just replace it with the code in main.dart

// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:vertical_scrollable_tabview/vertical_scrollable_tabview.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

class MyHomePage extends StatefulWidget {
final String title;

const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);

@OverRide
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State
with SingleTickerProviderStateMixin {
ScrollController sliverController = ScrollController();
ScrollController listController = ScrollController();

late TabController tabController;
final List data = ExampleData.data;
@OverRide
void initState() {
super.initState();

tabController = TabController(vsync: this, length: data.length);

// listController.addListener(() {
//   print(listController.offset);
//   sliverController
//       .jumpTo(listController.offset.clamp(0, sliverController.position.maxScrollExtent));
// });

}

@OverRide
Widget build(BuildContext context) {
return Material(
child: CustomScrollView(
controller: sliverController,
slivers: [
SliverAppBar(
pinned: true,
expandedHeight: 250.0,
flexibleSpace: const FlexibleSpaceBar(
title: Text('SliverAppBar'),
titlePadding: EdgeInsets.only(bottom: 50),
background: FlutterLogo(),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(50),
child: TabBar(
isScrollable: true,
controller: tabController,
indicatorPadding: const EdgeInsets.symmetric(horizontal: 16.0),
indicatorColor: Colors.cyan,
labelColor: Colors.cyan,
unselectedLabelColor: Colors.white,
indicatorWeight: 3.0,
tabs: data.map((e) {
return Tab(text: e.title);
}).toList(),
onTap: (index) {
VerticalScrollableTabBarStatus.setIndex(index);
},
),
),
),
SliverToBoxAdapter(
child: Container(
height: 200,
color: Colors.red,
),
),
SliverFillRemaining(
child: NotificationListener(
onNotification: () {
sliverController.jumpTo(
.metrics.pixels
.abs()
.clamp(0, sliverController.position.maxScrollExtent));
return false;
},
child: VerticalScrollableTabView(
tabController: tabController,
listItemData: data,
verticalScrollPosition: VerticalScrollPosition.middle,
//Change this to your preferred scroll direction
scrollDirection: Axis.vertical,
eachItemChild: (object, index) =>
CategorySection(category: object as Category)),
),
),
],
),
);
}
}

class ExampleData {
ExampleData._internal();

static List images = [
"https://github.com/wayne900204/vertical_scrollable_tabview/blob/main/example/assets/food.jpeg?raw=true",
"https://github.com/wayne900204/vertical_scrollable_tabview/blob/main/example/assets/food.jpeg?raw=true",
"https://github.com/wayne900204/vertical_scrollable_tabview/blob/main/example/assets/food.jpeg?raw=true",
"https://github.com/wayne900204/vertical_scrollable_tabview/blob/main/example/assets/food.jpeg?raw=true",
"https://github.com/wayne900204/vertical_scrollable_tabview/blob/main/example/assets/food.jpeg?raw=true",
];

static List data = [
category1,
category2,
category3,
category4,
category4,
category4,
category3,
category4,
category4,
category3,
];

static Category category1 = Category(
title: "人氣火鍋",
subtitle: "附副餐一份,鍋類肉品「煙嶿肉、醃牛肉」,擇一",
isHotSale: true,
foods: List.generate(
5,
(index) {
return Food(
name: "701. 超人氣泡菜鍋",
price: "200",
comparePrice: "$198",
imageUrl: images[index % images.length],
isHotSale: false,
);
},
),
);

static Category category2 = Category(
title: "特級火鍋",
subtitle: "附副餐一份",
isHotSale: false,
foods: List.generate(
3,
(index) {
return Food(
name: "706. 迷你原味鍋",
price: "230",
comparePrice: "$250",
imageUrl: images[index % images.length],
isHotSale: index == 2 ? true : false,
);
},
),
);

static Category category3 = Category(
title: "經典火鍋",
subtitle: null,
isHotSale: false,
foods: List.generate(
1,
(index) {
return Food(
name: "經典火鍋",
price: "258",
comparePrice: "$289",
imageUrl: images[index % images.length],
isHotSale: false,
);
},
),
);

static Category category4 = Category(
title: "素食火鍋",
subtitle: "附附餐一份,可烹煮為鍋邊素,若有需要請備著告知",
isHotSale: false,
foods: List.generate(
5,
(index) {
return Food(
name: "728. 連庭素食鍋",
price: "240",
comparePrice: "$300",
imageUrl: images[index % images.length],
isHotSale: index == 3 ? true : false,
);
},
),
);
}

class Category {
String title;
String? subtitle;
List foods;
bool isHotSale;

Category({
required this.title,
required this.subtitle,
required this.foods,
required this.isHotSale,
});
}

class Food {
String name;
String price;
String comparePrice;
String imageUrl;
bool isHotSale;

Food({
required this.name,
required this.price,
required this.comparePrice,
required this.imageUrl,
required this.isHotSale,
});
}

class CategorySection extends StatelessWidget {
const CategorySection({
Key? key,
required this.category,
}) : super(key: key);

final Category category;

@OverRide
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
margin: const EdgeInsets.only(bottom: 16),
color: Colors.cyanAccent.withOpacity(0.1),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionTileHeader(context),
_buildFoodTileList(context),
],
),
);
}

Widget _buildFoodTileList(BuildContext context) {
return Column(
children: List.generate(
category.foods.length,
(index) {
final food = category.foods[index];
bool isLastIndex = index == category.foods.length - 1;
return _buildFoodTile(
food: food,
context: context,
isLastIndex: isLastIndex,
);
},
),
);
}

Widget _buildSectionTileHeader(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 16),
_sectionTitle(context),
const SizedBox(height: 8.0),
category.subtitle != null
? _sectionSubtitle(context)
: const SizedBox(),
const SizedBox(height: 16),
],
);
}

Widget _sectionTitle(BuildContext context) {
return Row(
children: [
if (category.isHotSale) _buildSectionHoteSaleIcon(),
Text(
category.title,
style: _textTheme(context).headline6,
)
],
);
}

Widget _sectionSubtitle(BuildContext context) {
return Text(
category.subtitle!,
style: _textTheme(context).subtitle2,
);
}

Widget _buildFoodTile({
required BuildContext context,
required bool isLastIndex,
required Food food,
}) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildFoodDetail(food: food, context: context),
_buildFoodImage(food.imageUrl),
],
),
!isLastIndex ? const Divider(height: 16.0) : const SizedBox(height: 8.0)
],
);
}

Widget _buildFoodImage(String url) {
return FadeInImage.assetNetwork(
placeholder: 'assets/transparent.png',
image: url,
width: 64,
);
}

Widget _buildFoodDetail({
required BuildContext context,
required Food food,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(food.name, style: _textTheme(context).subtitle1),
const SizedBox(height: 16),
Row(
children: [
Text(
"特價" + food.price + " ",
style: _textTheme(context).caption,
),
Text(
food.comparePrice,
style: _textTheme(context)
.caption
?.copyWith(decoration: TextDecoration.lineThrough),
),
const SizedBox(width: 8.0),
if (food.isHotSale) _buildFoodHotSaleIcon(),
],
),
],
);
}

Widget _buildSectionHoteSaleIcon() {
return Container(
margin: const EdgeInsets.only(right: 4.0),
child: Icon(
Icons.whatshot,
color: Colors.pink,
size: 20.0,
),
);
}

Widget _buildFoodHotSaleIcon() {
return Container(
child: Icon(Icons.whatshot, color: Colors.pink, size: 16.0),
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Colors.pink.withOpacity(0.1),
borderRadius: BorderRadius.circular(16.0),
),
);
}

TextTheme _textTheme(context) => Theme.of(context).textTheme;
}

@aytunch
Copy link

aytunch commented Jan 12, 2022

You can find these issues from other similar packages
The problem arises when we want to use this package inside of a NestedScrollView
firatcetiner/scrollable_list_tabview#9
firatcetiner/scrollable_list_tabview#7

wayne900204 added a commit that referenced this issue Jan 17, 2022
@wayne900204
Copy link
Owner

@aytunch @Foodnet24App
I just fixed it. But I haven't published yet. You can clone the project and see what other features do you want.

@aytunch
Copy link

aytunch commented Jan 17, 2022

@wayne900204 thank you very much
I can test this out in mid week, I hope it is no problem.

@wayne900204
Copy link
Owner

@aytunch @Foodnet24App
I just published.
You can try again

@aytunch
Copy link

aytunch commented Jan 21, 2022

@wayne900204
Thanks
Ok I am ready to test but before I do, quick question:
Should we use it as usual? Is there any guide on how to use VerticleScrollableTabview inside of NestedScrollView or CustomScrollView?

@wayne900204
Copy link
Owner

Yes, Well, VerticleScrollableTabview is a CustomScrollView. you can use VerticleScrollableTabviewlike a CustomScrollView

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants