亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

flutter輪子計(jì)劃之進(jìn)度條

 更新時(shí)間:2021年10月09日 17:09:27   作者:卡路里我的天敵  
這篇文章主要為大家詳細(xì)介紹了flutter輪子計(jì)劃之進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言

本文的記錄如何用CustomPaint、GestureDetector實(shí)現(xiàn)一個(gè)進(jìn)度條控件。首先需要說(shuō)明的是 flutter Material 組件庫(kù)中提供了兩種進(jìn)度指示器:LinearProgressIndicator和CircularProgressIndicator。如果這兩種進(jìn)度指示器可以滿足開(kāi)發(fā)需求,就不要嘗試自己造輪子了。本文實(shí)現(xiàn)的進(jìn)度條控件,功能如下:

  • 進(jìn)度的范圍為0到1的double類型數(shù)據(jù)
  • 支持拖動(dòng),通過(guò)回調(diào)函數(shù)獲取進(jìn)度值
  • 支持跳轉(zhuǎn),點(diǎn)擊某個(gè)位置后進(jìn)度跳轉(zhuǎn),回調(diào)進(jìn)度值
  • 樣式為Material風(fēng)格的樣式,可以根據(jù)需要修改

識(shí)別拖動(dòng)手勢(shì)

使用GestureDetector可以方便得對(duì)滑動(dòng),點(diǎn)擊事件進(jìn)行監(jiān)聽(tīng)。如下是監(jiān)聽(tīng)的四個(gè)事件,重點(diǎn)關(guān)注onHorizontalDragUpdate即可,其回調(diào)函數(shù)將水平拖動(dòng)事件的坐標(biāo)等信息傳遞給_seekToRelativePosition函數(shù)。_seekToRelativePosition函數(shù)的功能是計(jì)算滑動(dòng)時(shí)進(jìn)度條的值,并更新界面。代碼如下:

GestureDetector(
        onHorizontalDragStart: (DragStartDetails details) {
          widget.onDragStart?.call();
        },
        onHorizontalDragUpdate: (DragUpdateDetails details) {
          widget.onDragUpdate?.call();
          _seekToRelativePosition(details.globalPosition);
        },
        onHorizontalDragEnd: (DragEndDetails details) {
          widget.onDragEnd?.call(progress);
        },
        onTapDown: (TapDownDetails details) {
          widget.onTapDown?.call(progress);
          _seekToRelativePosition(details.globalPosition);
        },
 
        // ....
 
)

_seekToRelativePosition 將全局坐標(biāo)轉(zhuǎn)換為進(jìn)度條控件所在的舉動(dòng)坐標(biāo)。將點(diǎn)擊處的橫坐標(biāo),即x與進(jìn)度條控件的長(zhǎng)度的比率作為進(jìn)度條的值。然后調(diào)用setState()更新界面。上面

void _seekToRelativePosition(Offset globalPosition) {
    final box = context.findRenderObject()! as RenderBox;
    final Offset tapPos = box.globalToLocal(globalPosition);
    progress = tapPos.dx / box.size.width;
    if (progress < 0) progress = 0;
    if (progress > 1) progress = 1;
 
    setState(() {
        widget.controller.progressBarValue = progress;
    });
  } 

上面代碼中有一個(gè)controller控件,其定義如下:

class VideoProgressBarController extends ChangeNotifier
{
  double progressBarValue = .0;
 
   updateProgressValue(double value){
     progressBarValue = value;
    notifyListeners();
  }
}

其繼承自ChangeNotifier, 因?yàn)榇诉M(jìn)度條控件的狀態(tài)由其他控件和控件本身混合管理狀態(tài)。當(dāng)其他控件想改變進(jìn)度條的值時(shí),可以通過(guò)VidoeProgressBarController通知進(jìn)度條控件更新界面。當(dāng)然,將進(jìn)度條控件改用statelesswidget實(shí)現(xiàn),然后直接調(diào)用setState()更新界面實(shí)現(xiàn)起來(lái)會(huì)更簡(jiǎn)單一點(diǎn),讀者有需要可以嘗試。

使用CustomPaint繪制進(jìn)度條

繪制部分比較簡(jiǎn)單。如下,先繪制灰色背景,然后繪制紅色的進(jìn)度,再回事圓點(diǎn)。

class _VideoProgressBarPainter extends CustomPainter {
  _VideoProgressBarPainter(
      {required this.barHeight,
      required this.handleHeight,
      required this.value,
      required this.colors});
 
  final double barHeight;
  final double handleHeight;
  final ProgressColors colors;
  final double value;
 
  @override
  bool shouldRepaint(CustomPainter painter) {
    return true;
  }
 
  @override
  void paint(Canvas canvas, Size size) {
    final baseOffset = size.height / 2 - barHeight / 2;
    final double radius = 4.0;
 
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromPoints(
          Offset(0.0, baseOffset),
          Offset(size.width, baseOffset + barHeight),
        ),
        const Radius.circular(4.0),
      ),
      colors.backgroundPaint,
    );
 
    double playedPart =
        value > 1 ? size.width - radius : value * size.width - radius;
    if (playedPart < radius) {
      playedPart = radius;
    }
 
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromPoints(
          Offset(0.0, baseOffset),
          Offset(playedPart, baseOffset + barHeight),
        ),
        Radius.circular(radius),
      ),
      colors.playedPaint,
    );
 
    canvas.drawCircle(
      Offset(playedPart, baseOffset + barHeight / 2),
      handleHeight,
      colors.playedPaint,
    );
  }
}

完整代碼:

import 'package:flutter/cupertino.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: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
 
class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
 
  final String title;
 
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
 
class _MyHomePageState extends State<MyHomePage> {
  double _progressValue = .5;
  late VideoProgressBarController controller;
 
