Commit c137b2bc authored by Brian Egan's avatar Brian Egan

Add FaIcon Widget to fix alignment / cutoff issues for folks

parent c2044e29
...@@ -26,9 +26,9 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; ...@@ -26,9 +26,9 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class MyWidget extends StatelessWidget { class MyWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new IconButton( return IconButton(
// Use the FontAwesomeIcons class for the IconData // Use the FaIcon Widget + FontAwesomeIcons class for the IconData
icon: new Icon(FontAwesomeIcons.gamepad), icon: FaIcon(FontAwesomeIcons.gamepad),
onPressed: () { print("Pressed"); } onPressed: () { print("Pressed"); }
); );
} }
......
...@@ -3,28 +3,28 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; ...@@ -3,28 +3,28 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:font_awesome_flutter_example/icons.dart'; import 'package:font_awesome_flutter_example/icons.dart';
void main() { void main() {
runApp(new FontAwesomeGalleryApp()); runApp(FontAwesomeGalleryApp());
} }
class FontAwesomeGalleryApp extends StatelessWidget { class FontAwesomeGalleryApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new MaterialApp( return MaterialApp(
title: 'Font Awesome Flutter Gallery', title: 'Font Awesome Flutter Gallery',
theme: new ThemeData.light().copyWith( theme: ThemeData.light().copyWith(
iconTheme: new IconThemeData(size: 36.0, color: Colors.black87), iconTheme: IconThemeData(size: 36.0, color: Colors.black87),
textTheme: new TextTheme( textTheme: TextTheme(
body1: new TextStyle(fontSize: 16.0, color: Colors.black87), body1: TextStyle(fontSize: 16.0, color: Colors.black87),
), ),
), ),
home: new FontAwesomeGalleryHome(), home: FontAwesomeGalleryHome(),
); );
} }
} }
class FontAwesomeGalleryHome extends StatefulWidget { class FontAwesomeGalleryHome extends StatefulWidget {
@override @override
State<StatefulWidget> createState() => new FontAwesomeGalleryHomeState(); State<StatefulWidget> createState() => FontAwesomeGalleryHomeState();
} }
class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> { class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
...@@ -40,67 +40,67 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> { ...@@ -40,67 +40,67 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
.toList(); .toList();
final orientation = MediaQuery.of(context).orientation; final orientation = MediaQuery.of(context).orientation;
return new Scaffold( return Scaffold(
appBar: _isSearching ? _searchBar(context) : _titleBar(), appBar: _isSearching ? _searchBar(context) : _titleBar(),
body: new GridView.builder( body: GridView.builder(
itemCount: filteredIcons.length, itemCount: filteredIcons.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: orientation == Orientation.portrait ? 2 : 3, crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
), ),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final icon = filteredIcons[index]; final icon = filteredIcons[index];
return new InkWell( return InkWell(
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
new MaterialPageRoute<Null>( MaterialPageRoute<Null>(
builder: (BuildContext context) { builder: (BuildContext context) {
return new GestureDetector( return GestureDetector(
onTap: () { onTap: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
child: new Container( child: Container(
color: Colors.white, color: Colors.white,
child: new SizedBox.expand( alignment: Alignment.center,
child: new Hero( child: Hero(
tag: icon, tag: icon,
child: new Icon( child: FaIcon(
icon.iconData, icon.iconData,
size: 100.0, size: 100,
),
),
), ),
), ),
); ),
}, );
), },
); ),
}, );
child: new Column( },
mainAxisAlignment: MainAxisAlignment.center, child: Column(
children: <Widget>[ mainAxisAlignment: MainAxisAlignment.center,
new Hero(tag: icon, child: new Icon(icon.iconData)), children: <Widget>[
new Container( Hero(tag: icon, child: FaIcon(icon.iconData)),
padding: new EdgeInsets.only(top: 16.0), Container(
child: new Text(icon.title), padding: EdgeInsets.only(top: 16.0),
) child: Text(icon.title),
], )
), ],
); ),
}), );
},
),
); );
} }
AppBar _titleBar() { AppBar _titleBar() {
return new AppBar( return AppBar(
title: new Text("Font Awesome Flutter Gallery"), title: Text("Font Awesome Flutter Gallery"),
actions: [ actions: [
new IconButton( IconButton(
icon: new Icon(FontAwesomeIcons.search), icon: FaIcon(FontAwesomeIcons.search),
onPressed: () { onPressed: () {
ModalRoute.of(context).addLocalHistoryEntry( ModalRoute.of(context).addLocalHistoryEntry(
new LocalHistoryEntry( LocalHistoryEntry(
onRemove: () { onRemove: () {
setState(() { setState(() {
_searchTerm = ""; _searchTerm = "";
...@@ -119,9 +119,9 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> { ...@@ -119,9 +119,9 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
} }
AppBar _searchBar(BuildContext context) { AppBar _searchBar(BuildContext context) {
return new AppBar( return AppBar(
leading: new IconButton( leading: IconButton(
icon: new Icon(FontAwesomeIcons.arrowLeft), icon: FaIcon(FontAwesomeIcons.arrowLeft),
onPressed: () { onPressed: () {
setState( setState(
() { () {
...@@ -132,11 +132,11 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> { ...@@ -132,11 +132,11 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
); );
}, },
), ),
title: new TextField( title: TextField(
onChanged: (text) => setState(() => _searchTerm = text), onChanged: (text) => setState(() => _searchTerm = text),
autofocus: true, autofocus: true,
style: new TextStyle(fontSize: 18.0), style: TextStyle(fontSize: 18.0),
decoration: new InputDecoration(border: InputBorder.none), decoration: InputDecoration(border: InputBorder.none),
), ),
); );
} }
......
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
/// Creates an Icon Widget that works for non-material Icons, such as the
/// Font Awesome Icons.
///
/// The default `Icon` Widget from the Material package assumes all Icons are
/// square in size and wraps all Icons in a square SizedBox Widget. Icons from
/// the FontAwesome package are often wider than they are tall, which causes
/// alignment and cutoff issues.
///
/// This Widget does not wrap the icons in a fixed square box, which allows the
/// icons to render based on their size.
class FaIcon extends StatelessWidget {
/// Creates an icon.
///
/// The [size] and [color] default to the value given by the current [IconTheme].
const FaIcon(
this.icon, {
Key key,
this.size,
this.color,
this.semanticLabel,
this.textDirection,
}) : assert(icon != null),
super(key: key);
/// The icon to display. The available icons are described in [Icons].
///
/// The icon can be null, in which case the widget will render as an empty
/// space of the specified [size].
final IconData icon;
/// The size of the icon in logical pixels.
///
/// Icons occupy a square with width and height equal to size.
///
/// Defaults to the current [IconTheme] size, if any. If there is no
/// [IconTheme], or it does not specify an explicit size, then it defaults to
/// 24.0.
///
/// If this [FaIcon] is being placed inside an [IconButton], then use
/// [IconButton.iconSize] instead, so that the [IconButton] can make the splash
/// area the appropriate size as well. The [IconButton] uses an [IconTheme] to
/// pass down the size to the [FaIcon].
final double size;
/// The color to use when drawing the icon.
///
/// Defaults to the current [IconTheme] color, if any.
///
/// The given color will be adjusted by the opacity of the current
/// [IconTheme], if any.
///
///
/// In material apps, if there is a [Theme] without any [IconTheme]s
/// specified, icon colors default to white if the theme is dark
/// and black if the theme is light.
///
/// If no [IconTheme] and no [Theme] is specified, icons will default to black.
///
/// See [Theme] to set the current theme and [ThemeData.brightness]
/// for setting the current theme's brightness.
///
/// {@tool snippet}
/// Typically, a material design color will be used, as follows:
///
/// ```dart
/// Icon(
/// Icons.widgets,
/// color: Colors.blue.shade400,
/// )
/// ```
/// {@end-tool}
final Color color;
/// Semantic label for the icon.
///
/// Announced in accessibility modes (e.g TalkBack/VoiceOver).
/// This label does not show in the UI.
///
/// See also:
///
/// * [Semantics.label], which is set to [semanticLabel] in the underlying
/// [Semantics] widget.
final String semanticLabel;
/// The text direction to use for rendering the icon.
///
/// If this is null, the ambient [Directionality] is used instead.
///
/// Some icons follow the reading direction. For example, "back" buttons point
/// left in left-to-right environments and right in right-to-left
/// environments. Such icons have their [IconData.matchTextDirection] field
/// set to true, and the [FaIcon] widget uses the [textDirection] to determine
/// the orientation in which to draw the icon.
///
/// This property has no effect if the [icon]'s [IconData.matchTextDirection]
/// field is false, but for consistency a text direction value must always be
/// specified, either directly using this property or using [Directionality].
final TextDirection textDirection;
@override
Widget build(BuildContext context) {
assert(this.textDirection != null || debugCheckHasDirectionality(context));
final TextDirection textDirection =
this.textDirection ?? Directionality.of(context);
final IconThemeData iconTheme = IconTheme.of(context);
final double iconSize = size ?? iconTheme.size;
if (icon == null) {
return Semantics(
label: semanticLabel,
child: SizedBox(width: iconSize, height: iconSize),
);
}
final double iconOpacity = iconTheme.opacity;
Color iconColor = color ?? iconTheme.color;
if (iconOpacity != 1.0)
iconColor = iconColor.withOpacity(iconColor.opacity * iconOpacity);
Widget iconWidget = RichText(
overflow: TextOverflow.visible, // Never clip.
textDirection:
textDirection, // Since we already fetched it for the assert...
text: TextSpan(
text: String.fromCharCode(icon.codePoint),
style: TextStyle(
inherit: false,
color: iconColor,
fontSize: iconSize,
fontFamily: icon.fontFamily,
package: icon.fontPackage,
),
),
);
if (icon.matchTextDirection) {
switch (textDirection) {
case TextDirection.rtl:
iconWidget = Transform(
transform: Matrix4.identity()..scale(-1.0, 1.0, 1.0),
alignment: Alignment.center,
transformHitTests: false,
child: iconWidget,
);
break;
case TextDirection.ltr:
break;
}
}
return Semantics(
label: semanticLabel,
child: ExcludeSemantics(
child: iconWidget,
),
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(
IconDataProperty('icon', icon, ifNull: '<empty>', showName: false));
properties.add(DoubleProperty('size', size, defaultValue: null));
properties.add(ColorProperty('color', color, defaultValue: null));
}
}
...@@ -2,6 +2,7 @@ library font_awesome_flutter; ...@@ -2,6 +2,7 @@ library font_awesome_flutter;
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:font_awesome_flutter/icon_data.dart'; import 'package:font_awesome_flutter/icon_data.dart';
export 'fa_icon.dart';
// THIS FILE IS AUTOMATICALLY GENERATED! // THIS FILE IS AUTOMATICALLY GENERATED!
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment