mirror of
https://github.com/alibaba/flutter-go.git
synced 2025-05-20 14:26:23 +08:00
Merge pull request #17 from Nealyang/master
add collection and judge mounted
This commit is contained in:
@ -5,7 +5,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.2'
|
||||
classpath 'com.android.tools.build:gradle:3.2.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
#Thu Jan 10 15:37:36 CST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
|
BIN
assets/images/nothing.png
Normal file
BIN
assets/images/nothing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
56
lib/common/list_view_item.dart
Normal file
56
lib/common/list_view_item.dart
Normal file
@ -0,0 +1,56 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import '../routers/application.dart';
|
||||
|
||||
class ListViewItem extends StatelessWidget {
|
||||
final String itemUrl;
|
||||
final String itemTitle;
|
||||
final String data;
|
||||
|
||||
const ListViewItem({Key key, this.itemUrl, this.itemTitle, this.data})
|
||||
: super(key: key);
|
||||
|
||||
void _launchURL(String url, BuildContext context) async {
|
||||
if (url.contains("https") || url.contains("http")) {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
} else {
|
||||
Application.router.navigateTo(context, "${url}");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
elevation: 4.0,
|
||||
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
|
||||
child: ListTile(
|
||||
onTap: () {
|
||||
_launchURL(itemUrl, context);
|
||||
},
|
||||
title: Padding(
|
||||
child: Text(
|
||||
itemTitle,
|
||||
style: TextStyle(color: Colors.black, fontSize: 15.0),
|
||||
),
|
||||
padding: EdgeInsets.only(top: 10.0),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
child: Text(data,
|
||||
style: TextStyle(color: Colors.black54, fontSize: 10.0)),
|
||||
padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
|
||||
)
|
||||
],
|
||||
),
|
||||
trailing:
|
||||
Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class ListViewItem extends StatelessWidget {
|
||||
final String itemUrl;
|
||||
final String itemTitle;
|
||||
final String data;
|
||||
|
||||
const ListViewItem({Key key, this.itemUrl, this.itemTitle, this.data})
|
||||
: super(key: key);
|
||||
|
||||
|
||||
void _launchURL(String url,BuildContext context) async {
|
||||
if (url.contains("https") || url.contains("http")) {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
}else{
|
||||
Navigator.of(context).pushNamed(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
elevation: 4.0,
|
||||
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
|
||||
child: ListTile(
|
||||
onTap: () {
|
||||
_launchURL(itemUrl,context);
|
||||
},
|
||||
title: Padding(
|
||||
child: Text(
|
||||
itemTitle,
|
||||
style: TextStyle(color: Colors.black, fontSize: 15.0),
|
||||
),
|
||||
padding: EdgeInsets.only(top: 10.0),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
child: Text(data,
|
||||
style: TextStyle(color: Colors.black54, fontSize: 10.0)),
|
||||
padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
|
||||
)
|
||||
],
|
||||
),
|
||||
trailing: Icon(Icons.keyboard_arrow_right,
|
||||
color: Colors.grey, size: 30.0)));
|
||||
}
|
||||
}
|
@ -14,18 +14,21 @@ class Provider {
|
||||
//Get a location using getDatabasesPath
|
||||
String databasesPath = await getDatabasesPath();
|
||||
String path = join(databasesPath, 'flutter.db');
|
||||
List<Map> list;
|
||||
// try {
|
||||
// db = await openDatabase(path, readOnly: true);
|
||||
List<Map> tables;
|
||||
try {
|
||||
db = await openDatabase(path);
|
||||
tables = await db
|
||||
.rawQuery('SELECT name FROM sqlite_master WHERE type = "table"');
|
||||
print('${tables.length} 7891');
|
||||
} catch (e) {
|
||||
print("Error $e");
|
||||
}
|
||||
|
||||
// } catch (e) {
|
||||
// print("Error $e");
|
||||
// }
|
||||
|
||||
if (db == null) {
|
||||
if (tables.length < 3) {
|
||||
// Delete the database
|
||||
await deleteDatabase(path);
|
||||
|
||||
// 关闭上面打开的db,否则无法执行open
|
||||
db.close();
|
||||
ByteData data = await rootBundle.load(join("assets", "app.db"));
|
||||
List<int> bytes =
|
||||
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
|
||||
|
@ -10,6 +10,8 @@ import '../components/markdown.dart';
|
||||
import '../model/collection.dart';
|
||||
import '../widgets/index.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import '../event/event-bus.dart';
|
||||
import '../event/event-model.dart';
|
||||
|
||||
class WidgetDemo extends StatefulWidget {
|
||||
final List<dynamic> contentList;
|
||||
@ -84,9 +86,11 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
||||
_router = item.routerName;
|
||||
}
|
||||
});
|
||||
setState(() {
|
||||
if(this.mounted){
|
||||
setState(() {
|
||||
_hasCollected = list.length > 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -100,6 +104,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
||||
_hasCollected = false;
|
||||
});
|
||||
showInSnackBar('已取消收藏');
|
||||
ApplicationEvent.event.fire(CollectionEvent(widget.title,true));
|
||||
return;
|
||||
}
|
||||
print('删除错误');
|
||||
@ -113,6 +118,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
||||
setState(() {
|
||||
_hasCollected = true;
|
||||
});
|
||||
ApplicationEvent.event.fire(CollectionEvent(widget.title,false));
|
||||
showInSnackBar('收藏成功');
|
||||
}
|
||||
});
|
||||
@ -167,6 +173,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _getCollection,
|
||||
mini: true,
|
||||
tooltip: '收藏',
|
||||
child: Icon(
|
||||
Icons.star,
|
||||
|
@ -9,12 +9,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:math';
|
||||
|
||||
|
||||
class ListRefresh extends StatefulWidget {
|
||||
final renderItem;
|
||||
final requestApi;
|
||||
|
||||
const ListRefresh([this.requestApi,this.renderItem]) : super();
|
||||
const ListRefresh([this.requestApi, this.renderItem]) : super();
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => listRefresh();
|
||||
@ -34,7 +33,8 @@ class listRefresh extends State<ListRefresh> {
|
||||
_getMoreData();
|
||||
_scrollController.addListener(() {
|
||||
// 如果下拉的当前位置到scroll的最下面
|
||||
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent) {
|
||||
_getMoreData();
|
||||
}
|
||||
});
|
||||
@ -43,7 +43,7 @@ class listRefresh extends State<ListRefresh> {
|
||||
/*
|
||||
* 回弹效果
|
||||
* */
|
||||
backElasticEffect(){
|
||||
backElasticEffect() {
|
||||
// double edge = 50.0;
|
||||
// double offsetFromBottom = _scrollController.position.maxScrollExtent - _scrollController.position.pixels;
|
||||
// if (offsetFromBottom < edge) { // 添加一个动画没有更多数据的时候 ListView 向下移动覆盖正在加载更多数据的标志
|
||||
@ -58,18 +58,22 @@ class listRefresh extends State<ListRefresh> {
|
||||
* list探底,执行的具体事件
|
||||
* */
|
||||
Future _getMoreData() async {
|
||||
if (!isLoading && _hasMore) { // 如果上一次异步请求数据完成 同时有数据可以加载
|
||||
if (!isLoading && _hasMore) {
|
||||
// 如果上一次异步请求数据完成 同时有数据可以加载
|
||||
setState(() => isLoading = true);
|
||||
//if(_hasMore){ // 还有数据可以拉新
|
||||
List newEntries = await mokeHttpRequest();
|
||||
//if (newEntries.isEmpty) {
|
||||
_hasMore = (_pageIndex <= _pageTotal);
|
||||
setState(() {
|
||||
items.addAll(newEntries);
|
||||
isLoading = false;
|
||||
});
|
||||
if (this.mounted) {
|
||||
setState(() {
|
||||
items.addAll(newEntries);
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
backElasticEffect();
|
||||
}else if (!isLoading && !_hasMore){ // 这样判断,减少以后的绘制
|
||||
} else if (!isLoading && !_hasMore) {
|
||||
// 这样判断,减少以后的绘制
|
||||
_pageIndex = 0;
|
||||
backElasticEffect();
|
||||
}
|
||||
@ -79,12 +83,12 @@ class listRefresh extends State<ListRefresh> {
|
||||
* 伪装吐出新数据
|
||||
* */
|
||||
Future<List> mokeHttpRequest() async {
|
||||
if(widget.requestApi is Function){
|
||||
final listObj = await widget.requestApi({'pageIndex':_pageIndex});
|
||||
if (widget.requestApi is Function) {
|
||||
final listObj = await widget.requestApi({'pageIndex': _pageIndex});
|
||||
_pageIndex = listObj['pageIndex'];
|
||||
_pageTotal = listObj['total'];
|
||||
return listObj['list'];
|
||||
}else {
|
||||
} else {
|
||||
return Future.delayed(Duration(seconds: 2), () {
|
||||
return [];
|
||||
});
|
||||
@ -97,20 +101,23 @@ class listRefresh extends State<ListRefresh> {
|
||||
* */
|
||||
Future<Null> _handleRefresh() async {
|
||||
List newEntries = await mokeHttpRequest();
|
||||
setState(() {
|
||||
items.clear();
|
||||
items.addAll(newEntries);
|
||||
isLoading = false;
|
||||
_hasMore = true;
|
||||
return null;
|
||||
});
|
||||
if (this.mounted) {
|
||||
setState(() {
|
||||
items.clear();
|
||||
items.addAll(newEntries);
|
||||
isLoading = false;
|
||||
_hasMore = true;
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 加载中的提示
|
||||
* */
|
||||
Widget _buildLoadText() {
|
||||
return Container(child: Padding(
|
||||
return Container(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: Center(
|
||||
child: Text("数据没有更多了!!!"),
|
||||
@ -122,23 +129,28 @@ class listRefresh extends State<ListRefresh> {
|
||||
* 上提加载loading的widget,如果数据到达极限,显示没有更多
|
||||
* */
|
||||
Widget _buildProgressIndicator() {
|
||||
if(_hasMore){
|
||||
if (_hasMore) {
|
||||
return new Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: new Center(
|
||||
child:Column(
|
||||
children: <Widget>[
|
||||
new Opacity(
|
||||
opacity: isLoading ? 1.0 : 0.0,
|
||||
child: new CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.blue)),
|
||||
),
|
||||
SizedBox(height:20.0),
|
||||
Text('稍等片刻更精彩...',style: TextStyle(fontSize: 14.0),)
|
||||
],)
|
||||
//child:
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
new Opacity(
|
||||
opacity: isLoading ? 1.0 : 0.0,
|
||||
child: new CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation(Colors.blue)),
|
||||
),
|
||||
SizedBox(height: 20.0),
|
||||
Text(
|
||||
'稍等片刻更精彩...',
|
||||
style: TextStyle(fontSize: 14.0),
|
||||
)
|
||||
],
|
||||
)
|
||||
//child:
|
||||
),
|
||||
);
|
||||
}else {
|
||||
} else {
|
||||
return _buildLoadText();
|
||||
}
|
||||
}
|
||||
@ -152,11 +164,11 @@ class listRefresh extends State<ListRefresh> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new RefreshIndicator(
|
||||
child:ListView.builder(
|
||||
child: ListView.builder(
|
||||
itemCount: items.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if(index == 0 && index != items.length){
|
||||
return Container(height:0);
|
||||
if (index == 0 && index != items.length) {
|
||||
return Container(height: 0);
|
||||
}
|
||||
if (index == items.length) {
|
||||
//return _buildLoadText();
|
||||
@ -165,7 +177,7 @@ class listRefresh extends State<ListRefresh> {
|
||||
//print('itemsitemsitemsitems:${items[index].title}');
|
||||
//return ListTile(title: Text("Index${index}:${items[index].title}"));
|
||||
if (widget.renderItem is Function) {
|
||||
return widget.renderItem(index,items[index]);
|
||||
return widget.renderItem(index, items[index]);
|
||||
}
|
||||
//return makeCard(index,items[index]);
|
||||
}
|
||||
@ -175,4 +187,4 @@ class listRefresh extends State<ListRefresh> {
|
||||
onRefresh: _handleRefresh,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
lib/event/event-bus.dart
Normal file
5
lib/event/event-bus.dart
Normal file
@ -0,0 +1,5 @@
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
|
||||
class ApplicationEvent{
|
||||
static EventBus event;
|
||||
}
|
6
lib/event/event-model.dart
Normal file
6
lib/event/event-model.dart
Normal file
@ -0,0 +1,6 @@
|
||||
class CollectionEvent{
|
||||
final String widgetName;
|
||||
final bool isRemove;
|
||||
// token uid...
|
||||
CollectionEvent(this.widgetName,this.isRemove);
|
||||
}
|
@ -14,6 +14,8 @@ import 'model/widget.dart';
|
||||
import './widgets/index.dart';
|
||||
import 'package:flutter_rookie_book/components/SearchInput.dart';
|
||||
|
||||
|
||||
|
||||
const int ThemeColor = 0xFFC91B3A;
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_rookie_book/common/myListView.dart';
|
||||
import 'package:flutter_rookie_book/common/list_view_item.dart';
|
||||
//import 'package:flutter_rookie_book/components/CompList.dart';
|
||||
import 'package:flutter_rookie_book/components/ListRefresh.dart' as listComp;
|
||||
import 'package:flutter_rookie_book/components/Pagination.dart';
|
||||
|
@ -6,30 +6,123 @@
|
||||
*/
|
||||
import 'package:flutter/material.dart';
|
||||
import '../model/collection.dart';
|
||||
import '../routers/application.dart';
|
||||
import '../event/event-bus.dart';
|
||||
import '../event/event-model.dart';
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
|
||||
class CollectionPage extends StatefulWidget {
|
||||
_CollectionPageState createState() => _CollectionPageState();
|
||||
}
|
||||
|
||||
class _CollectionPageState extends State<CollectionPage> {
|
||||
_CollectionPageState() {
|
||||
final eventBus = new EventBus();
|
||||
ApplicationEvent.event = eventBus;
|
||||
}
|
||||
CollectionControlModel _collectionControl = new CollectionControlModel();
|
||||
List<Collection> _collectionList = [];
|
||||
List<Collection> _collectionList;
|
||||
ScrollController _scrollController = new ScrollController();
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
_getList();
|
||||
ApplicationEvent.event.on<CollectionEvent>().listen((event) {
|
||||
_getList();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _getList() {
|
||||
_collectionList = [];
|
||||
_collectionControl.getAllCollection().then((resultList) {
|
||||
resultList.forEach((item) {
|
||||
_collectionList.add(item);
|
||||
});
|
||||
if (this.mounted) {
|
||||
setState(() {
|
||||
_collectionList = _collectionList;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget _renderList(context, index) {
|
||||
if (index == 0) {
|
||||
return Container(
|
||||
height: 40.0,
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.warning,
|
||||
size: 22.0,
|
||||
),
|
||||
SizedBox(
|
||||
width: 5.0,
|
||||
),
|
||||
Text('模拟器重新运行会丢失收藏'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
margin: const EdgeInsets.only(bottom: 7.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [
|
||||
new BoxShadow(
|
||||
color: const Color(0xFFd0d0d0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 2.0,
|
||||
offset: Offset(3.0, 2.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
_collectionList[index - 1].name,
|
||||
style: TextStyle(fontSize: 17.0),
|
||||
),
|
||||
trailing:
|
||||
Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
|
||||
onTap: () {
|
||||
Application.router
|
||||
.navigateTo(context, "${_collectionList[index - 1].router}");
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_collectionControl.getAllCollection().then((resultList) {
|
||||
_collectionList = resultList;
|
||||
_collectionList.forEach((item){
|
||||
print(item.toMap());
|
||||
});
|
||||
});
|
||||
return Container(
|
||||
child: Text('敬请期待'),
|
||||
print(_collectionList);
|
||||
if (_collectionList.length == 0) {
|
||||
return ListView(
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Image.asset(
|
||||
'assets/images/nothing.png',
|
||||
fit: BoxFit.contain,
|
||||
width: MediaQuery.of(context).size.width / 2,
|
||||
),
|
||||
Text('暂无收藏,赶紧去收藏一个吧!'),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
itemBuilder: _renderList,
|
||||
itemCount: _collectionList.length + 1,
|
||||
controller: _scrollController,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user