Imageview changes location on runtime - Swift - image

Hello,
My imageView that I have set in my custom table view cell moves the set image to a different place on run time.
The thing that confuses me is that if I manually set the image in the attributes inspector the image is in the place it is supposed to be. Only when setting the image programatically does this problem arise.
Below is the code I am using my cell creation function to generate the tick or cross.
// Cell Information
if answersBool[indexPath.row] == false {
cell.imageView!.image = UIImage(named: "crossIcon.png")
} else {
cell.imageView!.image = UIImage(named: "tickIcon.png")
}
This is what happens on run time.
This is what the cell looks like in my storyboard.

First of all remove all constraint from your imageView after that select your imageView and click on pin menu then add this five constraint shown in below Image:
Hope it will help you.

You need to constraints for your imageView in storyboard.
Try sticking it to right.

Related

ScrollView with embedded StackView issue

I have a scrollView with a stackView placed in it. The scrollView is constrained to the rootview. The stack view will show a xib view.
The xib views are all different lengths.
The xib views are labeled simpleVC0 and simpleVC1. The length of the simpleVC0is 2500 and the length of simpleVC1 is 1000.
My problem is that when the xib views are presented in the stack view the length of the scrollView does not change to the length of the presented xib view.
It is like the xib view is presented but the scroll view is locked at a specific length.
Here is simpleVC0 xib view. followed by it when run. When I try to scroll it doesn't allow me to scroll to the bottom of the xib view. it seems to cut the xib view off at a certain length.
Am right in saying that this is possibly an issue that may have to be resolved in code? or can it it solved souled by the constraints.
I have tried auto layout constraints however they have not worked.
I have constrained the scrollView to the rootview on all four sides.
When the root view is loaded the xibs are established using the following code:
//Different subViews for ingredients and steps
if counter == 0 {
simpleViewX = SimpleVC0().view
simpleViewY = SimpleVC1().view
stack.addArrangedSubview(simpleViewX)
stack.addArrangedSubview(simpleViewY)
}
The views are the hidden shown by changing the value of the segmented view controller. Shown below:
#IBAction func tabselected(_ sender: Any) {
switch (sender as AnyObject).selectedSegmentIndex {
case 0:
simpleViewY.isHidden = true
simpleViewX.isHidden = false
break
case 1:
simpleViewX.isHidden = true
simpleViewY.isHidden = false
break
case 2:
//calledvideo in array is the value of the counter.
calledVideo = vids[counter]
geturl()
break
default:
break
}
}
To use a UIStackView with a UIScrollView you need to allow the stack view to expand its height based on its content.
When laying it out in storyboard, give the stack view a height constraint (to satisfy IB's requirements), but give that height constraint a low Priority.
Then, when adding arranged subviews, the stack view will grow vertically.
Here's a complete example, based on the images you've shown: https://github.com/DonMag/XIBsInScrollView
You have to modify the contentSize property of your scrollView in the code. I don’t know how to deal with it with storyboards, but you can make an outlet of your scrollView and calculate the new height each times it changes (each time you add something or remove something in it)
scrollView.contentSize = CGSize(width:yourNewW, height:yourNewH)

UITextField backgroundColor in UISearchBar iOS 10+

I'm trying to set the background color of the text field in my search bar to a custom color. I looked at the answer here to no avail:
Cannot change search bar background color
See how that search bar has a red text field? I followed the code and can even verify that the UISearchBarTextField object was found and the background color of it is being set to UIColor.red, but the color does not change.
I've messed around with all the background colors of the superviews with hopes that it might help but I cannot get that color to change. Maybe there's some new trick or someone can shed some light on something that may be overriding the color somehow.
extension UISearchBar {
var textField: UITextField? {
return subviews.first?.subviews.first(where: { $0.isKind(of: UITextField.self) }) as? UITextField
}
}
searchBar.textField?.backgroundColor = UIColor.red // <-- Not working
let textFieldInsideUISearchBarLabel = searchBar.textField?.value(forKey: "placeholderLabel") as? UILabel
textFieldInsideUISearchBarLabel?.textColor = UIColor.lightGray
Note that the text inside the UITextField object is changing to the lightGray like I want it, just not the UITextField background color.
After a long wait for an answer, I decided to try some experiments. I created a new project, dragged a search bar, connected it to the ViewController, added the UISearchBar extension, and set the color - exactly the same as I did in my main project.
Voila! It does set the background color as it should, and as it shows in the linked topic in the main question.
So, I put the projects side by side, opened the storyboard in each of them and started setting the properties of the searchBar, one at a time, until I could see why the bar is not being set like it should in the main project.
The very first thing I tried was, search style. My project has it set to "Minimal". I changed it to "Minimal" in the test project and noticed right away that the color was no longer set.
So, setting the "Search Style" property of the searchBar in the main project to "Default" allowed that background color to be set.
I would appreciate it greatly if anyone could comment and say why it is that I can't use "Minimal" if I want to customize the background color, or how I could make it work.

How do I alter the position of a UIImage inside a UIImageView

I have a UIImage called image I want to change the position of it inside the imageView so it can be dragged down slightly, roughly 30px. Can some one tell me how to do it? This is where I am up to but its not coming out correct.
var image = UIImage()
var imageView = UIImageView(frame: CGRectMake(0, 0, view.frame.size.height * 0.22, view.frame.size.height * 0.22))
imageView.center = CGPointMake(self.view.center.x, view.frame.size.height * 0.414)
imageView.image = self.image
imageView.layer.cornerRadius = imageView.frame.size.width / 2
imageView.layer.borderWidth = 2.0
imageView.layer.borderColor = UIColor(red: 254.0/255, green: 216.0/255, blue: 0/255, alpha: 1.0).CGColor
imageView.clipsToBounds = true
imageView.layer.contentsRect = CGRectMake(0, 20, imageView.frame.size.width, imageView.frame.size.height) //This is where I have being trying to do it but no success.
imageView.contentMode = .ScaleAspectFill
view.addSubview(imageView)
Short answer: You don't.
What you would do is add the image view as a subview of another view. The trivial way to do this would be to put the image view in a scroll view, constrained so that the only place it can scroll is down, and only slightly. Then you could achieve the scrolling with zero code.
EDIT:
This isn't really a coding problem - it's more of an Interface Builder problem. You need to set up a scroll view.
A scroll view is a view that lets you look at a portion of a larger view.
You can think of a scroll view like a piece of paper with a rectangular hole in it. You put a bigger piece of paper under it (The scroll view's content view) and you can slide the bigger piece of paper around and view different parts of it through the hole.
Here's how you would set it up.
Drag a scroll view onto your view controller. Size it and add constraints to it to position it where you want. If you want your image view to be 300x300 points in size, for example, and want to be able to drag it up or down by 20 points, then make the scroll view 20 points taller. (w: 300, h: 320)
Select the view inside the scrollview and set it's width to the same width as it's scrollview, but 20 points taller than the scroll view. (w: 300, h: 340). Add constraints to lock it's height and width.
Now you have a scroll view that's big enough for a 300x300 point image, with 20 points of total white space at the top and bottom.
You've created a content view that's 20 points bigger than that, so it can slide up or down by 20 points in the scroll view.
Drag your 300x300 point image view into the view inside the scroll view, assign an image to it, and add constraints to lock it's size and center it horizontally and vertically in it's superview.
The final step is to set the content size of the scroll view. Normally you just set a scroll view's content size to the size of it's content view. You can do that by adding this bit of code to your view controller's viewDidLoad:
(Assuming you've connected an outlet to your scrollview that's called theScrollView)
//Get the first (and only) subview of the scrollView.
let subview = theScrollView.subviews[0] as! UIView;
//Make the scroll view's contentSize the same size as the content view.
theScrollView!.contentSize = subview.bounds.size;
It's also possible to set the content size of the scroll view without any code at all. You'd use a feature of IB (Interface Builder) called "User Defined Runtime Attributes". Here's how you'd do that: (If you use this approach don't add the code above to viewDidLoad)
Select the scroll view in IB.
Press command-option 3 to select the "identity inspector".
In the section headed "User Defined Runtime Attributes", tap the plus sign on the left. Edit the Key Path to "contentSize" (all lower case except the "S" in "Size". That's very important.) Press enter to change the key path. Then tap on the "type" column and select "size". The value field will show "{0,0}". Enter your desired content size: ("{300,340}" in the example above.)
What this does is tell IB "At runtime, look for a property called "contentSize" in the selected object (the scroll view.) Set that property to the specified value of type CGSize.
Once you're done your IB "identity inspector" should look like this:
Note that if you get a key name wrong when using "User Defined Runtime Attributes" then the app crashes when you display that view controller, with a very cryptic message.
By default scrollviews let you "overshoot" when dragging their contents around, and then bounce back into place when you let go. You can turn that feature off by unchecking the "Bounce" checkbox in the IB "Attributes Inspector" (command option 4)
You shouldn't do that. But if you want to you can play with anchorPoint property of backing layer of UImageView. link
Note: Keep in mind any layout process may alter this property later.

Can I disable autolayout for a specific subview at runtime?

I have a view that needs to have its frame manipulated programmatically - it's a kind of document view that wraps to its content which is then scrolled and zoomed around a superview by manipulating the frame origin. Autolayout fights with this at runtime.
Disabling autolayout completely seems a bit harsh because it could reasonably be used to handle layout for the other views. It seems like what I might want is some kind of "null constraint".
I had the same problem. But I have resolved it.
Yes, you can disable auto layout at runtime for a specific UIView, instead of disabling it for the whole xib or storyboard which is set by default in Xcode 4.3 and later.
Set translatesAutoresizingMaskIntoConstraints to YES, before you set the frame of your subview:
self.exampleView.translatesAutoresizingMaskIntoConstraints = YES;
self.exampleView.frame = CGRectMake(20, 20, 50, 50);
I had a similar issue where Autolayout was overriding some of my frame-setting at run time (I had a dynamic view that in some cases pushed a new view controller...pushing and then pressing Back would reset the initial view).
I got around this by putting my manipulation code in viewDidLayoutSubviews of my View Controller. This seems to get called after whatever constraint mojo gets called, but before viewDidAppear, so the user is none the wiser.
Perhaps just setting translatesAutoresizingMaskIntoConstraints to YES (and not adding additional constraints affecting that view) will let you set the frame without fighting the auto layout system.
In iOS 8 you can set an NSLayoutConstraint to be active or not. So if I'm using interface builder, I add all my constraints to an OutletCollection and then activate or deactivate using:
NSLayoutConstraint.deactivateConstraints(self.landscapeConstraintsPad)
NSLayoutConstraint.activateConstraints(self.portraitConstraintsPad)
The particular application I'm using it for here is having different constraints in portrait and landscape mode and I activate/deactivate based on the rotation of the device. It means I can create some complex layout changes all in interface builder for both orientations, and still use auto layout without the verbose auto layout code.
Or you can activate / deactivate using removeConstraints and addConstraints.
I don't know if this will help anyone else, but I wrote a category to make this convenient because I find myself doing this a lot.
UIView+DisableAutolayoutTemporarily.h
#import <UIKit/UIKit.h>
#interface UIView (DisableAutolayoutTemporarily)
// the view as a parameter is a convenience so we don't have to always
// guard against strong-reference cycles
- (void)resizeWithBlock:(void (^)(UIView *view))block;
#end
UIView+DisableAutolayoutTemporarily.m
#import "UIView+DisableAutoResizeTemporarily.h"
#implementation UIView (DisableAutoResizeTemporarily)
- (void)resizeWithBlock:(void (^)(UIView * view))block
{
UIView *superview = self.superview;
[self removeFromSuperview];
[self setTranslatesAutoresizingMaskIntoConstraints:YES];
__weak UIView *weakSelf = self;
block(weakSelf);
[superview addSubview:self];
}
#end
I use it like this:
[cell.argumentLabel resizeWithBlock:^(UIView *view) {
[view setFrame:frame];
}];
Hope it helps.
You can set the translatesAutoresizingMaskIntoConstraints type Boolean, Value Yes in the User Defined Runtime Attributes of the UIView you want in the xib/storyboard.
In my view I had a Label and a Text. The label had pan gesture. The label moves around fine during drag. But when I use the text box keyboard, the label resets its position to the original location defined in auto layout. The issue got resolved when I added the following in swift for the label. I added this in viewWillAppear but it can be added pretty much anywhere you have access to the target field.
self.captionUILabel.translatesAutoresizingMaskIntoConstraints = true
Open project in 4.5
Select storyboard
Open the file inspector
Under Interface Builder Document uncheck 'Use Autolayout'
You can split across multiple storyboards if you want to use autolayout for some views.
For me it worked to create the subview programmatically, in my case the auto layout was messing with a view that I needed to rotate around its center but once I created this view programmatically it worked.
I've encountered a similar scenario, where I joined a project that was initiated with auto-layout, but I needed to make dynamic adjustments to several views. Here is what has worked for me:
Do NOT have views or components laid out in interface builder.
Add your views purely programmatically starting with alloc/init and setting their frames appropriately.
Done.
This happened to me in a project without storyboards or xib files. All 100% code. I had an ad banner at the bottom and wanted the view bounds to stop at the ad banner. The view would resize itself automatically after loading. I tried every resolution on this page but none of them worked.
I ended up just creating a sub view with the shortened height and placed that in into the main view of the controller. Then all my content went inside the sub view. That solved the problem very easily without doing anything that felt like it was going against the grain.
I am thinking if you want a view that is not the normal size that fills the window then you should use a sub view for that.
Instead of disabling autolayout, I would just calculate the new constraint with the frame you are replacing. That appears to me to be the appropriate way. If you are adjusting components that rely on constraints, adjust them accordingly.
For example, if you have a vertical constraint of 0 between two views (myView and otherView), and you have a pan gesture or something that adjusts the height of myView then you can recalculate the constraint with the adjusted values.
self.verticalConstraint.constant = newMyViewYOriginValue - (self.otherView.frame.origin.y + self.otherView.frame.size.height);
[self.myView needsUpdateConstraints];
For those of you who are using auto layout, please check out my solution here. You should be making #IBOutlet's of the constraints you want to adjust and then change their constants.
if it's xib file:
select the .xib file
select the "File's Owner"
show the Utilities
click on: "File Inspector"
Under "Interface Builder Document" disable: "Use Autolayout"

Autoresize the root view when device is rotated

I am developing PDF reader. I am facing problem while rotating the simulator. What I am doing is, when view is loaded by the ViewController(i.e. in the loadView), I am creating the UIScrollView which contains UIImageView and UIView of the same size(i.e. size of the PDF page). It is working perfectly in the portrait mode. But when I rotate the simulator in the landscape mode, the view is not autoresized according to device. I have tried
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
in the viewDidLoad() of the ViewController
But it's not working. I am confused how the above two properties work. I guess these properties will autoresize the UIScrollView to the size of root view in which I am loading UIScrollView. But what should be done to autoresize the main view in which UIScrollView is loaded??
I've experienced the same problem when trying to utilise the auto resizing methods. So, I hope this will help. (P.S. I'm assuming you're creating the UI programmatically and not via IB)
So have you tried this?
Inside your viewcontroller add the following:
// Set the View Controller to fit the whole screen.
-(BOOL)wantsFullScreenLayout{
return YES;
}
Inside the loadView method amend your scrollView to:
// set the initial size of your scrollView object.
[scrollView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
// Set the auto resizing attributes.
[scrollView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
In addition to this you might need to set the autoresizingmask margins for either the UIView or UIImageView depending on the type of layout you require when the device is rotated.
This is late reply... It may help if you didn't Fix it yet.
When you create any app in portraid mode and if you want it to rotate (resize) to landscape mode, you should do it in User Interface Builder or .xib (or in Storyboard iPad or iPhone)file.
So to check or to check rotate in the Simulator:
Go to "USER INTERFACE BUILDER", or ".XIB" (or "Storyboard iPad or iPhone") file.
Then select "UIImageView" and go to "SHOW THE ATTRIBUES INSPECTOR".
In the fourth tab (Attributes Inspector) set the mode to “Aspect Fit”, and in the third tab (Size Inspector) and in the fifth tab (Size Inspector) set the autosizing attributes to the following:
Set the arrows to all directions. Sorry can't load image.
Do the same for "UIView" (3).
Before you move on, you can double check that you’ve gotten all of the autosizing attributes right by selecting the Detail View Controller, and changing the orientation from Portrait to Landscape: Sorry can't load image for now...
You can Check or Change to "Landscape or Portrait" on the top right side "Simulated Metrics" select under "Size" the "Orientation".
If something isn’t right, don't worry: Just change it back to Portrait and double check the settings.

Resources