【源码版】flutter3.19仿抖音实战企业级APP应用

flutter3.19仿抖音实战企业级APP应用

近年来各大公司对Flutter技能的要求越来越高,有些专门提供培训并设立岗位,但掌握Flutter高阶技能的人才寥寥无几,市面上干货Flutter高阶课程少之又少,导致Flutter高阶人才缺口大。为此我们专门为大家设计了这门课程,助力你早日成为企业抢手的新一代工程师。

全新Flutter原创基于flutter3.19.5+dart3.3.3+getx等技术开发仿抖音app实战项目。实现了类似抖音整屏丝滑式上下滑动视频、左右滑动切换页面模块,商城、购物车、支付功能等模块。
同时接入了友盟SDK统计数据。 

由于文件比较大,这里只是将部分截图出来,如果你觉得这些内容对你有帮助:

【扫描下方卡片即可免费领取!!!】

学习目标

Flutter进阶高手分为三个阶段,从易到难,学习完成后,可以使用Flutter来开发独立的APP,适用于Android、iOS双平台的应用程序。

第一阶段是 Flutter开发必备Dart基础

第二个阶段是 Flutter核心技术, 一次性掌握,组件大全、页面布局、路由、网络请求、数据缓存、动画等等

第三个阶段是 开发实战企业级APP

flutter运用技术
编辑器:vscode
技术框架:flutter3.19.5+dart3.3.3
路由/状态插件:get: ^4.6.6
网络数据:dio: ^5.3.3
缓存服务:shared_preferences: ^2.2.1
图片预览插件:photo_view: ^0.14.0
刷新加载:easy_refresh^3.3.4
toast轻提示:toast^0.3.0
视频播放器:video_player: ^2.8.3
视频播放器: chewie: ^1.7.5 

实现启动页与自定义开屏广告,可换成穿山甲广告实现收益:

flutter3.19.x仿抖音教你开发商业级APP

接入字节跳动穿山甲广告

await FlutterUnionad.register(
        androidAppId: "5098580",
        //穿山甲广告 Android appid 必填
        iosAppId: "5098580",
        //穿山甲广告 ios appid 必填
        useTextureView: true,
        //使用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView冲突的场景,可以使用TextureView 选填
        appName: "unionad_test",
        //appname 必填
        allowShowNotify: true,
        //是否允许sdk展示通知栏提示 选填
        allowShowPageWhenScreenLock: true,
        //是否在锁屏场景支持展示广告落地页 选填
        debug: true,
        //测试阶段打开,可以通过日志排查问题,上线时去除该调用 选太难
        supportMultiProcess: true,
        //是否支持多进程,true支持 选填
        directDownloadNetworkType: [
          FlutterUnionad.NetCode.NETWORK_STATE_2G,
          FlutterUnionad.NetCode.NETWORK_STATE_3G,
          FlutterUnionad.NetCode.NETWORK_STATE_4G,
          FlutterUnionad.NetCode.NETWORK_STATE_WIFI
        ]); //允许直接下载的网络状态集合 选填//允许直接下载的网络状态集合 选填
flutter3.19.x+getx实现了类似抖音全屏上下滑动、左右切换页面效果:

使用 bottomNavigationBar 组件实现底部导航页面模块切换

flutter3.19.x+getx仿抖音教你开发商业级AP

flutter3.19.x+getx仿抖音教你开发商业级AP

视频页面布局,使用了 Stack 组件定位实现页面布局。

return Scaffold(
      backgroundColor: Colors.black,
      body: SafeArea(
        child: GetBuilder<VideoController>(builder: (c) {
          return controller.isLoading
              ? const Center(child: CircularProgressIndicator())
              : controller.videos.isEmpty
                  ? Center(
                      child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        const Padding(
                          padding: EdgeInsets.only(bottom: 8.0),
                          child: Text("暂无数据"),
                        ),
                        ElevatedButton(
                          style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.red)),
                          onPressed: controller.initLoad,
                          child: const Text("刷新"),
                        ),
                      ],
                    ))
                  : PageView.builder(
                      controller: PageController(
                        initialPage: controller.currentIndex,
                        viewportFraction: 1,
                      ),
                      itemCount: controller.videos.length,
                      onPageChanged: (index) {
                        controller.changeVideo(index);
                      },
                      scrollDirection: Axis.vertical,
                      itemBuilder: (context, index) {
                        return videoCard(controller.videos[index]);
                      },
                    );
        }),
      ),

 使用TabBar组件和PageView组件实现顶部菜单和页面联动切换效果

