How to programmatically create UIView with this setup? - uiview

I'd like to create a UIView programmatically with the exact equivalent of this setup in IB (see screenshot).
Whatever I have attempted myself would not behave the same when rotating and autoresizing the view, so I need a sample from an expert.

Swift 2.0:
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
Swift 3.0:
view.autoresizingMask = [.flexibleHeight, .flexibleWidth]

Example:
UIView *customView = [[UIView alloc] initWithFrame:frame];
[customView setAutoresizingMask:UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight];

View.autoresizingMask = [.FlexibleRightMargin, .FlexibleLeftMargin, .FlexibleBottomMargin,.FlexibleWidth,.FlexibleHeight,.FlexibleTopMargin]

Related

Trying to zoom a multilayer set of UIViews

Please point me in the right direction - I can find neither a solution nor a tutorial that solves my problem..
I have the following hierarchy of views in a ViewController:
UIView
ScrollView
Container
Drawing
Image
I can zoom in and out using a tap gesture, however, I don't want the pens in the drawing view to resize. I need to be able to draw lines on the image at a greater detail.
If I zoom the views separately, then the pens are out of sync with the image.
The views are setup in IB.
The code in ViewDidLoad to initialize things is as follows:
scrollView.backgroundColor = UIColor.black
scrollView.contentSize = imageView.frame.size
scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
tap.numberOfTapsRequired = 2
imageView.addGestureRecognizer(tap)
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 4.0
scrollView.delegate = self
And the zoom method is:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
I've tried starting the following alternatives:
scrollView.contentSize = drawingView.frame.size and
..
return drawingView
I've also set imageView as a subView of drawingView.
And finally, I've set both as subViews of the Container View (a UIView, not a UIContainerView.
I am conforming to the UIScrollViewDelegate.
Any help would be appreciated.

UIBlurEffectView smaller than autolayouted parentView although identical frame

