widgets.dart 4.41 KB
Newer Older
1 2 3 4
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/foundation.dart';
6 7 8 9 10 11 12 13
import 'package:flutter/material.dart';

import 'sections.dart';

const double kSectionIndicatorWidth = 32.0;

// The card for a single section. Displays the section's gradient and background image.
class SectionCard extends StatelessWidget {
14
  const SectionCard({ Key key, @required this.section })
15 16
    : assert(section != null),
      super(key: key);
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

  final Section section;

  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: const EdgeInsets.only(bottom: 1.0),
      child: new DecoratedBox(
        decoration: new BoxDecoration(
          borderRadius: new BorderRadius.circular(4.0),
          gradient: new LinearGradient(
            begin: FractionalOffset.topLeft,
            end: FractionalOffset.topRight,
            colors: <Color>[
              section.leftColor,
              section.rightColor,
            ],
          ),
        ),
36 37 38 39 40
        child: new Image.asset(
          section.backgroundAsset,
          color: const Color.fromRGBO(255, 255, 255, 0.075),
          colorBlendMode: BlendMode.modulate,
          fit: BoxFit.cover,
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
        ),
      ),
    );
  }
}

// The title is rendered with two overlapping text widgets that are vertically
// offset a little. It's supposed to look sort-of 3D.
class SectionTitle extends StatelessWidget {
  static const TextStyle sectionTitleStyle = const TextStyle(
    fontFamily: 'Raleway',
    inherit: false,
    fontSize: 24.0,
    fontWeight: FontWeight.w500,
    color: Colors.white,
    textBaseline: TextBaseline.alphabetic,
  );

  static final TextStyle sectionTitleShadowStyle = sectionTitleStyle.copyWith(
    color: const Color(0x19000000),
  );

63
  const SectionTitle({
64 65 66 67
    Key key,
    @required this.section,
    @required this.scale,
    @required this.opacity,
68 69 70 71
  }) : assert(section != null),
       assert(scale != null),
       assert(opacity != null && opacity >= 0.0 && opacity <= 1.0),
       super(key: key);
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

  final Section section;
  final double scale;
  final double opacity;

  @override
  Widget build(BuildContext context) {
    return new IgnorePointer(
      child: new Opacity(
        opacity: opacity,
        child: new Transform(
          transform: new Matrix4.identity()..scale(scale),
          alignment: FractionalOffset.center,
          child: new Stack(
            children: <Widget>[
              new Positioned(
                top: 4.0,
                child: new Text(section.title, style: sectionTitleShadowStyle),
              ),
              new Text(section.title, style: sectionTitleStyle),
            ],
          ),
        ),
      ),
    );
  }
}

// Small horizontal bar that indicates the selected section.
class SectionIndicator extends StatelessWidget {
102
  const SectionIndicator({ Key key, this.opacity: 1.0 }) : super(key: key);
103 104 105 106 107 108 109 110 111

  final double opacity;

  @override
  Widget build(BuildContext context) {
    return new IgnorePointer(
      child: new Container(
        width: kSectionIndicatorWidth,
        height: 3.0,
112
        color: Colors.white.withOpacity(opacity),
113 114 115 116 117 118 119
      ),
    );
  }
}

// Display a single SectionDetail.
class SectionDetailView extends StatelessWidget {
120 121 122 123
  SectionDetailView({ Key key, @required this.detail })
    : assert(detail != null && detail.imageAsset != null),
      assert((detail.imageAsset ?? detail.title) != null),
      super(key: key);
124 125 126 127 128 129 130 131

  final SectionDetail detail;

  @override
  Widget build(BuildContext context) {
    final Widget image = new DecoratedBox(
      decoration: new BoxDecoration(
        borderRadius: new BorderRadius.circular(6.0),
132
        image: new DecorationImage(
133
          image: new AssetImage(detail.imageAsset),
134
          fit: BoxFit.cover,
135 136 137 138 139 140 141 142 143 144 145 146 147
          alignment: FractionalOffset.center,
        ),
      ),
    );

    Widget item;
    if (detail.title == null && detail.subtitle == null) {
      item = new Container(
        height: 240.0,
        padding: const EdgeInsets.all(16.0),
        child: image,
      );
    } else {
148
      item = new ListTile(
149 150 151 152 153 154 155
        title: new Text(detail.title),
        subtitle: new Text(detail.subtitle),
        leading: new SizedBox(width: 32.0, height: 32.0, child: image),
      );
    }

    return new DecoratedBox(
156
      decoration: new BoxDecoration(color: Colors.grey.shade200),
157 158 159 160
      child: item,
    );
  }
}