Files
FlutterUnit/lib/painter_system/gallery_unit.dart
2022-05-20 08:35:27 +08:00

227 lines
6.5 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_unit/app/blocs/color_change_bloc.dart';
import 'package:flutter_unit/components/permanent/feedback_widget.dart';
import 'package:flutter_unit/components/project/default/loading_shower.dart';
import 'package:flutter_unit/components/project/items/gallery/gallery_card_item.dart';
import 'package:flutter_unit/painter_system/bloc/gallery_unit/bloc.dart';
import 'package:flutter_unit/painter_system/gallery_factory.dart';
import 'gallery_detail_page.dart';
/// create by 张风捷特烈 on 2020/11/28
/// contact me by email 1981462002@qq.com
/// 说明:
class GalleryUnit extends StatefulWidget {
const GalleryUnit({Key? key}) : super(key: key);
@override
_GalleryUnitState createState() => _GalleryUnitState();
}
class _GalleryUnitState extends State<GalleryUnit> {
final ValueNotifier<double> factor = ValueNotifier<double>(0);
late PageController _ctrl;
final int _firstOffset = 1000; //初始偏移
int _position = 0; //页面位置
@override
void initState() {
super.initState();
_position = _position + _firstOffset;
double value = ((_position - _firstOffset + 1) % 5) / 5;
factor.value = value == 0 ? 1 : value;
_ctrl = PageController(
viewportFraction: 0.9,
initialPage: _position,
)..addListener(() {
if(_ctrl.page!=null){
double value = (_ctrl.page! - _firstOffset + 1) % 5 / 5;
factor.value = value == 0 ? 1 : value;
}
});
}
@override
void dispose() {
_ctrl.dispose();
factor.dispose();
super.dispose();
}
Color get color => BlocProvider.of<ColorChangeCubit>(context).state.tabColor;
Color get nextColor => BlocProvider.of<ColorChangeCubit>(context).state.nextTabColor;
bool get isDark => Theme.of(context).brightness == Brightness.dark;
BoxDecoration get boxDecoration => BoxDecoration(
color: isDark?Colors.white.withAlpha(33):Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(40), topRight: Radius.circular(40)),
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ValueListenableBuilder(
child: Column(
children: [
_buildTitle(context),
Expanded(
child: Container(
margin: const EdgeInsets.only(left: 8, right: 8),
child: BlocBuilder<GalleryUnitBloc,String>(
builder: _buildContentByState,
),
decoration: boxDecoration,
))
],
),
valueListenable: factor,
builder: (_,double value, child) => Container(
color: isDark?null:Color.lerp(
color,
nextColor,
value,
),
child: child,
),
),
);
}
Widget _buildTitle(BuildContext context) {
return Container(
alignment: const Alignment(0, 0.3),
height: MediaQuery.of(context).size.height * 0.2,
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
FlutterLogo(
size: 40,
),
SizedBox(
width: 10,
),
Text(
"绘制集录",
style: TextStyle(fontSize: 26, color: Colors.white),
),
],
),
);
}
Widget _buildContentByState(BuildContext context, String state) {
if(state.isEmpty){
return const LoadingShower();
}
return _buildContent(state);
}
Widget _buildContent(String galleryInfo) {
final List<Widget> widgets = (json.decode(galleryInfo) as List).map((e) {
GalleryInfo info = GalleryInfo.fromJson(e);
List<Widget> children = GalleryFactory.getGalleryByName(info.type);
return FeedbackWidget(
a: 0.95,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => GalleryDetailPage(
galleryInfo: info,
children: children,
)));
},
child: GalleryCardItem(
galleryInfo: info,
count: children.length,
),
);
}).toList();
return Container(
padding: const EdgeInsets.only(bottom: 80, top: 40),
child: Column(
children: [
Expanded(
child: PageView.builder(
controller: _ctrl,
itemBuilder: (_, index) {
return AnimatedBuilder(
child: Padding(
padding: const EdgeInsets.all(6.0),
child: widgets[
_fixPosition(index, _firstOffset, widgets.length)],
),
animation: _ctrl,
builder: (context, child) =>
_buildAnimItemByIndex(context, child, index),
);
},
onPageChanged: (index) {
_position = index;
},
),
),
_buildDiver(),
],
));
}
Widget _buildAnimItemByIndex(BuildContext context, Widget? child, int index) {
double value;
if (_ctrl.position.haveDimensions&&_ctrl.page!=null) {
value = _ctrl.page! - index;
} else {
value = (_position - index).toDouble();
}
value = (1 - ((value.abs()) * .5)).clamp(0, 1).toDouble();
value = Curves.easeOut.transform(value);
return Transform(
transform: Matrix4.diagonal3Values(1.0, value, 1.0),
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.all(6.0),
child: child,
),
);
}
Widget _buildDiver() => Container(
margin: const EdgeInsets.only(bottom: 12, left: 48, right: 48, top: 10),
height: 2,
child: ValueListenableBuilder(
valueListenable: factor,
builder: (context, value, widget) {
return LinearProgressIndicator(
backgroundColor: Colors.black,
value: factor.value,
valueColor: AlwaysStoppedAnimation(
Color.lerp(
color,
nextColor,
factor.value,
),
),
);
},
),
);
int _fixPosition(int realPos, int initPos, int length) {
final int offset = realPos - initPos;
int result = offset % length;
return result < 0 ? length + result : result;
}
}