I have an UIView for login purposes centered in the middle of the screen. It is constrained to a 0.25 height of the surrounding view (covering the whole window)
I noticed, that if I create an UIVisualEffectView (via the method blurBackgroundForView(_)as background for the UIView, that it is too small (check the code how I create the UIVisualEffectView) although it has the same frame.
You can see the effect, when you change the backgroundColor to .greenColor.
The View is higher than the Blureffect.
ViewController
override func viewWillAppear(animated: Bool) {
AnimationHelper.blurBackgroundForView(self.view)
view.backgroundColor = .greenColor()
}
blurBackgroundForView(_)
static func blurBackgroundForView(view: UIView!){
view.backgroundColor = .clearColor()
let blurEffect = UIBlurEffect(style: .Light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
view.insertSubview(blurEffectView, atIndex: 0)
}
Frames are not guaranteed to be set by auto layout in viewWillAppear.
Try setting the blur view's frame in viewDidLayoutSubviews instead. Alternatively, you can directly set the autoresizing mask on your blur view so that it resizes when its superview resizes:
blurView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
You should also call the super method in viewWillAppear.

tableHeaderView on top of first cell

I'm trying to create a tableview programmatically that has a search bar in the tableHeaderView. For some reason the search bar appears on top of the first cell.
I'm using Masonry to build constraints.
Can someone point me to what i'm doing wrong.
- (void)setupViews {
...
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.tableView];
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
self.tableView.tableHeaderView = self.searchBar;
...
}
- (void)updateViewConstraints {
[self.searchBar mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.view);
make.height.equalTo(#(44));
}];
[self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
make.self.top.equalTo(self.view);
make.self.bottom.equalTo(self.toolbar.mas_top);
make.width.equalTo(self.view);
}];
...
}
You can see here that the header is at the same level as the cells.
Thanks for your help, I found a gist on GitHub which talked about changing the size of tableViewHeader using AutoLayout:
https://gist.github.com/andreacremaschi/833829c80367d751cb83
- (void) sizeHeaderToFit {
UIView *headerView = self.tableHeaderView;
[headerView setNeedsLayout];
[headerView layoutIfNeeded];
CGFloat height = [headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
headerView.frame = ({
CGRect headerFrame = headerView.frame;
headerFrame.size.height = height;
headerFrame;
});
self.tableHeaderView = headerView;
}
If I call this method during updateViewConstraints then it works.
However, I don't fully understand it.
Using Extension in Swift 3.0
extension UITableView {
func setTableHeaderView(headerView: UIView?) {
// prepare the headerView for constraints
headerView?.translatesAutoresizingMaskIntoConstraints = false
// set the headerView
tableHeaderView = headerView
// check if the passed view is nil
guard let headerView = headerView else { return }
// check if the tableHeaderView superview view is nil just to avoid
// to use the force unwrapping later. In case it fail something really
// wrong happened
guard let tableHeaderViewSuperview = tableHeaderView?.superview else {
assertionFailure("This should not be reached!")
return
}
// force updated layout
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
// set tableHeaderView width
tableHeaderViewSuperview.addConstraint(headerView.widthAnchor.constraint(equalTo: tableHeaderViewSuperview.widthAnchor, multiplier: 1.0))
// set tableHeaderView height
let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
tableHeaderViewSuperview.addConstraint(headerView.heightAnchor.constraint(equalToConstant: height))
}
func setTableFooterView(footerView: UIView?) {
// prepare the headerView for constraints
headerView?.translatesAutoresizingMaskIntoConstraints = false
// set the footerView
tableFooterView = footerView
// check if the passed view is nil
guard let footerView = footerView else { return }
// check if the tableFooterView superview view is nil just to avoid
// to use the force unwrapping later. In case it fail something really
// wrong happened
guard let tableFooterViewSuperview = tableFooterView?.superview else {
assertionFailure("This should not be reached!")
return
}
// force updated layout
footerView.setNeedsLayout()
footerView.layoutIfNeeded()
// set tableFooterView width
tableFooterViewSuperview.addConstraint(footerView.widthAnchor.constraint(equalTo: tableFooterViewSuperview.widthAnchor, multiplier: 1.0))
// set tableFooterView height
let height = footerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
tableFooterViewSuperview.addConstraint(footerView.heightAnchor.constraint(equalToConstant: height))
}
}
I think the problem is because you are using autolayout and setting frames to views manually, replace this code:
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.tableView];
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
self.tableView.tableHeaderView = self.searchBar;
with something like this:
self.tableView = [UITableView new];
self.tableView.translatesAutoresizingMasksIntoConstraints = NO;
[self.view addSubview:self.tableView];
self.searchBar = [UISearchBar new];
self.searchBar.translatesAutoresizingMasksIntoConstraints = NO;
self.tableView.tableHeaderView = self.searchBar;
It may not work, because maybe searchBar's frame needs to be set manually without constraints.
Here issue regarding space between table view Header and table view Cell. You can handle using Attribute Inspector. Please review that.
- select UITableView
- Under attribute inspector -> Scroll view size -> Content insets, set Top = 44 (or whichever is your nav bar height).
Or you can Handle it programmatically.
- (void)viewDidLoad {
UIEdgeInsets inset = UIEdgeInsetsMake(20, 0, 0, 0);
self.tableView.contentInset = inset;
}

UITableViewController - Fixed Background Image

