【问题标题】:removeAt removes the last item not the item stated in the indexremoveAt 删除最后一项而不是索引中所述的项
【发布时间】:2019-06-07 18:51:54
【问题描述】:

您好,我有一个用于添加图像的屏幕。我使用 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);
  }
}

【问题讨论】:

  • 你的问题出在Asset,请see this answer
  • 您好,我更改了它并创建了一个新类并传递了资产。然后我在你提到的链接中创建了 2 种方法,但它仍然是一样的
  • 你解决了吗?有同样的问题
  • 有没有人找到解决方案我也面临同样的问题它的索引大于零但是当索引零的第一项被删除时,它会删除最后一项

标签: android flutter


【解决方案1】:

添加key: Key(YOUR_LIST.length.toString()), 拥有 KEY 有助于更新 ListView 在 ListView.builder 上对我有用

【讨论】:

    猜你喜欢
    • 2013-12-16
    • 2020-09-12
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    相关资源
    最近更新 更多