Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class MyApp extends StatelessWidget {
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;

@override
Expand Down
2 changes: 1 addition & 1 deletion example/test/widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:example/main.dart';
import '../lib/main.dart';

void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
Expand Down
78 changes: 42 additions & 36 deletions lib/flutter_section_list_view.dart
Original file line number Diff line number Diff line change
@@ -1,72 +1,77 @@
library flutter_section_list_view;
// ignore_for_file: library_private_types_in_public_api

// library flutter_section_list_view;

import 'package:flutter/material.dart';

typedef int NumberOfRowsCallBack(int section);
typedef int NumberOfSectionCallBack();
typedef Widget SectionWidgetCallBack(int section);
typedef Widget RowsWidgetCallBack(int section, int row);
typedef Future<void> LoadMoreData();
typedef Future<void> RefreshList();
typedef NumberOfRowsCallBack = int Function(int section);
typedef NumberOfSectionCallBack = int Function();
typedef SectionWidgetCallBack = Widget Function(int section);
typedef RowsWidgetCallBack = Widget Function(int section, int row);
typedef LoadMoreData = Future<void> Function();
typedef RefreshList = Future<void> Function();

// ignore: must_be_immutable
class FlutterSectionListView extends StatefulWidget {
FlutterSectionListView({
this.numberOfSection,
@required this.numberOfRowsInSection,
this.sectionWidget,
@required this.rowWidget,
}) : assert(!(numberOfRowsInSection == null || rowWidget == null),
'numberOfRowsInSection and rowWidget are mandatory');
FlutterSectionListView({
required this.numberOfRowsInSection,
required this.rowWidget, this.numberOfSection, this.sectionWidget, this.physics,
Key? key,
}) : super(key: key);

/// Defines the total number of sections
final NumberOfSectionCallBack numberOfSection;
final NumberOfSectionCallBack? numberOfSection;

/// Mandatory callback method to get the rows count in each section
final NumberOfRowsCallBack numberOfRowsInSection;
final NumberOfRowsCallBack? numberOfRowsInSection;

/// Callback method to get the section widget
final SectionWidgetCallBack sectionWidget;
final SectionWidgetCallBack? sectionWidget;

/// Mandatory callback method to get the row widget
final RowsWidgetCallBack rowWidget;

/// [ScrollPhysics] provided by that behavior will take precedence after[physics]
final ScrollPhysics? physics;

/// A callback method used to load more data when listview reached to end.
LoadMoreData loadMoreData;
LoadMoreData? loadMoreData;

/// Return false when there are no more pages to return
bool isMoreAvailable = true;

/// Handle this callback when need pull to refresh.
RefreshList refresh;
RefreshList? refresh;

@override
_FlutterSectionListViewState createState() => _FlutterSectionListViewState();
}

class _FlutterSectionListViewState extends State<FlutterSectionListView> {
/// List of total number of rows and section in each group
var itemList = new List<int>();
List<int> itemList = [];
bool isLoading = false;
int itemCount = 0;
int sectionCount = 0;
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();
GlobalKey<RefreshIndicatorState>();

@override
void initState() {
sectionCount = widget.numberOfSection();
sectionCount = widget.numberOfSection!();
itemCount = listItemCount();
super.initState();
}

Future<void> refreshList() async {
await widget.refresh().whenComplete(() {
setState(() {
sectionCount = widget.numberOfSection();
itemCount = listItemCount();
if (widget.refresh != null) {
await widget.refresh!().whenComplete(() {
setState(() {
sectionCount = widget.numberOfSection!();
itemCount = listItemCount();
});
});
});
}
}

@override
Expand All @@ -93,11 +98,11 @@ class _FlutterSectionListViewState extends State<FlutterSectionListView> {
setState(() {
isLoading = true;
});
final Future<void> loadMoreResult = widget.loadMoreData();
final Future<void> loadMoreResult = widget.loadMoreData!();
loadMoreResult.whenComplete(() {
setState(() {
isLoading = false;
sectionCount = widget.numberOfSection();
sectionCount = widget.numberOfSection!();
itemCount = listItemCount();
});
});
Expand All @@ -111,14 +116,15 @@ class _FlutterSectionListViewState extends State<FlutterSectionListView> {
return buildItemWidget(index);
},
key: widget.key,
physics: widget.physics,
),
),
),
Container(
height: isLoading ? 50.0 : 0,
color: Colors.transparent,
child: Center(
child: new CircularProgressIndicator(),
child: const Center(
child: CircularProgressIndicator(),
),
),
],
Expand All @@ -127,12 +133,12 @@ class _FlutterSectionListViewState extends State<FlutterSectionListView> {

/// Get the total count of items in list(including both row and sections)
int listItemCount() {
itemList = new List<int>();
itemList = [];
int rowCount = 0;

for (int i = 0; i < sectionCount; i++) {
/// Get the number of rows in each section using callback
int rows = widget.numberOfRowsInSection(i);
int rows = widget.numberOfRowsInSection!(i);

/// Here 1 is added for each section in one group
rowCount += rows + 1;
Expand All @@ -148,8 +154,8 @@ class _FlutterSectionListViewState extends State<FlutterSectionListView> {
/// If the row number is -1 of any indexPath it will represent a section else row
if (indexPath.row < 0) {
return widget.sectionWidget != null
? widget.sectionWidget(indexPath.section)
: SizedBox(
? widget.sectionWidget!(indexPath.section)
: const SizedBox(
height: 0,
);
} else {
Expand All @@ -175,7 +181,7 @@ class _FlutterSectionListViewState extends State<FlutterSectionListView> {

/// Helper class for indexPath of each item in list
class IndexPath {
IndexPath({this.section, this.row});
IndexPath({required this.section, required this.row});

int section = 0;
int row = 0;
Expand Down
129 changes: 77 additions & 52 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,50 @@ packages:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.0"
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.5"
charcode:
version: "2.1.1"
characters:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.2"
version: "1.3.0"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.17.1"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.14.11"
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
Expand All @@ -39,41 +59,46 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
matcher:
js:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.5"
meta:
version: "0.6.7"
matcher:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.7"
path:
version: "0.12.15"
material_color_utilities:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.4"
pedantic:
version: "0.2.0"
meta:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0+1"
quiver:
version: "1.9.1"
path:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.5"
version: "1.8.3"
sky_engine:
dependency: transitive
description: flutter
Expand All @@ -83,57 +108,57 @@ packages:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.5"
version: "1.9.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.3"
version: "1.11.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
version: "2.1.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.5"
version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.5"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.6"
version: "0.5.1"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.8"
version: "2.1.4"
sdks:
dart: ">=2.2.2 <3.0.0"
dart: ">=3.0.6 <4.0.0"
Loading