mirror of
https://github.com/alibaba/flutter-go.git
synced 2025-07-15 03:04:25 +08:00
Merge branch 'develop' of github.com:alibaba/flutter-common-widgets-app into develop
This commit is contained in:
BIN
assets/images/calendar.png
Normal file
BIN
assets/images/calendar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 555 B |
BIN
assets/images/house.png
Normal file
BIN
assets/images/house.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 978 B |
BIN
assets/images/p1.png
Normal file
BIN
assets/images/p1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/images/p2.png
Normal file
BIN
assets/images/p2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 853 KiB |
BIN
assets/images/p3.png
Normal file
BIN
assets/images/p3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 871 KiB |
BIN
assets/images/plane.png
Normal file
BIN
assets/images/plane.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -14,8 +14,6 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
const String _kStartTag = '// START ';
|
|
||||||
const String _kEndTag = '// END';
|
|
||||||
|
|
||||||
Map<String, String> _exampleCode;
|
Map<String, String> _exampleCode;
|
||||||
String _code;
|
String _code;
|
||||||
@ -38,7 +36,6 @@ Future<void> _parseExampleCode(context,String filePath, AssetBundle bundle) asyn
|
|||||||
try {
|
try {
|
||||||
code = await bundle.loadString('lib/widgets/$filePath');
|
code = await bundle.loadString('lib/widgets/$filePath');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
print('${Application.github['widgetsURL']} $filePath');
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
_launchURL(Application.github['widgetsURL'] + filePath);
|
_launchURL(Application.github['widgetsURL'] + filePath);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* @Author: 一凨
|
||||||
|
* @Date: 2019-01-14 17:53:54
|
||||||
|
* @Last Modified by: 一凨
|
||||||
|
* @Last Modified time: 2019-01-14 17:57:51
|
||||||
|
*/
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import '../routers/application.dart';
|
||||||
|
import '../routers/routers.dart';
|
||||||
|
import 'dart:core';
|
||||||
|
|
||||||
|
|
||||||
class ListViewItem extends StatelessWidget {
|
class ListViewItem extends StatelessWidget {
|
||||||
final String itemUrl;
|
final String itemUrl;
|
||||||
@ -9,15 +18,6 @@ class ListViewItem extends StatelessWidget {
|
|||||||
const ListViewItem({Key key, this.itemUrl, this.itemTitle, this.data})
|
const ListViewItem({Key key, this.itemUrl, this.itemTitle, this.data})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
void _launchURL(String url, BuildContext context) async {
|
|
||||||
|
|
||||||
if (await canLaunch(url)) {
|
|
||||||
await launch(url);
|
|
||||||
} else {
|
|
||||||
throw 'Could not launch $url';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,7 +27,8 @@ class ListViewItem extends StatelessWidget {
|
|||||||
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
|
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_launchURL(itemUrl, context);
|
// _launchURL(itemUrl, context);
|
||||||
|
Application.router.navigateTo(context, '${Routes.webViewPage}?title=${Uri.encodeComponent(itemTitle)}&url=${Uri.encodeComponent(itemUrl)}');
|
||||||
},
|
},
|
||||||
title: Padding(
|
title: Padding(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -46,7 +46,6 @@ class Provider {
|
|||||||
|
|
||||||
for(int i = 0; i < expectTables.length; i++) {
|
for(int i = 0; i < expectTables.length; i++) {
|
||||||
if (!tables.contains(expectTables[i])) {
|
if (!tables.contains(expectTables[i])) {
|
||||||
print("table lost in app");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,14 @@
|
|||||||
* 新widget详情页模板
|
* 新widget详情页模板
|
||||||
*/
|
*/
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
import '../routers/application.dart';
|
import '../routers/application.dart';
|
||||||
|
import '../routers/routers.dart';
|
||||||
import '../components/markdown.dart';
|
import '../components/markdown.dart';
|
||||||
import '../model/collection.dart';
|
import '../model/collection.dart';
|
||||||
import '../widgets/index.dart';
|
import '../widgets/index.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import '../event/event-bus.dart';
|
import '../event/event-bus.dart';
|
||||||
import '../event/event-model.dart';
|
import '../event/event-model.dart';
|
||||||
import './full_screen_code_dialog.dart';
|
|
||||||
import '../routers/application.dart';
|
|
||||||
import '../routers/routers.dart';
|
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
|
||||||
class WidgetDemo extends StatefulWidget {
|
class WidgetDemo extends StatefulWidget {
|
||||||
@ -40,10 +37,9 @@ class WidgetDemo extends StatefulWidget {
|
|||||||
class _WidgetDemoState extends State<WidgetDemo> {
|
class _WidgetDemoState extends State<WidgetDemo> {
|
||||||
bool _hasCollected = false;
|
bool _hasCollected = false;
|
||||||
CollectionControlModel _collectionControl = new CollectionControlModel();
|
CollectionControlModel _collectionControl = new CollectionControlModel();
|
||||||
Color _collectionColor;
|
var _collectionIcons;
|
||||||
List widgetDemosList = new WidgetDemoList().getDemos();
|
List widgetDemosList = new WidgetDemoList().getDemos();
|
||||||
String _router = '';
|
String _router = '';
|
||||||
String _collText = '';
|
|
||||||
|
|
||||||
void showInSnackBar(String value) {
|
void showInSnackBar(String value) {
|
||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
@ -55,13 +51,6 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
|||||||
textColor: Colors.white);
|
textColor: Colors.white);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _launchURL(String url) async {
|
|
||||||
if (await canLaunch(url)) {
|
|
||||||
await launch(url);
|
|
||||||
} else {
|
|
||||||
throw 'Could not launch $url';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Widget> _buildContent() {
|
List<Widget> _buildContent() {
|
||||||
List<Widget> _list = [
|
List<Widget> _list = [
|
||||||
@ -143,24 +132,20 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
|||||||
|
|
||||||
void _selectValue(value){
|
void _selectValue(value){
|
||||||
if(value == 'doc'){
|
if(value == 'doc'){
|
||||||
_launchURL(widget.docUrl);
|
// _launchURL(widget.docUrl);
|
||||||
|
Application.router.navigateTo(context, '${Routes.webViewPage}?title=${Uri.encodeComponent(widget.title)} Doc&&url=${Uri.encodeComponent(widget.docUrl)}');
|
||||||
}else if(value =='code'){
|
}else if(value =='code'){
|
||||||
// _launchURL(Application.github['widgetsURL'] + widget.codeUrl);
|
|
||||||
Application.router.navigateTo(context, '${Routes.codeView}?filePath=${Uri.encodeComponent(widget.codeUrl)}');
|
Application.router.navigateTo(context, '${Routes.codeView}?filePath=${Uri.encodeComponent(widget.codeUrl)}');
|
||||||
|
|
||||||
}else{
|
|
||||||
_getCollection();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (_hasCollected) {
|
if (_hasCollected) {
|
||||||
_collectionColor = Colors.red;
|
_collectionIcons = Icons.favorite;
|
||||||
_collText='取消收藏';
|
|
||||||
} else {
|
} else {
|
||||||
_collectionColor =null;
|
_collectionIcons = Icons.favorite_border;
|
||||||
_collText='组件收藏';
|
|
||||||
}
|
}
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -173,6 +158,11 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
|||||||
},
|
},
|
||||||
icon: Icon(Icons.home),
|
icon: Icon(Icons.home),
|
||||||
),
|
),
|
||||||
|
new IconButton(
|
||||||
|
tooltip: 'collection',
|
||||||
|
onPressed: _getCollection,
|
||||||
|
icon: Icon(_collectionIcons),
|
||||||
|
),
|
||||||
PopupMenuButton<String>(
|
PopupMenuButton<String>(
|
||||||
onSelected: _selectValue,
|
onSelected: _selectValue,
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
||||||
@ -191,15 +181,6 @@ class _WidgetDemoState extends State<WidgetDemo> {
|
|||||||
title: Text('查看Demo'),
|
title: Text('查看Demo'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const PopupMenuDivider(),
|
|
||||||
PopupMenuItem<String>(
|
|
||||||
value: 'collection',
|
|
||||||
child: ListTile(
|
|
||||||
leading: Icon(Icons.star,size: 22.0,color: _collectionColor,),
|
|
||||||
title: Text(_collText),
|
|
||||||
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
192
lib/components/fourth_page_feature/page_dragger.dart
Normal file
192
lib/components/fourth_page_feature/page_dragger.dart
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import './pager_indicator.dart';
|
||||||
|
|
||||||
|
class PageDragger extends StatefulWidget {
|
||||||
|
|
||||||
|
final canDragLeftToRight;
|
||||||
|
final canDragRightToLeft;
|
||||||
|
|
||||||
|
final StreamController<SlideUpdate> slideUpdateStream;
|
||||||
|
|
||||||
|
|
||||||
|
PageDragger({
|
||||||
|
this.canDragLeftToRight,
|
||||||
|
this.canDragRightToLeft,
|
||||||
|
this.slideUpdateStream,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PageDraggerState createState() => _PageDraggerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PageDraggerState extends State<PageDragger> {
|
||||||
|
|
||||||
|
static const FULL_TRANSTITION_PX = 300.0;
|
||||||
|
|
||||||
|
Offset dragStart;
|
||||||
|
SlideDirection slideDirection;
|
||||||
|
double slidePercent = 0.0;
|
||||||
|
|
||||||
|
onDragStart(DragStartDetails details){
|
||||||
|
dragStart = details.globalPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragUpdate(DragUpdateDetails details) {
|
||||||
|
if (dragStart != null) {
|
||||||
|
final newPosition = details.globalPosition;
|
||||||
|
final dx = dragStart.dx - newPosition.dx;
|
||||||
|
|
||||||
|
if (dx > 0 && widget.canDragRightToLeft) {
|
||||||
|
slideDirection = SlideDirection.rightToLeft;
|
||||||
|
} else if (dx < 0 && widget.canDragLeftToRight) {
|
||||||
|
slideDirection = SlideDirection.leftToRight;
|
||||||
|
} else {
|
||||||
|
slideDirection = SlideDirection.none;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slideDirection != SlideDirection.none){
|
||||||
|
slidePercent = (dx / FULL_TRANSTITION_PX).abs().clamp(0.0, 1.0);
|
||||||
|
} else {
|
||||||
|
slidePercent = 0.0;
|
||||||
|
}
|
||||||
|
widget.slideUpdateStream.add(
|
||||||
|
new SlideUpdate(
|
||||||
|
UpdateType.dragging,
|
||||||
|
slideDirection,
|
||||||
|
slidePercent
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragEnd(DragEndDetails details){
|
||||||
|
widget.slideUpdateStream.add(
|
||||||
|
new SlideUpdate(
|
||||||
|
UpdateType.doneDragging,
|
||||||
|
SlideDirection.none,
|
||||||
|
0.0,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
dragStart = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onHorizontalDragStart: onDragStart ,
|
||||||
|
onHorizontalDragUpdate: onDragUpdate ,
|
||||||
|
onHorizontalDragEnd: onDragEnd ,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnimatedPageDragger{
|
||||||
|
|
||||||
|
static const PERCENT_PER_MILLISECOND = 0.005;
|
||||||
|
|
||||||
|
final slideDirection;
|
||||||
|
final transitionGoal;
|
||||||
|
|
||||||
|
AnimationController completionAnimationController;
|
||||||
|
|
||||||
|
AnimatedPageDragger({
|
||||||
|
this.slideDirection,
|
||||||
|
this.transitionGoal,
|
||||||
|
slidePercent,
|
||||||
|
StreamController<SlideUpdate> slideUpdateStream,
|
||||||
|
TickerProvider vsync,
|
||||||
|
}) {
|
||||||
|
final startSlidePercent = slidePercent;
|
||||||
|
var endSlidePercent;
|
||||||
|
var duration;
|
||||||
|
|
||||||
|
if ( transitionGoal == TransitionGoal.open){
|
||||||
|
endSlidePercent = 1.0;
|
||||||
|
|
||||||
|
final slideRemaining = 1.0 - slidePercent;
|
||||||
|
|
||||||
|
duration = new Duration(
|
||||||
|
milliseconds: (slideRemaining / PERCENT_PER_MILLISECOND).round()
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
endSlidePercent = 0.0;
|
||||||
|
duration = new Duration(
|
||||||
|
milliseconds: (slidePercent / PERCENT_PER_MILLISECOND).round()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
completionAnimationController = new AnimationController(
|
||||||
|
duration: duration,
|
||||||
|
vsync: vsync
|
||||||
|
)
|
||||||
|
..addListener((){
|
||||||
|
slidePercent = lerpDouble(
|
||||||
|
startSlidePercent,
|
||||||
|
endSlidePercent,
|
||||||
|
completionAnimationController.value
|
||||||
|
);
|
||||||
|
|
||||||
|
slideUpdateStream.add(
|
||||||
|
new SlideUpdate(
|
||||||
|
UpdateType.animating,
|
||||||
|
slideDirection,
|
||||||
|
slidePercent,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
..addStatusListener((AnimationStatus status){
|
||||||
|
|
||||||
|
if(status == AnimationStatus.completed){
|
||||||
|
slideUpdateStream.add(
|
||||||
|
new SlideUpdate(
|
||||||
|
UpdateType.doneAnimating,
|
||||||
|
slideDirection,
|
||||||
|
endSlidePercent,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
run(){
|
||||||
|
completionAnimationController.forward(from: 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(){
|
||||||
|
completionAnimationController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TransitionGoal{
|
||||||
|
open,
|
||||||
|
close,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UpdateType{
|
||||||
|
dragging,
|
||||||
|
doneDragging,
|
||||||
|
animating,
|
||||||
|
doneAnimating,
|
||||||
|
}
|
||||||
|
|
||||||
|
class SlideUpdate {
|
||||||
|
final updateType;
|
||||||
|
final direction;
|
||||||
|
final slidePercent;
|
||||||
|
|
||||||
|
SlideUpdate(
|
||||||
|
this.updateType,
|
||||||
|
this.direction,
|
||||||
|
this.slidePercent
|
||||||
|
);
|
||||||
|
}
|
53
lib/components/fourth_page_feature/page_reveal.dart
Normal file
53
lib/components/fourth_page_feature/page_reveal.dart
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class PageReveal extends StatelessWidget {
|
||||||
|
|
||||||
|
final double revealPercent;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
PageReveal({
|
||||||
|
this.revealPercent,
|
||||||
|
this.child
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ClipOval(
|
||||||
|
clipper: new CircleRevealClipper(revealPercent),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CircleRevealClipper extends CustomClipper<Rect>{
|
||||||
|
|
||||||
|
final double revealPercent;
|
||||||
|
|
||||||
|
|
||||||
|
CircleRevealClipper(
|
||||||
|
this.revealPercent
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Rect getClip(Size size) {
|
||||||
|
|
||||||
|
final epicenter = new Offset(size.width / 2, size.height * 0.9);
|
||||||
|
|
||||||
|
double theta = atan(epicenter.dy / epicenter.dx);
|
||||||
|
final distanceToCorner = epicenter.dy / sin(theta);
|
||||||
|
|
||||||
|
final radius = distanceToCorner * revealPercent;
|
||||||
|
final diameter = 2 * radius;
|
||||||
|
|
||||||
|
return new Rect.fromLTWH(epicenter.dx - radius, epicenter.dy - radius, diameter, diameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReclip(CustomClipper<Rect> oldClipper) {
|
||||||
|
// TODO: implement shouldReclip
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
156
lib/components/fourth_page_feature/pager_indicator.dart
Normal file
156
lib/components/fourth_page_feature/pager_indicator.dart
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import './pages.dart';
|
||||||
|
|
||||||
|
class PagerIndicator extends StatelessWidget {
|
||||||
|
|
||||||
|
final PagerIndicatorViewModel viewModel;
|
||||||
|
|
||||||
|
PagerIndicator({
|
||||||
|
this.viewModel,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
List<PageBubble> bubbles = [];
|
||||||
|
for(var i = 0; i < viewModel.pages.length; ++i ){
|
||||||
|
final page = viewModel.pages[i];
|
||||||
|
|
||||||
|
var percentActive;
|
||||||
|
|
||||||
|
if(i == viewModel.activeIndex){
|
||||||
|
percentActive = 1.0 - viewModel.slidePercent;
|
||||||
|
} else if (i == viewModel.activeIndex - 1 && viewModel.slideDirection == SlideDirection.leftToRight){
|
||||||
|
percentActive = viewModel.slidePercent;
|
||||||
|
} else if (i == viewModel.activeIndex + 1 && viewModel.slideDirection == SlideDirection.rightToLeft){
|
||||||
|
percentActive = viewModel.slidePercent;
|
||||||
|
}else {
|
||||||
|
percentActive = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHollow = i > viewModel.activeIndex || (i == viewModel.activeIndex && viewModel.slideDirection == SlideDirection.leftToRight);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bubbles.add(
|
||||||
|
new PageBubble(
|
||||||
|
viewModel: new PageBubbleViewModel(
|
||||||
|
page.iconAssetPath,
|
||||||
|
page.color,
|
||||||
|
isHollow,
|
||||||
|
percentActive,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final BUBBLE_WIDHT = 55.0 ;
|
||||||
|
final baseTranslation = ((viewModel.pages.length * BUBBLE_WIDHT) / 2) - (BUBBLE_WIDHT / 2) ;
|
||||||
|
var translation = baseTranslation - (viewModel.activeIndex * BUBBLE_WIDHT);
|
||||||
|
|
||||||
|
if (viewModel.slideDirection == SlideDirection.leftToRight){
|
||||||
|
translation += BUBBLE_WIDHT * viewModel.slidePercent;
|
||||||
|
}else if (viewModel.slideDirection == SlideDirection.rightToLeft){
|
||||||
|
translation -= BUBBLE_WIDHT * viewModel.slidePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Column(
|
||||||
|
children: <Widget>[
|
||||||
|
new Expanded(child: new Container()),
|
||||||
|
new Transform(
|
||||||
|
transform: new Matrix4.translationValues(translation, 0.0, 0.0),
|
||||||
|
child: new Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: bubbles,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SlideDirection{
|
||||||
|
leftToRight,
|
||||||
|
rightToLeft,
|
||||||
|
none,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PagerIndicatorViewModel{
|
||||||
|
final List<PageViewModel> pages;
|
||||||
|
final int activeIndex;
|
||||||
|
final SlideDirection slideDirection;
|
||||||
|
final double slidePercent;
|
||||||
|
|
||||||
|
PagerIndicatorViewModel(
|
||||||
|
this.pages,
|
||||||
|
this.activeIndex,
|
||||||
|
this.slideDirection,
|
||||||
|
this.slidePercent
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class PageBubble extends StatelessWidget {
|
||||||
|
|
||||||
|
final PageBubbleViewModel viewModel;
|
||||||
|
|
||||||
|
|
||||||
|
PageBubble({
|
||||||
|
this.viewModel
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Container(
|
||||||
|
width: 55.0,
|
||||||
|
height: 65.0,
|
||||||
|
child: new Center(
|
||||||
|
child: new Container(
|
||||||
|
width: lerpDouble(20.0,45.0,viewModel.activePercent),
|
||||||
|
height: lerpDouble(20.0,45.0,viewModel.activePercent),
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: viewModel.isHollow
|
||||||
|
? const Color(0x88FFFFFF).withAlpha(0x88 * viewModel.activePercent.round())
|
||||||
|
: const Color(0x88FFFFFF),
|
||||||
|
border: new Border.all(
|
||||||
|
color: viewModel.isHollow
|
||||||
|
? const Color(0x88FFFFFF).withAlpha((0x88 * (1.0 - viewModel.activePercent)).round())
|
||||||
|
: Colors.transparent,
|
||||||
|
width: 3.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: new Opacity(
|
||||||
|
opacity: viewModel.activePercent,
|
||||||
|
child: Image.asset(
|
||||||
|
viewModel.iconAssetPath,
|
||||||
|
color: viewModel.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PageBubbleViewModel {
|
||||||
|
final String iconAssetPath;
|
||||||
|
final Color color;
|
||||||
|
final bool isHollow;
|
||||||
|
final double activePercent;
|
||||||
|
|
||||||
|
PageBubbleViewModel (
|
||||||
|
this.iconAssetPath,
|
||||||
|
this.color,
|
||||||
|
this.isHollow,
|
||||||
|
this.activePercent,
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
136
lib/components/fourth_page_feature/pages.dart
Normal file
136
lib/components/fourth_page_feature/pages.dart
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../routers/application.dart';
|
||||||
|
import '../../routers/routers.dart';
|
||||||
|
|
||||||
|
final pages = [
|
||||||
|
new PageViewModel(
|
||||||
|
const Color(0xFFcd344f),
|
||||||
|
//'assets/mountain.png',
|
||||||
|
'assets/images/p2.png',
|
||||||
|
'FlutterGo是什么?',
|
||||||
|
'【FlutterGo】 是由"阿里拍卖"前端团队几位 Flutter 粉丝,用业余时间开发的一款,用于 Flutter 教学帮助的App,这里没有高大尚的概念,只有一个一个亲历的尝试,用最直观的方式展示的 Flutter 官方demo',
|
||||||
|
'assets/images/plane.png'),
|
||||||
|
new PageViewModel(
|
||||||
|
const Color(0xFF638de3),
|
||||||
|
//'assets/world.png',
|
||||||
|
'assets/images/p1.png',
|
||||||
|
'FLutterGo的背景',
|
||||||
|
'🐢 官网文档示例较不够健全,不够直观\n🐞 运行widget demo要到处翻阅资料\n🐌 英文文档翻译生涩难懂,学习资料太少\n',
|
||||||
|
'assets/images/calendar.png'),
|
||||||
|
new PageViewModel(
|
||||||
|
const Color(0xFFFF682D),
|
||||||
|
//'assets/home.png',
|
||||||
|
'assets/images/p3.png',
|
||||||
|
'FlutterGo的特点',
|
||||||
|
'🐡 详解常用widget多达 130+ 个\n🦋 持续迭代追新官方版本\n🐙 配套Demo详解widget用法\n🚀 一站式搞定所有常用widget,开箱即查\n',
|
||||||
|
'assets/images/house.png',
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
class Page extends StatelessWidget {
|
||||||
|
final PageViewModel viewModel;
|
||||||
|
final double percentVisible;
|
||||||
|
|
||||||
|
Page({
|
||||||
|
this.viewModel,
|
||||||
|
this.percentVisible = 1.0,
|
||||||
|
});
|
||||||
|
|
||||||
|
Widget creatButton(BuildContext context,String txt,IconData iconName,String type){
|
||||||
|
return RaisedButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
if(type == 'start'){
|
||||||
|
//Navigator.popUntil(context, ModalRoute.withName('/'));
|
||||||
|
}else if(type == 'goGithub'){
|
||||||
|
Application.router.navigateTo(context, '${Routes.webViewPage}?title=${Uri.encodeComponent(txt)} Doc&&url=${Uri.encodeComponent("https://github.com/alibaba/flutter-go")}');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
elevation: 10.0,
|
||||||
|
color:Colors.black26,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20)),
|
||||||
|
//如果不手动设置icon和text颜色,则默认使用foregroundColor颜色
|
||||||
|
icon: new Icon(iconName,color: Colors.white,size:20.0),
|
||||||
|
label: new Text(txt, maxLines: 1,style: TextStyle(color:Colors.white,fontSize: 16,fontWeight: FontWeight.w700),)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return new Container(
|
||||||
|
width: double.infinity,
|
||||||
|
color: viewModel.color,
|
||||||
|
child: new Opacity(
|
||||||
|
opacity: percentVisible,
|
||||||
|
child: new Column(
|
||||||
|
crossAxisAlignment:CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
new Transform(
|
||||||
|
transform: new Matrix4.translationValues(0.0, 50.0 * (1.0 - percentVisible) ,0.0),
|
||||||
|
child: new Padding(
|
||||||
|
padding: new EdgeInsets.only(top: 20.0, bottom: 10.0),
|
||||||
|
child:
|
||||||
|
new Image.asset(
|
||||||
|
viewModel.heroAssetPath,
|
||||||
|
width: 200.0,
|
||||||
|
height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
new Transform(
|
||||||
|
transform: new Matrix4.translationValues(0.0, 30.0 * (1.0 - percentVisible) ,0.0),
|
||||||
|
child: new Padding(
|
||||||
|
padding: new EdgeInsets.only(top: 10.0, bottom: 10.0),
|
||||||
|
child: new Text(
|
||||||
|
viewModel.title,
|
||||||
|
style: new TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontFamily: 'FlamanteRoma',
|
||||||
|
fontSize: 34.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
new Transform(
|
||||||
|
transform: new Matrix4.translationValues(0.0, 30.0 * (1.0 - percentVisible) ,0.0),
|
||||||
|
child: new Padding(
|
||||||
|
padding: new EdgeInsets.only(bottom: 10.0),
|
||||||
|
child: new Text(
|
||||||
|
viewModel.body,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: new TextStyle(
|
||||||
|
height:1.2,
|
||||||
|
color: Colors.white,
|
||||||
|
fontFamily: 'FlamanteRomaItalic',
|
||||||
|
fontSize: 18.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ButtonBar(
|
||||||
|
alignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
creatButton(context,'开始使用',Icons.add_circle_outline,'start'),
|
||||||
|
creatButton(context,'GitHub',Icons.arrow_forward,'goGithub'),
|
||||||
|
],)
|
||||||
|
]),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PageViewModel {
|
||||||
|
final Color color;
|
||||||
|
final String heroAssetPath;
|
||||||
|
final String title;
|
||||||
|
final String body;
|
||||||
|
final String iconAssetPath;
|
||||||
|
|
||||||
|
PageViewModel(
|
||||||
|
this.color,
|
||||||
|
this.heroAssetPath,
|
||||||
|
this.title,
|
||||||
|
this.body,
|
||||||
|
this.iconAssetPath,
|
||||||
|
);
|
||||||
|
}
|
@ -168,8 +168,8 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
tabs: <Tab>[
|
tabs: <Tab>[
|
||||||
Tab(text: '业界动态', icon: Icon(Icons.language)),
|
Tab(text: '业界动态', icon: Icon(Icons.language)),
|
||||||
Tab(text: '组件', icon: Icon(Icons.extension)),
|
Tab(text: '组件', icon: Icon(Icons.extension)),
|
||||||
Tab(text: '组件收藏', icon: Icon(Icons.star)),
|
Tab(text: '组件收藏', icon: Icon(Icons.favorite)),
|
||||||
Tab(text: '关于手册', icon: Icon(Icons.favorite)),
|
Tab(text: '关于手册', icon: Icon(Icons.line_weight)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -3,24 +3,32 @@ import 'package:fluro/fluro.dart';
|
|||||||
import '../views/category.dart';
|
import '../views/category.dart';
|
||||||
import '../widgets/404.dart';
|
import '../widgets/404.dart';
|
||||||
import '../common/full_screen_code_dialog.dart';
|
import '../common/full_screen_code_dialog.dart';
|
||||||
|
import '../views/web_view_page.dart';
|
||||||
|
|
||||||
var categoryHandler = new Handler(
|
var categoryHandler = new Handler(
|
||||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
String name = params["type"]?.first;
|
String name = params["type"]?.first;
|
||||||
|
|
||||||
return new CategoryHome(name);
|
return new CategoryHome(name);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
var widgetNotFoundHandler = new Handler(
|
var widgetNotFoundHandler = new Handler(
|
||||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
return new WidgetNotFound();
|
return new WidgetNotFound();
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
var fullScreenCodeDialog = new Handler(
|
var fullScreenCodeDialog = new Handler(
|
||||||
handlerFunc: (BuildContext context,Map<String, List<String>> params){
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
String path = params['filePath']?.first;
|
String path = params['filePath']?.first;
|
||||||
return new FullScreenCodeDialog(filePath: path,);
|
return new FullScreenCodeDialog(
|
||||||
}
|
filePath: path,
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
var webViewPageHand = new Handler(
|
||||||
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
|
String title = params['title']?.first;
|
||||||
|
String url = params['url']?.first;
|
||||||
|
return new WebViewPage(url, title);
|
||||||
|
});
|
||||||
|
@ -8,6 +8,7 @@ class Routes {
|
|||||||
static String root = "/";
|
static String root = "/";
|
||||||
static String widgetDemo = '/widget-demo';
|
static String widgetDemo = '/widget-demo';
|
||||||
static String codeView = '/code-view';
|
static String codeView = '/code-view';
|
||||||
|
static String webViewPage = '/web-view-page';
|
||||||
|
|
||||||
static void configureRoutes(Router router) {
|
static void configureRoutes(Router router) {
|
||||||
List widgetDemosList = new WidgetDemoList().getDemos();
|
List widgetDemosList = new WidgetDemoList().getDemos();
|
||||||
@ -19,6 +20,7 @@ class Routes {
|
|||||||
router.define('/category/:type', handler: categoryHandler);
|
router.define('/category/:type', handler: categoryHandler);
|
||||||
router.define('/category/error/404', handler: widgetNotFoundHandler);
|
router.define('/category/error/404', handler: widgetNotFoundHandler);
|
||||||
router.define(codeView,handler:fullScreenCodeDialog);
|
router.define(codeView,handler:fullScreenCodeDialog);
|
||||||
|
router.define(webViewPage,handler:webViewPageHand);
|
||||||
widgetDemosList.forEach((demo) {
|
widgetDemosList.forEach((demo) {
|
||||||
Handler handler = new Handler(
|
Handler handler = new Handler(
|
||||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
* @Author: 一凨
|
* @Author: 一凨
|
||||||
* @Date: 2019-01-08 17:12:58
|
* @Date: 2019-01-08 17:12:58
|
||||||
* @Last Modified by: 一凨
|
* @Last Modified by: 一凨
|
||||||
* @Last Modified time: 2019-01-08 20:14:56
|
* @Last Modified time: 2019-01-14 20:02:46
|
||||||
*/
|
*/
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../model/collection.dart';
|
import '../model/collection.dart';
|
||||||
import '../routers/application.dart';
|
import '../routers/application.dart';
|
||||||
|
import '../routers/routers.dart';
|
||||||
import '../event/event-bus.dart';
|
import '../event/event-bus.dart';
|
||||||
import '../event/event-model.dart';
|
import '../event/event-model.dart';
|
||||||
import 'package:event_bus/event_bus.dart';
|
import 'package:event_bus/event_bus.dart';
|
||||||
@ -15,8 +16,7 @@ class CollectionPage extends StatefulWidget {
|
|||||||
_CollectionPageState createState() => _CollectionPageState();
|
_CollectionPageState createState() => _CollectionPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CollectionPageState extends State<CollectionPage>
|
class _CollectionPageState extends State<CollectionPage> {
|
||||||
with AutomaticKeepAliveClientMixin {
|
|
||||||
_CollectionPageState() {
|
_CollectionPageState() {
|
||||||
final eventBus = new EventBus();
|
final eventBus = new EventBus();
|
||||||
ApplicationEvent.event = eventBus;
|
ApplicationEvent.event = eventBus;
|
||||||
@ -24,9 +24,7 @@ class _CollectionPageState extends State<CollectionPage>
|
|||||||
CollectionControlModel _collectionControl = new CollectionControlModel();
|
CollectionControlModel _collectionControl = new CollectionControlModel();
|
||||||
List<Collection> _collectionList = [];
|
List<Collection> _collectionList = [];
|
||||||
ScrollController _scrollController = new ScrollController();
|
ScrollController _scrollController = new ScrollController();
|
||||||
|
var _icons;
|
||||||
@override
|
|
||||||
bool get wantKeepAlive => true;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -76,8 +74,17 @@ class _CollectionPageState extends State<CollectionPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (_collectionList[index - 1].router.contains('http')) {
|
||||||
|
if (_collectionList[index - 1].name.endsWith('Doc')) {
|
||||||
|
_icons = Icons.library_books;
|
||||||
|
} else {
|
||||||
|
_icons = Icons.bookmark;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_icons = Icons.extension;
|
||||||
|
}
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 5.0),
|
||||||
margin: const EdgeInsets.only(bottom: 7.0),
|
margin: const EdgeInsets.only(bottom: 7.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -91,15 +98,26 @@ class _CollectionPageState extends State<CollectionPage>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
leading: Icon(
|
||||||
|
_icons,
|
||||||
|
size: 30.0,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
_collectionList[index - 1].name,
|
_collectionList[index - 1].name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontSize: 17.0),
|
style: TextStyle(fontSize: 17.0),
|
||||||
),
|
),
|
||||||
trailing:
|
trailing:
|
||||||
Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
|
Icon(Icons.keyboard_arrow_right, color: Colors.grey, size: 30.0),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Application.router
|
if (_collectionList[index - 1].router.contains('http')) {
|
||||||
.navigateTo(context, "${_collectionList[index - 1].router}");
|
Application.router.navigateTo(context,
|
||||||
|
'${Routes.webViewPage}?title=${Uri.encodeComponent(_collectionList[index - 1].name)}&url=${Uri.encodeComponent(_collectionList[index - 1].router)}');
|
||||||
|
} else {
|
||||||
|
Application.router
|
||||||
|
.navigateTo(context, "${_collectionList[index - 1].router}");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -107,7 +125,6 @@ class _CollectionPageState extends State<CollectionPage>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
|
||||||
if (_collectionList.length == 0) {
|
if (_collectionList.length == 0) {
|
||||||
return ListView(
|
return ListView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
@ -1,22 +1,118 @@
|
|||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../components/comp_list.dart';
|
import 'package:flutter_go/components/fourth_page_feature/page_dragger.dart';
|
||||||
|
import 'package:flutter_go/components/fourth_page_feature/page_reveal.dart';
|
||||||
|
import 'package:flutter_go/components/fourth_page_feature/pager_indicator.dart';
|
||||||
|
import 'package:flutter_go/components/fourth_page_feature/pages.dart';
|
||||||
|
|
||||||
|
import '../components/comp_list.dart';
|
||||||
|
|
||||||
class FourthPage extends StatefulWidget {
|
class FourthPage extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
FourthPageState createState() => new FourthPageState();
|
FourthPageState createState() => new FourthPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class FourthPageState extends State<FourthPage> {
|
class FourthPageState extends State<FourthPage> with TickerProviderStateMixin {
|
||||||
|
|
||||||
|
StreamController<SlideUpdate> slideUpdateStream;
|
||||||
|
AnimatedPageDragger animatedPageDragger;
|
||||||
|
|
||||||
|
int activeIndex = 0 ;
|
||||||
|
SlideDirection slideDirection = SlideDirection.none;
|
||||||
|
int nextPageIndex = 0 ;
|
||||||
|
double slidePercent= 0.0;
|
||||||
|
|
||||||
|
FourthPageState(){
|
||||||
|
slideUpdateStream = new StreamController<SlideUpdate>();
|
||||||
|
|
||||||
|
slideUpdateStream.stream.listen((SlideUpdate event){
|
||||||
|
setState(() {
|
||||||
|
if( event.updateType == UpdateType.dragging){
|
||||||
|
slideDirection = event.direction;
|
||||||
|
slidePercent = event.slidePercent;
|
||||||
|
|
||||||
|
if( slideDirection == SlideDirection.leftToRight ){
|
||||||
|
nextPageIndex = activeIndex - 1;
|
||||||
|
} else if (slideDirection == SlideDirection.rightToLeft){
|
||||||
|
nextPageIndex = activeIndex + 1;
|
||||||
|
} else{
|
||||||
|
nextPageIndex = activeIndex;
|
||||||
|
}
|
||||||
|
} else if( event.updateType == UpdateType.doneDragging){
|
||||||
|
if(slidePercent > 0.5){
|
||||||
|
|
||||||
|
animatedPageDragger = new AnimatedPageDragger(
|
||||||
|
slideDirection: slideDirection,
|
||||||
|
transitionGoal: TransitionGoal.open,
|
||||||
|
slidePercent: slidePercent,
|
||||||
|
slideUpdateStream: slideUpdateStream,
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
} else{
|
||||||
|
animatedPageDragger = new AnimatedPageDragger(
|
||||||
|
slideDirection: slideDirection,
|
||||||
|
transitionGoal: TransitionGoal.close,
|
||||||
|
slidePercent: slidePercent,
|
||||||
|
slideUpdateStream: slideUpdateStream,
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
nextPageIndex = activeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
animatedPageDragger.run();
|
||||||
|
}
|
||||||
|
else if( event.updateType == UpdateType.animating){
|
||||||
|
slideDirection = event.direction;
|
||||||
|
slidePercent = event.slidePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (event.updateType == UpdateType.doneAnimating){
|
||||||
|
activeIndex = nextPageIndex;
|
||||||
|
|
||||||
|
slideDirection = SlideDirection.none;
|
||||||
|
slidePercent = 0.0;
|
||||||
|
|
||||||
|
animatedPageDragger.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return new Container(
|
return new Stack(
|
||||||
child: new CompList()
|
children: [
|
||||||
|
new Page( // page 的主要内容
|
||||||
|
viewModel: pages[activeIndex],
|
||||||
|
percentVisible: 1.0 ,
|
||||||
|
),
|
||||||
|
new PageReveal(
|
||||||
|
revealPercent: slidePercent,
|
||||||
|
child: new Page(
|
||||||
|
viewModel: pages[nextPageIndex],
|
||||||
|
percentVisible: slidePercent ,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
new PagerIndicator(
|
||||||
|
viewModel: new PagerIndicatorViewModel(
|
||||||
|
pages,
|
||||||
|
activeIndex,
|
||||||
|
slideDirection,
|
||||||
|
slidePercent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
new PageDragger(
|
||||||
|
canDragLeftToRight: activeIndex > 0 ,
|
||||||
|
canDragRightToLeft: activeIndex < pages.length - 1 ,
|
||||||
|
slideUpdateStream: this.slideUpdateStream,
|
||||||
|
)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
120
lib/views/web_view_page.dart
Normal file
120
lib/views/web_view_page.dart
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* @Author: 一凨
|
||||||
|
* @Date: 2019-01-14 17:44:47
|
||||||
|
* @Last Modified by: 一凨
|
||||||
|
* @Last Modified time: 2019-01-14 19:47:14
|
||||||
|
*/
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
|
||||||
|
import '../model/collection.dart';
|
||||||
|
import '../event/event-bus.dart';
|
||||||
|
import '../event/event-model.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
|
||||||
|
class WebViewPage extends StatefulWidget {
|
||||||
|
final String url;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
WebViewPage(this.url, this.title);
|
||||||
|
_WebViewPageState createState() => _WebViewPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WebViewPageState extends State<WebViewPage> {
|
||||||
|
bool _hasCollected = false;
|
||||||
|
String _router = '';
|
||||||
|
var _collectionIcons;
|
||||||
|
CollectionControlModel _collectionControl = new CollectionControlModel();
|
||||||
|
|
||||||
|
void showInSnackBar(String value) {
|
||||||
|
Fluttertoast.showToast(
|
||||||
|
msg: value,
|
||||||
|
toastLength: Toast.LENGTH_SHORT,
|
||||||
|
gravity: ToastGravity.CENTER,
|
||||||
|
timeInSecForIos: 1,
|
||||||
|
backgroundColor: Colors.grey,
|
||||||
|
textColor: Colors.white);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_collectionControl.getRouterByName(widget.title.trim()).then((list) {
|
||||||
|
|
||||||
|
list.forEach((item) {
|
||||||
|
if(widget.title.trim() == item['name']){
|
||||||
|
_router = item['router'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_hasCollected = list.length > 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击收藏按钮
|
||||||
|
_getCollection() {
|
||||||
|
if (_hasCollected) {
|
||||||
|
// 删除操作
|
||||||
|
_collectionControl.deleteByName(widget.title.trim()).then((result) {
|
||||||
|
if (result > 0 && this.mounted) {
|
||||||
|
setState(() {
|
||||||
|
_hasCollected = false;
|
||||||
|
});
|
||||||
|
showInSnackBar('已取消收藏');
|
||||||
|
|
||||||
|
if (ApplicationEvent.event != null) {
|
||||||
|
ApplicationEvent.event
|
||||||
|
.fire(CollectionEvent(widget.title, _router, true));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print('删除错误');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 插入操作
|
||||||
|
_collectionControl
|
||||||
|
.insert(Collection(name: widget.title.trim(), router: widget.url))
|
||||||
|
.then((result) {
|
||||||
|
if (this.mounted) {
|
||||||
|
setState(() {
|
||||||
|
_hasCollected = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ApplicationEvent.event != null) {
|
||||||
|
ApplicationEvent.event
|
||||||
|
.fire(CollectionEvent(widget.title, _router, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
showInSnackBar('收藏成功');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (_hasCollected) {
|
||||||
|
_collectionIcons = Icons.favorite;
|
||||||
|
} else {
|
||||||
|
_collectionIcons = Icons.favorite_border;
|
||||||
|
}
|
||||||
|
return WebviewScaffold(
|
||||||
|
url: widget.url,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(widget.title),
|
||||||
|
actions: <Widget>[
|
||||||
|
new IconButton(
|
||||||
|
tooltip: 'goBack home',
|
||||||
|
onPressed: _getCollection,
|
||||||
|
icon: Icon(_collectionIcons,),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
withZoom: false,
|
||||||
|
withLocalStorage: true,
|
||||||
|
withJavascript: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -96,7 +96,6 @@ class PopupMenuButtonCustom extends StatelessWidget {
|
|||||||
: super();
|
: super();
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print('onSelected1:${widget.options}');
|
|
||||||
final String selectStr = widget.options['defaultSelect'];
|
final String selectStr = widget.options['defaultSelect'];
|
||||||
return PopupMenuButton(
|
return PopupMenuButton(
|
||||||
//如果提供,则用于此按钮的widget。
|
//如果提供,则用于此按钮的widget。
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/*
|
// 基本示例
|
||||||
* 基本示例
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class DefaultTextField extends StatelessWidget {
|
class DefaultTextField extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -20,7 +20,6 @@ class _MemoryImageDemoState extends State<MemoryImageDemo> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
rootBundle.load('assets/images/food01.jpeg').then((data) {
|
rootBundle.load('assets/images/food01.jpeg').then((data) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
print(data);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
bytes = data.buffer.asUint8List();
|
bytes = data.buffer.asUint8List();
|
||||||
});
|
});
|
||||||
|
@ -29,6 +29,7 @@ dependencies:
|
|||||||
# 本地存储、收藏功能
|
# 本地存储、收藏功能
|
||||||
shared_preferences: ^0.4.3
|
shared_preferences: ^0.4.3
|
||||||
dio: ^1.0.6
|
dio: ^1.0.6
|
||||||
|
flutter_webview_plugin: ^0.3.0+2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Reference in New Issue
Block a user