iOS Swift Add SVG Image to button like Android - android

In Android, we can import SVG as Vector XML,
Use this as Drawable,
Change colors of SVG Icons and add to button
void setSvgIcnForBtnFnc(Button setBtnVar, int setSvgVar, int setClrVar, String PosVar)
{
Drawable DevDmjVar = getDrawable(setSvgVar);
DevDmjVar.setBounds(0,0,Dpx24,Dpx24);
DevDmjVar.setColorFilter(new PorterDuffColorFilter(setClrVar, PorterDuff.Mode.SRC_IN));
switch (PosVar)
{
case "Tit" : setBtnVar.setCompoundDrawables(null, DevDmjVar, null, null); break;
case "Rit" : setBtnVar.setCompoundDrawables(null, null, DevDmjVar, null); break;
case "Pit" : setBtnVar.setCompoundDrawables(null, null, null, DevDmjVar); break;
default: setBtnVar.setCompoundDrawables(DevDmjVar, null, null, null); break;
}
}
How do I do this in swift for iphones ?
setBtnVar.setImage(<image: UIImage?>, forState: <UIControlState>)

UPD: Also see this UseYourLoaf blog post
Just found on Erica Sadun blog post that on iOS 11 you could use Vector Assets.
What "Vector Assets" mean:
If you click that box, the vector data will be shipped with your
application. Which, on the one hand, makes your application a little
bit larger, because the vector data takes up some space. But on the
other hand, will give you the opportunity to scale these images, which
might be useful in a number of different situations. So, one is, if
you know that this particular image is going to be used at multiple
sizes. But that might be less obvious. So, one case is a symbolic
glyph that should resize with dynamic type. Since we're thinking about
dynamic type, you should also be thinking about having glyphs that are
appearing next to type resize appropriately. Another case that's
really not obvious, is tab bar images.
... there's a really great accessibility feature that we strongly
recommend supporting, that allows for user that have turned their
dynamic type size up. ... So, we really recommend doing that to increase the usability of your app across all users
How to use:
Convert your SVG file into PDF, e.g. on ZamZar.com
Add your pdf to Assets.xcassets
Click "Preserve Vector Data" for the imported pdf.
Create UIImageView in your UIViewController and assign pdf file like UIImage.
or Asset Catalog Creator available in the Mac App Store will do steps 1 and 2 with a simple drag and drop.
iOS < 11
There is no native way to use SVG image.
Take a look at Macaw
Import framework via Cocoapod
pod "Macaw", "0.8.2"
Check their example project: this is how you render tiger.svg (located in project directory, not in an Assets.xcassets file)
import UIKit
import Macaw
class SVGExampleView: MacawView {
required init?(coder aDecoder: NSCoder) {
super.init(node: SVGParser.parse(path: "tiger"), coder: aDecoder)
}
}
There are some other third-party libraries of course:
SwiftSVG
Snowflake
SVGKit Objective-C framework

After a nightmare I came up with this solution for using SVG in button using Swift.
This is for all who dont wish to struggle like me
I used the simple SwiftSVG library for getting UIView from SVG File
Usage :
namBtnVar.setSvgImgFnc("ikn_sev", ClrVar: UIColor.cyanColor())
Install SwiftSVG Library
1) Use pod to install :
// For Swift 3
pod 'SwiftSVG'
// For Swift 2.3
pod 'SwiftSVG', '1.1.5'
2) Add framework
Goto AppSettings
-> General Tab
-> Scroll down to Linked Frameworks and Libraries
-> Click on plus icon
-> Select SVG.framework
3) Add below code anywhere in your project
extension UIButton
{
func setSvgImgFnc(svgImjFileNameVar: String, ClrVar: UIColor)
{
setImage((getSvgImgFnc(svgImjFileNameVar, ClrVar : ClrVar)), forState: .Normal)
}
}
func getSvgImgFnc(svgImjFileNameVar: String, ClrVar: UIColor) -> UIImage
{
let svgURL = NSBundle.mainBundle().URLForResource(svgImjFileNameVar, withExtension: "svg")
let svgVyuVar = UIView(SVGURL: svgURL!)
/* The width, height and viewPort are set to 100
<svg xmlns="http://www.w3.org/2000/svg"
width="100%" height="100%"
viewBox="0 0 100 100">
So we need to set UIView Rect also same
*/
svgVyuVar.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
for svgVyuLyrIdx in svgVyuVar.layer.sublayers!
{
for subSvgVyuLyrIdx in svgVyuLyrIdx.sublayers!
{
if(subSvgVyuLyrIdx.isKindOfClass(CAShapeLayer))
{
let SvgShpLyrIdx = subSvgVyuLyrIdx as? CAShapeLayer
SvgShpLyrIdx!.fillColor = ClrVar.CGColor
}
}
}
return svgVyuVar.getImgFromVyuFnc()
}
extension UIView
{
func getImgFromVyuFnc() -> UIImage
{
UIGraphicsBeginImageContext(self.frame.size)
self.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}

You can use vector-based PDFs natively if you select Single Scale for Scale Factors after importing.
The dimensions of the PDF will be the 1x dimensions for the asset.
Xcode will generate the rasterized image for every scale. You can then use it like any other image.

I used Aleksey Potapov's answer. The conversion and everything is perfect!
However I had an issue where my image was too large for my application.
So use this to resize it to a good size for ios development:
<svg xmlns="http://www.w3.org/2000/svg" height="30" width="30" viewBox="0 0 1000 1000" xmlns:xlink="http://www.w3.org/1999/xlink">

Check out my app: Speculid
It will automatically convert SVGs into PDFs or PNGs depending on how your asset library is setup.

Related

Is there a way to dynamically load Material Icons in native android (Java)?

Recently i was able to dynamically load Material Design Icons in Flutter by using the flutter_icons/flutter_icons.dart
// First Approach
Icon icon = new Icon(Icons.settings);
// Second Approach
icon = new Icon(MaterialIcons.getIconData(Model.dynamic_icon_name);
Flutter Screenshot
This got me thinking if i could do something similar using a native android approach, with something like
// Glide Theoretical Example
Glide.with(context.getApplicationContext())
.asBitmap()
.load(MaterialIcons.getIconData(Model.dynamic_icon_name))
.apply(new RequestOptions().fitCenter())
.into(iconView);
I think it would be interesting to know, since i think could provide some advantage that a developer would not need to bundle those assets with the app
There was no effective way of handling this natively on Android, so the solution i ended up going with was having the server host these icons and i could just serve them down using Glide like this.
Step 1: Backend setup
Download the png assets for the icon of your choice, ie: the thumbs_up icon from this Material Icons link
Now you can go ahead and unzip the image assets into your server's assets folder, in my case this was in my public folder of the server since i was using a Laravel backend. In the end my icons resided in the path public/material-icons/thumb_up_black.png and made sure to keep a consistent naming convention public/material-icons/{icon_name_color}.png this was the vital point since i needed to reference these assets again.
Now we can link the icon with the respective item
Server side
...
// Creating the item
new Item::create([
'name' => 'Like-able item',
'icon' => 'thumb_up_black',
]);
...
List items API endpoint result
[
{
"name": "Like-able item",
"icon_url": "https//server-name.fancy/thumb_up_black.png"
},
{
"name": "Like-able item #2",
"icon_url": "https//server-name.fancy/thumb_up_black.png"
},
....
]
Step 2: Client Setup (Android app)
Once i have consumed the API data and about to display the items, i can use Glide to accomplish this.
ItemModel item = new ItemModel(itemDataFromServer);
Glide.with(context.getApplicationContext())
.asBitmap()
.load(MaterialIcons.getIconData(item.icon_url))
.apply(new RequestOptions().fitCenter())
.into(iconView);
This was finally how i was able to solve this problem, the nice thing with this implementation was that from our three client apps (Android, iOs and Web) we could use the same if not similar method to display accordingly.

Nativescript and FontAwesome

I am trying to use icon font FontAwesome in Nativescript application, which is possible according to this article https://www.nativescript.org/blog/mobile-app-best-practices---use-font-instead-of-image-to-show-an-icon
I did everything that is described in that article:
Added .ttf in app/fonts
Added class in app.css
.fa{
font-family: "FontAwesome";
}
Used it in XML like so
text="" class="fa"
But result is rather disappointing:
I also tried the "\uf230" syntax, but that renders as plain text.
What am I doing wrong?
Could be a few things. Does it work on iOS? As your CSS definition is iOS compatible, not Android as Android needs the actual filename (without extension) whereas iOS needs the font name. So I have this to be xplatform-ready (the file is 'fontawesome-webfont.ttf'):
.fa {
font-family: 'FontAwesome', fontawesome-webfont;
}
The \f005 syntax is OK (<Label class="fa" [text]="'\uf005'"></Label>), but I'm using the splendid nativescript-ngx-fonticon plugin (there's also a non-Angular one) to be able to do this instead:
<Label class="fa" [text]="'fa-shopping-basket' | fonticon"></Label>
To make it work, you must make sure that the "fonts" directory is inside the "app" folder and that the following files exist:
font-awesome.eot
font-awesome.ttf
I opted to adopt this font as the default of my application, so I do not have to worry about where I'm going to use it and how much to enter the right class, everything is getting very good and the result is perfect.
In CSS, you only have to define a selector according to your interest for the source to be used, so just use the directive:
page {
font-family: 'FontAwesome'
}
Then where you want an icon, just use an html entity that represents it as it searches the site: http://fontawesome.io/icons/
See images:
You can see this video where I was based to start. It corrects in the video the extension used to be attentive.

Is any function in swift similar to R.java in Android?

I am a beginner in iOS and swift.
I used to write Android and I think the R.java is a good idea to manage ids, drawables, strings and other resources.
So I'm surprised that iOS does't provide a good function to access resources.
If I want to get a Image from assets, I call UIImage(named: "img_name"), but I don't think this is the best way to access img_name, I may use a wrong name and I can't get the image.
I found some open source project like Shark and SwiftGen, but Shark only support images and SwiftGen it seems need to run a command not automatically.
Do you have any better solution? Thank you!
I have a open source project R.swift-plugin it provides features as you mentioned. You just need to install the Xcode Plugin via Alcatraz and search R.swift
The plugin will automatically generate a resource file to manage your images, localizable strings and colors, and you can access them like using R.java
Usage:
Sincerely recommend you to try it. And feel free to give me any suggestion to improve it :)
If you are using InterfaceBuilder (also called Storyboard, xib), there is no need to define id for each view. You can bind outlets in code.
If you want to retrieve views using their ids (like R.java as you asked), you can set tag to each view and manipulate them in code.
Unlike AndroidStudio, Xcode will not generate any file.
func viewDidLoad() {
let labelView = self.view.viewWithTag(0) as? UILabel
}
There is no such function in Xcode itself, but there is an open source project that does just this: R.swift
It automatically updates the generated file and supports a lot of different resource types such as images, fonts, segues and more.
You can have similar functionality by using extensions and enums.
Using enums allows you to avoid typos and benefit from Xcode's autosuggest/autocomplete.
Example for UIImage:
extension UIImage {
enum ImageId: String {
// These are your images NAMES,
// as in "SpriteMonster.jpg"
case SpriteMonster, SpriteHero, BaseLandscape
}
convenience init!(id: ImageId) {
self.init(named: id.rawValue)
}
}
Usage:
let monster = UIImage(id: .SpriteMonster) // the "SpriteMonster.jpg" image
For this example I'm force-unwrapping the convenience init, so be careful to actually have the image with the correct name in your bundle.
For String:
extension String {
enum StringId: String {
case Welcome = "Welcome to the game!"
case GameOver = "You loose! Game over!"
}
init(id: StringId) {
self = id.rawValue
}
}
Usage:
let label = String(id: .Welcome) // "Welcome to the game!"
For fonts:
extension UIFont {
enum FontId {
case HelveticaNeueLarge
case HelveticaNeueMedium
case HelveticaNeueSmall
func font() -> UIFont {
switch self {
case .HelveticaNeueLarge:
return UIFont(name: "HelveticaNeue", size: 18)!
case .HelveticaNeueSmall:
return UIFont(name: "HelveticaNeue", size: 12)!
default:
return UIFont(name: "HelveticaNeue", size: 14)!
}
}
}
class func get(id: FontId) -> UIFont {
return id.font()
}
}
Usage:
let font = UIFont.get(.HelveticaNeueLarge) // <UICTFont: 0x7ffd38f09180> font-family: "Helvetica Neue"; font-weight: normal; font-style: normal; font-size: 18.00pt
These are only examples to demonstrate the concept, you can go much further with this.
If you use Tuist is has SwiftGen inside. It allows to use it out of the box without adding third-party solutions. The disadvantage is that you have to run it every time when you change resource

QLabel pixmap works in Designer but not in the actual program

I've set a company logo above the main menu. This is what it looks like in QtDesigner:
I distorted the logo on purpose. The point is that the image is there.
This is the resource folder in QtCreator project view:
This is what it looks like on my android phone:
So, well, what's going on here? I see no file errors in console (and loading CSS files from resources works form me). One thing that is possibly relevant is that the image is a SVG file.
SVG was indeed an issue. While QtDesigner displays SVG without problems, the actual Qt library cannot handle that. I used this code to test it:
QPixmap pixmap;
if (!pixmap.load( ":/logo.svg" )) {
QDebug("Failed to load main svg logo.");
if (!pixmap.load( ":/logo.png" )) {
QDebug("Failed to load main png logo.");
}
else {
QDebug("PNG logo loaded.");
}
}
else {
QDebug("SVG logo loaded.");
}

Using Cordova, is there a way to reference native icons?

I'm using Cordova 3.5 to build an app which contains a menu with pretty standard items in the list (home, contacts, etc.), and I want to use the native menu icons whenever possible. I believe those icons are already on the device as part of the OS, but I don't know if Cordova gives me a way to reference them.
I suppose I'd need to write a Javascript function to choose the right file name based on the platform, e.g.:
// this is pseudocode
var icon = '';
if (platform === 'android') {
icon = 'some/path/home.png';
} else {
icon = 'other/path/icon.home.png';
// or maybe a function such as the following exists:
// icon = cordova.getNativeIcon('icon.home.png');
}
$('.selector').css('background-image', icon);
Alternatively, I may be able to make do by referencing the files in CSS, e.g.:
.android .home-icon {
background-image: url('some/path/home.png');
}
.ios .home-icon {
background-image: url('other/path/icon.home.png');
}
So, how do folks handle this sort of thing in Cordova? Is there a function I can use to access native icons? Are folks just copying them into their projects? What's the best practice?
If you're working with Cordova, then you'll be working inside a web view provided by the host OS and you won't have direct access to any artwork. I've found that using icon fonts and CSS "themes" to work well enough, but that approach will replicate artwork already provided. There's extra work involved with theming for iOS 6 vs iOS 7 or 8, for example, but it's not as bad as it sounds.
IBM does have an article on partitioning your view between native and web controls, but it sounds a bit cumbersome. More details here: https://www.ibm.com/developerworks/community/blogs/worklight/entry/ios_combining_native_and_web_controls_in_cordova_based_applications

Categories

Resources