草庐IT

dart - Flutter 自定义范围 slider

coder 2023-05-09 原文

我正在尝试在应该创建音频波形的容器行顶部创建一个范围 slider ,但我什至不知道从哪里开始...

主要问题是范围 slider 位于容器行的正上方,它应该在“选定”部分更改它们的颜色。

这是我目前拥有的:

创建图像和细节的代码。

class BeatLyricsPage extends StatefulWidget {
  final Beat beat;
  BeatLyricsPage(this.beat);

  @override
  _BeatLyricsPageState createState() => _BeatLyricsPageState(beat);
}

class _BeatLyricsPageState extends State<BeatLyricsPage> {
  final Beat beat;


  final _kPicHeight = 190.0;
  // used in _buildPageHeading to add the beat key and beat bpm
  Widget _buildBeatInfoItem(String text) => DecoratedBox(
        decoration: BoxDecoration(
          border: Border.all(color: MyColor.white, width: 1.0),
          borderRadius: BorderRadius.circular(4.0),
        ),
        child: Padding(
          padding: EdgeInsets.symmetric(vertical: 3.0, horizontal: 12.0),
          child: Text(text, style: TextStyle(color: MyColor.white, fontSize: 10.0, fontWeight: FontWeight.w600)),
        ),
      );

  final _kAudioControlsWidth = 180.0;
  final _kAudioControlsHeight = 36.0;
  final _kAudioControlsMainButtonSize = 56.0;

  Widget _buildAudioControls(BuildContext context) => Positioned(
        left: (MediaQuery.of(context).size.width / 2) - (_kAudioControlsWidth / 2),
        top: _kPicHeight - (_kAudioControlsHeight / 2),
        child: Stack(
          overflow: Overflow.visible,
          children: [
            Container(
              width: _kAudioControlsWidth,
              height: _kAudioControlsHeight,
              decoration: BoxDecoration(color: MyColor.darkGrey, borderRadius: BorderRadius.circular(100.0)),
              padding: EdgeInsets.symmetric(horizontal: LayoutSpacing.sm),
              child: Row(
                children: [
                  CButtonLike(beatId: beat.id),
                  Spacer(),
                  GestureDetector(
                    behavior: HitTestBehavior.opaque,
                    child: Icon(BeatPulseIcons.cart),
                    onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => LicenseOptionsPage(beat))),
                  ),
                ],
              ),
            ),
            // ****** MAIN BUTTON (Play/Pause) ******
            Positioned(
              left: (_kAudioControlsWidth / 2) - (_kAudioControlsMainButtonSize / 2),
              top: (_kAudioControlsHeight - _kAudioControlsMainButtonSize) / 2,
              child: Container(
                height: _kAudioControlsMainButtonSize,
                width: _kAudioControlsMainButtonSize,
                decoration: BoxDecoration(
                    gradient: LinearGradient(begin: Alignment.topLeft, colors: [MyColor.primary, Color(0xFFf80d0a)]),
                    borderRadius: BorderRadius.circular(100.0)),
                child: CButtonPlay(),
              ),
            )
          ],
        ),
      );

  Widget _buildWaveForm() {
    // creates a random list of doubles, "fake data"
    var rng = Random();
    final List waveFormData = [];
    for (var i = 0; i < 90; i++) {
      waveFormData.add(rng.nextInt(45).toDouble());
    }
    // player bloc
    final playerBloc = BlocProvider.getPlayerBloc(context);
    // renders
    return Container(
      height: _kPicHeight,
      padding: EdgeInsets.symmetric(vertical: LayoutSpacing.xxxl),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          // current playing second
          StreamBuilder<double>(
            stream: playerBloc.playingSecond,
            initialData: 0.0,
            builder: (_, playingSecondSnapshot) {
              // current beat playing
              return StreamBuilder<Beat>(
                stream: playerBloc.playingBeat,
                builder: (_, playingBeatSnapshot) {
                  final playingBeat = playingBeatSnapshot.data;
                  // if the beat playing is the same as the beat selected for the lyrics, show playing seconds
                  if (playingBeat?.id == beat.id)
                    return Text(secondsToTime(playingSecondSnapshot.data), style: MyFontStyle.sizeXxs);
                  // otherwise show 0:00
                  else
                    return Text(secondsToTime(0), style: MyFontStyle.sizeXxs);
                },
              );
            },
          ),
          SizedBox(width: LayoutSpacing.xs),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.end,
            children: waveFormData
                .map((waveFormDataIndex) => Container(
                      height: waveFormDataIndex > 5.0 ? waveFormDataIndex : 5.0,
                      width: 2,
                      color: MyColor.white,
                      margin: EdgeInsets.only(right: 1),
                    ))
                .toList(),
          ),
          SizedBox(width: LayoutSpacing.xs),
          Text(secondsToTime(beat.length), style: MyFontStyle.sizeXxs),
        ],
      ),
    );
  }

  Widget _buildPageHeading(BuildContext context, {@required String imageUrl}) => Stack(
        children: [
          Column(
            children: [
              Hero(
                tag: MyKeys.makePlayerCoverKey(beat.id),
                child: Opacity(
                  opacity: 0.3,
                  child: Container(
                    height: _kPicHeight,
                    decoration: BoxDecoration(
                      image: DecorationImage(image: CachedNetworkImageProvider(imageUrl), fit: BoxFit.cover),
                    ),
                  ),
                ),
              ),
              Container(color: MyColor.background, height: LayoutSpacing.xl)
            ],
          ),
          Padding(
            padding: EdgeInsets.all(LayoutSpacing.xs),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                _buildBeatInfoItem(beat.key),
                SizedBox(width: 4.0),
                _buildBeatInfoItem('${beat.bpm} BPM'),
              ],
            ),
          ),
          _buildAudioControls(context),
          _buildWaveForm(),
        ],
      );
}

最佳答案

要创建自定义范围 slider ,您可以使用 GestureRecognizer并将每个 slider 的位置保存在 StatefulWidget 内的变量中.要确定索引为 i 的条是否在范围内,您可以将限制器的像素位置(bar1&bar2 划分为下面的来源)通过条的宽度并将其与 i 进行比较。

很遗憾,我无法使用您的代码示例。相反,我创建了一个最低限度的示例,如下所示。如果您花一点时间阅读,我相信您可以将其转移到您的应用程序中。

import 'dart:math';

import 'package:flutter/material.dart';

List<int> bars = [];

void main() {
  // generate random bars
  Random r = Random();
  for (var i = 0; i < 50; i++) {
    bars.add(r.nextInt(200));
  }

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => HomeState();
}

class HomeState extends State<Home> {
  static const barWidth = 5.0;
  double bar1Position = 60.0;
  double bar2Position = 180.0;

  @override
  Widget build(BuildContext context) {
    int i = 0;

    return Scaffold(
      body: Center(
        child: Stack(
          alignment: Alignment.centerLeft,
          children: <Widget>[
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.start,
              children: bars.map((int height) {
                Color color =
                    i >= bar1Position / barWidth && i <= bar2Position / barWidth
                        ? Colors.deepPurple
                        : Colors.blueGrey;
                i++;

                return Container(
                  color: color,
                  height: height.toDouble(),
                  width: 5.0,
                );
              }).toList(),
            ),
            Bar(
              position: bar2Position,
              callback: (DragUpdateDetails details) {
                setState(() {
                  bar2Position += details.delta.dx;
                });
              },
            ),
            Bar(
              position: bar1Position,
              callback: (DragUpdateDetails details) {
                setState(() {
                  bar1Position += details.delta.dx;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

class Bar extends StatelessWidget {
  final double position;
  final GestureDragUpdateCallback callback;

  Bar({this.position, this.callback});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(left: position >= 0.0 ? position : 0.0),
      child: GestureDetector(
        onHorizontalDragUpdate: callback,
        child: Container(
          color: Colors.red,
          height: 200.0,
          width: 5.0,
        ),
      ),
    );
  }
}

关于dart - Flutter 自定义范围 slider ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52987440/

有关dart - Flutter 自定义范围 slider的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  5. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  6. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  9. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  10. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

随机推荐