I have added a right bar button in my navigation bar, and then assign image to the UIButton and set the size to 20px * 20px
the view is good in editor, but when I run the app in simulator, the image is very stretched, can anyone help me please
image is here
Control Click and Drag from Button to View Controller as IBOutlet
override func viewDidLoad(){
yourButtonOutletName.image.contentMode = .ScaleAspectFit
//
}
In your UIButton, set button.imageView.contentMode = UIViewContentModeScaleAspectFit
Related
I'm trying to display a large button at the bottom of the screen, so that it appears above the toolbar.
Button Overlapping Toolbar
My first attempt at this works on the iPad, and on the iPhone in Landscape mode, but the button appears behind the toolbar in Portrait mode. So, this is probably related to the difference in rendering with the Split View Controller:
addButton.frame = CGRect(x:0, y:0, width:48, height:48)
addButton.setBackgroundImage(UIImage(named:"Button - Add"), for: .normal)
let topView = self.navigationController?.view
topView?.addSubview(addButton)
I don't want it to appear above all other view controllers, e.g. popovers and modal segues, so I can't place the button on the application's topmost window, i.e. the following doesn't give me the right result either:
let topView = UIApplication.shared.windows.first
topView?.addSubview(addButton)
The only solution that works for me is to add the button to the toolbar, but this isn't great because the touch zone for the button is clipped by the toolbar:
self.navigationController?.toolbar.addSubview(addButton)
let topView: UIView? = addButton.superview
So, does anyone know of a way to place a UIView or UIControl in a layer or view above the toolbar, but still on the active viewController?
tl;dr
I'm trying to set a background image for a UINavigationBar. Is there a way to configure the navbar so that it uses scaleAspectFill-like behavior (as a UIImageView with contentMode set to scaleAspectFill)?
The goal
I have an image roughly fitting the navbar dimension of a landscape iPhone (64pt height, about 800pt width; the exact dimension should not matter here though), which I set with navigationBar.setBackgroundImage(img, for: .default). The image is a blurred photo, so no need for pixel-perfection. Btw -- I'm using UINavigationBar.appearance to set the background for all navbars at once.
What I'd like it to do: show the center part of the image when in portrait orientation, and show the full image without cropping when in landscape orientation. If the height doesn't match up exactly (as is to be expected on iPhone X) it should scale up a bit to fill the additional height.
As fallback solution I'd also accept if an image of lesser width is shown centered and fills up the additional horizontal space by stretching the first and last pixel column.
What I tried so far
Goal 1: setting the contentMode of UINavigationBar -- seems to be ignored when rendering the image
Goal 2: using a smaller image and making it strechable with stretchableImage(withLeftCapWidth:topCapHeight:) -- fills the navbar but the image is pushed to the right bottom (apparently because this method only considers left and top as strechable margins)
Goal 2: using a smaller image and making it resizable with resizableImage(withCapInsets:resizingMode:) with resizingMode set to stretch -- in landscape it just stretches the image to full width, ignoring the cap insets (probably this method does not do what I think).
Solved by adding an image view to the UINavigationController's view, as described here. The image view is attached to the top, left and right of the nav controller's view and to the bottom of the navbar.
In contrast to the example in the article, I don't use a custom navigation bar; instead I insert the image view behind the existing navbar. Note that the navbar has to be transparent to make this work. Also, the image view has to be clipped, else it strangely extends beyond the navbar's bottom.
Maybe this can be of help to someone else, so here's some code (this should only be applied once to a nav controller, so maybe you are better off putting this code in a subclass than in an extension):
extension UINavigationController {
func setBackgroundImage(_ image: UIImage) {
navigationBar.isTranslucent = true
navigationBar.barStyle = .blackTranslucent
let logoImageView = UIImageView(image: image)
logoImageView.contentMode = .scaleAspectFill
logoImageView.clipsToBounds = true
logoImageView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(logoImageView, belowSubview: navigationBar)
NSLayoutConstraint.activate([
logoImageView.leftAnchor.constraint(equalTo: view.leftAnchor),
logoImageView.rightAnchor.constraint(equalTo: view.rightAnchor),
logoImageView.topAnchor.constraint(equalTo: view.topAnchor),
logoImageView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor)
])
}
}
You might try adding the UIImageView with contentMode = .scaleAspectFill, directly inside the UINavigationBar, doing so:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let imgView = UIImageView(image: UIImage(named: "desert"))
imgView.contentMode = .scaleAspectFill
imgView.frame = self.navigationController!.navigationBar.frame
self.navigationController?.navigationBar.addSubview(imgView)
self.navigationController?.navigationBar.sendSubview(toBack: imgView)
}
}
the result is:
So I have a .png that's 428x176 px:
I want to use it as a tab bar background image for when an item is in the selected state. The problem is that the image is too big. So now, I'm exploring the different resolution suffixes: #1x, #2x, #3x. But regardless of which I append to the image filename, the image remains too big for the tab bar item's background, although it does get smaller as I increase the resolution factor. How do I determine what the correct dimensions for this image should be?
Keep in mind that this is a background image for when any particular UITabBarItem is in the selected state. It is meant to be the entire width and height of the UITabBarItem. My tab bar will have three items laid across the width of the screen.
Update:
A lot of answers are providing swift based solutions, but what I'm asking for is what dimensions my image should be in pixels, in other words, what sized images should I be including in my bundle, so that the image will fit in the tab bar at all screen sizes. I imagine that since a UITabBar by default expects a UIImage for its selectionIndicatorImage field and not a UIImageView that there must be a solution that doesn't involve hacking around the UITabBar and adding a UIImageView as a subview of it and managing what position the image view should be in, manually, based on which UITabBarItem is currently selected.
Making my answer for this question how to make UITabBar selection indicator image fill the whole space? as reference:
Subclass the UITabBarController
It works for multiple devices even with rotation.
Notes:
Make your images' rendering mode as Original.
Assign this class below to your UITabBarController in your Storyboard or as your base class if you're doing your screen programmatically.
//
// BaseTabBarController.swift
// MyApp
//
// Created by DRC on 1/27/17.
// Copyright © 2017 PrettyITGirl. All rights reserved.
//
import UIKit
class BaseTabBarController: UITabBarController {
let numberOfTabs: CGFloat = 4
let tabBarHeight: CGFloat = 60
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateSelectionIndicatorImage()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
updateSelectionIndicatorImage()
}
func updateSelectionIndicatorImage() {
let width = tabBar.bounds.width
var selectionImage = UIImage(named:"myimage.png")
let tabSize = CGSize(width: width/numberOfTabs, height: tabBarHeight)
UIGraphicsBeginImageContext(tabSize)
selectionImage?.draw(in: CGRect(x: 0, y: 0, width: tabSize.width, height: tabSize.height))
selectionImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
tabBar.selectionIndicatorImage = selectionImage
}
}
There's no clear cut answer for this as the tab bar itself isn't of fixed size on various iOS versions and various iOS devices.
Starting iOS 11, tab bar will have smaller height and titles will move to right in landscape mode.
So the idea is to have a stretchable image that can be stretched along all all edges - top/leading/bottom/trailing.
For your reference -
http://macoscope.com/blog/stretchable-images-using-interface-builder/
Here are few images from above blog post to help make it clear -
Hope this helps.
Use the below two lines.
self.tabBarController.tabBar.autoresizesSubviews = NO;
self.tabBarController.tabBar.clipsToBounds = YES;
Xcode works with point, not pixels, so the width will always be 320. In the case of retina display one point is 2x2 pixels and in normal mode it is 1x1.
I think the height for the tab bar should be 320x49 for normal and 640x98 for retina.
the retina image should have the same name as the normal one with the #2x at the end.
Rename your image to tabbarBack#2x.png. This is called pixel doubling for the Retina Display.
Without the #2x iOS doesn't know that it should apply a scale factor and it will be used as it is and though it should be halved.
tabbarBack.png (45 px or so)
tabbarBack#2x.png
[[[self tabBarController] tabBar] setBackgroundImage:[UIImage imageNamed:#"tabbarBack.png"]];
Have you tried with adding imageView as subview of tabbar
var bgView: UIImageView = UIImageView(image: UIImage(named: "background.png"))
bgView.frame = CGRectMake(0, 420, 320, 60)//you might need to modify this frame to your tabbar frame
self.view.addSubview(bgView)
If we talk about height & width of tabbar ,it is 320*49 / 640*98 #2x for standard tabbar. so if you want to keep same dimension try with these width/height ratio.
To add to Tarun Tyagi's answer:
If you add the image to the asset store you can also do visual slicing with the system tools.
Create an asset catalog
Drag & Drop your image into the asset catalog.
Select that image in the asset catalog and click on the "Show Slicing" button on the bottom right
Click on "Start Slicing" and slice that image
Try resizing the image to the tab bar size. Or Add an imageView to the tabBar as subview, and then use the image in that imageView.
Subclass the TabBarController and add imageview there:
class YourTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = UIImageView(image: UIImage(named: "gray background"))
backgroundImage.frame = backgroundImage.bounds
self.view.addSubview(backgroundImage)
}
I want to set the right button item to be this:
It has the title and the down image.
But in storyboard, I can not do that:
I only can set one of the title and image, if I set image, I can not set the title, if I set the title, I can not set the image.
I have tried use the UIButton and the Button Bar Item to do it, get the same result.
Some friend know how to do with that?
You can simply add drag UIButton to rightBarItem in storyBoard . and customise that button as per your needs ..
Check View hierarchy after adding UIButton .
you can try this add the custom view to your bar button item
var RightView = UIView(frame: CGRectMake(0, 0, 100, 44))
// you can add in RightView, your title in uilable and your image in imageview
var RightBarButton = UIBarButtonItem(customView: RightView)
self.navigationItem.rightBarButtonItem = RightBarButton
I have a UISearchBar and I would like to change the position of the initial magnify icon (the one that appears in the middle of the UISearchBar) as well as the color or icon.
So far I changed the tint and the icon image.
However, the new icon shows up only if I test the app on a simulator but on an actual device(both run iOS 9.3) it still shows the default icon.
UISearchBar.appearance().setImage(UIImage(named: "SearchbarIcon"), forSearchBarIcon: UISearchBarIcon.Search, state: UIControlState.Normal)
As for the magnify icon position, I want it in the left side, where it shows up if I activate the UISearchBar.
I found quite a lot of answers around here many of the provided solutions don't work on iOS 8.0+ or are in Objective-C and I am having some problems understanding them.
I tried to add a custom background containing the icon but it shows up at the bottom of the search bar while the icon is still there:
The background shows up OK if I change the background offset for Y to -44 (the height of the UISearchBar) but I can no longer type since it seems the entire text field is pushed up. I also tried to change the vertical offset for the SearchText to 44 to compensate but no luck. To be honest, I am not sure what Search Text and the Background offsets are supposed to do but I decided to give them a try.
Is there any way to accomplish this? Or maybe a different approach?
You can adjust the position of the search bar icon using
func positionAdjustmentForSearchBarIcon(_ icon: UISearchBarIcon) -> UIOffset
See https://developer.apple.com/library/ios/documentation/UIKit/Reference/UISearchBar_Class/#//apple_ref/occ/instm/UISearchBar/positionAdjustmentForSearchBarIcon:
You can use:
uiSearchBar.setPositionAdjustment(UIOffset, for: UISearchBar.Icon)
replace UIOffset with your desired offset value UIOffset(horizontal: CGFloatvertical: CGFloat) and UISearchBar.Icon with .search
#Michael - Thanks for all the help.
I managed to grab the UISearchBar's UITextField:
func customizeSearchBar()
{
for subview in srcRegimenSearchBar.subviews
{
for view in subview.subviews
{
if let searchField = view as? UITextField
{
let imageView = UIImageView()
let image = UIImage(named: "SearchBarIcon.png")
imageView.image = image;
imageView.frame = CGRectMake(0, 0, 0, 0)
/*imageView.frame = CGRectMake(100, 0, 20, 19)*/
searchField.leftView = imageView
searchField.leftViewMode = UITextFieldViewMode.Always
}
}
}
}
I wanted to change the position since I have access to the frame but it seems only the the top and height can be modified, at least the way I tried so I set the height and width to 0 (I couldn't find a way to make it nil or remove it completely) and I added an UIImageView with the new icon over in the left side of the UISearchbar and added a custom horizontal offset for the tint.
Not the best solution out there, I'm sure of it, but for now it works.