Merge pull request #17 from Nealyang/master

add collection and judge mounted
This commit is contained in:
Nealyang
2019-01-10 19:47:41 +08:00
committed by GitHub
13 changed files with 247 additions and 118 deletions

View File

@ -5,7 +5,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.android.tools.build:gradle:3.2.0'
}
}

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View 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),
),
);
}
}

View File

@ -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)));
}
}

View File

@ -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);

View File

@ -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,

View File

@ -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
View File

@ -0,0 +1,5 @@
import 'package:event_bus/event_bus.dart';
class ApplicationEvent{
static EventBus event;
}

View File

@ -0,0 +1,6 @@
class CollectionEvent{
final String widgetName;
final bool isRemove;
// token uid...
CollectionEvent(this.widgetName,this.isRemove);
}

View File

@ -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 {

View File

@ -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';

View File

@ -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,
);
}
}