Skip to content

Instantly share code, notes, and snippets.

@scottbaggett
Created May 29, 2019 15:43
Show Gist options
  • Save scottbaggett/70a9ab7a0e2d23cfd2d91aa39e2d57ef to your computer and use it in GitHub Desktop.
Save scottbaggett/70a9ab7a0e2d23cfd2d91aa39e2d57ef to your computer and use it in GitHub Desktop.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:mgm_resorts/indigo_theme.dart';
import 'package:mgm_resorts/widgets/fade_in_on_scroll.dart';
import 'package:mgm_resorts/widgets/typography/typography.dart';
import 'package:provider/provider.dart';
import 'package:flutter_range_slider/flutter_range_slider.dart';
class _FiltersViewModel with ChangeNotifier {
List _activeFilters = [];
double _sliderLowerValue = 0;
double _sliderUpperValue = 4;
_FiltersViewModel();
set activeFilters(filters) {
_activeFilters = filters;
notifyListeners();
}
void setSliderValues(lower, upper) {
_sliderLowerValue = lower;
_sliderUpperValue = upper;
print('slider lower: $_sliderLowerValue, upper: $_sliderUpperValue');
notifyListeners();
}
void toggleFilter(filter) {
_activeFilters.contains(filter)
? _activeFilters.remove(filter)
: _activeFilters.add(filter);
notifyListeners();
}
void clearFilters() {
_activeFilters = [];
_sliderLowerValue = 0;
_sliderUpperValue = 4;
notifyListeners();
}
double get sliderLowerValue => _sliderLowerValue;
double get sliderUpperValue => _sliderUpperValue;
List get activeFilters => _activeFilters;
}
class _ClearButton extends StatelessWidget {
const _ClearButton({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
var model = Provider.of<_FiltersViewModel>(context);
return GestureDetector(
onTap: () {
model.clearFilters();
},
child: Body("clear"),
);
}
}
class _AppBar extends StatelessWidget {
final ScrollController controller;
final _pageTitle = 'Filters';
const _AppBar({
Key key,
this.controller,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return CupertinoSliverNavigationBar(
padding: EdgeInsetsDirectional.only(start: 0, end: 16),
backgroundColor: white,
border: Border(),
leading: IconButton(
padding: EdgeInsets.all(0),
alignment: Alignment.centerLeft,
icon: SvgPicture.asset('assets/svg/close.svg', color: black),
onPressed: () {},
),
largeTitle: Text(
_pageTitle,
style: Theme.of(context).textTheme.display1,
),
trailing: _ClearButton(),
middle: FadeInOnScroll(
child: Text(_pageTitle),
controller: controller,
offset: 22,
),
);
}
}
class _FilterGroupTitle extends StatelessWidget {
final String title;
const _FilterGroupTitle({
Key key,
@required this.title,
}) : assert(title != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 32,
child: Text(title),
);
}
}
class FilterButton extends StatelessWidget {
final bool active;
final String label;
final Function onPressed;
const FilterButton({
Key key,
this.active,
this.label,
this.onPressed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return (active)
? FlatButton(
color: indigo,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(4),
),
onPressed: () {
if (onPressed != null) onPressed();
},
child: Caption(
label,
height: 0.8,
color: white,
),
)
: OutlineButton(
onPressed: () {
if (onPressed != null) onPressed();
},
color: white,
splashColor: indigo,
borderSide: BorderSide(color: black),
highlightedBorderColor: indigo,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(4),
),
child: Caption(
label,
height: 0.8,
));
}
}
class _FilterButtonGroupButtons extends StatelessWidget {
final List filters;
const _FilterButtonGroupButtons({Key key, this.filters}) : super(key: key);
@override
Widget build(BuildContext context) {
var model = Provider.of<_FiltersViewModel>(context);
return Wrap(
runSpacing: -4,
children: filters.map((
filter,
) {
return Padding(
padding: const EdgeInsets.only(right: 6.0),
child: FilterButton(
label: filter,
active: model.activeFilters.contains(filter),
onPressed: () {
model.toggleFilter(filter);
},
),
);
}).toList());
}
}
class _FilterButtonGroup extends StatelessWidget {
final String title;
final List filters;
final List selectedFilters;
/// Allow the header to be pinned to the appbar as user scrolls
final bool pinned;
const _FilterButtonGroup({
Key key,
this.title,
this.filters,
this.selectedFilters,
this.pinned = false,
}) : assert(filters != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_FilterGroupTitle(title: title),
_FilterButtonGroupButtons(filters: filters),
],
),
);
}
}
class _PriceGraphClipper extends CustomClipper<Path> {
/// Adds a quadratic bezier segment that curves from the current
/// point to the given point (x2,y2), using the control point
/// (x1,y1).
// void quadraticBezierTo(double x1, double y1, double x2, double y2)
/// Adds a cubic bezier segment that curves from the current point
/// to the given point (x3,y3), using the control points (x1,y1) and
/// (x2,y2).
// void cubicTo(double x1, double y1, double x2, double y2, double x3, double y3) native 'Path_cubicTo';
@override
Path getClip(Size size) {
var path = new Path();
var w = size.width;
var h = size.height;
path.moveTo(0, h);
path.lineTo(20, h - 12);
path.lineTo(w / 6, h / 10);
path.lineTo(w / 4 + w / 8, 0);
path.lineTo(w / 2 + w / 8, h - 20);
path.lineTo(w * 0.8, h - 20);
path.lineTo(w, h);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
class _PriceRangeGraph extends StatelessWidget {
const _PriceRangeGraph({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: ThemePadding.insetHorizontalLarge,
child: ClipPath(
clipper: _PriceGraphClipper(),
child: Container(
color: Color(0xFFE0E2FD),
),
),
);
}
}
class _FilterPricePicker extends StatelessWidget {
const _FilterPricePicker({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
var model = Provider.of<_FiltersViewModel>(context);
var _disabled = Color(0xFFE0E2FD);
return Stack(
children: <Widget>[
Container(
height: 80,
child: Column(
children: <Widget>[
Expanded(
child: _PriceRangeGraph(),
),
SizedBox(height: 32),
],
),
),
Positioned(
bottom: -3,
left: 0,
right: 0,
child: Column(
children: <Widget>[
RangeSlider(
min: 0,
max: 4,
divisions: 4,
lowerValue: model.sliderLowerValue,
upperValue: model.sliderUpperValue,
onChanged: (double lower, double upper) {
model.setSliderValues(lower, upper);
},
),
Container(
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Caption(
"\$",
color: (model.sliderLowerValue < 1) ? indigo : _disabled,
),
Caption(
"\$\$",
color: (model.sliderLowerValue < 2 &&
model.sliderUpperValue > 1)
? indigo
: _disabled,
),
Caption(
"\$\$\$",
color: (model.sliderLowerValue < 3 &&
model.sliderUpperValue > 2)
? indigo
: _disabled,
),
Caption(
"\$\$\$\$",
color: (model.sliderUpperValue > 3) ? indigo : _disabled,
),
],
),
),
],
),
)
],
);
}
}
class Math {}
class Filters extends StatefulWidget {
@override
State<Filters> createState() => _Filters();
}
class _Filters extends State<Filters> {
ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
}
_separator() {
return SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Container(height: 1, color: inputGrey),
));
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<_FiltersViewModel>(
builder: (_) => _FiltersViewModel(),
child: Scaffold(
body: Container(
color: white,
child: SafeArea(
left: false,
right: false,
bottom: false,
child: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
_AppBar(
controller: _scrollController,
),
SliverToBoxAdapter(
child: Container(
padding: ThemePadding.insetPrimary,
child: _FilterButtonGroup(
title: 'Category',
filters: [
'Attractions',
'Cirque du Soleil',
'Comedy & Stand Up',
'Concerts',
'Magic',
'Mature Audiences',
'Sporting Events'
],
),
),
),
_separator(),
SliverToBoxAdapter(
child: Container(
padding: ThemePadding.insetPrimary,
child: _FilterButtonGroup(
title: 'Region',
filters: [
'Las Vegas',
'Maryland',
'Massachusetts',
],
),
),
),
_separator(),
SliverToBoxAdapter(
child: Container(
padding: ThemePadding.insetPrimary,
child: _FilterGroupTitle(title: 'Price'),
),
),
SliverToBoxAdapter(
child: Container(
padding: ThemePadding.insetPrimary,
child: _FilterPricePicker(),
),
),
_separator(),
SliverToBoxAdapter(
child: Container(
padding: ThemePadding.insetPrimary,
child: _FilterButtonGroup(
title: 'Property',
filters: [
'ARIA',
'Bellagio',
'Vdara',
'MGM Grand',
'Siganture',
'Mandalay Bay',
'Delano',
'Park MGM',
'NoMad',
'Mirage',
'New York-New York',
'Luxor',
'Excalibur',
'Circus Circus',
],
),
),
),
],
),
),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment