removeAt删除最后一个项目,而不是索引中指定的项目

时间:2019-01-13 15:37:55

标签: android flutter

嗨,我有一个添加图像的屏幕。我使用multi_image_picker来拾取图像。选择图像后,所有选择的图像都将显示在网格视图中,其中每个图像上方都有一个FloatingActionButton,用于移除每个图像。问题是,当我单击“删除图像”按钮时,最后一个图像将被删除,而不是我单击的图像。有人遇到过吗?

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:krakatoa/api/FileApi.dart';
import 'package:krakatoa/components/AssetView.dart';
import 'package:krakatoa/config/Themes.dart' as themes;
import 'package:krakatoa/mixins/SnackBarMixin.dart';
import 'package:krakatoa/podos/User.dart';
import 'package:krakatoa/utils/Common.dart' as common;
import 'package:multi_image_picker/multi_image_picker.dart';

class AddImageScreen extends StatefulWidget {
  final List<String> currentImageUrls;
  final String postUrl;

  AddImageScreen({this.currentImageUrls, @required this.postUrl});

  @override
  State<StatefulWidget> createState() => _AddImageState();
}

class _AddImageState extends State<AddImageScreen> with SnackBarMixin {
  List<Asset> _images = [];
  User _user;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: scaffoldKey,
      appBar: AppBar(
        title: Text('Add images'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(10.0),
        child: ListView(
          children: <Widget>[
            Container(
              padding: EdgeInsets.only(bottom: 10),
              child: Text(
                "Upload Images:",
                style: Theme.of(context).textTheme.headline,
              ),
            ),
            Container(
              padding: EdgeInsets.only(bottom: 10),
              child: GridView.count(
                shrinkWrap: true,
                crossAxisSpacing: 3,
                mainAxisSpacing: 3,
                crossAxisCount: 3,
                children: _renderPickedImages(),
              ),
            ),
            Container(
              child: FlatButton(
                child: Text('UPLOAD'),
                padding: EdgeInsets.symmetric(vertical: 15),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(30),
                ),
                color: themes.primaryColor,
                onPressed: _onUploadBtnPress,
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    for (var image in _images) {
      image.release();
    }
  }

  @override
  void initState() {
    super.initState();
    common.getCurrentUser().then((user) {
      if (user != null) {
        _user = user;
      } else {
        _user = User();
      }
    });
  }

  void showProgressAlert() {
    showDialog(
      context: context,
      builder: (context) {
        return WillPopScope(
          onWillPop: () async => false,
          child: AlertDialog(
            content: ListTile(
              leading: CircularProgressIndicator(
                value: null,
              ),
              title: Text('Processing...'),
            ),
          ),
        );
      },
      barrierDismissible: false,
    );
  }

  void _onAddImageBtnPress() async {
    List<Asset> resultList;

    try {
      resultList = await MultiImagePicker.pickImages(maxImages: 5, enableCamera: true);
    } on PlatformException catch (e) {
      debugPrint("AddImageScreen._onAddImageBtnPress: ${e.toString()}");
    }

    if (!mounted) return;

    if (resultList.isNotEmpty) {
      setState(() {
        _images.addAll(resultList);
      });
    }
  }

  void _onUploadBtnPress() {
    if (_images.isNotEmpty) {
      showProgressAlert();
      _uploadImages();
    } else {
      showSnackBarMessage("No images to upload", seconds: 5);
    }
  }

  void _removeImage(int index, Asset image) {
    debugPrint("INDEX: $index");
    debugPrint("Orig Image: ${_images[index].hashCode}");
    setState(() {
      _images.removeAt(index);
    });
  }

  List<Widget> _renderPickedImages() {
    List<Widget> imageWidgets = [];
    imageWidgets.add(InkWell(
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(
            width: 1,
            color: Colors.grey,
          ),
        ),
        child: Center(
          child: Icon(
            Icons.add,
            size: 60,
            color: Colors.grey,
          ),
        ),
      ),
      onTap: _onAddImageBtnPress,
    ));
    var ctr = 0;
    for (var image in _images) {
      imageWidgets.add(Container(
        child: Stack(
          fit: StackFit.expand,
          overflow: Overflow.visible,
          children: <Widget>[
            AssetView(image),
            Positioned(
              bottom: 0,
              right: 0,
              child: _ImageRemoveButton(
                index: ctr,
                removeItem: _removeImage,
                image: image,
              ),
            ),
          ],
        ),
      ));
      ctr++;
    }
    return imageWidgets;
  }

  Future<void> _uploadImages() async {
    if (_user.id <= 0) {
      showSnackBarMessage("User is not logged in");
      Navigator.of(context).pop("User is not logged in");
      return;
    }
    try {
      await FileApi.uploadImages(widget.postUrl, _images);

      Navigator.of(context).pop();
      Navigator.of(context).pop("Success");
    } on Exception catch (e) {
      debugPrint(e.toString());
      showSnackBarMessage(e.toString());
      Navigator.of(context).pop(e.toString());
    }
  }
}

class _ImageRemoveButton extends StatelessWidget {
  final Function removeItem;
  final Asset image;
  final int index;

  _ImageRemoveButton({this.removeItem, this.index, this.image});

  @override
  Widget build(BuildContext context) {
    return FloatingActionButton(
      backgroundColor: Colors.white,
      mini: true,
      heroTag: "ImageAction_$index",
      isExtended: false,
      child: Icon(
        Icons.close,
        size: 15,
        color: Colors.black,
      ),
      onPressed: _onPress,
    );
  }

  void _onPress() {
    debugPrint("${this.hashCode}");
    debugPrint("Passed Image: ${image.hashCode}");
    removeItem(index, image);
  }
}

1 个答案:

答案 0 :(得分:0)

添加Traceback (most recent call last): File "test1.py", line 31, in <module> wb2 = xl.load_workbook(filename1) File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\reader\exc el.py", line 315, in load_workbook reader.read() File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\reader\exc el.py", line 280, in read self.read_worksheets() File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\reader\exc el.py", line 266, in read_worksheets pivot = TableDefinition.from_tree(tree) File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\descriptor s\serialisable.py", line 83, in from_tree obj = desc.from_tree(el) File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\descriptor s\sequence.py", line 85, in from_tree return [self.expected_type.from_tree(el) for el in node] File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\descriptor s\sequence.py", line 85, in <listcomp> return [self.expected_type.from_tree(el) for el in node] File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\descriptor s\serialisable.py", line 103, in from_tree return cls(**attrib) File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\pivot\tabl e.py", line 601, in __init__ self.x = x File "C:\Users\xtvl6173\AppData\Local\Programs\Python\Python36\lib\site- packages\openpyxl\descriptor s\sequence.py", line 25, in __set__ raise TypeError("Value must be a sequence") TypeError: Value must be a sequence 使用KEY有助于更新ListView 在ListView.builder上对我有用的