ListView中的边框变化将在下面移动项目

问题描述 投票:0回答:1

我正在将ListView与简单容器一起使用,当您在列表视图中按容器时,它会更改选定容器的宽度和边框颜色,但是,当发生这种情况时,它也会在下面移动其他容器。我想得到的是,当您选择项目时,更改边框的宽度和颜色,并且不移动列表中的项目以及容器内部的项目。

请使用下面的代码重现该问题,谢谢!

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter border demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
  }

  List<int> values = [1, 2, 3];

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Border demo'),
          centerTitle: true,
        ),
        body: Container(
          child: ListView.builder(
              itemCount: values.length,
              itemBuilder: (BuildContext context, int index) =>
                  BorderContainer(value: values[index])),
        ));
  }
}

class BorderContainer extends StatefulWidget {
  final int value;

  const BorderContainer({Key key, this.value}) : super(key: key);

  @override
  _BorderContainerState createState() => _BorderContainerState();
}

class _BorderContainerState extends State<BorderContainer> {
  bool isTapped = false;

  @override
  Widget build(BuildContext context) {
    return Container(
//      height: 95, // if we add this rest of list items will not move however it will move items inside of container
      child: GestureDetector(
        onTapDown: (TapDownDetails details) => setState(() {
          isTapped = true;
        }),
        onTapUp: (TapUpDetails details) => setState(() {
          isTapped = false;
        }),
        child: Container(
            margin: EdgeInsets.all(8),
            decoration: BoxDecoration(
                border: Border.all(
                    width: isTapped ? 2.0 : 1.0,
                    //when pressing it moves other items because of width change
                    color:
                        isTapped ? Colors.grey : Colors.grey.withOpacity(0.3)),
                borderRadius: BorderRadius.circular(16)),
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                children: <Widget>[
                  Text('${widget.value}'),
                  Text('Another item in container number: ${widget.value}')
                ],
              ),
            )),
      ),
    );
  }
}

flutter dart flutter-layout flutter-animation
1个回答
0
投票

好,我通过以下方法解决了问题:在边框较小的容器上方创建额外的边框较粗的容器,仅更改颜色不透明度。


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter border demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
  }

  List<int> values = [1, 2, 3];

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Border demo'),
          centerTitle: true,
        ),
        body: Container(
          child: ListView.builder(
              itemCount: values.length,
              itemBuilder: (BuildContext context, int index) =>
                  BorderContainer(value: values[index])),
        ));
  }
}

class BorderContainer extends StatefulWidget {
  final int value;

  const BorderContainer({Key key, this.value}) : super(key: key);

  @override
  _BorderContainerState createState() => _BorderContainerState();
}

class _BorderContainerState extends State<BorderContainer> {
  bool isTapped = false;

  @override
  Widget build(BuildContext context) {
    var innerBorder = Border.all(
        width: 1.0,
        color: isTapped
            ? Colors.grey.withOpacity(0)
            : Colors.grey.withOpacity(0.3));

    var outerBorder = Border.all(
        width: 3.0, color: isTapped ? Colors.grey : Colors.grey.withOpacity(0));

    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Container(
        decoration: BoxDecoration(
            border: outerBorder, borderRadius: BorderRadius.circular(16)),
        child: GestureDetector(
          onTapDown: (TapDownDetails details) => setState(() {
            isTapped = true;
          }),
          onTapUp: (TapUpDetails details) => setState(() {
            isTapped = false;
          }),
          child: Container(
              decoration: BoxDecoration(
                  border: innerBorder, borderRadius: BorderRadius.circular(16)),
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  children: <Widget>[
                    Text('${widget.value}'),
                    Text('Another item in container number: ${widget.value}')
                  ],
                ),
              )),
        ),
      ),
    );
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.