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';
class MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
return new IconButton(
// Use the FontAwesomeIcons class for the IconData
icon: new Icon(FontAwesomeIcons.gamepad),
return IconButton(
// Use the FaIcon Widget + FontAwesomeIcons class for the IconData
icon: FaIcon(FontAwesomeIcons.gamepad),
onPressed: () { print("Pressed"); }
);
}
......
......@@ -3,28 +3,28 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:font_awesome_flutter_example/icons.dart';
void main() {
runApp(new FontAwesomeGalleryApp());
runApp(FontAwesomeGalleryApp());
}
class FontAwesomeGalleryApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
return MaterialApp(
title: 'Font Awesome Flutter Gallery',
theme: new ThemeData.light().copyWith(
iconTheme: new IconThemeData(size: 36.0, color: Colors.black87),
textTheme: new TextTheme(
body1: new TextStyle(fontSize: 16.0, color: Colors.black87),
theme: ThemeData.light().copyWith(
iconTheme: IconThemeData(size: 36.0, color: Colors.black87),
textTheme: TextTheme(
body1: TextStyle(fontSize: 16.0, color: Colors.black87),
),
),
home: new FontAwesomeGalleryHome(),
home: FontAwesomeGalleryHome(),
);
}
}
class FontAwesomeGalleryHome extends StatefulWidget {
@override
State<StatefulWidget> createState() => new FontAwesomeGalleryHomeState();
State<StatefulWidget> createState() => FontAwesomeGalleryHomeState();
}
class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
......@@ -40,67 +40,67 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
.toList();
final orientation = MediaQuery.of(context).orientation;
return new Scaffold(
return Scaffold(
appBar: _isSearching ? _searchBar(context) : _titleBar(),
body: new GridView.builder(
itemCount: filteredIcons.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
),
itemBuilder: (context, index) {
final icon = filteredIcons[index];
body: GridView.builder(
itemCount: filteredIcons.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
),
itemBuilder: (context, index) {
final icon = filteredIcons[index];
return new InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: new Container(
color: Colors.white,
child: new SizedBox.expand(
child: new Hero(
tag: icon,
child: new Icon(
icon.iconData,
size: 100.0,
),
),
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute<Null>(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Container(
color: Colors.white,
alignment: Alignment.center,
child: Hero(
tag: icon,
child: FaIcon(
icon.iconData,
size: 100,
),
),
);
},
),
);
},
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Hero(tag: icon, child: new Icon(icon.iconData)),
new Container(
padding: new EdgeInsets.only(top: 16.0),
child: new Text(icon.title),
)
],
),
);
}),
),
);
},
),
);
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Hero(tag: icon, child: FaIcon(icon.iconData)),
Container(
padding: EdgeInsets.only(top: 16.0),
child: Text(icon.title),
)
],
),
);
},
),
);
}
AppBar _titleBar() {
return new AppBar(
title: new Text("Font Awesome Flutter Gallery"),
return AppBar(
title: Text("Font Awesome Flutter Gallery"),
actions: [
new IconButton(
icon: new Icon(FontAwesomeIcons.search),
IconButton(
icon: FaIcon(FontAwesomeIcons.search),
onPressed: () {
ModalRoute.of(context).addLocalHistoryEntry(
new LocalHistoryEntry(
LocalHistoryEntry(
onRemove: () {
setState(() {
_searchTerm = "";
......@@ -119,9 +119,9 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
}
AppBar _searchBar(BuildContext context) {
return new AppBar(
leading: new IconButton(
icon: new Icon(FontAwesomeIcons.arrowLeft),
return AppBar(
leading: IconButton(
icon: FaIcon(FontAwesomeIcons.arrowLeft),
onPressed: () {
setState(
() {
......@@ -132,11 +132,11 @@ class FontAwesomeGalleryHomeState extends State<FontAwesomeGalleryHome> {
);
},
),
title: new TextField(
title: TextField(
onChanged: (text) => setState(() => _searchTerm = text),
autofocus: true,
style: new TextStyle(fontSize: 18.0),
decoration: new InputDecoration(border: InputBorder.none),
style: TextStyle(fontSize: 18.0),
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;
import 'package:flutter/widgets.dart';
import 'package:font_awesome_flutter/icon_data.dart';
export 'fa_icon.dart';
// 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