Флаттер: strokeWidth вызывается на нуль в listview.builder

#flutter #dart

Вопрос:

Я пытаюсь создать приложение для рисования, в котором теперь у вас может быть несколько кистей, когда вы добавляете кисть в список, она добавляется в список, но когда я пытаюсь показать listview.builder , как она отображается strokeWidth , она включается null .

класс поставщика,

 import 'package:flutter/material.dart';
import 'package:paint_app/models/brush.dart';

class BrushProvider extends ChangeNotifier {
  Map<String, Brush> _brush = {};
  Map<String, Brush> get brush => _brush;

  int get brushCount => _brush.length;

  void addBrush(double strokeWidth, Color color, String id) {
    if (_brush.containsKey(strokeWidth)) {
      _brush.update(
        id,
        (value) => Brush(color: color, id: id, strokeWidth: strokeWidth),
      );
      notifyListeners();
    } else {
      _brush.putIfAbsent(
        id,
        () => Brush(
            strokeWidth: strokeWidth,
            id: DateTime.now().toString(),
            color: color),
      );
      notifyListeners();
    }
    notifyListeners();
  }
}

 

место, где я пытаюсь это показать,

 class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
  List<Offset> _points = <Offset>[];
  AnimationController _controller;
  double value = 1;
  Color pickerColor = Color(0xff443a49);
  Color currentColor = Color(0xff443a49);
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 500),
    );
  }

  @override
  Widget build(BuildContext context) {
    final brushes = Provider.of<BrushProvider>(context);
    return Scaffold(
      key: _scaffoldKey,
      drawer: Drawer(
        child: Column(
          children: [
            SizedBox(
              height: 100,
            ),
            Text(
              'Add Stroke width',
              style: TextStyle(fontSize: 20),
            ),
            SliderTheme(
              data: SliderTheme.of(context).copyWith(
                activeTrackColor: Colors.red[700],
                inactiveTrackColor: Colors.red[100],
                trackShape: RoundedRectSliderTrackShape(),
                trackHeight: 4.0,
                thumbShape: RoundSliderThumbShape(enabledThumbRadius: 12.0),
                thumbColor: Colors.redAccent,
                overlayColor: Colors.red.withAlpha(32),
                overlayShape: RoundSliderOverlayShape(overlayRadius: 28.0),
                tickMarkShape: RoundSliderTickMarkShape(),
                activeTickMarkColor: Colors.red[700],
                inactiveTickMarkColor: Colors.red[100],
                valueIndicatorShape: PaddleSliderValueIndicatorShape(),
                valueIndicatorColor: Colors.redAccent,
                valueIndicatorTextStyle: TextStyle(
                  color: Colors.white,
                ),
              ),
              child: Slider(
                value: value,
                min: 1,
                max: 30,
                divisions: 30,
                label: '${value.round()}',
                onChanged: (v) {
                  setState(
                    () {
                      value = v;
                    },
                  );
                },
              ),
            ),
            ElevatedButton(
              onPressed: () {
                brushes.addBrush(
                    value, currentColor, DateTime.now().toString()); //<-- adding to the list
              },
              child: Icon(Icons.add),
              style: ElevatedButton.styleFrom(
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20),
                  ),
                  primary: Colors.blueGrey),
            ),
            Divider(
              thickness: 2,
            ),
            SizedBox(
              height: 50,
            ),
            ListView.builder(
                shrinkWrap: true,
                itemCount:
                     brushes.brush.length,
                itemBuilder: (context, index) {
                  if (brushes.brush.length == null ) {
                    return Text('No Brushes');
                  }
                  return Container(
                    height: 50,
                    width: double.infinity,
                    child: Text(
                        'Stroke Width: ${brushes.brush[index].strokeWidth}'), // <-- here trying to show
                    color: brushes.brush[index].color,
                  );
                }),
          ],
        ),
      ),
body:(rest of the code...)
 

класс модели,

 import 'package:flutter/cupertino.dart';

class Brush{
  final Color color;
  final double strokeWidth;
  final String id;

  Brush({this.strokeWidth,this.color,this.id});
}
 

кто-нибудь может сказать мне, что я здесь делаю не так?

Ответ №1:

Проблема в том , что вы работаете с картой brushes.brush , которая зависит от 'key':'value' пар, но вы рассматриваете ее как список, который зависит от [index] .

Вы можете преобразовать свою карту в список, а затем работать с ней ListView.builder .

Попробуйте это:

 Widget build(BuildContext context) {
final brushes = Provider.of<BrushProvider>(context, listen:true);
List<Brush> brushList = brushes.brush.entries.map((entry) =>  entry.value).toList();
 

и в вашем ListView.builder , измените его на этот:

       ListView.builder(
            shrinkWrap: true,
            itemCount:
                 brushList.length,
            itemBuilder: (context, index) {
              if (brushList.isEmpty ) {
                return Text('No Brushes');
              }
              return Container(
                height: 50,
                width: double.infinity,
                child: Text(
                    'Stroke Width: ${brushList[index].strokeWidth}'), // <-- should work now
                color: brushList[index].color,
              );
            }),
 

Комментарии:

1. хорошо, большое вам спасибо, это работает как шарм, но есть ли лучший способ сделать это, или у меня все в порядке?

2. Пожалуйста, я не эксперт, но я думаю, что у вас все в порядке. Я смог понять, что должен делать ваш код и управление состоянием, потому что вы используете имена, которые имеют смысл. Возможно, вам не хватало простой концепции, но все выглядит нормально. Я сменил вашего провайдера на listen: true , чтобы ваш список мог обновляться, если что-то будет удалено или добавлено. Продолжай идти!