Add scrollbars
This commit is contained in:
parent
ea13825026
commit
17cfc3d478
|
|
@ -56,11 +56,13 @@ class ScrollableListViewBuilder extends StatefulWidget {
|
|||
Key key,
|
||||
@required this.itemBuilder,
|
||||
@required this.itemCount,
|
||||
this.separatorBuilder,
|
||||
this.scrollController,
|
||||
this.padding,
|
||||
}) : super(key: key);
|
||||
|
||||
final IndexedWidgetBuilder itemBuilder;
|
||||
final IndexedWidgetBuilder separatorBuilder;
|
||||
final int itemCount;
|
||||
final ScrollController scrollController;
|
||||
final EdgeInsetsGeometry padding;
|
||||
|
|
@ -92,13 +94,22 @@ class _ScrollableListViewBuilderState extends State<ScrollableListViewBuilder> {
|
|||
onEnter: (event) => setState(() => _isHovered = true),
|
||||
onExit: (event) => setState(() => _isHovered = false),
|
||||
child: Scrollbar(
|
||||
child: ListView.builder(
|
||||
padding: widget.padding,
|
||||
itemBuilder: widget.itemBuilder,
|
||||
itemCount: widget.itemCount,
|
||||
controller: widget.scrollController ?? _scrollController,
|
||||
shrinkWrap: true,
|
||||
),
|
||||
child: widget.separatorBuilder != null
|
||||
? ListView.separated(
|
||||
separatorBuilder: widget.separatorBuilder,
|
||||
padding: widget.padding,
|
||||
itemBuilder: widget.itemBuilder,
|
||||
itemCount: widget.itemCount,
|
||||
controller: widget.scrollController ?? _scrollController,
|
||||
shrinkWrap: true,
|
||||
)
|
||||
: ListView.builder(
|
||||
padding: widget.padding,
|
||||
itemBuilder: widget.itemBuilder,
|
||||
itemCount: widget.itemCount,
|
||||
controller: widget.scrollController ?? _scrollController,
|
||||
shrinkWrap: true,
|
||||
),
|
||||
controller: widget.scrollController ?? _scrollController,
|
||||
isAlwaysShown: _isHovered,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/list_filter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/presenters/entity_presenter.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/app_data_table.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/app_paginated_data_table.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
|
|
@ -54,14 +55,11 @@ class EntityList extends StatefulWidget {
|
|||
|
||||
class _EntityListState extends State<EntityList> {
|
||||
EntityDataTableSource dataTableSource;
|
||||
ScrollController _scrollController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_scrollController = ScrollController();
|
||||
|
||||
final entityType = widget.entityType;
|
||||
final state = widget.state;
|
||||
final entityList = widget.entityList;
|
||||
|
|
@ -95,12 +93,6 @@ class _EntityListState extends State<EntityList> {
|
|||
dataTableSource.notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
|
|
@ -157,32 +149,28 @@ class _EntityListState extends State<EntityList> {
|
|||
fit: FlexFit.loose,
|
||||
child: entityList.isEmpty
|
||||
? HelpText(AppLocalization.of(context).noRecordsFound)
|
||||
: AppScrollbar(
|
||||
controller: _scrollController,
|
||||
child: ListView.separated(
|
||||
padding: const EdgeInsets.symmetric(vertical: 25),
|
||||
controller: _scrollController,
|
||||
separatorBuilder: (context, index) =>
|
||||
(index == 0 || index == entityList.length)
|
||||
? SizedBox()
|
||||
: ListDivider(),
|
||||
itemCount: entityList.length + 2,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
if (index == 0 || index == entityList.length + 1) {
|
||||
return Container(
|
||||
color: Theme.of(context).cardColor,
|
||||
height: 25,
|
||||
);
|
||||
} else {
|
||||
return widget.itemBuilder(context, index - 1);
|
||||
}
|
||||
},
|
||||
),
|
||||
: ScrollableListViewBuilder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 25),
|
||||
separatorBuilder: (context, index) =>
|
||||
(index == 0 || index == entityList.length)
|
||||
? SizedBox()
|
||||
: ListDivider(),
|
||||
itemCount: entityList.length + 2,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
if (index == 0 || index == entityList.length + 1) {
|
||||
return Container(
|
||||
color: Theme.of(context).cardColor,
|
||||
height: 25,
|
||||
);
|
||||
} else {
|
||||
return widget.itemBuilder(context, index - 1);
|
||||
}
|
||||
},
|
||||
) /*DraggableScrollbar.semicircle(
|
||||
backgroundColor: Theme.of(context).backgroundColor,
|
||||
scrollbarTimeToFade: Duration(seconds: 1),
|
||||
controller: _scrollController,
|
||||
child: ListView.separated(
|
||||
child: ScrollableListViewBuilder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 25),
|
||||
controller: _scrollController,
|
||||
separatorBuilder: (context, index) =>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/lists/activity_list_tile.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/view/client_view_vm.dart';
|
||||
|
||||
class ClientViewActivity extends StatefulWidget {
|
||||
|
|
@ -31,7 +32,7 @@ class _ClientViewActivityState extends State<ClientViewActivity> {
|
|||
return LoadingIndicator();
|
||||
}
|
||||
|
||||
return ListView.separated(
|
||||
return ScrollableListViewBuilder(
|
||||
itemCount: activities.length,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
separatorBuilder: (context, index) => ListDivider(),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
|
||||
import 'package:invoiceninja_flutter/ui/client/view/client_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||
import 'package:invoiceninja_flutter/utils/icons.dart';
|
||||
|
|
@ -40,8 +41,7 @@ class _ClientViewLedgerState extends State<ClientViewLedger> {
|
|||
return LoadingIndicator();
|
||||
}
|
||||
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
return ScrollableListViewBuilder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: ledgers.length + 1,
|
||||
separatorBuilder: (context, index) => ListDivider(),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
|
|||
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_sidebar_selectors.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
|
||||
import 'package:invoiceninja_flutter/ui/expense/expense_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment/payment_list_item.dart';
|
||||
|
|
@ -109,8 +110,7 @@ class InvoiceSidebar extends StatelessWidget {
|
|||
(upcomingInvoices.isNotEmpty ? ' (${upcomingInvoices.length})' : ''),
|
||||
list1: upcomingInvoices.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: upcomingInvoices.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return InvoiceListItem(
|
||||
|
|
@ -124,8 +124,7 @@ class InvoiceSidebar extends StatelessWidget {
|
|||
(pastDueInvoices.isNotEmpty ? ' (${pastDueInvoices.length})' : ''),
|
||||
list2: pastDueInvoices.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: pastDueInvoices.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return InvoiceListItem(
|
||||
|
|
@ -140,8 +139,7 @@ class InvoiceSidebar extends StatelessWidget {
|
|||
: localization.selectedInvoices + ' (${selectedIds.length})',
|
||||
list3: (selectedIds ?? <String>[]).isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: selectedIds?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final invoice = state.invoiceState.map[selectedIds[index]];
|
||||
|
|
@ -179,8 +177,7 @@ class PaymentSidebar extends StatelessWidget {
|
|||
(recentPayments.isNotEmpty ? ' (${recentPayments.length})' : ''),
|
||||
list1: recentPayments.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: recentPayments.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return PaymentListItem(
|
||||
|
|
@ -195,8 +192,7 @@ class PaymentSidebar extends StatelessWidget {
|
|||
: localization.selectedPayments + ' (${selectedIds.length})',
|
||||
list3: (selectedIds ?? <String>[]).isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: selectedIds?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final payment = state.paymentState.map[selectedIds[index]];
|
||||
|
|
@ -238,8 +234,7 @@ class QuoteSidebar extends StatelessWidget {
|
|||
(upcomingQuotes.isNotEmpty ? ' (${upcomingQuotes.length})' : ''),
|
||||
list1: upcomingQuotes.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: upcomingQuotes.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return QuoteListItem(
|
||||
|
|
@ -253,8 +248,7 @@ class QuoteSidebar extends StatelessWidget {
|
|||
(expriedQuotes.isNotEmpty ? ' (${expriedQuotes.length})' : ''),
|
||||
list2: expriedQuotes.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: expriedQuotes.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return QuoteListItem(
|
||||
|
|
@ -269,8 +263,7 @@ class QuoteSidebar extends StatelessWidget {
|
|||
: localization.selectedQuotes + ' (${selectedIds.length})',
|
||||
list3: (selectedIds ?? <String>[]).isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: selectedIds?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final quote = state.quoteState.map[selectedIds[index]];
|
||||
|
|
@ -312,8 +305,7 @@ class TaskSidebar extends StatelessWidget {
|
|||
(runningTasks.isNotEmpty ? ' (${runningTasks.length})' : ''),
|
||||
list1: runningTasks.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: runningTasks.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return TaskListItem(
|
||||
|
|
@ -327,8 +319,7 @@ class TaskSidebar extends StatelessWidget {
|
|||
(recentTasks.isNotEmpty ? ' (${recentTasks.length})' : ''),
|
||||
list2: recentTasks.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: recentTasks.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return TaskListItem(
|
||||
|
|
@ -343,8 +334,7 @@ class TaskSidebar extends StatelessWidget {
|
|||
: localization.selectedTasks + ' (${selectedIds.length})',
|
||||
list3: (selectedIds ?? <String>[]).isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: selectedIds?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final task = state.taskState.map[selectedIds[index]];
|
||||
|
|
@ -390,8 +380,7 @@ class ExpenseSidbar extends StatelessWidget {
|
|||
(upcomingExpenses.isNotEmpty ? ' (${upcomingExpenses.length})' : ''),
|
||||
list1: upcomingExpenses.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: upcomingExpenses.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ExpenseListItem(
|
||||
|
|
@ -406,8 +395,7 @@ class ExpenseSidbar extends StatelessWidget {
|
|||
(recentExpenses.isNotEmpty ? ' (${recentExpenses.length})' : ''),
|
||||
list1: recentExpenses.isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: recentExpenses.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ExpenseListItem(
|
||||
|
|
@ -422,8 +410,7 @@ class ExpenseSidbar extends StatelessWidget {
|
|||
: localization.selectedExpenses + ' (${selectedIds.length})',
|
||||
list3: (selectedIds ?? <String>[]).isEmpty
|
||||
? null
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
: ScrollableListViewBuilder(
|
||||
itemCount: selectedIds?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final expense = state.expenseState.map[selectedIds[index]];
|
||||
|
|
@ -455,9 +442,9 @@ class _DashboardSidebar extends StatelessWidget {
|
|||
final String label1;
|
||||
final String label2;
|
||||
final String label3;
|
||||
final ListView list1;
|
||||
final ListView list2;
|
||||
final ListView list3;
|
||||
final ScrollableListViewBuilder list1;
|
||||
final ScrollableListViewBuilder list2;
|
||||
final ScrollableListViewBuilder list3;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
|
||||
import 'package:invoiceninja_flutter/ui/invoice/view/invoice_view_vm.dart';
|
||||
import 'package:invoiceninja_flutter/utils/formatting.dart';
|
||||
import 'package:timeago/timeago.dart' as timeago;
|
||||
|
|
@ -37,8 +38,7 @@ class _InvoiceViewHistoryState extends State<InvoiceViewHistory> {
|
|||
final historyList = invoice.history.toList();
|
||||
historyList.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
return ScrollableListViewBuilder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
final history = historyList[index];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:invoiceninja_flutter/ui/app/help_text.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/scrollable_listview.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/tables/entity_datatable.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment_term/payment_term_list_item.dart';
|
||||
import 'package:invoiceninja_flutter/ui/payment_term/payment_term_list_vm.dart';
|
||||
|
|
@ -38,7 +39,7 @@ class _PaymentTermListState extends State<PaymentTermList> {
|
|||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => viewModel.onRefreshed(context),
|
||||
child: ListView.separated(
|
||||
child: ScrollableListViewBuilder(
|
||||
separatorBuilder: (context, index) => ListDivider(),
|
||||
itemCount: viewModel.paymentTermList.length,
|
||||
itemBuilder: (BuildContext context, index) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue