اضافة ايقونة زر تشغيل وايقاف المقطع الصوتي بشكل مختلف في فلاتر

اضافة ايقونة زر تشغيل وايقاف المقطع الصوتي بشكل مختلف في فلاتر

اضافة ايقونة زر تشغيل وايقاف المقطع الصوتي بشكل مختلف في فلاتر

في هذا المقال نشارك معكم طريقة جديده من الطرق التي تحسن من شكل التطبيق الخاص بك خصوصا لو كان التطبيق الخاص بك يوجد بداخله مقاطع صوتيه او حتى يحتوي على مقاطع فيديو في طبيعة الحال يوجد ايقونة توضح اذا كان التطبيق في حالة التشغيل او في حالة الايقاف وبالنسبة للايقونة فسوف نقوم في مقالة اليوم بتغيير شكلها الى مجموعه رائعه من الاشكال التي نقدمها لكم في مقالة اليوم وكل هذا سوف يكون من خلال الاكواد التي نضعها لكم في هذه المقالة حيث ان الكود الاول سوف يكون عباره عن مجموعة من الاوامر الموجوده بداخل فلاتر والكود الثاني عباره عن مجموعة من الموجات التي سوف تضيف تاثير رائع حول ايقونة التشغيل والايقاف في flutter .


يعد محرك التقديم لمكونات واجهة المستخدم أحد عوامل البيع الرئيسية في Flutter. يمكّن هذا المحرك ، وهو ميزة غير شائعة جدًا في أطر التطبيقات ، Flutter من رسم وعرض مكونات واجهة المستخدم الخاصة به بشكل مستقل عن النظام المستهدف.


القليل من الأطر يمكن أن يساوي مستوى التعقيد والتحكم وأداء وقت التشغيل الذي يحققه Flutter نتيجة للقيام بذلك. تتمثل الطريقة التقليدية لتقديم عناصر واجهة المستخدم مع إطار عمل تطبيق في بناء طبقة تجريد أو جسر يستدعي مكتبات واجهة المستخدم الأصلية للنظام ويترجم البيانات بين الاثنين. مع عيب زيادة الحمل في جسر التطبيق الذي يؤثر على الأداء ، فإن هذا يشجع النظام المستهدف على التعامل مع "الرفع الثقيل" لعرض الرسوم المتحركة والمكونات.


اضافة اشكال خلف زر التشغيل عند تشغيل المقطع الصوتي

في الكود الاول سوف نقوم بعمل ايقونة دائريه بداخلها عنصر لتوضيح اذا كان المقطع في حالة التشغيل او الايقاف , وبعدها سوف نقوم بعمل class منفصل يوضح حالة المقطع الصوتي وايضا سوف يتم اضافة مجموعة من الاشكال خلف ايقونة الزر كما هو موضح بالصورة الخاصه بالمقال , يمكنك تغيير الالوان والاشكال كما ترغب فكل الالوان موجود بالكود التالي فقط استبدل الالوان بالالوان التي تناسب شكل تطبيقك .


اضافة اشكال خلف زر التشغيل عند تشغيل المقطع الصوتي


style_1.dart



import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen>
    with SingleTickerProviderStateMixin {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Colors.white,
      ),
      body: Center(
        child: SizedBox(
          height: 200,
          width: 200,
          child: PlayButton(
            pauseIcon: Icon(Icons.pause, color: Colors.black, size: 90),
            playIcon: Icon(Icons.play_arrow, color: Colors.black, size: 90),
            onPressed: () {},
          ),
        ),
      ),
    );
  }
}

class PlayButton extends StatefulWidget {
  final bool initialIsPlaying;
  final Icon playIcon;
  final Icon pauseIcon;
  final VoidCallback onPressed;

  PlayButton({
    required this.onPressed,
    this.initialIsPlaying = false,
    this.playIcon = const Icon(Icons.play_arrow),
    this.pauseIcon = const Icon(Icons.pause),
  }) : assert(onPressed != null);

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

class _PlayButtonState extends State<PlayButton> with TickerProviderStateMixin {
  static const _kToggleDuration = Duration(milliseconds: 200);
  static const _kRotationDuration = Duration(seconds: 10);

  bool isPlaying = false;

  // rotation and scale animations
  late AnimationController _rotationController;
  late AnimationController _scaleController;
  double _rotation = 0;
  double _scale = 0.85;

  bool get _showWaves => !_scaleController.isDismissed;

  void _updateRotation() => _rotation = _rotationController.value * 2 * pi;

  void _updateScale() => _scale = (_scaleController.value * 0.2) + 0.85;

  @override
  void initState() {
    isPlaying = widget.initialIsPlaying;
    _rotationController =
        AnimationController(vsync: this, duration: _kRotationDuration)
          ..addListener(() => setState(_updateRotation))
          ..repeat();

    _scaleController =
        AnimationController(vsync: this, duration: _kToggleDuration)
          ..addListener(() => setState(_updateScale));

    super.initState();
  }

  void _onToggle() {
    setState(() => isPlaying = !isPlaying);

    if (_scaleController.isCompleted) {
      _scaleController.reverse();
    } else {
      _scaleController.forward();
    }
    widget.onPressed();
  }

  Widget buildIcon(bool isPlaying) {
    return SizedBox.expand(
      key: ValueKey<bool>(isPlaying),
      child: IconButton(
        icon: isPlaying ? widget.pauseIcon : widget.playIcon,
        onPressed: _onToggle,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return ConstrainedBox(
      constraints: BoxConstraints(minWidth: 48, minHeight: 48),
      child: Stack(
        alignment: Alignment.center,
        children: [
          if (_showWaves) ...[
            Blob(color: Color(0xff0092ff), scale: _scale, rotation: _rotation),
            Blob(
                color: Color(0xff4ac7b7),
                scale: _scale,
                rotation: _rotation * 2 - 30),
            Blob(
                color: Color(0xffa4a6f6),
                scale: _scale,
                rotation: _rotation * 3 - 45),
          ],
          Container(
            constraints: BoxConstraints.expand(),
            child: AnimatedSwitcher(
              duration: _kToggleDuration,
              child: buildIcon(isPlaying),
            ),
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: Colors.white,
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.1),
                  blurRadius: 10,
                  offset: Offset(0, 10),
                ),
              ]
            ),
          ),
        ],
      ),
    );
  }
}

class Blob extends StatelessWidget {
  final double scale;
  final double rotation;
  final Color color;

  const Blob({
    required this.scale,
    required this.rotation,
    required this.color,
  });

  @override
  Widget build(BuildContext context) {
    return Transform.scale(
      scale: scale,
      child: Transform.rotate(
        angle: rotation,
        child: Container(
          decoration: BoxDecoration(
            color: color,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(150),
              topRight: Radius.circular(240),
              bottomLeft: Radius.circular(220),
              bottomRight: Radius.circular(180),
            ),
          ),
        ),
      ),
    );
  }
}
    



اضافة شكل تردد عند تشغيل المقطع الصوتي

في هذا التصميم سوف تلاحظ استخدام موجات للصوت بمعدل 3 موجات , حيث يوجد مكتبة تقوم بنفس هذه الوظيفة تماما ولكن هنا لم يتم استخدام اي مكتبات خارجية فقط كل شيئ كان عن طريق مجموعة من الاكواد والاوامر كما هو موضح لحضراتكم , يمكنك استخدام احد الاشكال سواء هذا الشكل او الشكل السابق لتنفيذ التصميم الذي ترغب به بدون اي مشاكل في مشروعك .


اضافة شكل تردد عند تشغيل المقطع الصوتي

Frequency.dart


class FullPage extends StatefulWidget {
  const FullPage({Key? key}) : super(key: key);

  @override
  State<FullPage> createState() => _FullPageState();
}

class _FullPageState extends State<FullPage> with TickerProviderStateMixin{
  late AnimationController _controller;
  late AnimationController controller;
  bool _isPlaying = false;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      vsync: this,
      lowerBound: 0.3,
      duration: Duration(seconds: 3),
    )..repeat();

    controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 400));
  }

  @override
  void dispose() {
    controller.dispose();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // backgroundColor: Colors.black,
      body: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          _buildCircularContainer(200),
          _buildCircularContainer(250),
          _buildCircularContainer(300),
          Align(
              child: Container(
                width: 100,
                height: 100,
                decoration: BoxDecoration(
                  color: Colors.orange,
                  shape: BoxShape.circle,
                ),
                child:  IconButton(
                  iconSize: 50,
                  onPressed: trigger,
                  icon: AnimatedIcon(
                    icon: AnimatedIcons.play_pause,
                    color: Colors.white,
                    progress: controller,
                  ),
                ),
              )),
        ],
      ),
    );
  }

  MaterialButton buildMaterialButton() {
    return MaterialButton(
      color: Colors.blueAccent,
      onPressed: (){},
      child: const Text(
        'Click Here.',
        style: TextStyle(color: Colors.white),
      ),
    );
  }

  Widget _buildCircularContainer(double radius) {
    return _isPlaying ? AnimatedBuilder(
      animation: CurvedAnimation(parent: _controller, curve: Curves.fastLinearToSlowEaseIn),
      builder: (context, child) {
        return Container(
            width: _controller.value * radius,
            height: _controller.value * radius,
            decoration: BoxDecoration(color: Colors.orangeAccent.withOpacity(1.0 - _controller.value), shape: BoxShape.circle),
        );
      },
    ) : SizedBox(height: 0.0,);
  }

  void trigger() {
    if (_isPlaying) {
      _controller.reset();
    } else {
      _controller.repeat();
    }
    setState((){
      _isPlaying = !_isPlaying;
      _isPlaying ? controller.forward() : controller.reverse();
    });
  }
}


style 3


style 3

style3.dart


class ShapeScreen extends StatefulWidget {
  const ShapeScreen({Key? key}) : super(key: key);

  @override
  State<ShapeScreen> createState() => _ShapeScreenState();
}

