【问题标题】:Carousel image on different page with onPressed index带有 onPressed 索引的不同页面上的轮播图像
【发布时间】:2020-07-08 11:08:54
【问题描述】:

我对扑扑有点陌生。我需要有关轮播图像的帮助。我有使用 carousel_pro 包的轮播图像。当使用 GestureDetector 按下时,我可以在新页面上打开图像。但我想在新页面上打开相同的轮播图像,但首先使用 onPressed 索引。我的意思是前。我有 5 张图片。当我按下第三张图片时,它必须在新的轮播上打开该图片而不是第一张。我希望我说清楚了。下面是一页一图的方式。我需要在图像轮播中带有压制图像起始索引的轮播。提前致谢。

import 'package:carousel_slider/carousel_slider.dart';
import './image_screen.dart';

void main() => runApp(MaterialApp(home: Demo()));

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

class _HomePageState extends State<Demo> {
  @override
  Widget build(BuildContext context) {
    Widget image_carousel = new Container(
        height: 345.0,
        child: CarouselSlider(
          height: 400.0,
          items: [
            'http://pic3.16pic.com/00/55/42/16pic_5542988_b.jpg',
            'http://photo.16pic.com/00/38/88/16pic_3888084_b.jpg',
            'http://pic3.16pic.com/00/55/42/16pic_5542988_b.jpg',
            'http://photo.16pic.com/00/38/88/16pic_3888084_b.jpg'
          ].map((i) {
            return Builder(
              builder: (BuildContext context) {
                return Container(
                    width: MediaQuery.of(context).size.width,
                    margin: EdgeInsets.symmetric(horizontal: 5.0),
                    decoration: BoxDecoration(color: Colors.amber),
                    child: GestureDetector(
                        child: Image.network(i, fit: BoxFit.fill),
                        onTap: () {
                          Navigator.push<Widget>(
                            context,
                            MaterialPageRoute(
                              builder: (context) => ImageScreen(i),
                            ),
                          );
                        }));
              },
            );
          }).toList(),
        ));

    return Scaffold(
      body: new Column(
        children: <Widget>[
          image_carousel,
        ],
      ),
    );
  }
}

编辑:我添加了上面的示例代码。这不是我需要的。我需要这样的东西:第 1 页有 5 张图片的轮播。当我按下第三张图像时,在第 2 页上打开相同的图像轮播,并带有按下的第三张图像的索引。我的意思是在第 2 页轮播必须从第 3 张图片开始。我希望这次我把自己说清楚了。

【问题讨论】:

  • 您的ImageScreen 是否包含与您的_HomePageState 相同的代码,并且您将整个列表传递给您的ImageScreen 或仅传递给index如果通过了索引 => 如果您只是通过索引,ImageScreen 如何获取所有图像
  • @Alok 我将所有图像传递给 ImagesScreen 并显示相同的图像轮播,但在轮播上首先按下图像。我想要实现的是:我有产品详细信息。在产品详细信息中,我在屏幕的第三个屏幕中的 1 个中显示该产品的图像。在剩下的我显示详细信息。当我在特定图像上按下该轮播时,我想在新页面上以全高显示相同的图像轮播,但在轮播的第一个被按下的图像。希望我说清楚
  • 嘿@Ruslan HasanOFF,看看我的答案。我希望这会在很大程度上帮助你。 :)
  • 嘿@Rusian HasanOFF,新版本的答案仅根据您的要求添加:)

标签: flutter dart indexing carousel


【解决方案1】:

回答 2.0 版

你看,UI元素工作正常,需要做的是,先想办法设置item,然后再push所有元素

在这里,我们需要了解DART SUBLIST 是什么。请仔细阅读以了解其中的概念。

算法

1. Select index of the image urls
2. If the item which is selected is first, then normal list would be passed
3. If not, then we get firstElements which is a sublist of (0, index), index not included [for example => If we select 3 from 1,2,3,4 => firstElements = [1,2]]
4. We maintain the lastElements, which is a sublist of (index, list.length), where list.length is ignore. [for example => If we select 3 from 1,2,3,4 => lastElements= [3,4]]
4. Finally we make a final list by adding lastElements + firstElements = [3,4,1,2]

这就是我们正在努力实现的目标,不是吗?

