提交 b7fc58b3 authored 作者: yueweilu's avatar yueweilu

我的界面基本布局

上级 51e319bb
import 'dart:ui';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
......@@ -26,15 +29,7 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: const Size(375, 667),
builder: (context, child) => RefreshConfiguration(
headerBuilder: () => const ClassicHeader(
refreshingIcon: CupertinoActivityIndicator(),
),
footerBuilder: () => const ClassicFooter(
loadingIcon: CupertinoActivityIndicator(),
),
hideFooterWhenNotFull: true,
child: GetBuilder<ConfigStore>(
builder: (context, child) => GetBuilder<ConfigStore>(
builder: (config) => MaterialApp.router(
debugShowCheckedModeBanner: false,
title: '紫荆云书',
......@@ -52,7 +47,7 @@ class MyApp extends StatelessWidget {
},
),
supportedLocales: const [
Locale('zh', 'CN'), // Chinese
Locale.fromSubtags(languageCode: 'zh'),
],
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
......@@ -60,11 +55,10 @@ class MyApp extends StatelessWidget {
GlobalCupertinoLocalizations.delegate,
// S.delegate,
],
// locale: config.locale,
locale: PlatformDispatcher.instance.locale,
// supportedLocales: S.delegate.supportedLocales,
),
),
)
);
}
}
......
library about;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_book/utils/index.dart';
import 'package:flutter_book/widgets/index.dart';
import 'package:go_router/go_router.dart';
import '../../routes/index.dart';
part 'view.dart';
\ No newline at end of file
......@@ -5,11 +5,9 @@ class AboutPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
top: false,
child: Scaffold(
return Scaffold(
appBar: AppBar(
title: Text('关于我们'),
title: const Text('关于我们'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
......@@ -19,30 +17,48 @@ class AboutPage extends StatelessWidget {
Column(
children: [
Container(
margin: EdgeInsets.only(top: 40),
height: 50,
width: 50,
margin: const EdgeInsets.only(top: 55),
height: 60,
width: 60,
color: Colors.cyan,
child: CustomImage.asset(url: 'assets/images/banner.png'),
child: const CustomImage.asset(url: 'assets/images/banner.png'),
),
Text('云教材'),
Text('V1.0.1'),
Gaps.hGaps15,
const Text('云教材',style: TextStyle(fontSize: 17,fontWeight: Fonts.medium,color: Colours.c3),),
const Text('V1.0.1',style: TextStyle(fontSize: 13,color: Colours.c9)),
],
),
Container(
color: Colors.cyan,
alignment: Alignment.center,
height: 50,
child: Row(
mainAxisAlignment:MainAxisAlignment.spaceBetween,
SafeArea(
child: Column(
children: [
Expanded(child: Text('《用户协议》',textAlign: TextAlign.right,)),
Expanded(child: Text('《隐私协议》',textAlign: TextAlign.left)),
],
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
child: const Text('《用户协议》',textAlign: TextAlign.right,style: TextStyle(fontSize: 10,color: Color(0xFF2A82D9)),),
onTap: (){
context.pushNamed(Routes.terms);
},
),
Gaps.vGaps15,
Container(width: 1,height: 10,color: const Color(0xFFC8C8C8),),
Gaps.vGaps15,
GestureDetector(
child: const Text('《隐私协议》',textAlign: TextAlign.left,style: TextStyle(fontSize: 10,color: Color(0xFF2A82D9))),
onTap:(){
context.pushNamed(Routes.terms);
} ,
)
],
),
Gaps.hGaps10,
const Text('Copyright © 2017 Zijing Education. All rights reserved.\n清控紫荆(北京)教育科技股份有限公司京\nICP证150431号',style: TextStyle(color: Colours.c9,fontSize:9),textAlign: TextAlign.center,)
],
),
)
],
),
);
}
......
part of course;
class CourseController extends GetxController {
late final List<String> courses;
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
final int _limit = 20;
int _page = 1;
bool _noMore = false;
@override
void onClose() {
refreshController.dispose();
super.onClose();
}
Future<void> _getCourse([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
/// 网路请求
List result = [];
/// 如果是刷新 清理数据
if (isRefresh) courses.clear();
courses.addAll([]);
_page ++;
_noMore = result.length < _limit;
update();
}
void onRefresh() async {
try {
await _getCourse(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
}
try {
await _getCourse();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
}
\ No newline at end of file
library course;
import 'dart:math';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:flutter_book/theme.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:get/get_state_manager/src/simple/get_controllers.dart';
import 'package:go_router/go_router.dart';
import 'package:ionicons/ionicons.dart';
import '../../routes/index.dart';
import '../../utils/index.dart';
import '../../widgets/index.dart';
import 'package:badges/badges.dart' as badges;
part 'view.dart';
part 'widgets/banner.dart';
part 'controller.dart';
part 'widgets/book.dart';
\ No newline at end of file
part of course;
class CoursePage extends StatefulWidget {
const CoursePage({Key? key}) : super(key: key);
@override
State<CoursePage> createState() => _CoursePageState();
}
class _CoursePageState extends State<CoursePage> {
@override
Widget build(BuildContext context) {
return GetBuilder<CourseController>(
init: CourseController(),
builder: (controller) =>Scaffold(
appBar: CustomAppBar(
titleSpacing: 0,
title: Padding(
padding: EdgeInsets.symmetric(horizontal: AppTheme.margin),
child: CustomInputSearch(
readOnly:true,
hintText: '请输入书籍名称',
onTap: () {
context.pushNamed(Routes.msgs);
}
),
),
actions: [
CustomButton.icon(
padding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
icon: const Icon(Ionicons.timer),
onPressed: () => context.pushNamed(Routes.msgs),
),
badges.Badge(
position: badges.BadgePosition.topEnd(top: -5, end: 0),
badgeContent: Text('10',style: TextStyle(fontSize: 7,color: Colors.white),),
badgeStyle: badges.BadgeStyle(
badgeColor: AppTheme.primary,
shape: badges.BadgeShape.circle
),
child: CustomButton.icon(
padding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
icon: const Icon(Ionicons.notifications),
onPressed: () => context.pushNamed(Routes.msgs),
),
)
// CustomButton.icon(
// padding: EdgeInsets.zero,
// backgroundColor: Colors.transparent,
// icon: const Icon(Ionicons.notifications),
// onPressed: () => context.pushNamed(Routes.msgs),
// ),
],
),
body:Column(
children: [
const BuildBanner(items: ['111','222','333'],),
Expanded(
child: CustomPullScrollView(
controller: controller.refreshController,
onRefresh: controller.onRefresh,
onLoading: controller.onLoading,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.5
),
itemBuilder: (BuildContext context, int index) {
return createCellWidget();
},
itemCount: 10,
),
// builder: (context,physics) => GridView.builder(
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2,
// crossAxisSpacing: 10,
// mainAxisSpacing: 10,
// childAspectRatio: 1.5
// ),
// itemBuilder: (BuildContext context, int index) {
// createCellWidget();
// },
// itemCount: 10,
// )
),
),
],
)
));
}
Widget createCellWidget(){
return GestureDetector(
child: Container(
// height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.cyan,
border: Border.all(color: Colours.c9,width: 2,style: BorderStyle.solid),
),
child: Stack(
children: [
Container(
color: Colors.white,
// height: double.infinity,
alignment: Alignment.center,
child:SizedBox()
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
alignment: Alignment.center,
height: 24,
width: double.infinity,
child: Text('假按揭啊'),
decoration: BoxDecoration(
borderRadius: BorderRadius.vertical(bottom:Radius.circular(5)),
color:Color(0x20FE250B),
),
),
),
],
)
),
onTap: (){
},
);
}
}
part of course;
class BuildBanner extends StatelessWidget {
final List items;
const BuildBanner({
Key? key,
this.items = const [],
}) : super(key:key);
@override
Widget build(BuildContext context) {
Random random = Random();
return CarouselSlider(
options: CarouselOptions(
// 自动滚动
autoPlay: items.length > 1,
// 是否无限滚动
enableInfiniteScroll: items.length > 1,
// 居中的是否放大
enlargeCenterPage: false,
// 宽高比例
aspectRatio: 19 / 9,
// 是否占满满视图
viewportFraction: 1,
),
items: items.map((item) {
return SafeArea(
minimum: const EdgeInsets.symmetric(horizontal: 0).copyWith(bottom: 0),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Color.fromRGBO(
random.nextInt(256), // Red
random.nextInt(256), // Green
random.nextInt(256), // Blue
1.0, // Alpha (opacity)
),
),
child: Text('$item'),
// child: CustomImage.asset(
// url: 'assets/images/banner.png',
// width: 130.w,
// fit: BoxFit.contain,
// ),
),
);
}).toList(),
);
}
}
part of course;
class Book extends StatelessWidget {
const Book({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
// icon
Container(
color: Colors.red,
height: 102,
width: 85,
),
Text('从现在开始,为精彩活从现在开始,为精彩活'),
Text('作者'),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
color: Colors.cyan,
padding: EdgeInsets.symmetric(horizontal: 3.5),
child: Text('未学习'),
),
Container(
color: Colors.cyan,
width: 40,
height: 40,
)
],
)
],
),
);
}
}
......@@ -3,11 +3,13 @@ library main;
import 'package:flutter/material.dart';
import 'package:flutter_book/pages/home/index.dart';
import 'package:flutter_book/pages/library/index.dart';
import 'package:flutter_book/pages/mine/index.dart';
import 'package:flutter_book/theme.dart';
import 'package:get/get.dart';
import 'package:ionicons/ionicons.dart';
import '../book_shop/index.dart';
import '../course/index.dart';
import '../record/index.dart';
import '../tts/index.dart';
import '../web/index.dart';
......
......@@ -39,11 +39,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver{
controller: controller.pageController,
onPageChanged: controller.onPageChanged,
children: const [
HomePage(),
CoursePage(),
LibraryPage(),
BookShopPage(),
// RecordPage(),
HomePage(),
MinePage(),
],
),
bottomNavigationBar: GetBuilder<MainController>(
......
part of mine;
class MineController extends GetxController {
}
\ No newline at end of file
library mine;
import 'package:flutter/material.dart';
import 'package:flutter_book/theme.dart';
import 'package:flutter_book/utils/index.dart';
import 'package:flutter_book/widgets/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:get/get_state_manager/src/simple/get_controllers.dart';
import 'package:go_router/go_router.dart';
import 'package:ionicons/ionicons.dart';
import '../../routes/index.dart';
import '../course/index.dart';
part 'view.dart';
part 'controller.dart';
part 'widgets/user.dart';
part 'widgets/read.dart';
part 'widgets/account.dart';
\ No newline at end of file
part of mine;
class MinePage extends StatefulWidget {
const MinePage({Key? key}) : super(key: key);
@override
State<MinePage> createState() => _MinePageState();
}
class _MinePageState extends State<MinePage> {
@override
Widget build(BuildContext context) {
return GetBuilder<MineController>(
init: MineController(),
builder:(controller) => Scaffold(
appBar: CustomAppBar(
backgroundColor: Colors.transparent,
actions: [
CustomButton.icon(
padding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
icon: const Icon(Ionicons.timer),
onPressed: () => context.pushNamed(Routes.msgs),
),
CustomButton.icon(
padding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
icon: const Icon(Ionicons.timer),
onPressed: () => context.pushNamed(Routes.msgs),
),
CustomButton.icon(
padding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
icon: const Icon(Ionicons.timer),
onPressed: () => context.pushNamed(Routes.msgs),
),
],
),
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: AppTheme.margin),
child: Column(
children: [
BuildUser(),
Gaps.vGaps10,
BuildRead(items: ['1','2','3','4'],),
Gaps.vGaps10,
BuildBanner(items: ['111','222','333'],),
Gaps.vGaps10,
BuildAccount(items: ['1','11','111','1111'],),
Gaps.vGaps10,
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.cyan,
),
child: Column(
children: [
_buildItem('账户安全', ''),
Container(color: Colours.cLine,margin: EdgeInsets.symmetric(horizontal: 15),height: 1,),
_buildItem('意见反馈', ''),
Container(color: Colours.cLine,margin: EdgeInsets.symmetric(horizontal: 15),height: 1,),
_buildItem('关于我们', ''),
],
),
),
BuildAccount(items: ['1','11','111','1111'],),
],
),
),
),
),
);
}
Widget _buildItem(String title, String linkTo,{VoidCallback? onTap}) {
return GestureDetector(
onTap: (){
if (linkTo.isNotEmpty){
context.pushNamed(linkTo);
if (onTap !=null) onTap;
}
},
child: Container(
padding: EdgeInsets.only(left: 18,right: 15),
height: 42,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('$title',style: TextStyle(fontSize: 14,color: Colours.c3,),),
Container(
width: 5,
height: 8,
color: Colors.cyan,
)
],
),
),
);
}
}
part of mine;
class BuildAccount extends StatelessWidget {
final List items ;
const BuildAccount({
super.key,
this.items = const []
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.cyan,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(left: 17,top: 14,bottom: 14,right: 17),
child: Text('我的账户',style: TextStyle(color: Colours.c3,fontSize: 16,height: 1.6,fontWeight: Fonts.medium),),
),
Container(
padding: EdgeInsets.only(bottom: 13,top: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: items.map((item){
return Column(
children: [
Container(
width: 25.w,
height: 25.w,
color: Colors.green,
),
Gaps.vGaps5,
Text('111',style: TextStyle(fontSize:12.w,height: 1.6,color: Colours.c9),),
items.indexOf(item) == 0?Row(
children: [
Text('3',style: TextStyle(fontSize: 16,height: 1.6,fontWeight: Fonts.medium,color: AppTheme.primary,),),
Text('张',style: TextStyle(fontSize: 12,height:1.6,color: Colours.c3),)
],
):Text('11',style: TextStyle(fontSize: 16,height:1.6,color: Colours.c3),)
],
);
} ).toList(),
),
)
],
),
);
}
}
part of mine;
class BuildRead extends StatelessWidget {
final void Function()? onTap;
final List items;
const BuildRead ({
super.key,
this.onTap,
this.items = const [],
});
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Container(
padding: EdgeInsets.symmetric(vertical: 16.5),
decoration: BoxDecoration(
borderRadius:BorderRadius.circular(8),
color: Colors.green,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: items.map((item){
return Container(
child: Column(
children: [
Text('3',style: TextStyle(fontSize: 18,height: 1.6,fontWeight: Fonts.medium,color: Colours.c3),),
Gaps.vGaps5,
Text('笔记',style: TextStyle(fontSize: 13,height:1.6,color: Colours.c6))
],
),
);
}).toList(),
),
),
);
}
}
part of mine;
/// 用户信息
class BuildUser extends StatelessWidget {
final void Function()? onTap;
const BuildUser ({
super.key,
this.onTap,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Row(
children: [
Container(
width: 45.w,
height: 45.w,
color: Colors.cyan,
),
Gaps.hGaps10,
Column(
children: [
Text('八仙过海',style: TextStyle(
color: Colours.c3,
fontSize: 15.w,
fontWeight: Fonts.medium,
height: 1.6.w
),),
Text('1881000000',style: TextStyle(
fontSize: 12.w,
color: Colours.c6
),)
],
),
Gaps.hGaps20,
Container(
width: 5,
height: 9,
color: Colors.cyan,
)
],
),
);
}
}
library user_msg;
import 'package:flutter/material.dart';
part 'view.dart';
\ No newline at end of file
part of user_msg;
class MsgPage extends StatelessWidget {
const MsgPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('消息中心'),
centerTitle: true,
),
);
}
}
library user_terms;
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
part 'view.dart';
\ No newline at end of file
/// 用户隐私 和 用户协议
part of user_terms;
class TermsPage extends StatelessWidget {
const TermsPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('用户协议'),
),
body: InAppWebView(
initialUrlRequest: URLRequest(
url: Uri.parse('http://192.168.11.39:5500/'),
),
)
);
}
}
......@@ -8,9 +8,12 @@ import 'package:flutter_book/pages/book_pay/index.dart';
import 'package:flutter_book/pages/login/index.dart';
import 'package:flutter_book/pages/main/index.dart';
import 'package:flutter_book/pages/splash/index.dart';
import 'package:flutter_book/pages/user_msg/index.dart';
import 'package:flutter_book/pages/web/index.dart';
import 'package:go_router/go_router.dart';
import '../pages/user_terms/index.dart';
part 'observers.dart';
part 'routes.dart';
\ No newline at end of file
......@@ -10,7 +10,12 @@ abstract class Routes {
static const login = 'login';
static const web = 'web';
static const about = 'about';
/// 支付界面
static const bookPay = 'book_pay';
/// 用户协议 和 隐私政策
static const terms = 'terms';
/// 消息
static const msgs = 'msgs';
static final GoRouter config = GoRouter(
......@@ -80,6 +85,24 @@ abstract class Routes {
key: state.pageKey,
child: const BookPayPage()
)
),
GoRoute(
path: '/$terms',
name: terms,
pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(),
key: state.pageKey,
child: const TermsPage()
)
),
GoRoute(
path: '/$msgs',
name: msgs,
pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(),
key: state.pageKey,
child: const MsgPage()
)
)
]
);
......
......@@ -5,6 +5,7 @@ import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:logger/logger.dart';
import 'package:crypto/crypto.dart';
......
......@@ -17,3 +17,41 @@ class TextStyles {
}
class Colours {
static const c9 = Color(0xFF999999);
static const c3 = Color(0xFF333333);
static const c6 = Color(0xFF666666);
static const cLine = Color(0xFFF0F0F0);
}
class Gaps {
static const Widget hGaps5 = SizedBox(width: 5,);
static const Widget hGaps10 = SizedBox(width: 10,);
static const Widget hGaps15 = SizedBox(width: 15,);
static const Widget hGaps20 = SizedBox(width: 20,);
static const Widget vGaps5 = SizedBox(height: 5,);
static const Widget vGaps10 = SizedBox(height: 10,);
static const Widget vGaps15 = SizedBox(height: 15,);
// static const Widget line = Padding(
// padding: EdgeInsets.symmetric(horizontal: 15.0),
// child: Divider(color: Colours.cLine,),
// );
}
class Fonts {
static const medium = FontWeight.w500;
static const bold = FontWeight.bold;
}
part of widgets;
class CustomAppBar extends AppBar {
CustomAppBar({
Key? key,
bool automaticallyImplyLeading = true,
Widget? title,
List<Widget>? actions,
bool? centerTitle,
double? titleSpacing,
Color? backgroundColor,
SystemUiOverlayStyle? systemOverlayStyle,
}) : super(
key: key,
title: title,
titleSpacing: titleSpacing,
systemOverlayStyle: systemOverlayStyle,
automaticallyImplyLeading: automaticallyImplyLeading,
backgroundColor: backgroundColor,
centerTitle: centerTitle,
actions: _buildActions(actions),
);
static List<Widget>? _buildActions(List<Widget>? items) {
if ((items ?? []).isEmpty) return null;
final ws = <Widget>[];
for (var element in items!) {
ws.add(Container(
alignment: Alignment.center,
padding: const EdgeInsets.only(right: AppTheme.margin),
child: element,
));
}
return ws;
}
}
part of widgets;
enum CustomButtonType { filled, ghost, borderless }
enum CustomButtonSize { large, medium, small }
enum CustomButtonShape { radius, stadium }
class CustomButton extends StatelessWidget {
final Widget child;
final void Function()? onPressed;
final Color? foregroundColor;
final Color? backgroundColor;
final CustomButtonType type;
final CustomButtonSize size;
final CustomButtonShape shape;
final double? width;
final double? height;
final EdgeInsetsGeometry? padding;
final bool isIcon;
const CustomButton({
Key? key,
required this.child,
this.onPressed,
this.foregroundColor,
this.backgroundColor,
this.type = CustomButtonType.filled,
this.size = CustomButtonSize.medium,
this.shape = CustomButtonShape.radius,
this.width,
this.height,
this.padding,
this.isIcon = false,
}) : super(key: key);
factory CustomButton.icon({
Key? key,
required Icon icon,
void Function()? onPressed,
Color? foregroundColor,
Color? backgroundColor,
CustomButtonShape shape,
CustomButtonSize size,
double? width,
double? height,
EdgeInsetsGeometry? padding,
}) = _ButtonWithIcon;
OutlinedBorder? get _shape {
switch (shape) {
case CustomButtonShape.stadium:
return const StadiumBorder();
case CustomButtonShape.radius:
return RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.w),
);
}
}
EdgeInsetsGeometry? get _padding {
switch (size) {
case CustomButtonSize.large:
return EdgeInsets.symmetric(horizontal: 18.w, vertical: 14.w);
case CustomButtonSize.medium:
return EdgeInsets.symmetric(horizontal: 16.w, vertical: 13.w);
case CustomButtonSize.small:
return EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.w);
}
}
double? get _fontSize {
switch (size) {
case CustomButtonSize.large:
return 18.w;
case CustomButtonSize.medium:
return 16.w;
case CustomButtonSize.small:
return 14.w;
}
}
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return SizedBox(
width: width,
height: height,
child: OutlinedButton(
onPressed: onPressed,
style: ButtonStyle(
textStyle: MaterialStateProperty.all(
Theme.of(context).textTheme.labelLarge?.copyWith(fontSize: _fontSize),
),
padding: MaterialStateProperty.all(padding ?? _padding),
foregroundColor: MaterialStateProperty.resolveWith((states) {
switch (type) {
case CustomButtonType.filled:
return foregroundColor ??
(isIcon ? colorScheme.primary : colorScheme.onPrimary);
case CustomButtonType.ghost:
case CustomButtonType.borderless:
final color = foregroundColor ?? colorScheme.primary;
final opacity = color.opacity / 2;
if (states.contains(MaterialState.pressed)) {
return color.withOpacity(opacity);
}
if (states.contains(MaterialState.disabled)) {
return color.withOpacity(opacity);
}
return color;
}
}),
backgroundColor: MaterialStateProperty.resolveWith((states) {
switch (type) {
case CustomButtonType.filled:
final color = backgroundColor ??
colorScheme.primary.withOpacity(isIcon ? 0.1 : 1);
final opacity = color.opacity / 2;
if (states.contains(MaterialState.pressed)) {
return color.withOpacity(opacity);
}
if (states.contains(MaterialState.disabled)) {
return color.withOpacity(opacity);
}
return color;
case CustomButtonType.ghost:
case CustomButtonType.borderless:
return Colors.transparent;
}
}),
side: MaterialStateProperty.resolveWith((states) {
switch (type) {
case CustomButtonType.filled:
case CustomButtonType.borderless:
return BorderSide.none;
case CustomButtonType.ghost:
final color = foregroundColor ?? colorScheme.primary;
final opacity = color.opacity / 2;
if (states.contains(MaterialState.pressed)) {
return BorderSide(
color: color.withOpacity(opacity),
width: 2.w,
);
}
if (states.contains(MaterialState.disabled)) {
return BorderSide(color: color.withOpacity(opacity));
}
return BorderSide(
color: color,
width: 2.w,
);
}
}),
shape: MaterialStateProperty.all(_shape),
),
child: child,
),
);
}
}
class _ButtonWithIcon extends CustomButton {
final Icon icon;
_ButtonWithIcon({
Key? key,
required this.icon,
void Function()? onPressed,
Color? foregroundColor,
Color? backgroundColor,
CustomButtonType type = CustomButtonType.filled,
CustomButtonSize size = CustomButtonSize.medium,
CustomButtonShape shape = CustomButtonShape.radius,
double? width,
double? height,
EdgeInsetsGeometry? padding,
}) : super(
key: key,
child: _ButtonWithIconChild(
icon: icon,
size: size,
padding: padding,
),
onPressed: onPressed,
foregroundColor: foregroundColor,
backgroundColor: backgroundColor ?? foregroundColor?.withOpacity(0.1),
type: type,
size: size,
shape: shape,
width: width,
height: height,
isIcon: true,
padding: padding ?? const EdgeInsets.all(0),
);
}
class _ButtonWithIconChild extends StatelessWidget {
final Icon icon;
final CustomButtonSize size;
final EdgeInsetsGeometry? padding;
const _ButtonWithIconChild({
Key? key,
required this.icon,
required this.size,
this.padding,
}) : super(key: key);
double? get _iconSize {
switch (size) {
case CustomButtonSize.large:
return 30.w;
case CustomButtonSize.medium:
return 24.w;
case CustomButtonSize.small:
return 18.w;
}
}
double get _padding {
switch (size) {
case CustomButtonSize.large:
return 12.w;
case CustomButtonSize.medium:
return 10.w;
case CustomButtonSize.small:
return 8.w;
}
}
@override
Widget build(BuildContext context) {
return Padding(
padding:
padding == null ? EdgeInsets.all(_padding) : const EdgeInsets.all(0),
child: IconTheme.merge(
data: IconThemeData(size: _iconSize),
child: icon,
),
);
}
}
......@@ -3,14 +3,23 @@ library widgets;
import 'dart:math';
import 'dart:io';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_book/utils/index.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:extended_image/extended_image.dart';
import '../theme.dart';
part 'toast.dart';
part 'loading.dart';
part 'empty.dart';
part 'image.dart';
part 'app_bar.dart';
part 'input.dart';
part 'button.dart';
part 'pull_scroll_view.dart';
\ No newline at end of file
part of widgets;
class CustomInputSearch extends StatelessWidget {
final IconData iconData;
final String? hintText;
final TextEditingController? controller;
final bool readOnly;
final void Function()? onTap;
const CustomInputSearch({
Key? key,
this.iconData = Icons.search_rounded,
this.hintText,
this.controller,
this.readOnly = false,
this.onTap,
}) : super(key: key);
EdgeInsetsGeometry get _padding {
return EdgeInsets.symmetric(
vertical: 7.w,
horizontal: 20.w,
);
}
@override
Widget build(BuildContext context) {
final inputDecoration = Theme.of(context).inputDecorationTheme;
return TextField(
readOnly: readOnly,
controller: controller,
onTap: onTap,
style: TextStyle(
// fontFamily: 'Sans',
fontSize: 16.w,
height: 1.2,
),
decoration: InputDecoration(
fillColor: Theme.of(context).colorScheme.tertiary,
contentPadding: _padding.subtract(EdgeInsets.symmetric(
horizontal: _padding.horizontal / 4,
)),
prefixIcon: Padding(
padding: EdgeInsets.symmetric(
horizontal: _padding.horizontal / 4,
),
child: Icon(
iconData,
size: 24.w,
color: const Color(0xFF858C94),
),
),
hintStyle: TextStyle(
color: Colours.c9,
fontSize: 12.w,
height: 1.5,
),
prefixIconConstraints: const BoxConstraints(),
hintText: hintText ?? '搜索',
enabledBorder: inputDecoration.enabledBorder?.copyWith(
borderSide: const BorderSide(color: Colors.transparent),
),
focusedBorder: inputDecoration.enabledBorder?.copyWith(
borderSide: const BorderSide(color: Colors.transparent),
),
disabledBorder: inputDecoration.enabledBorder?.copyWith(
borderSide: const BorderSide(color: Colors.transparent),
),
),
);
}
}
part of widgets;
class CustomPullScrollView extends StatelessWidget {
final EasyRefreshController controller;
final bool refreshOnStart;
final Widget? child;
final void Function()? onRefresh;
final void Function()? onLoading;
const CustomPullScrollView({
Key? key,
required this.controller,
this.refreshOnStart = true,
this.onRefresh,
this.onLoading,
this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return EasyRefresh(
header: const ClassicHeader(showText: false
),
footer: const ClassicFooter(showText: false),
controller: controller,
onRefresh: onRefresh,
onLoad: onLoading,
refreshOnStart: refreshOnStart,
child: child,
);
}
}
......@@ -17,6 +17,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.18"
badges:
dependency: "direct main"
description:
name: badges
sha256: a7b6bbd60dce418df0db3058b53f9d083c22cdb5132a052145dc267494df0b84
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.2"
boolean_selector:
dependency: transitive
description:
......@@ -25,6 +33,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
carousel_slider:
dependency: "direct main"
description:
name: carousel_slider
sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.2.1"
characters:
dependency: transitive
description:
......@@ -81,6 +97,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.3.3"
easy_refresh:
dependency: "direct main"
description:
name: easy_refresh
sha256: "77b025ea49f27b5ebc5eef40a6678be52564c293bd97ce91a4088d6646478329"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.3.2+1"
extended_image:
dependency: "direct main"
description:
......@@ -341,6 +365,22 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.3"
path_drawing:
dependency: transitive
description:
name: path_drawing
sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
path_provider:
dependency: "direct main"
description:
......
......@@ -38,26 +38,43 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
logger: 1.3.0
# getX
get: 4.6.5
# 路由
go_router: 10.1.0
flutter_easyloading: 3.0.5
# 存储基本数据
shared_preferences: 2.1.1
# 屏幕适配
flutter_screenutil: 5.8.2
pull_to_refresh_flutter3: 2.0.1
# 加载图片
extended_image: 8.0.2
# 图标库
ionicons: 0.2.2
# 网络
dio: 5.3.3
crypto: 3.0.3
convert: 3.0.1
# 录音
flutter_tts: 3.8.5
# webview
flutter_inappwebview: ^5.8.0
intl: 0.18.0
# 录音
flutter_sound: ^9.2.13
permission_handler: 11.0.1
audio_session: ^0.1.6
flutter_sound_platform_interface: 9.2.13
# 获取目录结构
path_provider: ^2.0.2
# 下拉刷新 上拉加载更多
easy_refresh: 3.3.2+1
# 角标
badges: ^3.1.2
# 图片预览 或 banner
carousel_slider: 4.2.1
dev_dependencies:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论