mirror of
https://github.com/flutter/samples.git
synced 2025-11-11 15:28:44 +00:00
180 lines
5.3 KiB
Dart
180 lines
5.3 KiB
Dart
// 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 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:gallery/layout/adaptive.dart';
|
|
import 'package:gallery/layout/highlight_focus.dart';
|
|
import 'package:gallery/studies/crane/model/data.dart';
|
|
import 'package:gallery/studies/crane/model/destination.dart';
|
|
|
|
class ItemCards extends StatefulWidget {
|
|
final int index;
|
|
|
|
const ItemCards({Key key, this.index}) : super(key: key);
|
|
|
|
static const totalColumns = 4;
|
|
|
|
@override
|
|
_ItemCardsState createState() => _ItemCardsState();
|
|
}
|
|
|
|
class _ItemCardsState extends State<ItemCards> {
|
|
List<Destination> flyDestinations;
|
|
List<Destination> sleepDestinations;
|
|
List<Destination> eatDestinations;
|
|
|
|
List<Widget> _buildDestinationCards({int listIndex}) {
|
|
final List<Destination> destinations = [
|
|
if (listIndex == 0) ...flyDestinations,
|
|
if (listIndex == 1) ...sleepDestinations,
|
|
if (listIndex == 2) ...eatDestinations,
|
|
];
|
|
|
|
return destinations
|
|
.map(
|
|
(d) => HighlightFocus(
|
|
debugLabel: 'DestinationCard: ${d.destination}',
|
|
highlightColor: Colors.red.withOpacity(0.5),
|
|
onPressed: () {},
|
|
child: RepaintBoundary(
|
|
child: _DestinationCard(destination: d),
|
|
),
|
|
),
|
|
)
|
|
.toList();
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
// We use didChangeDependencies because the initialization involves an
|
|
// InheritedWidget (for localization). However, we don't need to get
|
|
// destinations again when, say, resizing the window.
|
|
if (flyDestinations == null) {
|
|
flyDestinations = getFlyDestinations(context);
|
|
sleepDestinations = getSleepDestinations(context);
|
|
eatDestinations = getEatDestinations(context);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final isDesktop = isDisplayDesktop(context);
|
|
final List<Widget> destinationCards =
|
|
_buildDestinationCards(listIndex: widget.index);
|
|
|
|
if (isDesktop) {
|
|
var columns = List<List<Widget>>(ItemCards.totalColumns);
|
|
for (var i = 0; i < destinationCards.length; i++) {
|
|
final col = i % ItemCards.totalColumns;
|
|
|
|
if (columns[col] == null) {
|
|
columns[col] = List<Widget>();
|
|
}
|
|
|
|
columns[col].add(
|
|
// TODO: determine why this is isn't always respected
|
|
Semantics(
|
|
sortKey: OrdinalSortKey(i.toDouble(), name: 'destination'),
|
|
child: destinationCards[i],
|
|
),
|
|
);
|
|
}
|
|
|
|
return Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
for (var column in columns)
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsetsDirectional.only(end: 16),
|
|
child: Column(
|
|
children: column,
|
|
),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
} else {
|
|
return Column(children: destinationCards);
|
|
}
|
|
}
|
|
}
|
|
|
|
class _DestinationCard extends StatelessWidget {
|
|
_DestinationCard({this.destination}) : assert(destination != null);
|
|
final Destination destination;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final imageWidget = Semantics(
|
|
child: ExcludeSemantics(
|
|
child: Image.asset(
|
|
destination.assetName,
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
label: destination.assetSemanticLabel,
|
|
);
|
|
|
|
final isDesktop = isDisplayDesktop(context);
|
|
final textTheme = Theme.of(context).textTheme;
|
|
|
|
if (isDesktop) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 40),
|
|
child: Semantics(
|
|
container: true,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
|
child: imageWidget,
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 20, bottom: 10),
|
|
child: Text(
|
|
destination.destination,
|
|
style: textTheme.subhead,
|
|
),
|
|
),
|
|
Text(
|
|
destination.subtitle(context),
|
|
semanticsLabel: destination.subtitleSemantics(context),
|
|
style: textTheme.subtitle,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
} else {
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
ListTile(
|
|
contentPadding: EdgeInsetsDirectional.only(end: 8),
|
|
leading: ClipRRect(
|
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
|
child: SizedBox(
|
|
height: 60,
|
|
width: 60,
|
|
child: imageWidget,
|
|
),
|
|
),
|
|
title: Text(destination.destination, style: textTheme.subhead),
|
|
subtitle: Text(
|
|
destination.subtitle(context),
|
|
semanticsLabel: destination.subtitleSemantics(context),
|
|
style: textTheme.subtitle,
|
|
),
|
|
),
|
|
Divider(),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
}
|