从流(颤振)控制旋转木马滑块

时间:2020-02-10 08:01:03

标签: flutter dart flutter-layout flutter-dependencies dart-pub

我的数据来自主要来自队列和当前队列mediaItem的流。因此mediaItem总是在变化。 我使用了

index = queue.indexOf(mediaItem);

现在我想将轮播的当前页面设置为我的索引,我在轮播的initialPage上添加了索引,但是该索引仅在索引更改时起作用一次,并且不会更改当前页面。

我的流看起来像这样

//this stream is initialized inside initState()
stream = Rx.combineLatest3<List<MediaItem>, MediaItem, PlaybackState, ScreenState>(
  AudioService.queueStream,
  AudioService.currentMediaItemStream,
  AudioService.playbackStateStream,
      (queue, mediaItem, playbackState) => ScreenState(queue, mediaItem, playbackState)
);


Scaffold(
  body: new Center(
    child: StreamBuilder<ScreenState>(
      stream: stream,
      builder: (context, snapshot) {
        final screenState = snapshot.data;
        final queue = screenState?.queue;
        final mediaItem = screenState?.mediaItem;
        final state = screenState?.playbackState;
        final basicState = state?.basicState ?? BasicPlaybackState.none;
        int index = queue?.indexWhere((MediaItem mediaItemX){return (mediaItem?.id == mediaItemX.id);});
        return (queue!=null&& mediaItem!=null && basicState != null && index != null) 
          ? mainView(queue, mediaItem, basicState, state, index)
          : Container(
            child: Center(
              child: SpinKitWave(
                color: Colors.white70,
              ),
            ),
          );
      },
    ),
  ),
),

主视图

Widget mainView(List<MediaItem> queue, MediaItem mediaItemX, BasicPlaybackState basicState, PlaybackState state, int index){
  return CarouselSlider.builder(
    itemCount: queue.length,
    initialPage: queue.indexOf(mediaItemX),//only works first time
    itemBuilder: (BuildContext context, int itemIndex) {
      Stack(
        children: <Widget>[
          ClipRRect(
            borderRadius: BorderRadius.circular(8.0),
            child: Container(
              padding: EdgeInsets.fromLTRB(0,0,0,0),
              child: CachedNetworkImage(
                height: ScreenUtil().setWidth(1200),
                width: ScreenUtil().setWidth(1200),
                imageUrl: queue[itemIndex].artUri,
                fit: BoxFit.cover,
                placeholder: (context, url) => new SpinKitWave(color: Colors.white30, size: 30.0,),
                errorWidget: (context, url, error) => new Image.asset(
                  'images/addplaylist.png',
                  color: Colors.white30,
                ),
              ),
            )
          )
        ],
      ),
    }
  );
}

问题是当mediaItem从另一个地方更改时,需要轮播根据数据流的变化来更改其索引,换句话说,该功能与Carousel内部的currentPage几乎相同,因此每次索引进行更改,然后将currentPage设置为流中的新数据,或控制流中的轮播。 高度赞赏具有示例的解决方案或提示。

其他信息:我正在使用carousel_slider: ^1.4.1

1 个答案:

答案 0 :(得分:3)

initialPage可以在空容器中正常工作(请参见下面的代码),在我看来似乎缺少一些key,可能是在缓存的图像网络或您的容器中,请尝试放置UniqueKey()以确保小部件树将在新的snapthos出现时检测到更改...

使用StreamBuilder和滑块的示例:

import 'dart:async';
import 'dart:math';

import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(body: MyHomePage()),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final StreamController sc = StreamController();
  final rng = Random();

  final containers = [
    Container(color: Colors.pink),
    Container(color: Colors.black),
    Container(color: Colors.yellow),
    Container(color: Colors.brown),
  ];
  @override
  void initState() {
    super.initState();

    Timer.periodic(
      Duration(seconds: 5),
      (t) {
        sc.add(rng.nextInt(containers.length));
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: sc.stream,
      builder: (context, snapshot) {
        if (snapshot.hasData == false) {
          return CircularProgressIndicator();
        }
        return Container(
          child: mainView(containers, containers[snapshot.data]),
        );
      },
    );
  }

  Widget mainView(
    List<Container> queue,
    Container mediaItemX,
  ) {
    return CarouselSlider.builder(
      itemCount: queue.length,
      initialPage: queue.indexOf(mediaItemX), //only works first time
      itemBuilder: (BuildContext context, int itemIndex) {
        print('changed');

        return mediaItemX;
      },
    );
  }
}