├── README.md ├── README_Like.md ├── README_Video.md ├── README_layout.md ├── flutter_tiktok ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── flutter_tiktok │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── assets │ ├── images │ │ ├── actionbar_search.png │ │ ├── aliuser_title_back_normal.9.png │ │ ├── ic_playing.png │ │ ├── love.jpeg │ │ ├── v1.png │ │ ├── v2.png │ │ ├── video_icon_praise.png │ │ ├── video_msg_icon.png │ │ ├── video_share_icon.png │ │ ├── vides.png │ │ └── vides2.png │ └── videos │ │ ├── 1.MP4 │ │ └── 2.mp4 ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m ├── lib │ ├── demo │ │ ├── Layout │ │ │ ├── View │ │ │ │ ├── botton_view.dart │ │ │ │ ├── right_view.dart │ │ │ │ └── video_controller.dart │ │ │ └── layout_view_controller.dart │ │ ├── Video │ │ │ ├── video_play_view_controller.dart │ │ │ └── video_view_controller.dart │ │ └── like_view_controller.dart │ ├── main.dart │ └── service │ │ ├── event_bus_service.dart │ │ ├── navigation_service.dart │ │ ├── screen_service.dart │ │ └── widget_ext_service.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart └── res ├── 11.gif ├── 111.gif ├── 3.gif └── QQ20191224-093618.gif /README.md: -------------------------------------------------------------------------------- 1 | # flutter_TikTok 2 | # flutter 仿抖音功能目录 3 | 4 | ![QQ20191224-093618.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/QQ20191224-093618.gif) 5 | ![11.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/11.gif) 6 | ![111.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/111.gif) 7 | ![3.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/3.gif) 8 | 9 | [Flutter 仿抖音效果 (一) 全屏点爱星](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/README_Like.md) 10 | [Flutter 仿抖音效果 (二) 界面布局](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/README_Like.md) 11 | [Flutter 仿抖音效果 (三) 视频播放列表](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/README_Video.md) 12 | 13 | 项目地址:[https://github.com/CZXBigBrother/flutter_TikTok](https://github.com/CZXBigBrother/flutter_TikTok) 持续效果更新 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /README_Like.md: -------------------------------------------------------------------------------- 1 | # flutter_TikTok 2 | ![QQ20191224-093618.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/QQ20191224-093618.gif) 3 | 4 | 项目地址:[https://github.com/CZXBigBrother/flutter_TikTok](https://github.com/CZXBigBrother/flutter_TikTok) 持续效果更新 5 | # 实现点爱心的效果需要解决的问题 6 | * 1.onDoubleTap 无法获取到点击的坐标 7 | * 2.flutter 用tree布局的如何将爱心分离出原来StatefulWidget 进行动画和操作 8 | * 3.连贯动画如何实现 9 | 10 | # 如何解决flutter原生的double事件没有返回坐标 11 | flutter 有个onTapUp 事件,字面意思就是 点击抬起的,会返回 ```TapUpDetails details```,通过```localPosition```属性就能获取到x,y坐标 12 | 计算double 并不复杂,每次点击的时候记录下当前的事件戳,只要两个点击的时间戳和坐标距离小于自己设定的阈值,就可以视为双击事件 13 | ###### 代码如下 14 | ``` 15 | // 记录时间 16 | var touchTime = new DateTime.now(); 17 | // 记录坐标 18 | var touchPoint = new MathPoint(-999, -999); 19 | ``` 20 | 实现双击 21 | ``` 22 | onTapUp: (TapUpDetails details) { 23 | // 当前时间-上次记录的时间 24 | var t = new DateTime.now().millisecondsSinceEpoch - 25 | this.touchTime.millisecondsSinceEpoch; 26 | // 获取当前坐标 27 | var currentPoint = 28 | new MathPoint(details.localPosition.dx, details.localPosition.dy); 29 | //计算两次距离 30 | var distance = currentPoint.distanceTo(this.touchPoint); 31 | // 记录当前时间 32 | this.touchTime = new DateTime.now(); 33 | // 记录当前坐标 34 | this.touchPoint = currentPoint; 35 | // 判断两次间隔是否小于300毫秒 36 | if (t < 300 && distance < 20) { 37 | this.touchTime = new DateTime.fromMicrosecondsSinceEpoch(0); 38 | // print(details.localPosition.dx); 39 | // print(details.localPosition.dy); 40 | } 41 | ``` 42 | # 如何解决tree布局的如何将爱心分离出 43 | 我们使用OverlayEntry 控件,控件详细介绍 [https://www.jianshu.com/p/cc8aab935e11](https://www.jianshu.com/p/cc8aab935e11) 44 | ``` 45 | var overlayState = Overlay.of(context); 46 | OverlayEntry overlayEntry; 47 | double width = 50; 48 | double height = 50; 49 | double x = dx - width / 2; 50 | double y = dy + height / 2; 51 | 52 | overlayEntry = new OverlayEntry(builder: (context) { 53 | return Stack( 54 | children: [ 55 | new Positioned( 56 | left: x, 57 | top: y, 58 | child: new LikeView( 59 | overlayEntry: overlayEntry, 60 | ), 61 | ), 62 | ], 63 | ); 64 | }); 65 | ///插入全局悬浮控件 66 | overlayState.insert(overlayEntry); 67 | ``` 68 | # 连贯动画如何实现 69 | 效果一共有 缩小 → 上移 → 放大 → 消失 70 | 第一组动画(缩小 上移) → 第二组动画(放大 消失) 71 | flutter 动画需要两个类 72 | AnimationController 负责管理动画 73 | Animation 负责具体值操作 74 | * 分解第一步:缩小 75 | 我们设置初始值为1.5倍的大小,然后动画缩回1倍 76 | ``` 77 | scaleAnimate = Tween( 78 | begin: 1.5, 79 | end: 1, 80 | ).animate( 81 | CurvedAnimation( 82 | parent: controller, 83 | curve: Interval( 84 | 0, 85 | 1.0, 86 | curve: Curves.ease, 87 | ), 88 | ), 89 | ); 90 | ``` 91 | 然后通过 Transform.scale 函数的,对scale值进行改变 92 | ``` 93 | return AnimatedBuilder( 94 | builder: (BuildContext context, Widget child) { 95 | return Transform.scale( 96 | .......... 97 | scale: scaleAnimate.value, 98 | ); 99 | }, 100 | animation: controller, 101 | ); 102 | ``` 103 | * 分解第二步:上移 104 | 我们初始化时候先下20个坐标点,在动画还原到原来的位置,这点很关键,为什么我们不是从0开始下移20个坐标呢,主要是因为动画比较多,我们要将动画分成两次去刷新,如果我们是从0开始往上,我们再第二次动画时候就要手动改变初始化坐标,到上移的20个点,这样我们可以少做一次操作看后面的代码 105 | ``` 106 | // 向上移动 107 | upLocation = Tween( 108 | begin: EdgeInsets.only(top: 20.0), 109 | end: EdgeInsets.only(top: 0.0), 110 | ).animate( 111 | CurvedAnimation( 112 | parent: controller, 113 | curve: Interval( 114 | 0, 115 | 1.0, 116 | curve: Curves.ease, 117 | ), 118 | ), 119 | ); 120 | ``` 121 | 补全第一组动画 122 | ``` 123 | return AnimatedBuilder( 124 | builder: (BuildContext context, Widget child) { 125 | return Transform.scale( 126 | child: Padding( 127 | padding: upLocation.value, 128 | child: Image.asset( 129 | 'assets/images/love.jpeg', 130 | fit: BoxFit.fill, 131 | width: width, 132 | height: height, 133 | ), 134 | ), 135 | scale: scaleAnimate.value, 136 | ); 137 | }, 138 | animation: controller, 139 | ); 140 | ``` 141 | * 分解第三第四步 放大消失 同理 142 | ``` 143 | // 消失动画 144 | display = Tween( 145 | begin: 1, 146 | end: 0, 147 | ).animate( 148 | CurvedAnimation( 149 | parent: controller, 150 | curve: Interval( 151 | 0, 152 | 1.0, 153 | curve: Curves.ease, 154 | ), 155 | ), 156 | ); 157 | //放大 158 | scaleAnimate2 = Tween( 159 | begin: 1, 160 | end: 1.5, 161 | ).animate( 162 | CurvedAnimation( 163 | parent: controller, 164 | curve: Interval( 165 | 0, 166 | 1.0, 167 | curve: Curves.ease, 168 | ), 169 | ), 170 | ); 171 | ``` 172 | 现实 173 | ``` 174 | return AnimatedBuilder( 175 | builder: (BuildContext context, Widget child) { 176 | return Transform.scale( 177 | child: Opacity( 178 | opacity: display.value, 179 | child: Image.asset( 180 | 'assets/images/love.jpeg', 181 | fit: BoxFit.fill, 182 | width: width, 183 | height: height, 184 | ), 185 | ), 186 | scale: scaleAnimate2.value, 187 | ); 188 | }, 189 | animation: controller, 190 | ); 191 | ``` 192 | * 第一组和第二组动画刷新 193 | 我们设置一个标签step,通过对AnimationController的监听,我在第一次动画结束时更新step,然后开始第二组动画,当第二组动画结束时 删除对象 194 | ``` 195 | controller = new AnimationController( 196 | duration: const Duration(milliseconds: 1000), vsync: this) 197 | ..addStatusListener((status) { 198 | if (status == AnimationStatus.completed) { 199 | print("status is completed"); 200 | if (this.step == 0) { 201 | this.step = 1; 202 | controller.reset(); 203 | this.setState(() {}); 204 | } else if (this.step == 1) { 205 | widget.overlayEntry.remove(); 206 | } 207 | } 208 | }); 209 | ``` 210 | ![QQ20191224-093618.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/QQ20191224-093618.gif) 211 | 212 | 项目地址:[https://github.com/CZXBigBrother/flutter_TikTok](https://github.com/CZXBigBrother/flutter_TikTok) 持续效果更新 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /README_Video.md: -------------------------------------------------------------------------------- 1 | ![3.gif](https://upload-images.jianshu.io/upload_images/3258209-1788c1d5e28a8e35.gif?imageMogr2/auto-orient/strip) 2 | [Flutter 仿抖音效果 (一) 全屏点爱星](https://www.jianshu.com/p/e527aab4fc4b) 3 | [Flutter 仿抖音效果 (二) 界面布局](https://www.jianshu.com/p/f5b75a4bb126) 4 | 5 | 6 | 项目地址:[https://github.com/CZXBigBrother/flutter_TikTok](https://github.com/CZXBigBrother/flutter_TikTok) 持续效果更新 7 | # 实现抖音视频播放列表需要解决的问题 8 | * 1.视频播放 9 | * 2.切换时开始和停止视频的播放 10 | 11 | # 视频播放 12 | 视频播放实际实现是非常简单的只用使用VideoPlayerController就能快速的接入 13 | ``` 14 | video_player: ^0.10.1+5 15 | ``` 16 | 使用到的API 17 | ``` 18 | /// finished. 19 | Future play() async { 20 | /// Sets whether or not the video should loop after playing once. See also 21 | /// [VideoPlayerValue.isLooping]. 22 | Future setLooping(bool looping) async 23 | /// Pauses the video. 24 | Future pause() async 25 | ``` 26 | ![Snip20200113_2.png](https://upload-images.jianshu.io/upload_images/3258209-9966d301b79dd8be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 27 | 加载完成前,使用第一帧的图片作为预留图,加载完成之后,隐藏预览图,保证短视频加载缓慢是不会出现黑屏的情况 ,播放按键和预留图都通过stack布局的方式进行. 28 | ``` 29 | return Stack( 30 | children: [ 31 | GestureDetector( 32 | child: Stack( 33 | children: [ 34 | Container( 35 | margin: EdgeInsets.only(top: ScreenService.topSafeHeight), 36 | width: ScreenService.width, 37 | height: h, //h/w = sh/sw 38 | child: VideoPlayer(_controller), 39 | ), 40 | getPauseView() 41 | ], 42 | ), 43 | onTap: () { 44 | if (_controller.value.isPlaying) { 45 | _controller.pause(); 46 | _hideActionButton = false; 47 | } else { 48 | _controller.play(); 49 | videoPrepared = true; 50 | _hideActionButton = true; 51 | } 52 | setState(() {}); 53 | }), 54 | // this.getVideo(), 55 | getPreviewImg(), 56 | getLikesView(), 57 | this.getUserAndTitle() 58 | ], 59 | ); 60 | ``` 61 | # 上下切换列表 62 | 使用Swiper 63 | ``` 64 | body: Container( 65 | child: Swiper( 66 | autoStart: false, 67 | circular: false, 68 | direction: Axis.vertical, 69 | children: children, 70 | controller: _controller, 71 | ), 72 | color: Colors.black, 73 | ), 74 | ``` 75 | # 切换时开始和停止视频的播放 76 | 添加 SwiperController监听 77 | ``` 78 | SwiperController _controller = SwiperController(); 79 | ``` 80 | 初始化时 我们会使用 81 | ``` 82 | 会标记 一个tag值用来判断当前队列的编号 83 | ``` 84 | 然后在当滑动到某个视频时通知开始播放 85 | ``` 86 | _controller.addListener(() { 87 | if (_controller.page.floor() == _controller.page) { 88 | eventBus.emit(keyPlayVideo + _controller.page.floor().toString(), 89 | _controller.page.floor()); 90 | } 91 | }); 92 | ``` 93 | 这里会用到一个东西就是eventBus.这个和iOS 的KVO 差不多的意思.添加监听的KEY 然后注册接受.内部存储里一个事件的队列.发送通知是会执行所有的接受者 94 | 在视频controller中注册监听eventBus 95 | ``` 96 | eventBus.on(keyPlayVideo + widget.positionTag.toString(), (arg) { 97 | if (arg == widget.positionTag) { 98 | _controller.play(); 99 | videoPrepared = true; 100 | _hideActionButton = true; 101 | } else { 102 | _controller.pause(); 103 | _hideActionButton = false; 104 | } 105 | setState(() {}); 106 | }); 107 | ``` 108 | 在dispose的时候必须移除eventBus 和 等等的Controller,否则会报错 109 | ``` 110 | @override 111 | void dispose() { 112 | this.scroController.dispose(); 113 | this.timer.cancel(); 114 | _controller.dispose(); //释放播放器资源 115 | 116 | super.dispose(); 117 | } 118 | 119 | ``` 120 | -------------------------------------------------------------------------------- /README_layout.md: -------------------------------------------------------------------------------- 1 | # flutter_TikTok 2 | ![QQ20191231-184930.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/11.gif) 3 | 4 | [Flutter 仿抖音效果 (一) 全屏点爱星](https://www.jianshu.com/p/e527aab4fc4b) 5 | [Flutter 仿抖音效果 (二) 界面布局](https://www.jianshu.com/p/f5b75a4bb126) 6 | 7 | 项目地址:[https://github.com/CZXBigBrother/flutter_TikTok](https://github.com/CZXBigBrother/flutter_TikTok) 持续效果更新 8 | 9 | # 实现界面布局效果需要解决的问题 10 | * 1.整体布局实现 11 | * 2.底部歌曲左右移动效果 12 | ![Snip20191231_10.png](https://upload-images.jianshu.io/upload_images/3258209-2a5723784d5e1fe2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400) 13 | #布局的实现 14 | 1.基本的布局是简单的,外层通过Stack作为根 15 | 2.左边点赞的控件组通过Align进行统一布局 16 | 3.顶部控件组通过Positioned进行布局,设置顶部距离,其实也可以用align,我们多使用几种来习惯flutter的布局 17 | 4.底部同样使用Positioned,设置底部距离 18 | 5.子页面的左右滑动使用PageView,一开始我们要从推荐开始左滑到关注,可以使用reverse属性,不需要更多额外的操作 19 | #细节实现 20 | 1.pageController监听 21 | ``` 22 | PageController pageController = new PageController(keepPage: false); 23 | pageController.addListener(() { 24 | // print(pageController.page); 25 | if (pageController.page == 1) { 26 | this.stream.sink.add(1); 27 | } else if (pageController.page == 0) { 28 | this.stream.sink.add(0); 29 | } 30 | }); 31 | ``` 32 | 刷新顶部的下划线时,我们一样使用StreamController刷新,这样效率比setstate高很多 33 | ``` 34 | StreamController stream = new StreamController.broadcast(); 35 | StreamBuilder( 36 | initialData: 0, 37 | builder: (context, snapshot) { 38 | return Text( 39 | "推荐", 40 | style: TextStyle( 41 | color: Colors.white, 42 | decoration: snapshot.data == 0 43 | ? TextDecoration.underline 44 | : TextDecoration.none, 45 | ), 46 | ); 47 | }, 48 | stream: this.stream.stream, 49 | ) 50 | ``` 51 | 2.歌曲名走马灯效果 52 | 53 | ![111.gif](https://github.com/CZXBigBrother/flutter_TikTok/blob/master/res/111.gif) 54 | 这个效果看起来挺麻烦的其实实现起来超级的简单用最普通的ListView就能快速的实现 55 | 首页listview里面套入的是最简单的container+text 56 | ``` 57 | Container( 58 | // color: Colors.red, 59 | // alignment: Alignment.centerLeft, 60 | child: Text( 61 | "三根皮带歌曲,哗啦啦啦啦啦啦啦啦啦啦啦", 62 | maxLines: 1, 63 | style: TextStyle( 64 | color: Colors.white, 65 | ), 66 | textAlign: TextAlign.left, 67 | ), 68 | ) 69 | ``` 70 | listview添加一个ScrollController做为滑动的控制 71 | ``` 72 | ScrollController scroController = new ScrollController(); 73 | ``` 74 | 使用一个定时器,把listview滑到最大的位置之后,在滑回去 75 | 先通过scroController.position.maxScrollExtent获取最大位置, 76 | 然后通过scroController.animateTo进行滑动,因为我设置一次循环的时间是3000毫秒,所以滑过去和滑回来的时间各占一般 new Duration(milliseconds: (time * 0.5).toInt()),还有就是歌名没有大于最大宽度时候其实我们不需要进行滑动,所以判断maxScrollExtent是否大于0来确定是否进行滑动动画 77 | ``` 78 | Timer timer; 79 | void startTimer() { 80 | int time = 3000; 81 | timer = Timer.periodic(new Duration(milliseconds: time), (timer) { 82 | if (scroController.positions.isNotEmpty == false) { 83 | print('界面被销毁'); 84 | return; 85 | } 86 | double maxScrollExtent = scroController.position.maxScrollExtent; 87 | // print(maxScrollExtent); 88 | // double pixels = scroController.position.pixels; 89 | if (maxScrollExtent > 0) { 90 | scroController.animateTo(maxScrollExtent, 91 | duration: new Duration(milliseconds: (time * 0.5).toInt()), 92 | curve: Curves.linear); 93 | Future.delayed(Duration(milliseconds: (time * 0.5).toInt()), () { 94 | if (scroController.positions.isNotEmpty == true) { 95 | scroController.animateTo(0, 96 | duration: new Duration(milliseconds: (time * 0.5).toInt()), 97 | curve: Curves.linear); 98 | } 99 | }); 100 | } else { 101 | print('不需要移动'); 102 | timer.cancel(); 103 | } 104 | }); 105 | } 106 | ``` 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /flutter_tiktok/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | -------------------------------------------------------------------------------- /flutter_tiktok/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c06bf6503a8b6690b2740a7101852fcc8f133057 8 | channel: master 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /flutter_tiktok/README.md: -------------------------------------------------------------------------------- 1 | # flutter_tiktok 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /flutter_tiktok/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /flutter_tiktok/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.example.flutter_tiktok" 37 | minSdkVersion 16 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'androidx.test:runner:1.1.1' 60 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 61 | } 62 | -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/java/com/example/flutter_tiktok/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.flutter_tiktok; 2 | 3 | import androidx.annotation.NonNull; 4 | import io.flutter.embedding.android.FlutterActivity; 5 | import io.flutter.embedding.engine.FlutterEngine; 6 | import io.flutter.plugins.GeneratedPluginRegistrant; 7 | 8 | public class MainActivity extends FlutterActivity { 9 | @Override 10 | public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { 11 | GeneratedPluginRegistrant.registerWith(flutterEngine); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_tiktok/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_tiktok/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /flutter_tiktok/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /flutter_tiktok/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /flutter_tiktok/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/actionbar_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/actionbar_search.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/aliuser_title_back_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/aliuser_title_back_normal.9.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/ic_playing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/ic_playing.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/love.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/love.jpeg -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/v1.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/v2.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/video_icon_praise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/video_icon_praise.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/video_msg_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/video_msg_icon.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/video_share_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/video_share_icon.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/vides.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/vides.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/images/vides2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/images/vides2.png -------------------------------------------------------------------------------- /flutter_tiktok/assets/videos/1.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/videos/1.MP4 -------------------------------------------------------------------------------- /flutter_tiktok/assets/videos/2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/assets/videos/2.mp4 -------------------------------------------------------------------------------- /flutter_tiktok/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | generated_key_values = {} 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) do |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | generated_key_values[podname] = podpath 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | end 32 | generated_key_values 33 | end 34 | 35 | target 'Runner' do 36 | # Flutter Pod 37 | 38 | copied_flutter_dir = File.join(__dir__, 'Flutter') 39 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') 40 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') 41 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) 42 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. 43 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. 44 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. 45 | 46 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') 47 | unless File.exist?(generated_xcode_build_settings_path) 48 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" 49 | end 50 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) 51 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; 52 | 53 | unless File.exist?(copied_framework_path) 54 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) 55 | end 56 | unless File.exist?(copied_podspec_path) 57 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) 58 | end 59 | end 60 | 61 | # Keep pod path relative so it can be checked into Podfile.lock. 62 | pod 'Flutter', :path => 'Flutter' 63 | 64 | # Plugin Pods 65 | 66 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 67 | # referring to absolute paths on developers' machines. 68 | system('rm -rf .symlinks') 69 | system('mkdir -p .symlinks/plugins') 70 | plugin_pods = parse_KV_file('../.flutter-plugins') 71 | plugin_pods.each do |name, path| 72 | symlink = File.join('.symlinks', 'plugins', name) 73 | File.symlink(path, symlink) 74 | pod name, :path => File.join(symlink, 'ios') 75 | end 76 | end 77 | 78 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. 79 | install! 'cocoapods', :disable_input_output_paths => true 80 | 81 | post_install do |installer| 82 | installer.pods_project.targets.each do |target| 83 | target.build_configurations.each do |config| 84 | config.build_settings['ENABLE_BITCODE'] = 'NO' 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - screen (0.0.1): 4 | - Flutter 5 | - video_player (0.0.1): 6 | - Flutter 7 | - video_player_web (0.0.1): 8 | - Flutter 9 | 10 | DEPENDENCIES: 11 | - Flutter (from `Flutter`) 12 | - screen (from `.symlinks/plugins/screen/ios`) 13 | - video_player (from `.symlinks/plugins/video_player/ios`) 14 | - video_player_web (from `.symlinks/plugins/video_player_web/ios`) 15 | 16 | EXTERNAL SOURCES: 17 | Flutter: 18 | :path: Flutter 19 | screen: 20 | :path: ".symlinks/plugins/screen/ios" 21 | video_player: 22 | :path: ".symlinks/plugins/video_player/ios" 23 | video_player_web: 24 | :path: ".symlinks/plugins/video_player_web/ios" 25 | 26 | SPEC CHECKSUMS: 27 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec 28 | screen: abd91ca7bf3426e1cc3646d27e9b2358d6bf07b0 29 | video_player: 69c5f029fac4ffe4fc8a85ea7f7b793709661549 30 | video_player_web: da8cadb8274ed4f8dbee8d7171b420dedd437ce7 31 | 32 | PODFILE CHECKSUM: 3dbe063e9c90a5d7c9e4e76e70a821b9e2c1d271 33 | 34 | COCOAPODS: 1.8.4 35 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 07D45A952332E7D06A21F2C6 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 47E0D2230599AD2825B27CAE /* libPods-Runner.a */; }; 11 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 18 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 19 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 20 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 21 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXCopyFilesBuildPhase section */ 25 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 26 | isa = PBXCopyFilesBuildPhase; 27 | buildActionMask = 2147483647; 28 | dstPath = ""; 29 | dstSubfolderSpec = 10; 30 | files = ( 31 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 32 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 33 | ); 34 | name = "Embed Frameworks"; 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXCopyFilesBuildPhase section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 41 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 42 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 43 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 44 | 47E0D2230599AD2825B27CAE /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 56471A27C261CF6FED6524B0 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 46 | 5F14B6C777AED01452242853 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 47 | 667BD4FE8A8D661788A80155 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 48 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 49 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 50 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 52 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 53 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 54 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 56 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 57 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 59 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 68 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 69 | 07D45A952332E7D06A21F2C6 /* libPods-Runner.a in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXFrameworksBuildPhase section */ 74 | 75 | /* Begin PBXGroup section */ 76 | 88A470B8B7A3925519F6F036 /* Pods */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 667BD4FE8A8D661788A80155 /* Pods-Runner.debug.xcconfig */, 80 | 56471A27C261CF6FED6524B0 /* Pods-Runner.release.xcconfig */, 81 | 5F14B6C777AED01452242853 /* Pods-Runner.profile.xcconfig */, 82 | ); 83 | name = Pods; 84 | path = Pods; 85 | sourceTree = ""; 86 | }; 87 | 9740EEB11CF90186004384FC /* Flutter */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 3B80C3931E831B6300D905FE /* App.framework */, 91 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 92 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 93 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 94 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 95 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 96 | ); 97 | name = Flutter; 98 | sourceTree = ""; 99 | }; 100 | 97C146E51CF9000F007C117D = { 101 | isa = PBXGroup; 102 | children = ( 103 | 9740EEB11CF90186004384FC /* Flutter */, 104 | 97C146F01CF9000F007C117D /* Runner */, 105 | 97C146EF1CF9000F007C117D /* Products */, 106 | 88A470B8B7A3925519F6F036 /* Pods */, 107 | FCC3051F032383CB44A07473 /* Frameworks */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | 97C146EF1CF9000F007C117D /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 97C146EE1CF9000F007C117D /* Runner.app */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | 97C146F01CF9000F007C117D /* Runner */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 123 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 124 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 125 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 126 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 127 | 97C147021CF9000F007C117D /* Info.plist */, 128 | 97C146F11CF9000F007C117D /* Supporting Files */, 129 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 130 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 131 | ); 132 | path = Runner; 133 | sourceTree = ""; 134 | }; 135 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 97C146F21CF9000F007C117D /* main.m */, 139 | ); 140 | name = "Supporting Files"; 141 | sourceTree = ""; 142 | }; 143 | FCC3051F032383CB44A07473 /* Frameworks */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 47E0D2230599AD2825B27CAE /* libPods-Runner.a */, 147 | ); 148 | name = Frameworks; 149 | sourceTree = ""; 150 | }; 151 | /* End PBXGroup section */ 152 | 153 | /* Begin PBXNativeTarget section */ 154 | 97C146ED1CF9000F007C117D /* Runner */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 157 | buildPhases = ( 158 | A986F3D20165475E7D01B8E9 /* [CP] Check Pods Manifest.lock */, 159 | 9740EEB61CF901F6004384FC /* Run Script */, 160 | 97C146EA1CF9000F007C117D /* Sources */, 161 | 97C146EB1CF9000F007C117D /* Frameworks */, 162 | 97C146EC1CF9000F007C117D /* Resources */, 163 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 164 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 165 | 6219AAF187388DAC17AF011D /* [CP] Embed Pods Frameworks */, 166 | ); 167 | buildRules = ( 168 | ); 169 | dependencies = ( 170 | ); 171 | name = Runner; 172 | productName = Runner; 173 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 174 | productType = "com.apple.product-type.application"; 175 | }; 176 | /* End PBXNativeTarget section */ 177 | 178 | /* Begin PBXProject section */ 179 | 97C146E61CF9000F007C117D /* Project object */ = { 180 | isa = PBXProject; 181 | attributes = { 182 | LastUpgradeCheck = 1020; 183 | ORGANIZATIONNAME = ""; 184 | TargetAttributes = { 185 | 97C146ED1CF9000F007C117D = { 186 | CreatedOnToolsVersion = 7.3.1; 187 | }; 188 | }; 189 | }; 190 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 191 | compatibilityVersion = "Xcode 3.2"; 192 | developmentRegion = en; 193 | hasScannedForEncodings = 0; 194 | knownRegions = ( 195 | en, 196 | Base, 197 | ); 198 | mainGroup = 97C146E51CF9000F007C117D; 199 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 200 | projectDirPath = ""; 201 | projectRoot = ""; 202 | targets = ( 203 | 97C146ED1CF9000F007C117D /* Runner */, 204 | ); 205 | }; 206 | /* End PBXProject section */ 207 | 208 | /* Begin PBXResourcesBuildPhase section */ 209 | 97C146EC1CF9000F007C117D /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 214 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 215 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 216 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXResourcesBuildPhase section */ 221 | 222 | /* Begin PBXShellScriptBuildPhase section */ 223 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 224 | isa = PBXShellScriptBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | ); 228 | inputPaths = ( 229 | ); 230 | name = "Thin Binary"; 231 | outputPaths = ( 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | shellPath = /bin/sh; 235 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 236 | }; 237 | 6219AAF187388DAC17AF011D /* [CP] Embed Pods Frameworks */ = { 238 | isa = PBXShellScriptBuildPhase; 239 | buildActionMask = 2147483647; 240 | files = ( 241 | ); 242 | inputPaths = ( 243 | ); 244 | name = "[CP] Embed Pods Frameworks"; 245 | outputPaths = ( 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | shellPath = /bin/sh; 249 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 250 | showEnvVarsInLog = 0; 251 | }; 252 | 9740EEB61CF901F6004384FC /* Run Script */ = { 253 | isa = PBXShellScriptBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ); 257 | inputPaths = ( 258 | ); 259 | name = "Run Script"; 260 | outputPaths = ( 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | shellPath = /bin/sh; 264 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 265 | }; 266 | A986F3D20165475E7D01B8E9 /* [CP] Check Pods Manifest.lock */ = { 267 | isa = PBXShellScriptBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | ); 271 | inputFileListPaths = ( 272 | ); 273 | inputPaths = ( 274 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 275 | "${PODS_ROOT}/Manifest.lock", 276 | ); 277 | name = "[CP] Check Pods Manifest.lock"; 278 | outputFileListPaths = ( 279 | ); 280 | outputPaths = ( 281 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | shellPath = /bin/sh; 285 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 286 | showEnvVarsInLog = 0; 287 | }; 288 | /* End PBXShellScriptBuildPhase section */ 289 | 290 | /* Begin PBXSourcesBuildPhase section */ 291 | 97C146EA1CF9000F007C117D /* Sources */ = { 292 | isa = PBXSourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 296 | 97C146F31CF9000F007C117D /* main.m in Sources */, 297 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | }; 301 | /* End PBXSourcesBuildPhase section */ 302 | 303 | /* Begin PBXVariantGroup section */ 304 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 305 | isa = PBXVariantGroup; 306 | children = ( 307 | 97C146FB1CF9000F007C117D /* Base */, 308 | ); 309 | name = Main.storyboard; 310 | sourceTree = ""; 311 | }; 312 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 313 | isa = PBXVariantGroup; 314 | children = ( 315 | 97C147001CF9000F007C117D /* Base */, 316 | ); 317 | name = LaunchScreen.storyboard; 318 | sourceTree = ""; 319 | }; 320 | /* End PBXVariantGroup section */ 321 | 322 | /* Begin XCBuildConfiguration section */ 323 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 324 | isa = XCBuildConfiguration; 325 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 326 | buildSettings = { 327 | ALWAYS_SEARCH_USER_PATHS = NO; 328 | CLANG_ANALYZER_NONNULL = YES; 329 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 330 | CLANG_CXX_LIBRARY = "libc++"; 331 | CLANG_ENABLE_MODULES = YES; 332 | CLANG_ENABLE_OBJC_ARC = YES; 333 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 334 | CLANG_WARN_BOOL_CONVERSION = YES; 335 | CLANG_WARN_COMMA = YES; 336 | CLANG_WARN_CONSTANT_CONVERSION = YES; 337 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 338 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 339 | CLANG_WARN_EMPTY_BODY = YES; 340 | CLANG_WARN_ENUM_CONVERSION = YES; 341 | CLANG_WARN_INFINITE_RECURSION = YES; 342 | CLANG_WARN_INT_CONVERSION = YES; 343 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 344 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 345 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 347 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 348 | CLANG_WARN_STRICT_PROTOTYPES = YES; 349 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 350 | CLANG_WARN_UNREACHABLE_CODE = YES; 351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 352 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 353 | COPY_PHASE_STRIP = NO; 354 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 355 | ENABLE_NS_ASSERTIONS = NO; 356 | ENABLE_STRICT_OBJC_MSGSEND = YES; 357 | GCC_C_LANGUAGE_STANDARD = gnu99; 358 | GCC_NO_COMMON_BLOCKS = YES; 359 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 360 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 361 | GCC_WARN_UNDECLARED_SELECTOR = YES; 362 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 363 | GCC_WARN_UNUSED_FUNCTION = YES; 364 | GCC_WARN_UNUSED_VARIABLE = YES; 365 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 366 | MTL_ENABLE_DEBUG_INFO = NO; 367 | SDKROOT = iphoneos; 368 | SUPPORTED_PLATFORMS = iphoneos; 369 | TARGETED_DEVICE_FAMILY = "1,2"; 370 | VALIDATE_PRODUCT = YES; 371 | }; 372 | name = Profile; 373 | }; 374 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 375 | isa = XCBuildConfiguration; 376 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 377 | buildSettings = { 378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 379 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 380 | ENABLE_BITCODE = NO; 381 | FRAMEWORK_SEARCH_PATHS = ( 382 | "$(inherited)", 383 | "$(PROJECT_DIR)/Flutter", 384 | ); 385 | INFOPLIST_FILE = Runner/Info.plist; 386 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 387 | LIBRARY_SEARCH_PATHS = ( 388 | "$(inherited)", 389 | "$(PROJECT_DIR)/Flutter", 390 | ); 391 | PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterTiktok; 392 | PRODUCT_NAME = "$(TARGET_NAME)"; 393 | VERSIONING_SYSTEM = "apple-generic"; 394 | }; 395 | name = Profile; 396 | }; 397 | 97C147031CF9000F007C117D /* Debug */ = { 398 | isa = XCBuildConfiguration; 399 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 400 | buildSettings = { 401 | ALWAYS_SEARCH_USER_PATHS = NO; 402 | CLANG_ANALYZER_NONNULL = YES; 403 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 404 | CLANG_CXX_LIBRARY = "libc++"; 405 | CLANG_ENABLE_MODULES = YES; 406 | CLANG_ENABLE_OBJC_ARC = YES; 407 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 408 | CLANG_WARN_BOOL_CONVERSION = YES; 409 | CLANG_WARN_COMMA = YES; 410 | CLANG_WARN_CONSTANT_CONVERSION = YES; 411 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_EMPTY_BODY = YES; 414 | CLANG_WARN_ENUM_CONVERSION = YES; 415 | CLANG_WARN_INFINITE_RECURSION = YES; 416 | CLANG_WARN_INT_CONVERSION = YES; 417 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 418 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 419 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 420 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 421 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 422 | CLANG_WARN_STRICT_PROTOTYPES = YES; 423 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 424 | CLANG_WARN_UNREACHABLE_CODE = YES; 425 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 426 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 427 | COPY_PHASE_STRIP = NO; 428 | DEBUG_INFORMATION_FORMAT = dwarf; 429 | ENABLE_STRICT_OBJC_MSGSEND = YES; 430 | ENABLE_TESTABILITY = YES; 431 | GCC_C_LANGUAGE_STANDARD = gnu99; 432 | GCC_DYNAMIC_NO_PIC = NO; 433 | GCC_NO_COMMON_BLOCKS = YES; 434 | GCC_OPTIMIZATION_LEVEL = 0; 435 | GCC_PREPROCESSOR_DEFINITIONS = ( 436 | "DEBUG=1", 437 | "$(inherited)", 438 | ); 439 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 441 | GCC_WARN_UNDECLARED_SELECTOR = YES; 442 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 443 | GCC_WARN_UNUSED_FUNCTION = YES; 444 | GCC_WARN_UNUSED_VARIABLE = YES; 445 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 446 | MTL_ENABLE_DEBUG_INFO = YES; 447 | ONLY_ACTIVE_ARCH = YES; 448 | SDKROOT = iphoneos; 449 | TARGETED_DEVICE_FAMILY = "1,2"; 450 | }; 451 | name = Debug; 452 | }; 453 | 97C147041CF9000F007C117D /* Release */ = { 454 | isa = XCBuildConfiguration; 455 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 456 | buildSettings = { 457 | ALWAYS_SEARCH_USER_PATHS = NO; 458 | CLANG_ANALYZER_NONNULL = YES; 459 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 460 | CLANG_CXX_LIBRARY = "libc++"; 461 | CLANG_ENABLE_MODULES = YES; 462 | CLANG_ENABLE_OBJC_ARC = YES; 463 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 464 | CLANG_WARN_BOOL_CONVERSION = YES; 465 | CLANG_WARN_COMMA = YES; 466 | CLANG_WARN_CONSTANT_CONVERSION = YES; 467 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 468 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 469 | CLANG_WARN_EMPTY_BODY = YES; 470 | CLANG_WARN_ENUM_CONVERSION = YES; 471 | CLANG_WARN_INFINITE_RECURSION = YES; 472 | CLANG_WARN_INT_CONVERSION = YES; 473 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 474 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 475 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 476 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 477 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 478 | CLANG_WARN_STRICT_PROTOTYPES = YES; 479 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 480 | CLANG_WARN_UNREACHABLE_CODE = YES; 481 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 482 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 483 | COPY_PHASE_STRIP = NO; 484 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 485 | ENABLE_NS_ASSERTIONS = NO; 486 | ENABLE_STRICT_OBJC_MSGSEND = YES; 487 | GCC_C_LANGUAGE_STANDARD = gnu99; 488 | GCC_NO_COMMON_BLOCKS = YES; 489 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 490 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 491 | GCC_WARN_UNDECLARED_SELECTOR = YES; 492 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 493 | GCC_WARN_UNUSED_FUNCTION = YES; 494 | GCC_WARN_UNUSED_VARIABLE = YES; 495 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 496 | MTL_ENABLE_DEBUG_INFO = NO; 497 | SDKROOT = iphoneos; 498 | SUPPORTED_PLATFORMS = iphoneos; 499 | TARGETED_DEVICE_FAMILY = "1,2"; 500 | VALIDATE_PRODUCT = YES; 501 | }; 502 | name = Release; 503 | }; 504 | 97C147061CF9000F007C117D /* Debug */ = { 505 | isa = XCBuildConfiguration; 506 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 507 | buildSettings = { 508 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 509 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 510 | ENABLE_BITCODE = NO; 511 | FRAMEWORK_SEARCH_PATHS = ( 512 | "$(inherited)", 513 | "$(PROJECT_DIR)/Flutter", 514 | ); 515 | INFOPLIST_FILE = Runner/Info.plist; 516 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 517 | LIBRARY_SEARCH_PATHS = ( 518 | "$(inherited)", 519 | "$(PROJECT_DIR)/Flutter", 520 | ); 521 | PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterTiktok; 522 | PRODUCT_NAME = "$(TARGET_NAME)"; 523 | VERSIONING_SYSTEM = "apple-generic"; 524 | }; 525 | name = Debug; 526 | }; 527 | 97C147071CF9000F007C117D /* Release */ = { 528 | isa = XCBuildConfiguration; 529 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 530 | buildSettings = { 531 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 532 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 533 | ENABLE_BITCODE = NO; 534 | FRAMEWORK_SEARCH_PATHS = ( 535 | "$(inherited)", 536 | "$(PROJECT_DIR)/Flutter", 537 | ); 538 | INFOPLIST_FILE = Runner/Info.plist; 539 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 540 | LIBRARY_SEARCH_PATHS = ( 541 | "$(inherited)", 542 | "$(PROJECT_DIR)/Flutter", 543 | ); 544 | PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterTiktok; 545 | PRODUCT_NAME = "$(TARGET_NAME)"; 546 | VERSIONING_SYSTEM = "apple-generic"; 547 | }; 548 | name = Release; 549 | }; 550 | /* End XCBuildConfiguration section */ 551 | 552 | /* Begin XCConfigurationList section */ 553 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 554 | isa = XCConfigurationList; 555 | buildConfigurations = ( 556 | 97C147031CF9000F007C117D /* Debug */, 557 | 97C147041CF9000F007C117D /* Release */, 558 | 249021D3217E4FDB00AE95B9 /* Profile */, 559 | ); 560 | defaultConfigurationIsVisible = 0; 561 | defaultConfigurationName = Release; 562 | }; 563 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 564 | isa = XCConfigurationList; 565 | buildConfigurations = ( 566 | 97C147061CF9000F007C117D /* Debug */, 567 | 97C147071CF9000F007C117D /* Release */, 568 | 249021D4217E4FDB00AE95B9 /* Profile */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | /* End XCConfigurationList section */ 574 | }; 575 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 576 | } 577 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_tiktok 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /flutter_tiktok/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/demo/Layout/View/botton_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter_tiktok/service/screen_service.dart'; 3 | 4 | Widget getBottom() { 5 | return Align( 6 | alignment: Alignment.bottomCenter, 7 | child: Container( 8 | color: Color(0x33FFFFFF), 9 | height: 60, 10 | width: ScreenService.width, 11 | ), 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/demo/Layout/View/right_view.dart: -------------------------------------------------------------------------------- 1 | //右边的喜欢 评价 分享 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | Widget getLikesView() { 6 | return Align( 7 | alignment: Alignment.centerRight, 8 | child: Padding( 9 | padding: EdgeInsets.only(top: 200), 10 | child: Column( 11 | mainAxisAlignment: MainAxisAlignment.center, 12 | children: [ 13 | Padding( 14 | padding: EdgeInsets.only(bottom: 10, right: 10), 15 | child: Column( 16 | children: [ 17 | Image.asset( 18 | "assets/images/video_icon_praise.png", 19 | width: 40, 20 | height: 40, 21 | ), 22 | Text("66.6W", style: TextStyle(color: Colors.white)), 23 | ], 24 | ), 25 | ), 26 | Padding( 27 | padding: EdgeInsets.only(bottom: 10, right: 10), 28 | child: Column( 29 | children: [ 30 | Image.asset( 31 | "assets/images/video_msg_icon.png", 32 | width: 40, 33 | height: 40, 34 | ), 35 | Text("55.6W", style: TextStyle(color: Colors.white)), 36 | ], 37 | ), 38 | ), 39 | Padding( 40 | padding: EdgeInsets.only(bottom: 10, right: 10), 41 | child: Column( 42 | children: [ 43 | Image.asset( 44 | "assets/images/video_share_icon.png", 45 | width: 40, 46 | height: 40, 47 | ), 48 | Text("44.6W", style: TextStyle(color: Colors.white)), 49 | ], 50 | ), 51 | ), 52 | ], 53 | ), 54 | ), 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/demo/Layout/View/video_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_tiktok/demo/Layout/View/right_view.dart'; 5 | import 'package:flutter_tiktok/service/screen_service.dart'; 6 | 7 | class VideoController extends StatefulWidget { 8 | String image; 9 | VideoController({Key key, this.image}) : super(key: key); 10 | 11 | @override 12 | State createState() { 13 | return ViewControllerState(); 14 | } 15 | } 16 | 17 | class ViewControllerState extends State { 18 | ScrollController scroController = new ScrollController(); 19 | Timer timer; 20 | void startTimer() { 21 | int time = 3000; 22 | timer = Timer.periodic(new Duration(milliseconds: time), (timer) { 23 | if (scroController.positions.isNotEmpty == false) { 24 | print('界面被销毁'); 25 | return; 26 | } 27 | double maxScrollExtent = scroController.position.maxScrollExtent; 28 | // print(maxScrollExtent); 29 | // double pixels = scroController.position.pixels; 30 | if (maxScrollExtent > 0) { 31 | scroController.animateTo(maxScrollExtent, 32 | duration: new Duration(milliseconds: (time * 0.5).toInt()), 33 | curve: Curves.linear); 34 | Future.delayed(Duration(milliseconds: (time * 0.5).toInt()), () { 35 | if (scroController.positions.isNotEmpty == true) { 36 | scroController.animateTo(0, 37 | duration: new Duration(milliseconds: (time * 0.5).toInt()), 38 | curve: Curves.linear); 39 | } 40 | }); 41 | } else { 42 | print('不需要移动'); 43 | timer.cancel(); 44 | } 45 | }); 46 | } 47 | 48 | @override 49 | void initState() { 50 | super.initState(); 51 | this.startTimer(); 52 | } 53 | 54 | @override 55 | void dispose() { 56 | this.scroController.dispose(); 57 | this.timer.cancel(); 58 | super.dispose(); 59 | } 60 | 61 | @override 62 | Widget build(BuildContext context) { 63 | return getVideoViewMain(); 64 | } 65 | 66 | Widget getVideoViewMain() { 67 | return Stack( 68 | children: [ 69 | this.getVideo(), 70 | getLikesView(), 71 | this.getUserAndTitle() 72 | ], 73 | ); 74 | } 75 | 76 | // 视频播放(假的不是重点) 77 | Widget getVideo() { 78 | return Container( 79 | color: Colors.black, 80 | child: Center( 81 | child: Image.asset(widget.image), 82 | ), 83 | ); 84 | } 85 | 86 | Widget getMusicTitle() { 87 | return Container( 88 | // color: Colors.red, 89 | // alignment: Alignment.centerLeft, 90 | child: Text( 91 | "三根皮带歌曲,哗啦啦啦啦啦啦啦啦啦啦啦", 92 | maxLines: 1, 93 | style: TextStyle( 94 | color: Colors.white, 95 | ), 96 | textAlign: TextAlign.left, 97 | ), 98 | ); 99 | } 100 | 101 | Widget getUserAndTitle() { 102 | return Positioned( 103 | bottom: 60, 104 | child: Padding( 105 | padding: EdgeInsets.only(left: 5, bottom: 5), 106 | child: Column( 107 | crossAxisAlignment: CrossAxisAlignment.start, 108 | children: [ 109 | Padding( 110 | padding: EdgeInsets.only(bottom: 5), 111 | child: Text( 112 | "@MarcoChen", 113 | style: TextStyle(color: Colors.white), 114 | ), 115 | ), 116 | Container( 117 | padding: EdgeInsets.only(bottom: 5), 118 | width: 250, 119 | child: Text("外星人来了,你们走不走,996做个毛赶紧辞职吧", 120 | style: TextStyle( 121 | color: Colors.white, 122 | )), 123 | ), 124 | Container( 125 | // color: Colors.red, 126 | // alignment: Alignment.centerLeft, 127 | padding: EdgeInsets.only(bottom: 5), 128 | width: 200, 129 | height: 25, 130 | child: ListView( 131 | // reverse: true, 132 | controller: scroController, 133 | physics: new NeverScrollableScrollPhysics(), 134 | scrollDirection: Axis.horizontal, 135 | children: [this.getMusicTitle()], 136 | ), 137 | ) 138 | ], 139 | ), 140 | ), 141 | ); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/demo/Layout/layout_view_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_tiktok/demo/Layout/View/botton_view.dart'; 6 | import 'package:flutter_tiktok/demo/Layout/View/right_view.dart'; 7 | import 'package:flutter_tiktok/demo/Layout/View/video_controller.dart'; 8 | import 'dart:ui' as ui show window; 9 | 10 | import 'package:flutter_tiktok/service/screen_service.dart'; 11 | 12 | class LayoutViewController extends StatefulWidget { 13 | @override 14 | State createState() { 15 | return LayoutViewControllerState(); 16 | } 17 | } 18 | 19 | class LayoutViewControllerState extends State 20 | with TickerProviderStateMixin { 21 | // ScrollController scroController = new ScrollController(); 22 | // Timer timer; 23 | List images = ["assets/images/vides.png", "assets/images/vides2.png"]; 24 | StreamController stream = new StreamController.broadcast(); 25 | PageController pageController = new PageController(keepPage: false); 26 | double flage = 0; 27 | @override 28 | void initState() { 29 | super.initState(); 30 | pageController.addListener(() { 31 | // print(pageController.page); 32 | if (pageController.page == 1) { 33 | this.stream.sink.add(1); 34 | } else if (pageController.page == 0) { 35 | this.stream.sink.add(0); 36 | } 37 | }); 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return WillPopScope( 43 | onWillPop: () { 44 | return new Future.value(false); 45 | }, 46 | child: Scaffold( 47 | backgroundColor: Colors.black, 48 | body: this.getMain(), 49 | ), 50 | ); 51 | } 52 | 53 | Widget getMain() { 54 | return Stack( 55 | children: [ 56 | this.getScrollView(), 57 | this.getTitleSwitch(), 58 | getBottom(), 59 | ], 60 | ); 61 | } 62 | 63 | // 滑动 64 | Widget getScrollView() { 65 | return Container( 66 | child: PageView.builder( 67 | controller: pageController, 68 | itemCount: images.length, 69 | reverse: true, 70 | // physics: PageScrollPhysics(), 71 | itemBuilder: (BuildContext context, int index) { 72 | return VideoController( 73 | image: this.images[index], 74 | ); 75 | }, 76 | scrollDirection: Axis.horizontal, 77 | ), 78 | ); 79 | } 80 | 81 | // title switch 82 | Widget getTitleSwitch() { 83 | return Positioned( 84 | top: 50, 85 | width: ScreenService.width, 86 | child: Column( 87 | children: [ 88 | Row( 89 | mainAxisAlignment: MainAxisAlignment.center, 90 | children: [ 91 | GestureDetector( 92 | behavior: HitTestBehavior.translucent, 93 | onTap: () { 94 | print('object -- 1'); 95 | this.stream.sink.add(1); 96 | pageController.jumpToPage(1); 97 | }, 98 | child: StreamBuilder( 99 | initialData: 0, 100 | builder: (context, snapshot) { 101 | return Text( 102 | "关注", 103 | style: TextStyle( 104 | color: Colors.white, 105 | decoration: snapshot.data == 1 106 | ? TextDecoration.underline 107 | : TextDecoration.none, 108 | ), 109 | ); 110 | }, 111 | stream: this.stream.stream, 112 | ), 113 | ), 114 | Container( 115 | width: 30, 116 | ), 117 | GestureDetector( 118 | behavior: HitTestBehavior.translucent, 119 | onTap: () { 120 | this.stream.sink.add(0); 121 | pageController.jumpToPage(0); 122 | }, 123 | child: StreamBuilder( 124 | initialData: 0, 125 | builder: (context, snapshot) { 126 | return Text( 127 | "推荐", 128 | style: TextStyle( 129 | color: Colors.white, 130 | decoration: snapshot.data == 0 131 | ? TextDecoration.underline 132 | : TextDecoration.none, 133 | ), 134 | ); 135 | }, 136 | stream: this.stream.stream, 137 | ), 138 | ) 139 | ], 140 | ), 141 | ], 142 | ), 143 | ); 144 | } 145 | 146 | @override 147 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { 148 | super.debugFillProperties(properties); 149 | properties 150 | .add(DiagnosticsProperty>('stream', stream)); 151 | } 152 | //---- 153 | } 154 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/demo/Video/video_play_view_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_tiktok/demo/Layout/View/right_view.dart'; 6 | import 'package:flutter_tiktok/service/event_bus_service.dart'; 7 | import 'package:flutter_tiktok/service/screen_service.dart'; 8 | import 'package:video_player/video_player.dart'; 9 | 10 | class VideoController extends StatefulWidget { 11 | String image; 12 | final int positionTag; 13 | String video; 14 | 15 | VideoController({Key key, this.image, this.positionTag, this.video}) 16 | : super(key: key); 17 | 18 | @override 19 | State createState() { 20 | return ViewControllerState(); 21 | } 22 | } 23 | 24 | class ViewControllerState extends State { 25 | ScrollController scroController = new ScrollController(); 26 | Timer timer; 27 | bool videoPrepared = false; //视频是否初始化 28 | bool _hideActionButton = true; 29 | VideoPlayerController _controller; 30 | 31 | static double h = Platform.isAndroid 32 | ? (16 / 9 * ScreenService.width - ScreenService.topSafeHeight <= 33 | ScreenService.height 34 | ? 16 / 9 * ScreenService.width - ScreenService.topSafeHeight 35 | : ScreenService.height) 36 | : (16 / 9 * ScreenService.width <= ScreenService.height 37 | ? 16 / 9 * ScreenService.width 38 | : ScreenService.height); 39 | void startTimer() { 40 | int time = 3000; 41 | timer = Timer.periodic(new Duration(milliseconds: time), (timer) { 42 | if (scroController.positions.isNotEmpty == false) { 43 | print('界面被销毁'); 44 | return; 45 | } 46 | double maxScrollExtent = scroController.position.maxScrollExtent; 47 | // print(maxScrollExtent); 48 | // double pixels = scroController.position.pixels; 49 | if (maxScrollExtent > 0) { 50 | scroController.animateTo(maxScrollExtent, 51 | duration: new Duration(milliseconds: (time * 0.5).toInt()), 52 | curve: Curves.linear); 53 | Future.delayed(Duration(milliseconds: (time * 0.5).toInt()), () { 54 | if (scroController.positions.isNotEmpty == true) { 55 | scroController.animateTo(0, 56 | duration: new Duration(milliseconds: (time * 0.5).toInt()), 57 | curve: Curves.linear); 58 | } 59 | }); 60 | } else { 61 | print('不需要移动'); 62 | timer.cancel(); 63 | } 64 | }); 65 | } 66 | 67 | @override 68 | void initState() { 69 | super.initState(); 70 | this.startTimer(); 71 | _controller = VideoPlayerController.asset(widget.video) 72 | ..initialize().then((_) {}) 73 | ..setLooping(true).then((_) { 74 | if (widget.positionTag == 0) { 75 | _controller.play(); 76 | videoPrepared = true; 77 | } else { 78 | videoPrepared = false; 79 | } 80 | setState(() {}); 81 | }); 82 | 83 | eventBus.on(keyPlayVideo + widget.positionTag.toString(), (arg) { 84 | if (arg == widget.positionTag) { 85 | _controller.play(); 86 | videoPrepared = true; 87 | _hideActionButton = true; 88 | } else { 89 | _controller.pause(); 90 | _hideActionButton = false; 91 | } 92 | setState(() {}); 93 | }); 94 | } 95 | 96 | @override 97 | void dispose() { 98 | this.scroController.dispose(); 99 | this.timer.cancel(); 100 | _controller.dispose(); //释放播放器资源 101 | 102 | super.dispose(); 103 | } 104 | 105 | @override 106 | Widget build(BuildContext context) { 107 | print("object_build"); 108 | return getVideoViewMain(); 109 | } 110 | 111 | Widget getVideoViewMain() { 112 | return Stack( 113 | children: [ 114 | GestureDetector( 115 | child: Stack( 116 | children: [ 117 | Container( 118 | margin: EdgeInsets.only(top: ScreenService.topSafeHeight), 119 | width: ScreenService.width, 120 | height: h, //h/w = sh/sw 121 | child: VideoPlayer(_controller), 122 | ), 123 | getPauseView() 124 | ], 125 | ), 126 | onTap: () { 127 | if (_controller.value.isPlaying) { 128 | _controller.pause(); 129 | _hideActionButton = false; 130 | } else { 131 | _controller.play(); 132 | videoPrepared = true; 133 | _hideActionButton = true; 134 | } 135 | setState(() {}); 136 | }), 137 | // this.getVideo(), 138 | getPreviewImg(), 139 | getLikesView(), 140 | this.getUserAndTitle() 141 | ], 142 | ); 143 | } 144 | 145 | getPauseView() { 146 | return Offstage( 147 | offstage: _hideActionButton, 148 | child: Stack( 149 | children: [ 150 | Align( 151 | child: Container( 152 | child: Image.asset('assets/images/ic_playing.png'), 153 | height: 50, 154 | width: 50), 155 | alignment: Alignment.center, 156 | ) 157 | ], 158 | ), 159 | ); 160 | } 161 | 162 | Widget getPreviewImg() { 163 | // var url; 164 | // HttpController.host.then((onValue) { 165 | // url = onValue + widget.previewImgUrl; 166 | // }); 167 | return Offstage( 168 | offstage: videoPrepared, 169 | child: Container( 170 | color: Colors.black, 171 | margin: EdgeInsets.only(top: ScreenService.topSafeHeight), 172 | child: Image.asset( 173 | widget.image, 174 | // getUrl(widget.previewImgUrl), 175 | fit: BoxFit.fill, 176 | width: ScreenService.width, 177 | height: ScreenService.height, 178 | ), 179 | )); 180 | } 181 | 182 | Widget getMusicTitle() { 183 | return Container( 184 | // color: Colors.red, 185 | // alignment: Alignment.centerLeft, 186 | child: Text( 187 | "三根皮带歌曲,哗啦啦啦啦啦啦啦啦啦啦啦", 188 | maxLines: 1, 189 | style: TextStyle( 190 | color: Colors.white, 191 | ), 192 | textAlign: TextAlign.left, 193 | ), 194 | ); 195 | } 196 | 197 | Widget getUserAndTitle() { 198 | return Positioned( 199 | bottom: 60, 200 | child: Padding( 201 | padding: EdgeInsets.only(left: 5, bottom: 5), 202 | child: Column( 203 | crossAxisAlignment: CrossAxisAlignment.start, 204 | children: [ 205 | Padding( 206 | padding: EdgeInsets.only(bottom: 5), 207 | child: Text( 208 | "@MarcoChen", 209 | style: TextStyle(color: Colors.white), 210 | ), 211 | ), 212 | Container( 213 | padding: EdgeInsets.only(bottom: 5), 214 | width: 250, 215 | child: Text("外星人来了,你们走不走,996做个毛赶紧辞职吧", 216 | style: TextStyle( 217 | color: Colors.white, 218 | )), 219 | ), 220 | Container( 221 | // color: Colors.red, 222 | // alignment: Alignment.centerLeft, 223 | padding: EdgeInsets.only(bottom: 5), 224 | width: 200, 225 | height: 25, 226 | child: ListView( 227 | // reverse: true, 228 | controller: scroController, 229 | physics: new NeverScrollableScrollPhysics(), 230 | scrollDirection: Axis.horizontal, 231 | children: [this.getMusicTitle()], 232 | ), 233 | ) 234 | ], 235 | ), 236 | ), 237 | ); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/demo/Video/video_view_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flukit/flukit.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_tiktok/demo/Video/video_play_view_controller.dart'; 4 | import 'package:flutter_tiktok/service/event_bus_service.dart'; 5 | 6 | class VideoViewController extends StatefulWidget { 7 | @override 8 | State createState() { 9 | // TODO: implement createState 10 | return VideoViewControllerState(); 11 | } 12 | } 13 | 14 | class VideoViewControllerState extends State { 15 | SwiperController _controller = SwiperController(); 16 | List images = ["assets/images/v1.png", "assets/images/v2.png"]; 17 | List videos = ["assets/videos/1.MP4", "assets/videos/2.mp4"]; 18 | 19 | @override 20 | void initState() { 21 | // TODO: implement initState 22 | super.initState(); 23 | _controller.addListener(() { 24 | if (_controller.page.floor() == _controller.page) { 25 | eventBus.emit(keyPlayVideo + _controller.page.floor().toString(), 26 | _controller.page.floor()); 27 | } 28 | }); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | List children = []; 34 | int index = 0; 35 | for (String item in this.images) { 36 | children.add(VideoController( 37 | image: item, positionTag: index, video: videos[index])); 38 | index++; 39 | } 40 | 41 | return Scaffold( 42 | // appBar: AppBar( 43 | // title: Text("video controller"), 44 | // ), 45 | body: Container( 46 | child: Swiper( 47 | autoStart: false, 48 | circular: false, 49 | direction: Axis.vertical, 50 | children: children, 51 | controller: _controller, 52 | ), 53 | color: Colors.black, 54 | ), 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/demo/like_view_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'dart:math' as math; 3 | 4 | class MathPoint { 5 | MathPoint(this.x, this.y); 6 | distanceTo(other) { 7 | var dx = x - other.x; 8 | var dy = y - other.y; 9 | return math.sqrt(dx * dx + dy * dy); 10 | } 11 | 12 | var x, y; 13 | } 14 | 15 | class LikeViewController extends StatefulWidget { 16 | @override 17 | State createState() { 18 | return LikeViewControllerState(); 19 | } 20 | } 21 | 22 | class LikeViewControllerState extends State { 23 | // 记录时间 24 | var touchTime = new DateTime.now(); 25 | // 记录坐标 26 | var touchPoint = new MathPoint(-999, -999); 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar( 31 | title: Text("like pop demo"), 32 | ), 33 | body: GestureDetector( 34 | onTapUp: (TapUpDetails details) { 35 | // 当前时间-上次记录的时间 36 | var t = new DateTime.now().millisecondsSinceEpoch - 37 | this.touchTime.millisecondsSinceEpoch; 38 | // 获取当前坐标 39 | var currentPoint = 40 | new MathPoint(details.localPosition.dx, details.localPosition.dy); 41 | //计算两次距离 42 | var distance = currentPoint.distanceTo(this.touchPoint); 43 | // 记录当前时间 44 | this.touchTime = new DateTime.now(); 45 | // 记录当前坐标 46 | this.touchPoint = currentPoint; 47 | // 判断两次间隔是否小于300毫秒 48 | if (t < 300 && distance < 20) { 49 | this.touchTime = new DateTime.fromMicrosecondsSinceEpoch(0); 50 | // print(details.localPosition.dx); 51 | // print(details.localPosition.dy); 52 | this.showLike(details.localPosition.dx, details.localPosition.dy); 53 | } 54 | }, 55 | behavior: HitTestBehavior.translucent, 56 | child: Center( 57 | child: Column( 58 | mainAxisAlignment: MainAxisAlignment.center, 59 | children: [ 60 | Image.asset( 61 | 'assets/images/love.jpeg', 62 | width: 100, 63 | height: 100, 64 | ), 65 | Text("double click") 66 | ], 67 | ), 68 | ), 69 | ), 70 | ); 71 | } 72 | 73 | void showLike(double dx, double dy) { 74 | var overlayState = Overlay.of(context); 75 | OverlayEntry overlayEntry; 76 | double width = 50; 77 | double height = 50; 78 | double x = dx - width / 2; 79 | double y = dy + height / 2; 80 | 81 | overlayEntry = new OverlayEntry(builder: (context) { 82 | return Stack( 83 | children: [ 84 | new Positioned( 85 | left: x, 86 | top: y, 87 | child: new LikeView( 88 | overlayEntry: overlayEntry, 89 | ), 90 | ), 91 | ], 92 | ); 93 | }); 94 | 95 | ///插入全局悬浮控件 96 | overlayState.insert(overlayEntry); 97 | } 98 | } 99 | 100 | class LikeView extends StatefulWidget { 101 | LikeView({Key key, this.overlayEntry}); 102 | OverlayEntry overlayEntry; 103 | @override 104 | State createState() { 105 | return LikeViewState(); 106 | } 107 | } 108 | 109 | class LikeViewState extends State with TickerProviderStateMixin { 110 | int step = 0; 111 | double width = 50; 112 | double height = 50; 113 | AnimationController controller; 114 | Animation upLocation; 115 | 116 | Animation display; 117 | Animation scaleAnimate; 118 | Animation scaleAnimate2; 119 | 120 | @override 121 | void initState() { 122 | super.initState(); 123 | controller = new AnimationController( 124 | duration: const Duration(milliseconds: 1000), vsync: this) 125 | ..addStatusListener((status) { 126 | if (status == AnimationStatus.completed) { 127 | print("status is completed"); 128 | if (this.step == 0) { 129 | this.step = 1; 130 | controller.reset(); 131 | this.setState(() {}); 132 | } else if (this.step == 1) { 133 | widget.overlayEntry.remove(); 134 | } 135 | } 136 | }); 137 | scaleAnimate = Tween( 138 | begin: 1.5, 139 | end: 1, 140 | ).animate( 141 | CurvedAnimation( 142 | parent: controller, 143 | curve: Interval( 144 | 0, 145 | 1.0, 146 | curve: Curves.ease, 147 | ), 148 | ), 149 | ); 150 | // 向上移动 151 | upLocation = Tween( 152 | begin: EdgeInsets.only(top: 20.0), 153 | end: EdgeInsets.only(top: 0.0), 154 | ).animate( 155 | CurvedAnimation( 156 | parent: controller, 157 | curve: Interval( 158 | 0, 159 | 1.0, 160 | curve: Curves.ease, 161 | ), 162 | ), 163 | ); 164 | // 动画二组 165 | // 消失动画 166 | display = Tween( 167 | begin: 1, 168 | end: 0, 169 | ).animate( 170 | CurvedAnimation( 171 | parent: controller, 172 | curve: Interval( 173 | 0, 174 | 1.0, 175 | curve: Curves.ease, 176 | ), 177 | ), 178 | ); 179 | //放大 180 | scaleAnimate2 = Tween( 181 | begin: 1, 182 | end: 1.5, 183 | ).animate( 184 | CurvedAnimation( 185 | parent: controller, 186 | curve: Interval( 187 | 0, 188 | 1.0, 189 | curve: Curves.ease, 190 | ), 191 | ), 192 | ); 193 | } 194 | 195 | @override 196 | Widget build(BuildContext context) { 197 | controller.forward(); 198 | if (this.step == 0) { 199 | return AnimatedBuilder( 200 | builder: (BuildContext context, Widget child) { 201 | return Transform.scale( 202 | child: Padding( 203 | padding: upLocation.value, 204 | child: Image.asset( 205 | 'assets/images/love.jpeg', 206 | fit: BoxFit.fill, 207 | width: width, 208 | height: height, 209 | ), 210 | ), 211 | scale: scaleAnimate.value, 212 | ); 213 | }, 214 | animation: controller, 215 | ); 216 | } else if (this.step == 1) { 217 | return AnimatedBuilder( 218 | builder: (BuildContext context, Widget child) { 219 | return Transform.scale( 220 | child: Opacity( 221 | opacity: display.value, 222 | child: Image.asset( 223 | 'assets/images/love.jpeg', 224 | fit: BoxFit.fill, 225 | width: width, 226 | height: height, 227 | ), 228 | ), 229 | scale: scaleAnimate2.value, 230 | ); 231 | }, 232 | animation: controller, 233 | ); 234 | } 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_tiktok/demo/Video/video_view_controller.dart'; 3 | import 'package:flutter_tiktok/service/navigation_service.dart'; 4 | 5 | import 'demo/Layout/layout_view_controller.dart'; 6 | import 'demo/like_view_controller.dart'; 7 | 8 | void main() => runApp(MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | // This widget is the root of your application. 12 | @override 13 | Widget build(BuildContext context) { 14 | return MaterialApp( 15 | navigatorKey: navigationService.navigatorKey, 16 | title: 'Flutter Tik Tok', 17 | theme: ThemeData( 18 | primarySwatch: Colors.blue, 19 | ), 20 | home: MyHomePage(title: 'Flutter Tik Tok Demo'), 21 | ); 22 | } 23 | } 24 | 25 | class MyHomePage extends StatefulWidget { 26 | MyHomePage({Key key, this.title}) : super(key: key); 27 | final String title; 28 | @override 29 | _MyHomePageState createState() => _MyHomePageState(); 30 | } 31 | 32 | class _MyHomePageState extends State { 33 | @override 34 | Widget build(BuildContext context) { 35 | return Scaffold( 36 | appBar: AppBar( 37 | title: Text(widget.title), 38 | ), 39 | body: ListView( 40 | children: ListTile.divideTiles(context: context, tiles: [ 41 | ListTile( 42 | title: Text("like pop demo"), 43 | onTap: () { 44 | navigationService.cNavigateTo(new LikeViewController()); 45 | }, 46 | ), 47 | ListTile( 48 | title: Text("layout view demo"), 49 | onTap: () { 50 | navigationService.cNavigateTo(new LayoutViewController()); 51 | }, 52 | ), 53 | ListTile( 54 | title: Text("video view demo"), 55 | onTap: () { 56 | navigationService.cNavigateTo(new VideoViewController()); 57 | }, 58 | ), 59 | ]).toList()), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/service/event_bus_service.dart: -------------------------------------------------------------------------------- 1 | typedef void EventCallback(arg); 2 | 3 | class EventBusService { 4 | EventBusService._internal(); 5 | static EventBusService _singleton = EventBusService._internal(); 6 | factory EventBusService() => _singleton; 7 | var _emap = Map>(); 8 | 9 | //添加订阅者 10 | void on(eventName, EventCallback f) { 11 | if (eventName == null || f == null) return; 12 | _emap[eventName] ??= List(); 13 | _emap[eventName].add(f); 14 | } 15 | 16 | //移除订阅者 17 | void off(eventName, [EventCallback f]) { 18 | var list = _emap[eventName]; 19 | if (eventName == null || list == null) return; 20 | if (f == null) { 21 | _emap[eventName] = null; 22 | } else { 23 | list.remove(f); 24 | } 25 | } 26 | 27 | //触发事件,事件触发后该事件所有订阅者会被调用 28 | void emit(eventName, [arg]) { 29 | var list = _emap[eventName]; 30 | if (list == null) return; 31 | int len = list.length - 1; 32 | for (var i = len; i > -1; --i) { 33 | list[i](arg); 34 | } 35 | } 36 | 37 | // static const keyStopVideo = "keyStopVideo"; 38 | } 39 | 40 | var eventBus = EventBusService(); 41 | 42 | const String keyStopVideo = "keyStopVideo"; 43 | const String keyPlayVideo = "keyPlayVideo"; 44 | const String keyLoginState = "keyLoginState"; 45 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/service/navigation_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | NavigationService navigationService = NavigationService(); 4 | 5 | class NavigationService { 6 | NavigationService() { 7 | navigatorKey = GlobalKey(); 8 | } 9 | GlobalKey navigatorKey; 10 | 11 | Future navigateTo(Route route) { 12 | return navigatorKey.currentState.push(route); 13 | } 14 | 15 | bool goBack() { 16 | return navigatorKey.currentState.pop(); 17 | } 18 | 19 | Future cNavigateTo(Widget controller) { 20 | return navigationService.navigateTo(CupertinoPageRoute( 21 | builder: (context) => controller, 22 | )); 23 | } 24 | // Navigator.of(context).push(new CupertinoPageRoute(builder: (ctx) => new SHController())); 25 | } 26 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/service/screen_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'dart:ui' as ui show window; 4 | 5 | class ScreenService { 6 | static double get width { 7 | MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); 8 | return mediaQuery.size.width; 9 | } 10 | 11 | static double get height { 12 | MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); 13 | return mediaQuery.size.height; 14 | } 15 | 16 | static double get scale { 17 | MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); 18 | return mediaQuery.devicePixelRatio; 19 | } 20 | 21 | static double get textScaleFactor { 22 | MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); 23 | return mediaQuery.textScaleFactor; 24 | } 25 | 26 | static double get navigationBarHeight { 27 | MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); 28 | return mediaQuery.padding.top + kToolbarHeight; 29 | } 30 | 31 | static double get topSafeHeight { 32 | MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); 33 | return mediaQuery.padding.top; 34 | } 35 | 36 | static double get bottomSafeHeight { 37 | MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); 38 | return mediaQuery.padding.bottom; 39 | } 40 | 41 | static updateStatusBarStyle(SystemUiOverlayStyle style) { 42 | SystemChrome.setSystemUIOverlayStyle(style); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /flutter_tiktok/lib/service/widget_ext_service.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/gestures.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// extension to make it is possible to use function calling instead of Widget Constructor 5 | /// 6 | /// For example: 7 | /// Container( 8 | /// color: Colors.white, 9 | /// Offstage( 10 | /// offstage: false, 11 | /// child: Text('hello'), 12 | /// ), 13 | /// ); 14 | /// now it is also can looks like this: 15 | /// Text('hello') 16 | /// .intoOffstage(offstage: false) 17 | /// .intoContainer(color: Colors.white); 18 | /// 19 | /// 20 | extension WidgetChantExt_Widget on Widget { 21 | List addNeighbor(Widget widget) { 22 | return [this, widget]; 23 | } 24 | 25 | List asList() { 26 | return [this]; 27 | } 28 | 29 | Align intoAlign({ 30 | Key key, 31 | Alignment alignment = Alignment.center, 32 | double widthFactor, 33 | double heightFactor, 34 | }) { 35 | return Align( 36 | key: key, 37 | alignment: alignment, 38 | widthFactor: widthFactor, 39 | heightFactor: heightFactor, 40 | child: this, 41 | ); 42 | } 43 | 44 | ClipRRect intoClipRRect({ 45 | Key key, 46 | BorderRadius borderRadius = BorderRadius.zero, 47 | CustomClipper clipper, 48 | Clip clipBehavior = Clip.antiAlias, 49 | }) { 50 | return ClipRRect( 51 | key: key, 52 | borderRadius: borderRadius, 53 | clipper: clipper, 54 | clipBehavior: clipBehavior, 55 | child: this, 56 | ); 57 | } 58 | 59 | ClipOval intoClipOval({ 60 | Key key, 61 | BorderRadius borderRadius = BorderRadius.zero, 62 | CustomClipper clipper, 63 | Clip clipBehavior = Clip.antiAlias, 64 | }) { 65 | return ClipOval( 66 | key: key, 67 | clipper: clipper, 68 | clipBehavior: clipBehavior, 69 | child: this, 70 | ); 71 | } 72 | 73 | ClipPath intoClipPath({ 74 | Key key, 75 | BorderRadius borderRadius = BorderRadius.zero, 76 | CustomClipper clipper, 77 | Clip clipBehavior = Clip.antiAlias, 78 | }) { 79 | return ClipPath( 80 | key: key, 81 | clipper: clipper, 82 | clipBehavior: clipBehavior, 83 | child: this, 84 | ); 85 | } 86 | 87 | Offstage intoOffstage({ 88 | Key key, 89 | bool offstage = true, 90 | }) { 91 | return Offstage( 92 | key: key, 93 | offstage: offstage, 94 | child: this, 95 | ); 96 | } 97 | 98 | Padding intoPadding({ 99 | Key key, 100 | EdgeInsetsGeometry padding, 101 | }) { 102 | return Padding( 103 | key: key, 104 | padding: padding, 105 | child: this, 106 | ); 107 | } 108 | 109 | Positioned intoPositioned({ 110 | Key key, 111 | double left, 112 | double top, 113 | double right, 114 | double bottom, 115 | double width, 116 | double height, 117 | }) { 118 | return Positioned( 119 | key: key, 120 | left: left, 121 | top: top, 122 | right: right, 123 | bottom: bottom, 124 | width: width, 125 | height: height, 126 | child: this, 127 | ); 128 | } 129 | 130 | Center intoCenter({ 131 | Key key, 132 | double widthFactor, 133 | double heightFactor, 134 | }) { 135 | return Center( 136 | key: key, 137 | widthFactor: widthFactor, 138 | heightFactor: heightFactor, 139 | child: this, 140 | ); 141 | } 142 | 143 | Expanded intoExpanded({ 144 | Key key, 145 | int flex = 1, 146 | }) { 147 | return Expanded( 148 | key: key, 149 | flex: flex, 150 | child: this, 151 | ); 152 | } 153 | 154 | Flexible intoFlexible({ 155 | Key key, 156 | int flex = 1, 157 | FlexFit fit = FlexFit.loose, 158 | }) { 159 | return Flexible( 160 | key: key, 161 | flex: flex, 162 | fit: fit, 163 | child: this, 164 | ); 165 | } 166 | 167 | SizedBox intoSizedBox({ 168 | Key key, 169 | double width, 170 | double height, 171 | }) { 172 | return SizedBox( 173 | key: key, 174 | width: width, 175 | height: height, 176 | child: this, 177 | ); 178 | } 179 | 180 | LimitedBox intoLimitedBox({ 181 | Key key, 182 | double maxWidth = double.infinity, 183 | double maxHeight = double.infinity, 184 | }) { 185 | return LimitedBox( 186 | key: key, 187 | maxWidth: maxWidth, 188 | maxHeight: maxHeight, 189 | child: this, 190 | ); 191 | } 192 | 193 | OverflowBox intoOverflowBox({ 194 | Key key, 195 | Alignment alignment = Alignment.center, 196 | double minWidth, 197 | double maxWidth, 198 | double minHeight, 199 | double maxHeight, 200 | }) { 201 | return OverflowBox( 202 | key: key, 203 | alignment: alignment, 204 | minWidth: minWidth, 205 | minHeight: minHeight, 206 | maxWidth: maxWidth, 207 | maxHeight: maxHeight, 208 | child: this, 209 | ); 210 | } 211 | 212 | SizedOverflowBox intoSizedOverflowBox({ 213 | Key key, 214 | @required Size size, 215 | Alignment alignment = Alignment.center, 216 | }) { 217 | return SizedOverflowBox( 218 | key: key, 219 | size: size, 220 | alignment: alignment, 221 | child: this, 222 | ); 223 | } 224 | 225 | FittedBox intoFittedBox({ 226 | Key key, 227 | BoxFit fit = BoxFit.contain, 228 | AlignmentGeometry alignment = Alignment.center, 229 | }) { 230 | return FittedBox( 231 | key: key, 232 | fit: fit, 233 | alignment: alignment, 234 | child: this, 235 | ); 236 | } 237 | 238 | DecoratedBox intoDecoratedBox({ 239 | Key key, 240 | @required Decoration decoration, 241 | DecorationPosition position = DecorationPosition.background, 242 | }) { 243 | return DecoratedBox( 244 | key: key, 245 | decoration: decoration, 246 | position: position, 247 | child: this, 248 | ); 249 | } 250 | 251 | RotatedBox intoRotatedBox({ 252 | Key key, 253 | @required int quarterTurns, 254 | }) { 255 | return RotatedBox( 256 | key: key, 257 | quarterTurns: quarterTurns, 258 | child: this, 259 | ); 260 | } 261 | 262 | ConstrainedBox intoConstrainedBox({ 263 | Key key, 264 | @required BoxConstraints constraints, 265 | }) { 266 | return ConstrainedBox( 267 | key: key, 268 | constraints: constraints, 269 | child: this, 270 | ); 271 | } 272 | 273 | UnconstrainedBox intoUnconstrainedBox({ 274 | Key key, 275 | TextDirection textDirection, 276 | Alignment alignment = Alignment.center, 277 | Axis constrainedAxis, 278 | }) { 279 | return UnconstrainedBox( 280 | key: key, 281 | textDirection: textDirection, 282 | alignment: alignment, 283 | constrainedAxis: constrainedAxis, 284 | child: this, 285 | ); 286 | } 287 | 288 | AnimatedAlign intoAnimatedAlign({ 289 | Key key, 290 | Alignment alignment = Alignment.center, 291 | Curve curve = Curves.linear, 292 | @required Duration duration, 293 | VoidCallback onEnd, 294 | }) { 295 | return AnimatedAlign( 296 | key: key, 297 | alignment: alignment, 298 | curve: curve, 299 | duration: duration, 300 | onEnd: onEnd, 301 | child: this, 302 | ); 303 | } 304 | 305 | AnimatedPadding intoAnimatedPadding({ 306 | Key key, 307 | @required EdgeInsetsGeometry padding, 308 | Curve curve = Curves.linear, 309 | @required Duration duration, 310 | VoidCallback onEnd, 311 | }) { 312 | return AnimatedPadding( 313 | key: key, 314 | padding: padding, 315 | curve: curve, 316 | duration: duration, 317 | onEnd: onEnd, 318 | child: this, 319 | ); 320 | } 321 | 322 | AnimatedContainer intoAnimatedContainer({ 323 | Key key, 324 | Alignment alignment, 325 | EdgeInsetsGeometry padding, 326 | Color color, 327 | Decoration decoration, 328 | Decoration foregroundDecoration, 329 | double width, 330 | double height, 331 | BoxConstraints constraints, 332 | EdgeInsetsGeometry margin, 333 | Matrix4 transform, 334 | Curve curve = Curves.linear, 335 | @required Duration duration, 336 | VoidCallback onEnd, 337 | }) { 338 | return AnimatedContainer( 339 | key: key, 340 | alignment: alignment, 341 | padding: padding, 342 | color: color, 343 | decoration: decoration, 344 | foregroundDecoration: foregroundDecoration, 345 | width: width, 346 | height: height, 347 | constraints: constraints, 348 | margin: margin, 349 | transform: transform, 350 | curve: curve, 351 | duration: duration, 352 | onEnd: onEnd, 353 | child: this, 354 | ); 355 | } 356 | 357 | SingleChildScrollView intoSingleChildScrollView({ 358 | Key key, 359 | Axis scrollDirection = Axis.vertical, 360 | bool reverse = false, 361 | EdgeInsetsGeometry padding, 362 | bool primary, 363 | ScrollPhysics physics, 364 | ScrollController controller, 365 | DragStartBehavior dragStartBehavior = DragStartBehavior.start, 366 | }) { 367 | return SingleChildScrollView( 368 | key: key, 369 | scrollDirection: scrollDirection, 370 | reverse: reverse, 371 | padding: padding, 372 | primary: primary, 373 | physics: physics, 374 | controller: controller, 375 | dragStartBehavior: dragStartBehavior, 376 | child: this, 377 | ); 378 | } 379 | 380 | FlatButton intoFlatButton({ 381 | Key key, 382 | @required VoidCallback onPressed, 383 | VoidCallback onLongPress, 384 | ValueChanged onHighlightChanged, 385 | ButtonTextTheme textTheme, 386 | Color textColor, 387 | Color disabledTextColor, 388 | Color color, 389 | Color disabledColor, 390 | Color focusColor, 391 | Color hoverColor, 392 | Color highlightColor, 393 | Color splashColor, 394 | Brightness colorBrightness, 395 | EdgeInsetsGeometry padding = const EdgeInsets.all(0), 396 | ShapeBorder shape, 397 | Clip clipBehavior = Clip.none, 398 | FocusNode focusNode, 399 | bool autofocus = false, 400 | MaterialTapTargetSize materialTapTargetSize, 401 | }) { 402 | return FlatButton( 403 | key: key, 404 | onPressed: onPressed, 405 | onLongPress: onLongPress, 406 | onHighlightChanged: onHighlightChanged, 407 | textTheme: textTheme, 408 | textColor: textColor, 409 | disabledTextColor: disabledTextColor, 410 | color: color, 411 | disabledColor: disabledColor, 412 | focusColor: focusColor, 413 | hoverColor: hoverColor, 414 | highlightColor: highlightColor, 415 | splashColor: splashColor, 416 | colorBrightness: colorBrightness, 417 | padding: padding, 418 | shape: shape, 419 | clipBehavior: clipBehavior, 420 | focusNode: focusNode, 421 | autofocus: autofocus, 422 | materialTapTargetSize: materialTapTargetSize, 423 | child: this, 424 | ); 425 | } 426 | 427 | GestureDetector onTap(GestureTapCallback onTap, {Key key}) { 428 | return intoGestureDetector(onTap: onTap, key: key); 429 | } 430 | 431 | GestureDetector onDoubleTap(GestureTapCallback onDoubleTap, {Key key}) { 432 | return intoGestureDetector(onDoubleTap: onDoubleTap, key: key); 433 | } 434 | 435 | GestureDetector onLongPress(GestureLongPressCallback onLongPress, {Key key}) { 436 | return intoGestureDetector(onLongPress: onLongPress, key: key); 437 | } 438 | 439 | GestureDetector intoGestureDetector({ 440 | Key key, 441 | GestureTapDownCallback onTapDown, 442 | GestureTapUpCallback onTapUp, 443 | GestureTapCallback onTap, 444 | GestureTapCancelCallback onTapCancel, 445 | GestureTapDownCallback onSecondaryTapDown, 446 | GestureTapUpCallback onSecondaryTapUp, 447 | GestureTapCancelCallback onSecondaryTapCancel, 448 | GestureTapCallback onDoubleTap, 449 | GestureLongPressCallback onLongPress, 450 | GestureLongPressStartCallback onLongPressStart, 451 | GestureLongPressMoveUpdateCallback onLongPressMoveUpdate, 452 | GestureLongPressUpCallback onLongPressUp, 453 | GestureLongPressEndCallback onLongPressEnd, 454 | GestureDragDownCallback onVerticalDragDown, 455 | GestureDragStartCallback onVerticalDragStart, 456 | GestureDragUpdateCallback onVerticalDragUpdate, 457 | GestureDragEndCallback onVerticalDragEnd, 458 | GestureDragCancelCallback onVerticalDragCancel, 459 | GestureDragDownCallback onHorizontalDragDown, 460 | GestureDragStartCallback onHorizontalDragStart, 461 | GestureDragUpdateCallback onHorizontalDragUpdate, 462 | GestureDragEndCallback onHorizontalDragEnd, 463 | GestureDragCancelCallback onHorizontalDragCancel, 464 | GestureForcePressStartCallback onForcePressStart, 465 | GestureForcePressPeakCallback onForcePressPeak, 466 | GestureForcePressUpdateCallback onForcePressUpdate, 467 | GestureForcePressEndCallback onForcePressEnd, 468 | GestureDragDownCallback onPanDown, 469 | GestureDragStartCallback onPanStart, 470 | GestureDragUpdateCallback onPanUpdate, 471 | GestureDragEndCallback onPanEnd, 472 | GestureDragCancelCallback onPanCancel, 473 | GestureScaleStartCallback onScaleStart, 474 | GestureScaleUpdateCallback onScaleUpdate, 475 | GestureScaleEndCallback onScaleEnd, 476 | HitTestBehavior behavior, 477 | bool excludeFromSemantics = false, 478 | DragStartBehavior dragStartBehavior = DragStartBehavior.start, 479 | }) { 480 | return GestureDetector( 481 | key: key, 482 | onTapDown: onTapDown, 483 | onTapUp: onTapUp, 484 | onTap: onTap, 485 | onTapCancel: onTapCancel, 486 | onSecondaryTapDown: onSecondaryTapDown, 487 | onSecondaryTapUp: onSecondaryTapUp, 488 | onSecondaryTapCancel: onSecondaryTapCancel, 489 | onDoubleTap: onDoubleTap, 490 | onLongPress: onLongPress, 491 | onLongPressStart: onLongPressStart, 492 | onLongPressMoveUpdate: onLongPressMoveUpdate, 493 | onLongPressUp: onLongPressUp, 494 | onLongPressEnd: onLongPressEnd, 495 | onVerticalDragDown: onVerticalDragDown, 496 | onVerticalDragStart: onVerticalDragStart, 497 | onVerticalDragUpdate: onVerticalDragUpdate, 498 | onVerticalDragEnd: onVerticalDragEnd, 499 | onVerticalDragCancel: onVerticalDragCancel, 500 | onHorizontalDragDown: onHorizontalDragDown, 501 | onHorizontalDragStart: onHorizontalDragStart, 502 | onHorizontalDragUpdate: onHorizontalDragUpdate, 503 | onHorizontalDragEnd: onHorizontalDragEnd, 504 | onHorizontalDragCancel: onHorizontalDragCancel, 505 | onForcePressStart: onForcePressStart, 506 | onForcePressPeak: onForcePressPeak, 507 | onForcePressUpdate: onForcePressUpdate, 508 | onForcePressEnd: onForcePressEnd, 509 | onPanDown: onPanDown, 510 | onPanStart: onPanStart, 511 | onPanUpdate: onPanUpdate, 512 | onPanEnd: onPanEnd, 513 | onPanCancel: onPanCancel, 514 | onScaleStart: onScaleStart, 515 | onScaleUpdate: onScaleUpdate, 516 | onScaleEnd: onScaleEnd, 517 | behavior: behavior, 518 | excludeFromSemantics: excludeFromSemantics, 519 | dragStartBehavior: dragStartBehavior, 520 | child: this, 521 | ); 522 | } 523 | 524 | Container intoContainer({ 525 | Key key, 526 | AlignmentGeometry alignment, 527 | EdgeInsetsGeometry padding, 528 | Color color, 529 | Decoration decoration, 530 | Decoration foregroundDecoration, 531 | double width, 532 | double height, 533 | BoxConstraints constraints, 534 | EdgeInsetsGeometry margin, 535 | Matrix4 transform, 536 | }) { 537 | return Container( 538 | key: key, 539 | alignment: alignment, 540 | padding: padding, 541 | color: color, 542 | decoration: decoration, 543 | foregroundDecoration: foregroundDecoration, 544 | width: width, 545 | height: height, 546 | constraints: constraints, 547 | margin: margin, 548 | transform: transform, 549 | child: this, 550 | ); 551 | } 552 | } 553 | -------------------------------------------------------------------------------- /flutter_tiktok/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.0.11" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "1.5.2" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "2.4.0" 25 | boolean_selector: 26 | dependency: transitive 27 | description: 28 | name: boolean_selector 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.0.5" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.1.2" 39 | chewie: 40 | dependency: "direct main" 41 | description: 42 | name: chewie 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "0.9.8+1" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "1.14.11" 53 | convert: 54 | dependency: transitive 55 | description: 56 | name: convert 57 | url: "https://pub.flutter-io.cn" 58 | source: hosted 59 | version: "2.1.1" 60 | crypto: 61 | dependency: transitive 62 | description: 63 | name: crypto 64 | url: "https://pub.flutter-io.cn" 65 | source: hosted 66 | version: "2.1.3" 67 | cupertino_icons: 68 | dependency: "direct main" 69 | description: 70 | name: cupertino_icons 71 | url: "https://pub.flutter-io.cn" 72 | source: hosted 73 | version: "0.1.3" 74 | flukit: 75 | dependency: "direct main" 76 | description: 77 | name: flukit 78 | url: "https://pub.flutter-io.cn" 79 | source: hosted 80 | version: "1.0.2" 81 | flutter: 82 | dependency: "direct main" 83 | description: flutter 84 | source: sdk 85 | version: "0.0.0" 86 | flutter_test: 87 | dependency: "direct dev" 88 | description: flutter 89 | source: sdk 90 | version: "0.0.0" 91 | flutter_web_plugins: 92 | dependency: transitive 93 | description: flutter 94 | source: sdk 95 | version: "0.0.0" 96 | image: 97 | dependency: transitive 98 | description: 99 | name: image 100 | url: "https://pub.flutter-io.cn" 101 | source: hosted 102 | version: "2.1.4" 103 | matcher: 104 | dependency: transitive 105 | description: 106 | name: matcher 107 | url: "https://pub.flutter-io.cn" 108 | source: hosted 109 | version: "0.12.6" 110 | meta: 111 | dependency: transitive 112 | description: 113 | name: meta 114 | url: "https://pub.flutter-io.cn" 115 | source: hosted 116 | version: "1.1.8" 117 | open_iconic_flutter: 118 | dependency: transitive 119 | description: 120 | name: open_iconic_flutter 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "0.3.0" 124 | path: 125 | dependency: transitive 126 | description: 127 | name: path 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "1.6.4" 131 | pedantic: 132 | dependency: transitive 133 | description: 134 | name: pedantic 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "1.8.0+1" 138 | petitparser: 139 | dependency: transitive 140 | description: 141 | name: petitparser 142 | url: "https://pub.flutter-io.cn" 143 | source: hosted 144 | version: "2.4.0" 145 | quiver: 146 | dependency: transitive 147 | description: 148 | name: quiver 149 | url: "https://pub.flutter-io.cn" 150 | source: hosted 151 | version: "2.0.5" 152 | screen: 153 | dependency: transitive 154 | description: 155 | name: screen 156 | url: "https://pub.flutter-io.cn" 157 | source: hosted 158 | version: "0.0.5" 159 | sky_engine: 160 | dependency: transitive 161 | description: flutter 162 | source: sdk 163 | version: "0.0.99" 164 | source_span: 165 | dependency: transitive 166 | description: 167 | name: source_span 168 | url: "https://pub.flutter-io.cn" 169 | source: hosted 170 | version: "1.5.5" 171 | stack_trace: 172 | dependency: transitive 173 | description: 174 | name: stack_trace 175 | url: "https://pub.flutter-io.cn" 176 | source: hosted 177 | version: "1.9.3" 178 | stream_channel: 179 | dependency: transitive 180 | description: 181 | name: stream_channel 182 | url: "https://pub.flutter-io.cn" 183 | source: hosted 184 | version: "2.0.0" 185 | string_scanner: 186 | dependency: transitive 187 | description: 188 | name: string_scanner 189 | url: "https://pub.flutter-io.cn" 190 | source: hosted 191 | version: "1.0.5" 192 | term_glyph: 193 | dependency: transitive 194 | description: 195 | name: term_glyph 196 | url: "https://pub.flutter-io.cn" 197 | source: hosted 198 | version: "1.1.0" 199 | test_api: 200 | dependency: transitive 201 | description: 202 | name: test_api 203 | url: "https://pub.flutter-io.cn" 204 | source: hosted 205 | version: "0.2.11" 206 | typed_data: 207 | dependency: transitive 208 | description: 209 | name: typed_data 210 | url: "https://pub.flutter-io.cn" 211 | source: hosted 212 | version: "1.1.6" 213 | vector_math: 214 | dependency: transitive 215 | description: 216 | name: vector_math 217 | url: "https://pub.flutter-io.cn" 218 | source: hosted 219 | version: "2.0.8" 220 | video_player: 221 | dependency: "direct main" 222 | description: 223 | name: video_player 224 | url: "https://pub.flutter-io.cn" 225 | source: hosted 226 | version: "0.10.5" 227 | video_player_platform_interface: 228 | dependency: transitive 229 | description: 230 | name: video_player_platform_interface 231 | url: "https://pub.flutter-io.cn" 232 | source: hosted 233 | version: "1.0.4" 234 | video_player_web: 235 | dependency: transitive 236 | description: 237 | name: video_player_web 238 | url: "https://pub.flutter-io.cn" 239 | source: hosted 240 | version: "0.1.1+1" 241 | xml: 242 | dependency: transitive 243 | description: 244 | name: xml 245 | url: "https://pub.flutter-io.cn" 246 | source: hosted 247 | version: "3.5.0" 248 | sdks: 249 | dart: ">=2.6.0 <3.0.0" 250 | flutter: ">=1.12.13+hotfix.4 <2.0.0" 251 | -------------------------------------------------------------------------------- /flutter_tiktok/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_tiktok 2 | description: A new Flutter project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.6.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | 23 | # The following adds the Cupertino Icons font to your application. 24 | # Use with the CupertinoIcons class for iOS style icons. 25 | cupertino_icons: ^0.1.2 26 | flukit: ^1.0.2 27 | video_player: ^0.10.1+5 28 | chewie: ^0.9.7 29 | 30 | dev_dependencies: 31 | flutter_test: 32 | sdk: flutter 33 | 34 | 35 | # For information on the generic Dart part of this file, see the 36 | # following page: https://dart.dev/tools/pub/pubspec 37 | 38 | # The following section is specific to Flutter. 39 | flutter: 40 | 41 | # The following line ensures that the Material Icons font is 42 | # included with your application, so that you can use the icons in 43 | # the material Icons class. 44 | uses-material-design: true 45 | 46 | # To add assets to your application, add an assets section, like this: 47 | assets: 48 | - assets/images/love.jpeg 49 | - assets/images/vides.png 50 | - assets/images/vides2.png 51 | - assets/images/ 52 | - assets/videos/ 53 | # assets: 54 | # - images/a_dot_burr.jpeg 55 | # - images/a_dot_ham.jpeg 56 | 57 | # An image asset can refer to one or more resolution-specific "variants", see 58 | # https://flutter.dev/assets-and-images/#resolution-aware. 59 | 60 | # For details regarding adding assets from package dependencies, see 61 | # https://flutter.dev/assets-and-images/#from-packages 62 | 63 | # To add custom fonts to your application, add a fonts section here, 64 | # in this "flutter" section. Each entry in this list should have a 65 | # "family" key with the font family name, and a "fonts" key with a 66 | # list giving the asset and other descriptors for the font. For 67 | # example: 68 | # fonts: 69 | # - family: Schyler 70 | # fonts: 71 | # - asset: fonts/Schyler-Regular.ttf 72 | # - asset: fonts/Schyler-Italic.ttf 73 | # style: italic 74 | # - family: Trajan Pro 75 | # fonts: 76 | # - asset: fonts/TrajanPro.ttf 77 | # - asset: fonts/TrajanPro_Bold.ttf 78 | # weight: 700 79 | # 80 | # For details regarding fonts from package dependencies, 81 | # see https://flutter.dev/custom-fonts/#from-packages 82 | -------------------------------------------------------------------------------- /flutter_tiktok/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:flutter_tiktok/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /res/11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/res/11.gif -------------------------------------------------------------------------------- /res/111.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/res/111.gif -------------------------------------------------------------------------------- /res/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/res/3.gif -------------------------------------------------------------------------------- /res/QQ20191224-093618.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CZXBigBrother/flutter_TikTok/374f82a0fbf9479421f8b852a3d46ff4ce14cd17/res/QQ20191224-093618.gif --------------------------------------------------------------------------------