add homepage

This commit is contained in:
jyuesong
2022-01-12 15:00:55 +08:00
parent 7bfae045fb
commit 9f7164db48
15 changed files with 786 additions and 135 deletions

View File

@@ -0,0 +1,84 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'base_viewmodel.dart';
class BaseStateWidget<T extends BaseViewModel> extends ConsumerStatefulWidget {
final Widget Function(BuildContext context, T value, Widget? child) builder;
final ProviderBase<T> model;
final Widget? child;
final Function(T)? onReady;
const BaseStateWidget({
Key? key,
required this.builder,
required this.model,
this.child,
this.onReady,
}) : super(key: key);
@override
_BaseStateWidgetState<T> createState() => _BaseStateWidgetState<T>();
}
class _BaseStateWidgetState<T extends BaseViewModel> extends ConsumerState<BaseStateWidget<T>> {
@override
void initState() {
super.initState();
if (widget.onReady != null) {
widget.onReady!(ref.read<T>(widget.model));
}
}
@override
Widget build(BuildContext context) {
var viewModel = ref.watch<T>(widget.model);
if (viewModel.currentState == PageState.CONTENT) {
return widget.builder(context, viewModel, widget.child);
}
if (viewModel.currentState == PageState.LOADING) {
return Container(
alignment: Alignment.center,
child: const CupertinoActivityIndicator(),
);
}
if (viewModel.currentState == PageState.FAILED) {
return Container(
alignment: Alignment.center,
child: Text("请求失败"),
);
}
if (viewModel.currentState == PageState.EMPTY) {
return Container(
alignment: Alignment.center,
child: Text("暂无数据"),
);
}
return Container();
}
}
abstract class BaseState<T extends StatefulWidget> extends State {
late T parent;
@override
void initState() {
parent = widget as T;
super.initState();
WidgetsBinding.instance?.endOfFrame.then((_) {
firstFrameCalled();
});
}
void firstFrameCalled() {}
@override
Widget build(BuildContext context) {
return buildWidgets(context);
}
Widget buildWidgets(BuildContext context);
}

View File

@@ -0,0 +1,41 @@
import 'package:flutter/cupertino.dart';
class BaseViewModel extends ChangeNotifier {
PageState currentState = PageState.START;
void loading({bool notify = false}) {
currentState = PageState.LOADING;
if (notify) {
notifyListeners();
}
}
void success({bool notify = true}) {
currentState = PageState.CONTENT;
if (notify) {
notifyListeners();
}
}
void failed({bool notify = false}) {
currentState = PageState.FAILED;
if (notify) {
notifyListeners();
}
}
void empty({bool notify = false}) {
currentState = PageState.EMPTY;
if (notify) {
notifyListeners();
}
}
}
enum PageState {
START,
LOADING,
EMPTY,
CONTENT,
FAILED,
}

48
lib/base/ql_app_bar.dart Normal file
View File

@@ -0,0 +1,48 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class QlAppBar extends StatelessWidget with PreferredSizeWidget {
final String title;
final List<Widget>? actions;
final VoidCallback? backCall;
final bool canBack;
final Widget? backWidget;
QlAppBar({
Key? key,
required this.title,
this.actions,
this.backCall,
this.canBack = true,
this.backWidget,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Widget back = backWidget ??
GestureDetector(
onTap: () {
if (backCall != null) {
backCall!();
}
},
child: const Center(
child: Icon(
CupertinoIcons.left_chevron,
size: 20,
),
),
);
return AppBar(
leading: canBack ? back : null,
automaticallyImplyLeading: canBack,
title: Text(title),
centerTitle: true,
actions: [...?actions],
);
}
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

20
lib/base/theme.dart Normal file
View File

@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
var themeProvider = ChangeNotifierProvider((ref) => ThemeViewModel());
class ThemeViewModel extends ChangeNotifier {
ThemeData currentTheme = lightTheme;
void changeTheme() {
if (currentTheme == darkTheme) {
currentTheme = lightTheme;
} else {
currentTheme = darkTheme;
}
notifyListeners();
}
}
ThemeData darkTheme = ThemeData.dark().copyWith();
ThemeData lightTheme = ThemeData.light().copyWith();