如何用带有箭头的仪表构建小部件,如flutter中提供的照片

时间:2018-07-14 20:03:08

标签: dart flutter

我想创建一个小部件,以构建此照片中的描述 this photo

我已经创建了仪表条,但我仍然不知道如何从条的开始到结尾添加数字,以及在底部的箭头放置位置,并在其上方以相同的颜色显示

ComponentDidMount()

1 个答案:

答案 0 :(得分:0)

结合使用RowColumnAlign,只需几行即可完成。

最困难的部分实际上是三角形。通常,您想对三角形使用CustomPainter,但是我在这里很懒。所以我结合了平移,旋转和剪辑。

enter image description here

import 'dart:math';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHome(),
    );
  }
}

class MyHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: ScoreMeter(
              score: 1,
            ),
          )
        ],
      ),
    );
  }
}

class ScoreMeter extends StatelessWidget {
  final int score;

  ScoreMeter(
      {
      this.score,
      Key key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 100.0,
      child: Row(
        children: <Widget>[
          Expanded(
            child: ScoreMeterItem(
                score: score, color: Colors.green, minRange: 0, maxRange: 50),
          ),
          Expanded(
            child: ScoreMeterItem(
                score: score,
                color: Colors.yellow,
                minRange: 51,
                maxRange: 100),
          ),
          Expanded(
            child: ScoreMeterItem(
                score: score,
                color: Colors.orange,
                minRange: 101,
                maxRange: 150),
          ),
          Expanded(
            child: ScoreMeterItem(
                score: score, color: Colors.red, minRange: 151, maxRange: 200),
          ),
          Expanded(
            child: ScoreMeterItem(
                score: score,
                color: Colors.purple,
                minRange: 201,
                maxRange: 250),
          ),
          Expanded(
            child: ScoreMeterItem(
                score: score,
                color: Colors.brown,
                minRange: 251,
                maxRange: 300),
          ),
        ],
      ),
    );
  }
}

class ScoreMeterItem extends StatelessWidget {
  /// Hello World
  final int score;
  final Color color;
  final int minRange;
  final int maxRange;

  ScoreMeterItem(
      {this.score,
      this.color = Colors.grey,
      @required this.minRange,
      @required this.maxRange,
      Key key})
      : assert(minRange != null),
        assert(maxRange != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 4.0),
      child: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Text(minRange.toString(), style: theme.textTheme.caption),
              Text(maxRange.toString(), style: theme.textTheme.caption),
            ],
          ),
          ScoreMeterBar(color: color),
          score >= minRange && score <= maxRange
              ? SizedBox(
                  height: 10.0,
                  child: Align(
                    alignment: Alignment(
                        (score - minRange) / (maxRange - minRange) * 2 - 1,
                        0.0),
                    child: Arrow(color: color),
                  ),
                )
              : SizedBox()
        ],
      ),
    );
  }
}

class Arrow extends StatelessWidget {
  final Color color;

  Arrow({this.color});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 5.0,
      width: 10.0,
      child: ClipRect(
        child: OverflowBox(
          maxWidth: 10.0,
          maxHeight: 10.0,
          child: Align(
            alignment: Alignment.topCenter,
            child: Transform.translate(
              offset: Offset(.0, 5.0),
              child: Transform.rotate(
                angle: pi / 4,
                child: Container(
                  width: 10.0,
                  height: 10.0,
                  color: color,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class ScoreMeterBar extends StatelessWidget {
  final Color color;

  ScoreMeterBar({this.color = Colors.grey, Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 8.0,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.all(
          Radius.circular(4.0),
        ),
        color: color,
      ),
    );
  }
}