Unverified Commit bccc2638 authored by Brian Egan's avatar Brian Egan Committed by GitHub

Merge pull request #74 from fluttercommunity/fa_icon

Add FaIcon Widget to fix alignment / cutoff issues for folks
parents c2044e29 21b1f5cd
## 8.7.0
* Add `FaIcon` widget for Font Awesome Icons
* Update `README` with FAQ
## 8.6.0 ## 8.6.0
* Move package to FlutterCommunity * Move package to FlutterCommunity
* Upgrade to Font Awesome Icons 5.12.1 * Upgrade to Font Awesome Icons 5.12.1
......
...@@ -15,9 +15,9 @@ Based on Font Awesome 5.12.1. Includes all free icons: ...@@ -15,9 +15,9 @@ Based on Font Awesome 5.12.1. Includes all free icons:
In the `dependencies:` section of your `pubspec.yaml`, add the following line: In the `dependencies:` section of your `pubspec.yaml`, add the following line:
```yaml ```yaml
dependencies:
font_awesome_flutter: <latest_version> font_awesome_flutter: <latest_version>
``` ```
When icons do not render try [this](https://github.com/brianegan/font_awesome_flutter/issues/28#issuecomment-460109786).
## Usage ## Usage
...@@ -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"); }
); );
} }
...@@ -39,27 +39,59 @@ class MyWidget extends StatelessWidget { ...@@ -39,27 +39,59 @@ class MyWidget extends StatelessWidget {
View the Flutter app in the `example` directory to see all the available `FontAwesomeIcons`. View the Flutter app in the `example` directory to see all the available `FontAwesomeIcons`.
## Include pro icons ## FAQ
### Why aren't the icons aligned properly or why are the icons being cut off?
Please use the `FaIcon` widget provided by the library instead of the `Icon`
widget provided by Flutter. The `Icon` widget assumes all icons are square, but
many Font Awesome Icons are not.
### Why aren't the icons showing up on Mobile devices?
If you're not seeing any icons at all, sometimes it means that Flutter has a cached version of the app on device and hasn't pushed the new fonts. I've run into that as well a few times...
Please try:
1. Stopping the app
2. Running `flutter clean` in your app directory
3. Deleting the app from your simulator / emulator / device
4. Rebuild & Deploy the app.
### Why aren't the icons showing up on Web?
Most likely, the fonts were not correctly added to the `FontManifest.json`.
Note: older versions of Flutter did not properly package non-Material fonts
in the `FontManifest.json` during the build step, but that issue has been
resolved and this shouldn't be much of a problem these days.
Please ensure you are using `Flutter 1.14.6 beta` or newer!
### How can I use pro icons?
If you bought font awesome pro icons, you can import them here. This library only packages the free Font Awesome icon fonts. If you own the pro
icon fonts and want to use them with Flutter, please follow these instructions.
:exclamation: By importing pro icons you acknowledge that it is your obligation to keep these files private. This includes **not** uploading your package to github or other public file sharing services. :exclamation: By importing pro icons you acknowledge that it is your obligation
to keep these files private. This includes **not** uploading your package to
a public github repository or other public file sharing services.
- Download this package's newest release, extract the folder and move it to a location of your choice * Download this package's newest release, extract the folder and move it to a location of your choice
- Remove `#`s from `pubspec.yaml` at the indicated position * Remove `#`s from `pubspec.yaml` at the indicated position
- run `flutter packages get` * run `flutter packages get`
- Download your font awesome pro icons (web version) * Download your font awesome pro icons (web version)
- Move all `.ttf` files from the `webfonts` directory to this package's lib/fonts (replace existing fonts) * Move all `.ttf` files from the `webfonts` directory to this package's lib/fonts (replace existing fonts)
- Move `icons.json` from `metadata` to this directory * Move `icons.json` from `metadata` to this directory
- Run `./tool/update.sh` * Run `./tool/update.sh`
- In your project's dependencies, replace the version tag for `font_awesome_flutter` with the path to your custom installation. * Uncomment `IconDataLight` in `lib/icon_data.dart`
* In your project's dependencies, replace the version tag for `font_awesome_flutter` with the path to your custom installation.
```yaml ```yaml
dependencies: dependencies:
font_awesome_flutter: font_awesome_flutter:
path: /path/to/font_awesome_flutter path: /path/to/font_awesome_flutter
... ...
``` ```
- Uncomment `IconDataLight` in `lib/icon_data.dart`
## Contributors ## Contributors
......
...@@ -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';
import 'package:font_awesome_flutter/font_awesome_flutter.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
/// [FontAwesomeIcons].
final IconData icon;
/// The font size of the icon.
///
/// 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.
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!
......
...@@ -5,7 +5,7 @@ authors: ...@@ -5,7 +5,7 @@ authors:
- Flutter Community <community@flutter.zone> - Flutter Community <community@flutter.zone>
- Brian Egan <brian@brianegan.com> - Brian Egan <brian@brianegan.com>
homepage: https://github.com/fluttercommunity/font_awesome_flutter homepage: https://github.com/fluttercommunity/font_awesome_flutter
version: 8.6.0 version: 8.7.0
environment: environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0" sdk: ">=2.0.0-dev.28.0 <3.0.0"
......
...@@ -38,6 +38,7 @@ void main(List<String> arguments) { ...@@ -38,6 +38,7 @@ void main(List<String> arguments) {
'', '',
"import 'package:font_awesome_flutter/font_awesome_flutter.dart';", "import 'package:font_awesome_flutter/font_awesome_flutter.dart';",
"import 'package:font_awesome_flutter_example/example_icon.dart';", "import 'package:font_awesome_flutter_example/example_icon.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