代码实现

  // suppose we have an array of Ints
  List<int> data = [1,2,3,4];
  
  // to keep a pointer, which one is selected
  // here we selected 3, so index will have 2 as it's value, 
  // which is the index of 3
  int index = data.indexOf(3);
  
  // now let say, we want to push 3 to the top, keeping 
  // 4, after it, and 1,2 after 4 in the same format 
  // similar to what you want to do with the selected image
  // CHECKS FOR FIRST ELEMENT IS SELECTED OR NOT, WHICH HAS INDEX 0
  if(index != 0){
    // get the sublist from 0 to index-1
    var firstElements = data.sublist(0, index);
    // get the sublist from index, to last
    var restElements = data.sublist(index, data.length);
    
    // restElements should be pushed to top, since we have want the 
    // to be there, then comes firstElements
    print(restElements+firstElements);
  }else{
    // since the first item is selected
    print(data);
  } 
  
  print(items);

  // OUTPUT => [3, 4, 1, 2]

看,上面的项目3是如何被推到第一个位置的,4在它之后,其余的分别被推到它的另一个位置。这就是我们正在努力实现的目标。 您也可以继续测试一些其他值

记住:逻辑应该清晰,其余的 UI 可以自己处理

我没有使用任何CarouselSlider,只是使用我自己的ListView 来展示,它是如何完成的。如果你明白了这个想法,我敢肯定,你也会明白如何去做。

主页

class _MyHomePageState extends State<MyHomePage> {
  // In the list, I have used all the images as different to show you the difference
  // in a clear way
  List<String> _imageUrls = [
    'http://pic3.16pic.com/00/55/42/16pic_5542988_b.jpg',
    'http://photo.16pic.com/00/38/88/16pic_3888084_b.jpg',
    'https://static.toiimg.com/thumb/msid-54559212,width-748,height-499,resizemode=4,imgsize-307081/Bangalore.jpg',
    'https://images.unsplash.com/photo-1535332371349-a5d229f49cb5?ixlib=rb-1.2.1&w=1000&q=80'
  ];
  
  // This is the widget which is responsible for creating 
  // list of images as a slider
  Widget get myWidget{
    List<Widget> _widgets = [SizedBox(width: 20.0)];
    
    for(int i=0; i<_imageUrls.length; i++){
      _widgets.add(
        GestureDetector(
          onTap: (){
            Navigator.of(context).push(
              // Our new page, takes ImageUrls list, and the selected index
             // top perform an operation
              MaterialPageRoute(
                builder: (context) => NewPage(imgUrls: _imageUrls, index: i)
              )
            );
          },
          child: Container(
            width: 300.0,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(15.0),
              image: DecorationImage(
                fit: BoxFit.cover,
                image: NetworkImage(_imageUrls[i])
              )
            )
          )
        )
      );
      
      _widgets.add(SizedBox(width: 20.0));
    }
    
    return Container(
      height: 400.0,
      child: ListView(
        shrinkWrap: true,
        scrollDirection: Axis.horizontal,
        children: _widgets
      )
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: Center(
          child: this.myWidget
        )
      )
    );
  }
}

新页面

class _NewPageState extends State<NewPage> {
  // This will keep a copy of all the items coming from immutable imageUrls
  // We will be doing operation in this list only
  // it has to be initialized as an empty array
  List<String> _newImageUrls = [];
  
  @override
  void initState(){
    super.initState();
    
    // same algo which is explained above
    if(widget.index != 0){
      // get the sublist from 0 to index-1
      var firstElements = widget.imgUrls.sublist(0, widget.index);
      // get the sublist from index, to last
      var restElements = widget.imgUrls.sublist(widget.index, widget.imgUrls.length);

      setState(() => _newImageUrls = restElements + firstElements);
    }else{
      // since the first item is selected
      // no _newImageUrls = widget.imgUrls cos, machine will
      // understand that both the items are same, so if one changes,
      // that means another has to change. So strict no-no to that
      widget.imgUrls.forEach((item){
        _newImageUrls.add(item);
      });
    }
  }
  
  // now this is same as our HomePage 
  // just a height change of the images and we're using our new 
  // list, not the passed one, since, it has changed data now
  Widget get myWidget{
    List<Widget> _widgets = [SizedBox(width: 20.0)];
    
    for(int i=0; i<_newImageUrls.length; i++){
      _widgets.add(
        Container(
          width: 300.0,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(15.0),
            image: DecorationImage(
              fit: BoxFit.cover,
              image: NetworkImage(_newImageUrls[i])
            )
          )
        )
      );
      
      _widgets.add(SizedBox(width: 20.0));
    }
    
    return Container(
      height: 500.0,
      child: ListView(
        shrinkWrap: true,
        scrollDirection: Axis.horizontal,
        children: _widgets
      )
    );
  }
  
  @override
  Widget build(BuildContext context) {
    
    return Scaffold(
      appBar: AppBar(
        title: Text('New Page'),
      ),
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: Center(
          child: this.myWidget
        )
      )
    );
  }
}

您将获得的结果几乎就是您想要的结果。也就是说,如果从 1,2,3,4 中选择了第 3 项,则另一个 NewPage 将显示 3,4,1,2 等等..

RESULT OF OUR NEW WORK WITH CORRECT REQUIREMENTS

您能看出NewPage 的代码中的区别吗?这只是逻辑,否则,用户界面和以前一样。这就是我想告诉你的。

【讨论】:

  • 就个人而言,@RuslanHasanOFF 很难。对此我深表歉意。在这里,在 StackOverFlow,您会找到最优秀的人才,他们可以比您想象的更好地解决您的问题。另外,我是一名工作时间有限的专业人士。但是很想在这里解决你的问题,如果我能在某个时候看到它:)
  • 谢谢。几乎是兄弟。但它改变了顺序。我怎么能做同样的事情但不改变订单。像 3,4,1,2.. 等等。你是这样的:3,1,2,4..顺便说一句,我投了赞成票,但不是我试图达到的目标。
  • 嗯...所以如果1 selected =&gt; 1,2,3,4。如果2 selected =&gt; 2,3,4,1。如果3 selected =&gt; 3,4,1,2。如果4 selected =&gt; 4,1,2,3?对@RuslanHasanOFF。感谢您的支持:)
  • 是的,终于有人明白了。有任何想法吗?我还是新手 :-)
  • 在同一页面上也在容器中为我工作。谢谢。
【解决方案2】:

这是一个可能对您有所帮助的代码示例。
主屏幕

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("test"),
      ),
      body: Container(
        height: 345.0,
        child: CarouselSlider(
          options: CarouselOptions(
            height: 400,
          ),
          items: [
            'http://pic3.16pic.com/00/55/42/16pic_5542988_b.jpg',
            'http://photo.16pic.com/00/38/88/16pic_3888084_b.jpg',
            'http://pic3.16pic.com/00/55/42/16pic_5542988_b.jpg',
            'http://photo.16pic.com/00/38/88/16pic_3888084_b.jpg'
          ].map(
            (i) {
              return Container(
                width: MediaQuery.of(context).size.width,
                margin: EdgeInsets.symmetric(horizontal: 5.0),
                decoration: BoxDecoration(color: Colors.amber),
                child: GestureDetector(
                  child: Image.network(i, fit: BoxFit.fill),
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (context) => Screen2(
                          image: i,
                        ),
                      ),
                    );
                  },
                ),
              );
            },
          ).toList(),
        ),
      ),
    );
  }
}

Screen2:带有轮播和 appBar 的屏幕,可返回到第一个屏幕

class Screen2 extends StatelessWidget {
  final List<String> images;
  final String selectedImages;
  Screen2({this.images, this.selectedImages});
  @override
  Widget build(BuildContext context) {
    images.removeWhere((i) => i == selectedImages);
    images.insert(0, selectedImages);
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        height: double.maxFinite,
        width: double.maxFinite,
        child: CarouselSlider(
          options: CarouselOptions(
            viewportFraction: 1.0,
            height: double.maxFinite,
          ),
          items: [
            ...images.map(
              (image) => Image.network(
                image,
                fit: BoxFit.fill,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

结果视频:click meclick me

【讨论】:

  • 谢谢兄弟的回答。虽然这不是我需要的。我已经在上面编辑了我的问题。
  • 我想我明白你想要什么我不明白这一点但无论如何我再次编辑了我的帖子我会尽快更改视频告诉我这是否是你想要的。
  • 谢谢兄弟。这几乎是我想要的。我想要实现的是:我有产品详细信息。在产品详细信息中,我在屏幕的第三个屏幕中的 1 个中显示该产品的图像。在剩下的我显示详细信息。当我在特定图像上按下该轮播时,我想在新页面上以全高显示相同的图像轮播,但在轮播的第一个按下图像。
  • 我正在投资您的代码。它从它的位置删除该图像并首先放置它。但是我怎么能做同样的事情但不改变地方。我的意思是像顺序的。您的代码就像:1,2,3 图像。当我按下第二个结果是 2,1,3。但我真正想要的是,当我按下第二个轮播时,必须从 2 开始,它是这样的:2,3,1,2,3... 像这样。
  • 不仅仅是删除images.removeWhere((i) =&gt; i == selectedImages);这一行
猜你喜欢
  • 2019-05-30
  • 1970-01-01
  • 2015-08-09
  • 2020-09-19
  • 2018-07-22
  • 1970-01-01
  • 2022-01-20
  • 2018-06-13
  • 1970-01-01
相关资源
最近更新 更多