reason

重构首页

......@@ -6,7 +6,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.2'
classpath 'com.android.tools.build:gradle:7.0.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}
......
......@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
\ No newline at end of file
......
No preview for this file type
import 'package:Parlando/common/permission_request_widget.dart';
import 'package:Parlando/routers/fluro_navigator.dart';
import 'package:Parlando/poem/components/video_slides.dart';
import 'package:flutter/material.dart';
import 'package:Parlando/account/page/account_page.dart';
import 'package:Parlando/poem/page/poem_page.dart';
import 'package:Parlando/widgets/double_tap_back_exit_app.dart';
import 'package:provider/provider.dart';
import 'provider/home_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
_HomeState createState() => _HomeState();
HomeState createState() => HomeState();
}
class _HomeState extends State<Home> with RestorationMixin {
late List<Widget> _pageList;
final PageController _pageController = PageController();
HomeProvider provider = HomeProvider();
class HomeState extends State<Home> {
final PageController _controller = PageController();
@override
void initState() {
super.initState();
initData();
List<String> list = [
"为您更好的体验应用,所以需要获取您的手机摄像头权限,以保存您的一些偏好设置",
"您已拒绝权限,所以无法保存您的一些偏好设置,将无法使用APP",
"您已拒绝权限,请在设置中心中同意APP的权限请求",
"其他错误"
];
Future.delayed(
Duration.zero,
() {
NavigatorUtils.pushPageByFade(
context: context,
//目标页面
targetPage: PermissionRequestWidget(
//所需要申请的权限
permission: Permission.camera,
//显示关闭应用按钮
isCloseApp: true,
//提示文案
permissionList: list,
),
//权限申请结果
dismissCallBack: (value) {},
);
},
);
//设置pageView 滑动监听
_controller.addListener(() {
if (_controller.position.pixels == _controller.position.maxScrollExtent) {
print('滑动到了最底部');
_getMore();
}
});
}
@override
void dispose() {
_pageController.dispose();
super.dispose();
/// 下拉刷新方法,为list重新赋值
Future<void> _onRefresh() async {
await Future.delayed(const Duration(seconds: 1), () {
print('refresh');
setState(() {});
});
}
void initData() {
_pageList = [
const PoemPage(),
const AccountPage(),
];
/// 上拉加载更多
Future<void> _getMore() async {
await Future.delayed(const Duration(seconds: 1), () {
print('_getMore');
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<HomeProvider>(
create: (_) => provider,
child: DoubleTapBackExitApp(
child: Scaffold(
// 使用PageView的原因参看 https://zhuanlan.zhihu.com/p/58582876
body: PageView(
physics: const NeverScrollableScrollPhysics(), // 禁止滑动
controller: _pageController,
onPageChanged: (int index) => provider.value = index,
children: _pageList,
return Stack(
children: [
RefreshIndicator(
//下拉刷新触发方法
onRefresh: _onRefresh,
//设置listView
child: PageView(
controller: _controller,
//设置滑动方向
scrollDirection: Axis.vertical,
children: const [
VideoSlides(),
VideoSlides(),
VideoSlides(),
],
),
),
Positioned(
top: 18.0,
left: 10.0,
right: 10.0,
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () {},
child: const Text(
"临境",
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
),
),
const Text(
"|",
style: TextStyle(color: Colors.white),
),
TextButton(
onPressed: () {},
child: const Text(
"妙众",
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
),
),
const Text(
"|",
style: TextStyle(color: Colors.white),
),
TextButton(
onPressed: () => {},
child: const Text(
"新鲜",
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
),
),
],
),
),
),
),
],
);
}
@override
String? get restorationId => 'home';
@override
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
registerForRestoration(provider, 'BottomNavigationBarCurrentIndex');
}
}
......
......@@ -115,7 +115,7 @@ class _SplashPageState extends State<SplashPage> {
void _goLogin() {
if (SpUtil.containsKey(Constant.userToken)!) {
NavigatorUtils.push(context, Routes.home, clearStack: true);
NavigatorUtils.push(context, Routes.navBarPage, clearStack: true);
} else {
NavigatorUtils.push(context, LoginRouter.loginPage, replace: true);
}
......
......@@ -113,7 +113,7 @@ class _LoginPageState extends State<LoginPage>
params: params,
onSuccess: (data) {
SpUtil.putString(Constant.userToken, data!.data!.token!);
NavigatorUtils.push(context, Routes.home, clearStack: true);
NavigatorUtils.push(context, Routes.navBarPage, clearStack: true);
_isLoading = false;
},
onError: (code, msg) {
......
......@@ -90,7 +90,7 @@ class _RegisterPageState extends State<RegisterPage>
params: params,
onSuccess: (data) {
SpUtil.putString(Constant.userToken, data!.data!.token!);
NavigatorUtils.push(context, Routes.home, clearStack: true);
NavigatorUtils.push(context, Routes.navBarPage, clearStack: true);
_isLoading = false;
},
onError: (code, msg) {
......
import 'package:Parlando/account/page/account_page.dart';
import 'package:Parlando/home/home_page.dart';
import 'package:Parlando/poem/theme/tik_theme.dart';
import 'package:flutter/material.dart';
class NavBarPage extends StatefulWidget {
const NavBarPage({Key? key, required this.initialPage}) : super(key: key);
final String initialPage;
@override
NavBarPageState createState() => NavBarPageState();
}
/// This is the private State class that goes with NavBarPage.
class NavBarPageState extends State<NavBarPage> {
String _currentPage = 'HomePage';
@override
void initState() {
super.initState();
_currentPage = widget.initialPage;
}
@override
Widget build(BuildContext context) {
final tabs = {
'HomePage': const Home(),
'UploadStatusPage': const AccountPage(),
'UserProfile': const AccountPage(),
};
return Scaffold(
body: tabs[_currentPage],
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.home_filled,
size: 24,
),
label: 'Home',
tooltip: '',
),
BottomNavigationBarItem(
icon: Icon(
Icons.add_circle_outline_rounded,
size: 50,
),
activeIcon: Icon(
Icons.add_circle_rounded,
size: 50,
),
label: '',
tooltip: '',
),
BottomNavigationBarItem(
icon: Icon(
Icons.person_rounded,
size: 26,
),
label: 'Profile',
tooltip: '',
)
],
backgroundColor: TikTheme.tertiaryColor,
currentIndex: tabs.keys.toList().indexOf(_currentPage),
selectedItemColor: TikTheme.primaryColor,
unselectedItemColor: const Color(0x53FFFFFF),
onTap: (i) => setState(() => _currentPage = tabs.keys.toList()[i]),
showSelectedLabels: true,
showUnselectedLabels: true,
type: BottomNavigationBarType.fixed,
),
);
}
}
import 'package:flutter/material.dart';
import 'package:share_plus/share_plus.dart';
import '../theme/tik_theme.dart';
import '../theme/tik_video_player.dart';
class VideoSlides extends StatefulWidget {
const VideoSlides({Key? key}) : super(key: key);
@override
VideoSlidesState createState() => VideoSlidesState();
}
class VideoSlidesState extends State<VideoSlides> {
bool isSharing = false;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
constraints: const BoxConstraints(
maxWidth: double.infinity,
maxHeight: double.infinity,
),
decoration: const BoxDecoration(
color: Colors.black,
),
child: TikVideoPlayer(
path: 'assets/video/1656599376238999.mp4',
videoType: VideoType.asset,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 1,
autoPlay: true,
looping: true,
showControls: false,
allowFullScreen: false,
allowPlaybackSpeedMenu: false,
),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 70,
height: 330,
decoration: const BoxDecoration(
color: Color(0x4DC4C4C4),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(40),
bottomRight: Radius.circular(0),
topLeft: Radius.circular(40),
topRight: Radius.circular(0),
),
shape: BoxShape.rectangle,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0, 10, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
0, 20, 0, 0),
child: Container(
width: 50,
height: 50,
decoration: const BoxDecoration(
color: Color(0x69EEEEEE),
shape: BoxShape.circle,
),
child: const Icon(
Icons.favorite_rounded,
color: Colors.white,
size: 24,
),
),
),
Text(
'121.9k',
style: TikTheme.bodyText1.override(
fontFamily: 'Poppins',
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w300,
),
),
],
),
],
),
),
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0, 10, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
0, 20, 0, 0),
child: InkWell(
onTap: () async {},
child: Container(
width: 50,
height: 50,
decoration: const BoxDecoration(
color: Color(0x69EEEEEE),
shape: BoxShape.circle,
),
child: const Icon(
Icons.star,
color: Colors.white,
size: 34,
),
),
),
),
Text(
'+8.5',
style: TikTheme.bodyText1.override(
fontFamily: 'Poppins',
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w300,
),
),
],
),
],
),
),
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0, 10, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
0, 20, 0, 0),
child: InkWell(
onTap: () async {
isSharing = true;
setState(() {});
Future.delayed(const Duration(seconds: 3),
() async {
setState(() => isSharing = false);
await Share.share('Share Me');
});
},
child: Container(
width: 50,
height: 50,
decoration: const BoxDecoration(
color: Color(0x69EEEEEE),
shape: BoxShape.circle,
),
child: isSharing
? const Text("I")
: const Icon(
Icons.share_rounded,
color: Colors.white,
size: 24,
),
),
),
),
Text(
'分享',
style: TikTheme.bodyText1.override(
fontFamily: 'Poppins',
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w300,
),
),
],
),
],
),
),
],
),
),
],
),
],
),
],
);
}
}
import 'package:flutter/material.dart';
class TikIconButton extends StatelessWidget {
const TikIconButton(
{Key? key,
this.borderColor,
this.borderRadius,
this.borderWidth,
this.buttonSize,
this.fillColor,
this.icon,
this.onPressed})
: super(key: key);
final double? borderRadius;
final double? buttonSize;
final Color? fillColor;
final Color? borderColor;
final double? borderWidth;
final Widget? icon;
final void Function()? onPressed;
@override
Widget build(BuildContext context) => Material(
borderRadius:
borderRadius != null ? BorderRadius.circular(borderRadius!) : null,
color: Colors.transparent,
clipBehavior: Clip.antiAlias,
child: Ink(
width: buttonSize,
height: buttonSize,
decoration: BoxDecoration(
color: fillColor,
border: Border.all(
color: borderColor ?? Colors.transparent,
width: borderWidth ?? 0,
),
borderRadius: borderRadius != null
? BorderRadius.circular(borderRadius!)
: null,
),
child: IconButton(
icon: icon!,
onPressed: onPressed,
splashRadius: buttonSize,
),
),
);
}
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class TikTheme {
static const Color primaryColor = Color(0xFFE48900);
static const Color secondaryColor = Color(0xFF1C1C4F);
static const Color tertiaryColor = Color(0xFF131B41);
String primaryFontFamily = 'Poppins';
String secondaryFontFamily = 'Roboto';
static TextStyle get title1 => GoogleFonts.getFont(
'Poppins',
color: const Color(0xFF303030),
fontWeight: FontWeight.w600,
fontSize: 24,
);
static TextStyle get title2 => GoogleFonts.getFont(
'Poppins',
color: const Color(0xFF303030),
fontWeight: FontWeight.w500,
fontSize: 22,
);
static TextStyle get title3 => GoogleFonts.getFont(
'Poppins',
color: const Color(0xFF303030),
fontWeight: FontWeight.w500,
fontSize: 20,
);
static TextStyle get subtitle1 => GoogleFonts.getFont(
'Poppins',
color: const Color(0xFF757575),
fontWeight: FontWeight.w500,
fontSize: 18,
);
static TextStyle get subtitle2 => GoogleFonts.getFont(
'Poppins',
color: const Color(0xFF616161),
fontWeight: FontWeight.normal,
fontSize: 16,
);
static TextStyle get bodyText1 => GoogleFonts.getFont(
'Poppins',
color: const Color(0xFF303030),
fontWeight: FontWeight.normal,
fontSize: 14,
);
static TextStyle get bodyText2 => GoogleFonts.getFont(
'Poppins',
color: const Color(0xFF424242),
fontWeight: FontWeight.normal,
fontSize: 14,
);
}
extension TextStyleHelper on TextStyle {
TextStyle override({
required String fontFamily,
required Color color,
double? fontSize,
FontWeight? fontWeight,
FontStyle? fontStyle,
bool useGoogleFonts = true,
}) =>
useGoogleFonts
? GoogleFonts.getFont(
fontFamily,
color: this.color,
fontSize: fontSize ?? this.fontSize,
fontWeight: fontWeight ?? this.fontWeight,
fontStyle: fontStyle ?? this.fontStyle,
)
: copyWith(
fontFamily: fontFamily,
color: color,
fontSize: fontSize,
fontWeight: fontWeight,
fontStyle: fontStyle,
);
}
import 'package:chewie/chewie.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';
const kDefaultAspectRatio = 16 / 9;
enum VideoType {
asset,
network,
}
class TikVideoPlayer extends StatefulWidget {
const TikVideoPlayer({
Key? key,
required this.path,
this.videoType = VideoType.network,
this.width,
this.height,
this.aspectRatio,
this.autoPlay = false,
this.looping = false,
this.showControls = true,
this.allowFullScreen = true,
this.allowPlaybackSpeedMenu = false,
}) : super(key: key);
final String path;
final VideoType videoType;
final double? width;
final double? height;
final double? aspectRatio;
final bool autoPlay;
final bool looping;
final bool showControls;
final bool allowFullScreen;
final bool allowPlaybackSpeedMenu;
@override
State<StatefulWidget> createState() => _TikVideoPlayerState();
}
class _TikVideoPlayerState extends State<TikVideoPlayer> {
late VideoPlayerController _videoPlayerController;
late ChewieController _chewieController;
@override
void initState() {
super.initState();
initializePlayer();
}
@override
void dispose() {
_videoPlayerController.dispose();
_chewieController.dispose();
super.dispose();
}
double? get width => widget.width == null || widget.width! >= double.infinity
? MediaQuery.of(context).size.width
: widget.width;
double? get height =>
widget.height == null || widget.height! >= double.infinity
? (width != null ? width! / aspectRatio : null)
: widget.height;
double get aspectRatio =>
_chewieController.videoPlayerController.value.aspectRatio;
Future initializePlayer() async {
_videoPlayerController = widget.videoType == VideoType.network
? VideoPlayerController.network(widget.path)
: VideoPlayerController.asset(widget.path);
await _videoPlayerController.initialize();
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController,
deviceOrientationsOnEnterFullScreen: [
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
],
deviceOrientationsAfterFullScreen: [DeviceOrientation.portraitUp],
aspectRatio: widget.aspectRatio,
autoPlay: widget.autoPlay,
looping: widget.looping,
showControls: widget.showControls,
allowFullScreen: widget.allowFullScreen,
allowPlaybackSpeedChanging: widget.allowPlaybackSpeedMenu,
);
setState(() {});
}
@override
Widget build(BuildContext context) => FittedBox(
fit: BoxFit.cover,
child: SizedBox(
height: height,
width: width,
child: _chewieController.videoPlayerController.value.isInitialized
? Chewie(controller: _chewieController)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
CircularProgressIndicator(),
SizedBox(height: 20),
Text('Loading'),
],
),
),
);
}
import 'package:Parlando/poem/components/nav_bar_page.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:Parlando/account/account_router.dart';
......@@ -15,6 +16,7 @@ import 'i_router.dart';
import 'not_found_page.dart';
class Routes {
static String navBarPage = '/nav/bar/page';
static String home = '/home';
static String webViewPage = '/webView';
......@@ -30,6 +32,12 @@ class Routes {
return const NotFoundPage();
});
router.define(navBarPage,
handler: Handler(
handlerFunc:
(BuildContext? context, Map<String, List<String>> params) =>
const NavBarPage(initialPage: 'HomePage')));
router.define(home,
handler: Handler(
handlerFunc:
......
......@@ -183,6 +183,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
chewie:
dependency: "direct main"
description:
name: chewie
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.4"
clock:
dependency: transitive
description:
......@@ -572,6 +579,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
google_fonts:
dependency: "direct main"
description:
name: google_fonts
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
graphs:
dependency: transitive
description:
......@@ -1506,6 +1520,41 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "8.2.2"
wakelock:
dependency: transitive
description:
name: wakelock
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.6.1+2"
wakelock_macos:
dependency: transitive
description:
name: wakelock_macos
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.0"
wakelock_platform_interface:
dependency: transitive
description:
name: wakelock_platform_interface
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.0"
wakelock_web:
dependency: transitive
description:
name: wakelock_web
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.0"
wakelock_windows:
dependency: transitive
description:
name: wakelock_windows
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.0"
watcher:
dependency: transitive
description:
......
......@@ -86,7 +86,8 @@ dependencies:
url: 'https://gitee.com/reasonpun/flutter_2d_amap.git'
# tiktok
video_player: ^2.2.10
video_player: ^2.4.5
chewie: ^1.3.4
# map取值
safemap: ^2.0.0-nullsafety.0
# 基础的点击
......@@ -123,6 +124,9 @@ dependencies:
image_gallery_saver: ^1.7.1
flutter_easy_permission: ^1.1.2
google_fonts: ^3.0.1
dependency_overrides:
decimal: 1.5.0
......@@ -206,6 +210,7 @@ flutter:
- assets/images/membership/
- assets/images/share/
- assets/data/
- assets/video/
- assets/data/Data.json
- assets/data/friends/
......