mirror of
https://github.com/flutter/samples.git
synced 2025-11-13 00:08:24 +00:00
[Gallery] Fix directory structure (#312)
This commit is contained in:
406
gallery/lib/studies/rally/finance.dart
Normal file
406
gallery/lib/studies/rally/finance.dart
Normal file
@@ -0,0 +1,406 @@
|
||||
// Copyright 2019 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
import 'package:gallery/data/gallery_options.dart';
|
||||
import 'package:gallery/l10n/gallery_localizations.dart';
|
||||
import 'package:gallery/layout/text_scale.dart';
|
||||
import 'package:gallery/studies/rally/charts/line_chart.dart';
|
||||
import 'package:gallery/studies/rally/charts/pie_chart.dart';
|
||||
import 'package:gallery/studies/rally/charts/vertical_fraction_bar.dart';
|
||||
import 'package:gallery/studies/rally/colors.dart';
|
||||
import 'package:gallery/studies/rally/data.dart';
|
||||
import 'package:gallery/studies/rally/formatters.dart';
|
||||
|
||||
class FinancialEntityView extends StatelessWidget {
|
||||
const FinancialEntityView({
|
||||
this.heroLabel,
|
||||
this.heroAmount,
|
||||
this.wholeAmount,
|
||||
this.segments,
|
||||
this.financialEntityCards,
|
||||
}) : assert(segments.length == financialEntityCards.length);
|
||||
|
||||
/// The amounts to assign each item.
|
||||
final List<RallyPieChartSegment> segments;
|
||||
final String heroLabel;
|
||||
final double heroAmount;
|
||||
final double wholeAmount;
|
||||
final List<FinancialEntityCategoryView> financialEntityCards;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final maxWidth = pieChartMaxSize + (cappedTextScale(context) - 1.0) * 100.0;
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
return Column(
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
// We decrease the max height to ensure the [RallyPieChart] does
|
||||
// not take up the full height when it is smaller than
|
||||
// [kPieChartMaxSize].
|
||||
maxHeight: math.min(
|
||||
constraints.biggest.shortestSide * 0.9,
|
||||
maxWidth,
|
||||
),
|
||||
),
|
||||
child: RallyPieChart(
|
||||
heroLabel: heroLabel,
|
||||
heroAmount: heroAmount,
|
||||
wholeAmount: wholeAmount,
|
||||
segments: segments,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Container(
|
||||
height: 1,
|
||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||
color: RallyColors.inputBackground,
|
||||
),
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||
color: RallyColors.cardBackground,
|
||||
child: Column(
|
||||
children: financialEntityCards,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// A reusable widget to show balance information of a single entity as a card.
|
||||
class FinancialEntityCategoryView extends StatelessWidget {
|
||||
const FinancialEntityCategoryView({
|
||||
@required this.indicatorColor,
|
||||
@required this.indicatorFraction,
|
||||
@required this.title,
|
||||
@required this.subtitle,
|
||||
@required this.semanticsLabel,
|
||||
@required this.amount,
|
||||
@required this.suffix,
|
||||
});
|
||||
|
||||
final Color indicatorColor;
|
||||
final double indicatorFraction;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final String semanticsLabel;
|
||||
final String amount;
|
||||
final Widget suffix;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
return Semantics.fromProperties(
|
||||
properties: SemanticsProperties(
|
||||
button: true,
|
||||
label: semanticsLabel,
|
||||
),
|
||||
excludeSemantics: true,
|
||||
child: FlatButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute<FinancialEntityCategoryDetailsPage>(
|
||||
builder: (context) => FinancialEntityCategoryDetailsPage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
height: 32 + 60 * (cappedTextScale(context) - 1),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: VerticalFractionBar(
|
||||
color: indicatorColor,
|
||||
fraction: indicatorFraction,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: textTheme.body1.copyWith(fontSize: 16),
|
||||
),
|
||||
Text(
|
||||
subtitle,
|
||||
style: textTheme.body1
|
||||
.copyWith(color: RallyColors.gray60),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
amount,
|
||||
style: textTheme.body2.copyWith(
|
||||
fontSize: 20,
|
||||
color: RallyColors.gray,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
constraints: BoxConstraints(minWidth: 32),
|
||||
padding: EdgeInsetsDirectional.only(start: 12),
|
||||
child: suffix,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
height: 1,
|
||||
indent: 16,
|
||||
endIndent: 16,
|
||||
color: Color(0xAA282828),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Data model for [FinancialEntityCategoryView].
|
||||
class FinancialEntityCategoryModel {
|
||||
const FinancialEntityCategoryModel(
|
||||
this.indicatorColor,
|
||||
this.indicatorFraction,
|
||||
this.title,
|
||||
this.subtitle,
|
||||
this.usdAmount,
|
||||
this.suffix,
|
||||
);
|
||||
|
||||
final Color indicatorColor;
|
||||
final double indicatorFraction;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final double usdAmount;
|
||||
final Widget suffix;
|
||||
}
|
||||
|
||||
FinancialEntityCategoryView buildFinancialEntityFromAccountData(
|
||||
AccountData model,
|
||||
int accountDataIndex,
|
||||
BuildContext context,
|
||||
) {
|
||||
final amount = usdWithSignFormat(context).format(model.primaryAmount);
|
||||
final shortAccountNumber = model.accountNumber.substring(6);
|
||||
return FinancialEntityCategoryView(
|
||||
suffix: const Icon(Icons.chevron_right, color: Colors.grey),
|
||||
title: model.name,
|
||||
subtitle: '• • • • • • $shortAccountNumber',
|
||||
semanticsLabel: GalleryLocalizations.of(context).rallyAccountAmount(
|
||||
model.name,
|
||||
shortAccountNumber,
|
||||
amount,
|
||||
),
|
||||
indicatorColor: RallyColors.accountColor(accountDataIndex),
|
||||
indicatorFraction: 1,
|
||||
amount: amount,
|
||||
);
|
||||
}
|
||||
|
||||
FinancialEntityCategoryView buildFinancialEntityFromBillData(
|
||||
BillData model,
|
||||
int billDataIndex,
|
||||
BuildContext context,
|
||||
) {
|
||||
final amount = usdWithSignFormat(context).format(model.primaryAmount);
|
||||
return FinancialEntityCategoryView(
|
||||
suffix: const Icon(Icons.chevron_right, color: Colors.grey),
|
||||
title: model.name,
|
||||
subtitle: model.dueDate,
|
||||
semanticsLabel: GalleryLocalizations.of(context).rallyBillAmount(
|
||||
model.name,
|
||||
model.dueDate,
|
||||
amount,
|
||||
),
|
||||
indicatorColor: RallyColors.billColor(billDataIndex),
|
||||
indicatorFraction: 1,
|
||||
amount: amount,
|
||||
);
|
||||
}
|
||||
|
||||
FinancialEntityCategoryView buildFinancialEntityFromBudgetData(
|
||||
BudgetData model,
|
||||
int budgetDataIndex,
|
||||
BuildContext context,
|
||||
) {
|
||||
final amountUsed = usdWithSignFormat(context).format(model.amountUsed);
|
||||
final primaryAmount = usdWithSignFormat(context).format(model.primaryAmount);
|
||||
final amount =
|
||||
usdWithSignFormat(context).format(model.primaryAmount - model.amountUsed);
|
||||
|
||||
return FinancialEntityCategoryView(
|
||||
suffix: Text(
|
||||
GalleryLocalizations.of(context).rallyFinanceLeft,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.body1
|
||||
.copyWith(color: RallyColors.gray60, fontSize: 10),
|
||||
),
|
||||
title: model.name,
|
||||
subtitle: amountUsed + ' / ' + primaryAmount,
|
||||
semanticsLabel: GalleryLocalizations.of(context).rallyBudgetAmount(
|
||||
model.name,
|
||||
model.amountUsed,
|
||||
model.primaryAmount,
|
||||
amount,
|
||||
),
|
||||
indicatorColor: RallyColors.budgetColor(budgetDataIndex),
|
||||
indicatorFraction: model.amountUsed / model.primaryAmount,
|
||||
amount: amount,
|
||||
);
|
||||
}
|
||||
|
||||
List<FinancialEntityCategoryView> buildAccountDataListViews(
|
||||
List<AccountData> items,
|
||||
BuildContext context,
|
||||
) {
|
||||
return List<FinancialEntityCategoryView>.generate(
|
||||
items.length,
|
||||
(i) => buildFinancialEntityFromAccountData(items[i], i, context),
|
||||
);
|
||||
}
|
||||
|
||||
List<FinancialEntityCategoryView> buildBillDataListViews(
|
||||
List<BillData> items,
|
||||
BuildContext context,
|
||||
) {
|
||||
return List<FinancialEntityCategoryView>.generate(
|
||||
items.length,
|
||||
(i) => buildFinancialEntityFromBillData(items[i], i, context),
|
||||
);
|
||||
}
|
||||
|
||||
List<FinancialEntityCategoryView> buildBudgetDataListViews(
|
||||
List<BudgetData> items,
|
||||
BuildContext context,
|
||||
) {
|
||||
return <FinancialEntityCategoryView>[
|
||||
for (int i = 0; i < items.length; i++)
|
||||
buildFinancialEntityFromBudgetData(items[i], i, context)
|
||||
];
|
||||
}
|
||||
|
||||
class FinancialEntityCategoryDetailsPage extends StatelessWidget {
|
||||
final List<DetailedEventData> items =
|
||||
DummyDataService.getDetailedEventItems();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<_DetailedEventCard> cards = items.map((detailedEventData) {
|
||||
return _DetailedEventCard(
|
||||
title: detailedEventData.title,
|
||||
date: detailedEventData.date,
|
||||
amount: detailedEventData.amount,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
return ApplyTextOptions(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
GalleryLocalizations.of(context).rallyAccountDataChecking,
|
||||
style: Theme.of(context).textTheme.body1.copyWith(fontSize: 18),
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 200,
|
||||
width: double.infinity,
|
||||
child: RallyLineChart(events: items),
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(shrinkWrap: true, children: cards),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DetailedEventCard extends StatelessWidget {
|
||||
const _DetailedEventCard({
|
||||
@required this.title,
|
||||
@required this.date,
|
||||
@required this.amount,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final DateTime date;
|
||||
final double amount;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
return FlatButton(
|
||||
onPressed: () {},
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
width: double.infinity,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: textTheme.body1.copyWith(fontSize: 16),
|
||||
),
|
||||
Text(
|
||||
shortDateFormat(context).format(date),
|
||||
semanticsLabel: longDateFormat(context).format(date),
|
||||
style:
|
||||
textTheme.body1.copyWith(color: RallyColors.gray60),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
usdWithSignFormat(context).format(amount),
|
||||
style: textTheme.body2
|
||||
.copyWith(fontSize: 20, color: RallyColors.gray),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 1,
|
||||
child: Container(
|
||||
color: const Color(0xAA282828),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user