Obx(
      () => Scaffold(
        body: IndexedStack(
          index: homeController.currentIndex.value,
          children: [
            IndexPage(),
            homeController.currentIndex.value == 1 ? VideoPage() : Container(),
            Container(),
            MessagePage(),
            MinePage(),
          ],
        ),
        bottomNavigationBar: Theme(
          data: Theme.of(context).copyWith(
            splashColor: Colors.transparent,
            highlightColor: Colors.transparent,
          ),
          child: BottomNavigationBar(
            elevation: 0,
            iconSize: 24,
            backgroundColor: homeController.currentIndex.value == 1 ? Colors.black : Colors.white,
            selectedItemColor: homeController.currentIndex.value == 1 ? Colors.white : Colors.black,
            unselectedItemColor: const Color(0xff999999),
            type: BottomNavigationBarType.fixed,
            currentIndex: homeController.currentIndex.value,
            unselectedFontSize: 16,
            selectedFontSize: 18,
            items: const [
              BottomNavigationBarItem(
                icon: SizedBox.shrink(),
                label: "首页",
              ),
              BottomNavigationBarItem(
                icon: SizedBox.shrink(),
                label: "视频",
              ),
              BottomNavigationBarItem(
                icon: Icon(
                  Icons.add_box,
                  size: 32,
                  color: Colors.red,
                ),
                label: "",
              ),
              BottomNavigationBarItem(
                icon: SizedBox.shrink(),
                label: "消息",
              ),
              BottomNavigationBarItem(
                icon: SizedBox.shrink(),
                label: "我",
              ),
            ],
            onTap: (index) {
              homeController.onChangePage(index);
            },
          ),
        ),
      ),
    );

video_player基本使用 

/// 声明控制器
late VideoPlayerController _controller;
/// 初始化控制器
_controller = VideoPlayerController.network(list[0]['video_url'])
      ///设置视频循环播放
      ..setLooping(true)
      ///设置监听
      ..addListener(() {
        setState(() {
        });
      })
      ///初始化
      ..initialize().then((_) async {
        ///初始化完成更新状态,不然播放器不会播放
        setState(() {
          playOrPauseVideo();
        });
      }).catchError((err) {
        ///播放出错
        print(err);
      });


/// 显示视频
SizedBox(
     height: 240,
     width: MediaQuery.of(context).size.width,
     child: _controller.value.isInitialized
              ? AspectRatio(
                          aspectRatio:
                          _controller.value.aspectRatio,
                         child: VideoPlayer(_controller),
                             )
                             : const Text(
                                    "没有要播放的视频",
                                    style: TextStyle(color: Colors.red),
                                ),
                       ),

注意点:在播放器initialize 完后一定要更新播放器的状态,不然是widget拿不到状态改变,是不会播放的

视频播放,暂停

/// 判断播放和暂停
  void playOrPauseVideo() {
    setState(() {
      if (_controller.value.isPlaying) {
        _controller.pause();
      } else {
        // If the video is paused, play it.
        _controller.play();
      }
    });
  }

实现抖音滑动效果

核心原理就是使用PageView来实现的,需要注意的是每次滑动的时候需要将上一个_controller释放掉以后再重新创建一个,不然上个视频还是会播放的.具体代码如下:

PageView.builder(
          physics: const QuickerScrollPhysics(),
          controller: _pageController,
          scrollDirection: Axis.vertical,
          itemCount: list.length,
          onPageChanged: (index) {
            _controller.dispose();
            _controller =
                VideoPlayerController.network(list[index]['video_url'])
                  ..setLooping(true)
                  ..addListener(() {
                    setState(() {
                    });
                  })
                  ..initialize().then((_) async {
                    setState(() {
                      playOrPauseVideo();
                    });
                  }).catchError((err) {
                    print(err);
                  });

            if (index == list.length - 1) {
              Future.delayed(
                  const Duration(milliseconds: 200)).then((lwh) {
                _pageController.jumpToPage(0);
              });
      
            }
          },
          itemBuilder: (context, i) {
            return Stack(
              children: [
                /// 播放器view
                Container(
                  color: Colors.black,
                  child: Center(
                    child: Stack(
                      children: [
                        AppNetImage(
                          fit: BoxFit.fitWidth,
                          imageUrl: list[i]['image_url'],
                          height: 240,
                          width: MediaQuery.of(context).size.width,
                        ),
                        Positioned(
                            child: Stack(
                          children: [
                            InkWell(
                              child: SizedBox(
                                height: 240,
                                width: MediaQuery.of(context).size.width,
                                child: _controller.value.isInitialized
                                    ? AspectRatio(
                                        aspectRatio:
                                            _controller.value.aspectRatio,
                                        child: VideoPlayer(_controller),
                                      )
                                    : const Text(
                                        "没有要播放的视频",
                                        style: TextStyle(color: Colors.red),
                                      ),
                              ),
                              onTap: () {
                                playOrPauseVideo();
                              },
                            ),
                          ],
                        )),
                        Positioned(
                          left: MediaQuery.of(context).size.width / 2 - 30,
                          top: 90,
                          child: _controller.value.isPlaying
                              ? const SizedBox()
                              : const Icon(
                                  Icons.play_arrow,
                                  color: Colors.white,
                                  size: 60,
                                ),
                        ),
                      ],
                    ),
                  ),
                ),

                /// 显示全屏按钮
                Positioned(
                    bottom: MediaQuery.of(context).padding.bottom + 100,
                    right: 8,
                    child: InkWell(
                      child: const Icon(
                        Icons.aspect_ratio,
                        color: Colors.white,
                        size: 30,
                      ),
                      onTap: () {
                        _toggleFullScreen();
                      },
                    )),

                /// 显示进度条
                Positioned(
                    bottom: MediaQuery.of(context).padding.bottom,
                    child: SizedBox(
                      width: MediaQuery.of(context).size.width,
                      height: 1,
                      child: VideoProgressIndicator(
                        _controller,
                        allowScrubbing: true,
                        padding: const EdgeInsets.all(0),
                        colors: const VideoProgressColors(
                          playedColor: Colors.white, // 已播放的颜色
                          bufferedColor:
                           Color.fromRGBO(255, 255, 255, .5), // 缓存中的颜色
                          backgroundColor:
                           Color.fromRGBO(255, 255, 255, .3), // 为缓存的颜色
                        ),
                      ),
                    ))
              ],
            );
          },
        )

 

flutter3.19.x+getx仿抖音教你开发商业级AP

 

 

常言道,学而不思则罔,思而不学则殆。在学习flutter时也应该多多思考,积极消化自己不会的知识,这也能强化我们的技术水平,帮助我们更好适应快节奏的开发进程,成为一名更有竞争力的Android开发者!

由于文件比较大,这里只是将部分截图出来,如果你觉得这些内容对你有帮助:

【扫描下方卡片即可免费领取!!!】

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于 Flutter 3.x 进行仿抖音跨平台混合开发,是一种使用最新本的Flutter框架来开发类似抖音应用程序的方法。 Flutter是一种跨平台的开发框架,可以让开发者使用同一套代码同时在iOSAndroid平台上构建高性能的应用程序。它提供了丰富的UI组件和工具,使开发过程更加简单和高效。 要实现仿抖音的跨平台混合开发,首先需要对抖音的功能和界面进行分析和设计。然后,使用Flutter框架来实现这些功能和界面。 Flutter提供了丰富的UI组件,如按钮、文本、图片、视频播放等,可以用于构建抖音的各种界面元素。开发者可以使用Dart语言来编写业务逻辑,同时可以使用Flutter提供的hot reload功能实时预览和调试应用程序。 为了实现跨平台开发,开发者可以使用Flutter的多平台支持。Flutter可以生成原生的iOSAndroid应用程序,以及Web和桌面应用程序。这使得开发者可以在不同的平台上发布和部署仿抖音应用程序。 在开发过程中,开发者可以使用Flutter的插件来集成各种第三方功能和服务,如视频播放、数据存储、社交分享等。这些插件可以帮助开发者更加方便地实现仿抖音的各种功能。 总之,基于Flutter 3.x进行仿抖音跨平台混合开发,是一种高效、灵活的开发方法。通过使用Flutter框架和相关工具,开发者可以快速构建出功能完善、界面精美的仿抖音应用程序,并在多个平台上进行发布和部署。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值