  @override
  void initState() {
    controller = VideoProgressBarController();
    super.initState();
  }
 
  @override
  Widget build(BuildContext context) {
    print("build:$_progressValue");
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(title: Text("test")),
        body: Column(
            //aspectRatio: 16 / 9,
            children: [
              Container(
                width: 200,
                height: 26,
                //color: Colors.blue,
                child: VideoProgressBar(
                  controller: controller,
                  barHeight: 2,
                  onDragEnd: (double progress) {
                    print("$progress");
                  },
                ),
              ),
              Text("value:$_progressValue"),
              ElevatedButton(
                  onPressed: (){
                      _progressValue = 1;
                      controller.updateProgressValue(_progressValue);
                  },
                  child: Text("increase")
              )
            ]
        ),
      ),
    );
  }
}
 
/// progress bar
class VideoProgressBar extends StatefulWidget {
  VideoProgressBar({
    ProgressColors? colors,
    Key? key,
    required this.controller,
    required this.barHeight,
    this.handleHeight = 6,
    this.onDragStart,
    this.onDragEnd,
    this.onDragUpdate,
    this.onTapDown,
  })  : colors = colors ?? ProgressColors(),
        super(key: key);
 
  final ProgressColors colors;
  final Function()? onDragStart;
  final Function(double progress)? onDragEnd;
  final Function()? onDragUpdate;
  final Function(double progress)? onTapDown;
 
  final double barHeight;
  final double handleHeight;
 
  final TVideoProgressBarController controller;
 
  //final bool drawShadow;
 
  @override
  _VideoProgressBarState createState() => _VideoProgressBarState();
}
 
class _VideoProgressBarState extends State<VideoProgressBar> {
  double progress = .0;
 
  @override
  void initState() {
    super.initState();
    progress = widget.controller.progressBarValue;
    widget.controller.addListener(_updateProgressValue);
  }
 
  @override
  void dispose() {
    widget.controller.removeListener(_updateProgressValue);
    super.dispose();
  }
 
  _updateProgressValue()
  {
    setState(() {
      progress = widget.controller.progressBarValue;
    });
  }
 
  void _seekToRelativePosition(Offset globalPosition) {
    final box = context.findRenderObject()! as RenderBox;
    final Offset tapPos = box.globalToLocal(globalPosition);
    progress = tapPos.dx / box.size.width;
    if (progress < 0) progress = 0;
    if (progress > 1) progress = 1;
 
    setState(() {
        widget.controller.progressBarValue = progress;
    });
  }
 
  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
 
    return GestureDetector(
        onHorizontalDragStart: (DragStartDetails details) {
          widget.onDragStart?.call();
        },
        onHorizontalDragUpdate: (DragUpdateDetails details) {
          widget.onDragUpdate?.call();
          _seekToRelativePosition(details.globalPosition);
        },
        onHorizontalDragEnd: (DragEndDetails details) {
          widget.onDragEnd?.call(progress);
        },
        onTapDown: (TapDownDetails details) {
          widget.onTapDown?.call(progress);
          _seekToRelativePosition(details.globalPosition);
        },
        child: Center(
          child: Container(
            height: MediaQuery.of(context).size.height,
            width: MediaQuery.of(context).size.width,
            child: CustomPaint(
                painter: _VideoProgressBarPainter(
                    barHeight: widget.barHeight,
                    handleHeight: widget.handleHeight,
                    colors: widget.colors,
                    value: progress)),
          ),
        ));
  }
}
 
class _VideoProgressBarPainter extends CustomPainter {
  _VideoProgressBarPainter(
      {required this.barHeight,
      required this.handleHeight,
      required this.value,
      required this.colors});
 
  final double barHeight;
  final double handleHeight;
  final ProgressColors colors;
  final double value;
 
  @override
  bool shouldRepaint(CustomPainter painter) {
    return true;
  }
 
  @override
  void paint(Canvas canvas, Size size) {
    final baseOffset = size.height / 2 - barHeight / 2;
    final double radius = 4.0;
 
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromPoints(
          Offset(0.0, baseOffset),
          Offset(size.width, baseOffset + barHeight),
        ),
        const Radius.circular(4.0),
      ),
      colors.backgroundPaint,
    );
 
    double playedPart =
        value > 1 ? size.width - radius : value * size.width - radius;
    if (playedPart < radius) {
      playedPart = radius;
    }
 
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromPoints(
          Offset(0.0, baseOffset),
          Offset(playedPart, baseOffset + barHeight),
        ),
        Radius.circular(radius),
      ),
      colors.playedPaint,
    );
 
    canvas.drawCircle(
      Offset(playedPart, baseOffset + barHeight / 2),
      handleHeight,
      colors.playedPaint,
    );
  }
}
 
class VideoProgressBarController extends ChangeNotifier
{
  double progressBarValue = .0;
 
   updateProgressValue(double value){
     progressBarValue = value;
    notifyListeners();
  }
}
 
class ProgressColors {
  ProgressColors({
    Color playedColor = const Color.fromRGBO(255, 0, 0, 0.7),
    Color bufferedColor = const Color.fromRGBO(30, 30, 200, 0.2),
    Color handleColor = const Color.fromRGBO(200, 200, 200, 1.0),
    Color backgroundColor = const Color.fromRGBO(200, 200, 200, 0.5),
  })  : playedPaint = Paint()..color = playedColor,
        bufferedPaint = Paint()..color = bufferedColor,
        handlePaint = Paint()..color = handleColor,
        backgroundPaint = Paint()..color = backgroundColor;
 
  final Paint playedPaint;
  final Paint bufferedPaint;
  final Paint handlePaint;
  final Paint backgroundPaint;
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論