diff --git a/lib/mIcons.dart b/lib/mIcons.dart index a9e8931..a87d1ce 100644 --- a/lib/mIcons.dart +++ b/lib/mIcons.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; @@ -5,15 +6,24 @@ class MIcon { String key; int codepoint; IconData iconData; + String category; MIcon( - {@required this.key, @required this.codepoint, @required this.iconData}); + {@required this.key, + @required this.codepoint, + @required this.iconData, + this.category = ""}); } class MIcons { List items = []; + List categories = []; - Future> fetchIcons() async { + Map _codepoints = {}; + + MIcons(); + + Future fetchCodepoints() async { String url = "https://raw.githubusercontent.com/flutter/flutter/master/packages/flutter/lib/src/material/icons.dart"; @@ -25,17 +35,41 @@ class MIcons { http.Response res = await http.get(url); regexp.allMatches(res.body).forEach((match) { String key = match.group(1); - int codepoint = int.tryParse(match.group(2), radix: 16); - IconData iconData = IconData(codepoint, fontFamily: "MaterialIcons"); - this.items.add( - MIcon( - key: key, - codepoint: codepoint, - iconData: iconData, - ), + String codepoint = match.group(2); + + this._codepoints[key] = int.tryParse(codepoint, radix: 16); + }); + } + + Future fetch() async { + if (this._codepoints.length == 0) { + await fetchCodepoints(); + } + + String url = "https://material.io/tools/icons/static/data.json"; + http.Response res = await http.get(url); + + var json = jsonDecode(res.body); + json["categories"].forEach((category) { + category["icons"].forEach((_icon) { + String key = _icon["id"].toString(); + if (this._codepoints.containsKey(key)) { + MIcon icon = MIcon( + key: key, + codepoint: this._codepoints[key], + iconData: + IconData(this._codepoints[key], fontFamily: "MaterialIcons"), + category: category["name"], ); + this.items.add(icon); + + if (!this.categories.contains(category["name"])) { + this.categories.add(category["name"]); + } + } + }); }); - return this.items; + return this; } } diff --git a/lib/main.dart b/lib/main.dart index 77f538b..fcd71ec 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,54 +11,96 @@ class MyApp extends StatelessWidget { } } -class MaterialIconsViewer extends StatelessWidget { +class MaterialIconsViewer extends StatefulWidget { + @override + _MaterialIconsViewerState createState() => _MaterialIconsViewerState(); +} + +class _MaterialIconsViewerState extends State { + List icons; + List categories; + + int columnsWidth; + + @override + void initState() { + this.columnsWidth = 64; + + MIcons().fetch().then((_icons) { + setState(() { + this.icons = _icons.items; + this.categories = _icons.categories; + }); + }); + + super.initState(); + } + @override Widget build(BuildContext context) { Size deviceSize = MediaQuery.of(context).size; - double columnWidth = 64; - int columnCount = deviceSize.width ~/ columnWidth; - return Scaffold( - appBar: AppBar( - title: Text("Material Icons Viewer"), - ), - body: SafeArea( - child: FutureBuilder( - future: MIcons().fetchIcons(), - builder: (context, future) { - if (!future.hasData) { - return Center(child: CircularProgressIndicator()); - } - - List icons = future.data; - return GridView.builder( - itemCount: icons.length, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: columnCount, + int columnCount = deviceSize.width ~/ this.columnsWidth; + return (this.icons == null) + ? Center(child: CircularProgressIndicator()) + : DefaultTabController( + length: this.categories.length, + child: Scaffold( + appBar: AppBar( + title: Text("Material Icons"), + bottom: TabBar( + isScrollable: true, + tabs: List.generate(this.categories.length, (index) { + return Text( + this.categories[index], + ); + }), + ), ), - itemBuilder: (context, index) { - MIcon icon = icons[index]; - return GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => VIcon(icon: icon), - fullscreenDialog: true, + body: TabBarView( + // physics: PageScrollPhysics(), + children: List.generate( + this.categories.length, + (index) { + List filderedIcons = this + .icons + .where( + (icon) => icon.category == this.categories[index]) + .toList(); + return SafeArea( + child: GridView.builder( + itemCount: filderedIcons.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: columnCount, + ), + itemBuilder: (context, index) { + MIcon icon = filderedIcons[index]; + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => VIcon(icon: icon), + fullscreenDialog: true, + ), + ); + }, + child: Card( + child: Hero( + tag: icon.key, + child: Icon( + icon.iconData, + size: this.columnsWidth * 0.8, + ), + ), + ), + ); + }, ), ); }, - child: Card( - child: Hero( - tag: icon.key, - child: Icon(icon.iconData, size: columnWidth * 0.8), - ), - ), - ); - }, - ); - }, - ), - ), - ); + ), + ), + ), + ); } }