class _ShapeScreenState extends State<ShapeScreen>
    with TickerProviderStateMixin {
  /// when playing, animation will be played
  bool playing = false;

  /// animation controller for the play pause button
  late AnimationController _playPauseAnimationController;

  /// animation & animation controller for the top-left and bottom-right bubbles
  late Animation<double> _topBottomAnimation;
  late AnimationController _topBottomAnimationController;

  /// animation & animation controller for the top-right and bottom-left bubbles
  late Animation<double> _leftRightAnimation;
  late AnimationController _leftRightAnimationController;

  @override
  void initState() {
    super.initState();
    _playPauseAnimationController = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 300));

    _topBottomAnimationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));

    _leftRightAnimationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));

    _topBottomAnimation = CurvedAnimation(
            parent: _topBottomAnimationController, curve: Curves.decelerate)
        .drive(Tween<double>(begin: 5, end: -5));
    _leftRightAnimation = CurvedAnimation(
            parent: _leftRightAnimationController, curve: Curves.easeInOut)
        .drive(Tween<double>(begin: 5, end: -5));

    _leftRightAnimationController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _leftRightAnimationController.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _leftRightAnimationController.forward();
      }
    });

    _topBottomAnimationController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _topBottomAnimationController.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _topBottomAnimationController.forward();
      }
    });
  }

  @override
  void dispose() {
    _playPauseAnimationController.dispose();
    _topBottomAnimationController.dispose();
    _leftRightAnimationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double width = 150;
    double height = 150;

    return Scaffold(
      backgroundColor: purple,
      body: Center(
        child: Stack(
          clipBehavior: Clip.none,
          alignment: Alignment.center,
          children: [
            // bottom right dark pink
            AnimatedBuilder(
              animation: _topBottomAnimation,
              builder: (context, _) {
                return Positioned(
                  bottom: _topBottomAnimation.value,
                  right: _topBottomAnimation.value,
                  child: Container(
                    width: width * 0.9,
                    height: height * 0.9,
                    decoration: BoxDecoration(
                      gradient: const LinearGradient(
                        colors: [pink, blue],
                        begin: Alignment.centerRight,
                        end: Alignment.centerLeft,
                      ),
                      shape: BoxShape.circle,
                      boxShadow: [
                        BoxShadow(
                          color: pink.withOpacity(0.5),
                          blurRadius: 10,
                          spreadRadius: 5,
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
            // top left pink
            AnimatedBuilder(
                animation: _topBottomAnimation,
                builder: (context, _) {
                  return Positioned(
                    top: _topBottomAnimation.value,
                    left: _topBottomAnimation.value,
                    child: Container(
                      width: width * 0.9,
                      height: height * 0.9,
                      decoration: BoxDecoration(
                        color: pink.withOpacity(0.5),
                        shape: BoxShape.circle,
                        gradient: const LinearGradient(
                          colors: [pink, blue],
                          begin: Alignment.centerLeft,
                          end: Alignment.centerRight,
                        ),
                        boxShadow: playing
                            ? [
                                BoxShadow(
                                  color: pink.withOpacity(0.5),
                                  blurRadius: 10,
                                  spreadRadius: 5,
                                ),
                              ]
                            : [],
                      ),
                    ),
                  );
                }), // light pink
            // bottom left blue
            AnimatedBuilder(
                animation: _leftRightAnimation,
                builder: (context, _) {
                  return Positioned(
                    bottom: _leftRightAnimation.value,
                    left: _leftRightAnimation.value,
                    child: Container(
                      width: width * 0.9,
                      height: height * 0.9,
                      decoration: BoxDecoration(
                        color: blue,
                        shape: BoxShape.circle,
                        gradient: const LinearGradient(
                          colors: [pink, blue],
                          begin: Alignment.centerRight,
                          end: Alignment.centerLeft,
                        ),
                        boxShadow: [
                          BoxShadow(
                            color: blue.withOpacity(0.5),
                            blurRadius: 15,
                            spreadRadius: 5,
                          ),
                        ],
                      ),
                    ),
                  );
                }),
            // top right dark blue
            AnimatedBuilder(
              animation: _leftRightAnimation,
              builder: (context, _) {
                return Positioned(
                  top: _leftRightAnimation.value,
                  right: _leftRightAnimation.value,
                  child: Container(
                    width: width * 0.9,
                    height: height * 0.9,
                    decoration: BoxDecoration(
                      color: blue,
                      shape: BoxShape.circle,
                      gradient: const LinearGradient(
                        colors: [pink, blue],
                        begin: Alignment.centerLeft,
                        end: Alignment.centerRight,
                      ),
                      boxShadow: playing
                          ? [
                              BoxShadow(
                                color: blue.withOpacity(0.5),
                                blurRadius: 10,
                                spreadRadius: 5,
                              ),
                            ]
                          : [],
                    ),
                  ),
                );
              },
            ),
            // play button
            GestureDetector(
              onTap: () {
                playing = !playing;

                if (playing) {
                  _playPauseAnimationController.forward();
                  _topBottomAnimationController.forward();
                  Future.delayed(const Duration(milliseconds: 500), () {
                    _leftRightAnimationController.forward();
                  });
                } else {
                  _playPauseAnimationController.reverse();
                  _topBottomAnimationController.stop();
                  _leftRightAnimationController.stop();
                }
              },
              child: Container(
                width: width,
                height: height,
                decoration: const BoxDecoration(
                  color: purple,
                  shape: BoxShape.circle,
                ),
                child: Center(
                  child: AnimatedIcon(
                    icon: AnimatedIcons.play_pause,
                    progress: _playPauseAnimationController,
                    size: 100,
                    color: white,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

const white = Colors.white;
const purple = Color(0xff1D0E2F);
const blue = Color(0xff4B5DFC);
const pink = Color(0xffD523A3);
  }

  Widget _buildIcon(bool isPlaying) {
    return SizedBox.expand(
      key: ValueKey<bool>(isPlaying),
      child: IconButton(
        icon: isPlaying ? widget.pauseIcon : widget.playIcon,
        onPressed: _onToggle,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return ConstrainedBox(
      constraints: BoxConstraints(minWidth: 48, minHeight: 48),
      child: Stack(
        alignment: Alignment.center,
        children: [
          if (_showWaves) ...[
            Blob(color: Color(0xff0092ff), scale: _scale, rotation: _rotation),
            Blob(color: Color(0xff4ac7b7), scale: _scale, rotation: _rotation * 2 - 30),
            Blob(color: Color(0xffa4a6f6), scale: _scale, rotation: _rotation * 3 - 45),
          ],
          Container(
            constraints: BoxConstraints.expand(),
            child: AnimatedSwitcher(
              child: _buildIcon(isPlaying),
              duration: _kToggleDuration,
            ),
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: Colors.white,
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _scaleController.dispose();
    _rotationController.dispose();
    super.dispose();
  }
}

class Blob extends StatelessWidget {
  final double rotation;
  final double scale;
  final Color color;

  const Blob({required this.color, this.rotation = 0, this.scale = 1});

  @override
  Widget build(BuildContext context) {
    return Transform.scale(
      scale: scale,
      child: Transform.rotate(
        angle: rotation,
        child: Container(
          decoration: BoxDecoration(
            color: color,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(150),
              topRight: Radius.circular(240),
              bottomLeft: Radius.circular(220),
              bottomRight: Radius.circular(180),
            ),
          ),
        ),
      ),
    );
  }
}

فيديو الشرح



تعليقات