flutter之敲木鱼练习--基础案例

前言:

实践是检验真理的唯一标准,前期语法学的如何,一个小小demo试试手。 要想学的好,练习不可少;

一、本期敲木鱼demo主要功能介绍:

复制代码
主界面木鱼可以敲击,加功德
功德历史列表
木鱼样式功能切换
木鱼音效功能切换

实现效果图如下:

功德数增加动画效果:

功德历史列表:

木鱼样式选择面板:

音效选择列表:

以上为实现效果图

二、敲木鱼案例功能拆分

2.1 主页面的部分划分

页面布局角度: 主页面:上下布局--各封装一个模块,上布局 :Stack+Center+Positioned 下布局 :Center, 整体布局为:Column+Expanded

布局样式我们进行上下划分,功德数、音效按钮、图片按钮为上半部分,木鱼图片为下半部分

上半部分为图片、音效功德数这些模块设计到后续功能,我们做一个单独的模块封装。

新建一个页面,countpanel.dart【上半部分模块】,使用st快捷输入,这里使用的是无状态Widget【StatelessWidget】

js 复制代码
import 'package:flutter/material.dart';

class CountPanel extends StatelessWidget {
  final int count;//定义功德总数
  final VoidCallback onTapSwitchAudio;//定义切换音效方法
  final VoidCallback onTapSwitchImage;//定义切换木鱼图片方法


  const CountPanel({
    super.key,
    required this.count,
    required this.onTapSwitchAudio,
    required this.onTapSwitchImage,
  });

  @override
  Widget build(BuildContext context) {
  //自定义按钮内容样式
  final ButtonStyle style = ElevatedButton.styleFrom(
      minimumSize: const Size(50, 50),
      padding: EdgeInsets.zero,
      backgroundColor: Colors.green,
      elevation: 0,
    );
  //stack 组件 层叠布局和 Web 中的绝对定位、Android 中的 Frame 布局是相似的,子组件可以根据距父容器四个角的位置来确定自身的位置。
    return Stack(
      children: [
       //center 组件顾名思义,居中内容的组件
        Center(
          child: Text(
            '功德数: $count',
            style: const TextStyle(
              fontSize: 24,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
        //右侧音效、图片切换按钮--使用定位来实现 Positioned
         Positioned(
            right: 10,
            top: 10,
            //# Wrap 流失布局,当一行超出屏幕流失布局会自动拆分,进行换行
            child: Wrap(
              spacing: 8,
              direction: Axis.vertical,
              children: [
              //`ElevatedButton` 即"漂浮"按钮,自带点击事件:onPressed
                ElevatedButton(
                  style: style,
                  onPressed: onTapSwitchAudio,
                  child: const Icon(
                    Icons.music_note_outlined,
                    color: Colors.white,
                  ),
                ),
                ElevatedButton(
                  style: style,
                  onPressed: onTapSwitchImage,
                  child: const Icon(
                    Icons.image,
                    color: Colors.white,
                  ),
                )
              ],
            )),
      ],
    );
  }
}

下半部分图片看似只有一个,但是其实背后是包含着木鱼图片和文字动画效果,这里也封装为一个单独的模块 切换图片时,便于接收不同的imgUrl.

图片组件模块如下:

// 存放木鱼在首页点击图片

js 复制代码
class MuyuAssetsImage extends StatelessWidget {
  final String image;
  final VoidCallback onTap; //接收一个回调方法
  const MuyuAssetsImage({super.key, required this.image, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return Center(
        // gestureDetector  组件监听手势回调
        child: GestureDetector(
      onTap: onTap,
      child: Image.asset(
        image,//接收父组件传递的url值
        height: 200,
      ),
    ));
  }
}

那么图片模块有了,我们来看一下文字动画效果如何实现

动画效果:是点击向上飘,放大又缩小 、文字由深色逐渐变淡

ScaleTransition 弹性动画,scale:放大数 SlideTransition ,根据位置变化的Widget
FadeTransition 淡出的动画效果, AnimationController 动画控制器

因此动画文字模块代码如下:

js 复制代码
import 'package:flutter/material.dart';
import 'package:flutter_app_seven/muyu/fishenity.dart';

// 敲木鱼动画文字组件 --之前有bug 点击切换图片样式时会触发动画
class AnimateText extends StatefulWidget {
  final MeritRecord record;
  const AnimateText({super.key, required this.record});

  @override
  State<AnimateText> createState() => _AnimateTextState();
}

// 加入这个用于加入动画控制器
class _AnimateTextState extends State<AnimateText>
    with SingleTickerProviderStateMixin {
  late AnimationController controller;
  late Animation<double> opacity;
  late Animation<Offset> position;
  late Animation<double> scale;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 500));
    // 动画器属性配置,从开始
    opacity = Tween(begin: 1.0, end: 0.0).animate(controller);//透明度
    scale = Tween(begin: 1.0, end: 0.9).animate(controller);//放大到缩小值
    //位置变化
    position = Tween<Offset>(
      begin: const Offset(0, 5),
      end: Offset.zero,
    ).animate(controller);
    controller.forward();
  }

  @override
  // 在父widget中调用setState
  void didUpdateWidget(covariant AnimateText oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 避免功德未变化的情况下,启动动画场景
    if (oldWidget.record.id != widget.record.id) {
      controller.forward(from: 0);
    }
  }
  
  
  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //过渡消失组件 还缺少缩放动画
    // 旋转
    return ScaleTransition(
      scale: scale,
      // 移动
      child: SlideTransition(
          position: position,
          child: FadeTransition(
            opacity: opacity,
            child: Text('功德数+${widget.record.value}'),
          )),
    );
  }
}

下期在续...

相关推荐
liulian09167 小时前
Flutter for OpenHarmony 跨平台开发:单位转换功能实战指南
flutter
千码君20168 小时前
Trae:一些关于flutter和 go前后端开发构建的分享
android·flutter·gradle·android-studio·trae·vibe code
maaath9 小时前
【maaath】Flutter for OpenHarmony 手表配饰应用实战开发
flutter·华为·harmonyos
maaath10 小时前
【maaath】Flutter for OpenHarmony 跨平台计算器应用开发实践
flutter·华为·harmonyos
maaath15 小时前
【maaath】Flutter for OpenHarmony 闹钟时钟应用开发实战
flutter·华为·harmonyos
maaath15 小时前
【maaath】Flutter for OpenHarmony 短信管理应用实战
flutter·华为·harmonyos
maaath16 小时前
【maaath】Flutter for OpenHarmony打造跨平台便签备忘录应用
flutter·华为·harmonyos
千码君201616 小时前
flutter:与Android Studio模拟器的调试分享
android·flutter
xmdy586617 小时前
Flutter+开源鸿蒙实战|智联邻里Day8 Lottie动画集成+url_launcher跳转拨号+个人中心完善+全局UI统一
flutter·开源·harmonyos
liulian09161 天前
Flutter for OpenHarmony 跨平台开发:颜色选择器功能实战指南
flutter