Is it possible to fix the position of a UITableViewController background image?
I've added the background image via the viewdidload method with the following code -
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"blurredBGW"]];
But as the table is fairly long (and also contains static cells if that matters) it scrolls (and repeats) as you scroll down the table.
you can try to add the background image as UIView and not as UIColor, try this:
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"blurredBGW.png"]];
for swift version 3.0.try this code.it will set a fixed background to a table view controller
self.tableView.backgroundView = UIImageView(image: UIImage(named: "background.png")!)
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bg.png"]];
[tempImageView setFrame:self.tableView.frame];
self.tableView.backgroundView = tempImageView;
Make the background of your table (and the cells) transparent, and set the image for the view underneath the table.
for
swift 2.2
you may use the following line of code
self.tableView.backgroundView = UIImageView(image: UIImage(named: "xxxx.png"))
I prefer to configure background with creating its specific xib, because background can be difficult. I do next:
1) Create a class, that helps me to load nib
class UIXIBView: UIView {
var view: UIView!
func setupXIBWithName(_ nibName: String) {
view = self.getViewFromNibWithName(nibName)
self.addSubview(view)
view.frame = self.bounds
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
}
func getViewFromNibWithName(_ nibName: String) -> UIView {
let bundle = Bundle.main
let views = bundle.loadNibNamed(nibName, owner: self, options: nil)! as [AnyObject]
let view = views[0] as! UIView
return view
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setupXIBWithName(String(describing: type(of: self)))
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setupXIBWithName(String(describing: type(of: self)))
}
}
2) I create your specific view, for example let it be LKBackgroundView.swift, and inherit it from UIXIBView
class LKBackgroundView: UIXIBView {
// You can add your own logic there or override smth
}
3) I create xib with the same name LKBackgroundView.xib
4) I set FileOwner's class to LKBackgroundView inside xib, don't make a mistake by setting LKBackgroundView to the view class
5) Configure you xib like you want
6) Initialize your view inside ViewDidLoad inside your View Controller
override func viewDidLoad() {
super.viewDidLoad()
LKBackgroundView(frame:tableView.bounds)
tableView.backgroundView = backgroundView
}
7) Test it
Xamarin/C# Solution
TableView.BackgroundView = new UIImageView(UIImage.FromBundle("blurredBGW"))

Adding Background Image into View Controller

I tried to use this code under in my app delegate in order to add a PNG image as a view controller's background :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[self window] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
return YES;
}
but I have no luck with it... the view controller still has a white background. What's wrong with that code?
The accepted answer and Michael's answer will work, however, proper way is to use a UIImageView instead. It gives more control over resizing, scaling etc according to different screen sizes on devices. Here is the example;
First create a UIImage.
UIImage *backgroundImage = [UIImage imageNamed:#"iphone_skyline3.jpg"];
Second create a UIImageView. Set the frame size to the parent's (self) frame size. This is important as the frame size will vary on different devices. Stretching will occur depending on the image size. Next assign the image to the view.
UIImageView *backgroundImageView=[[UIImageView alloc]initWithFrame:self.view.frame];
backgroundImageView.image=backgroundImage;
Finally, to keep the image behind all controls do the following. It is important if you are setting the image as a background for your app.
[self.view insertSubview:backgroundImageView atIndex:0];
You need to set the background for your ViewController's view
In your ViewController init or viewDidLoad:
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
Here is how it is in swift:
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(patternImage: UIImage(named: "background.png"))
}
Swift 4 version of the #hadaytullah answer with some improvements in image adjustments:
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = UIImage.init(named: "yourImageNameHere")
let backgroundImageView = UIImageView.init(frame: self.view.frame)
backgroundImageView.image = backgroundImage
backgroundImageView.contentMode = .scaleAspectFill
backgroundImageView.alpha = 0.1
self.view.insertSubview(backgroundImageView, at: 0)
}
You could also write extension to UIViewController to use in multiple places
extension UIViewController {
func setBackgroundImage(imageName: String) {
let backgroundImage = UIImage(named: imageName)
let backgroundImageView = UIImageView(frame: self.view.frame)
backgroundImageView.image = backgroundImage
self.view.insertSubview(backgroundImageView, at: 0)
}
}
In viewDidLoad, I use:
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"yourImageString.png"]];
Alternatively, if you want to do it in appDelegate, I think its possible to
[self.window setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"yourImageString.png"]]];
Then in viewDidLoad set background to [UIColor clearColor] ?
If your view controller is having tableView/collection view the below code will suitable for you.
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourImage.png"]];
}
you may consider the following solution i use in swift 3.0 and tested in xcode 8
// init and image with your pattern image
var bgUIImage : UIImage = UIImage(named: "yourIamgeName")!
let myInsets : UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
bgUIImage = bgUIImage.resizableImage(withCapInsets: myInsets)
self.view.backgroundColor = UIColor.init(patternImage:bgUIImage)
the result will be the following image
You can do it from the storyboard.
Add UIImageView and just set your background image for the Image property in the Attribute Inspector.

Resources