Swift get Y coordinate of current element - swift

I got some UILabel which can be pressed to open a menu. When pressed, they call my function with the label itself as a parameter. I make a popover that behave correctly in phone view but I would like to position it when it is on ipad view.
My problem is that I can not get the exact position of the UILabel that was pressed.
I tried
myYCoordinates = label.bounds.origin.y
or
myYCoordinates = label.frame.origin.y
to
optionMenu.popoverPresentationController?.sourceRect = CGRectMake(self.view.bounds.size.width / 2, myYCoordinates, 1.0, 1.0)
But I cant get the good coordinate.
I don't know if it is because my label are in a tableview with 2 section or if there is a way at all.
Thank in advance for the help.
Here is my sceen (cropped du to development confidentiality)
Here is what append when I press my label
And here is what I would like ti to look like
I tried
optionMenu.popoverPresentationController?.sourceRect = label.frame

Based on #Özgür Erzil answer, I found out that I could simply use
optionMenu.popoverPresentationController?.sourceView = label
optionMenu.popoverPresentationController?.sourceRect = CGRectMake(label.frame.width, label.frame.height / 2, 1.0, 1.0)
By setting the source view to my label and using the label width and height to position it.
Thank

if you create your UILabel dynamically, try to set the position when you set it like:
CGRectMake(x, y, width, height)
var label = UILabel(frame: CGRectMake(0, 0, 200, 20))
or if it is in storyBoard, you have to use constraint methods and use autolayout. Explained here

Related

Bottom Border for UITextField in Swift

I found this question with a solution to my problem but it still has some misbehavior when I'm using it.
How to only show bottom border of UITextField in Swift
In my Project it seems like the bottom border doesn't know the correct width of my UITextField and is longer than my UITextField. The UITextField has constraints to the SaveArea on the left and right and a constraint to the text above. I would say that the width is defined by the constraints at run time so that the code in the extension should be able to get the correct width. But the way my code is getting the width seems to be wrong. Can someone help me?
Thanks in advance :)
I know you found a workaround but just thought I might add a fix for this if you still were considering using this.
So it seems that your set up was fine but it works a little bit differently on different device sizes.
self.frame.size.width in the extension is not always returning back the correct width of the UITextField in some devices and on orientation changes.
So to get this to work, here are the small changes I made:
extension UITextField
{
func addBottomBorder() {
let bottomLine = CALayer()
// The border should be inside the text field
// so I changed frame.size.height + 5 to
// frame.size.height - 1
bottomLine.frame = CGRect(x: 0,
y: frame.size.height-1,
width: frame.size.width,
height: 1)
bottomLine.backgroundColor = UIColor.black.cgColor
borderStyle = .none
layer.addSublayer(bottomLine)
// Add this so the layer does not go beyond the
// bounds of the text field
layer.masksToBounds = true
}
}
After this, the result should be as you hope:

How to insert Custom Label with text into View with Animation?

Im making a small boxing app. This whole week iv been trying to work out how to solve my current problem above, with no luck :(.
Summary
Basically Its a 1 v 1 game. Each time the user hits the other player I want to make a tiny number pop up near him and float up and dissappear.
Its sort of like when you play MMORPG's and when you do dmg you see how much you did. See image below for an example!
So basically everytime the user hits the other player I want a little number to pop up on the screen to show the dmg and then float up and disappear.
Details
I am building the game on a simple UIView
The label is a UILabel
Anywhere How I can achieve this?
Thank you!
Create a label, then use UIView.animateWithDuration to animate it.
let label = UILabel(frame: CGRect(origin: point/*The point where you want to add your label*/, size: CGSize(width: 50, height: 50)))
label.text = "+1"
label.font = UIFont()//Your font
label.textColor = UIColor.blueColor()
label.alpha = 1
self.view.addSubview(label)
UIView.animateWithDuration(1) {
label.center = CGPoint()//The point where you want your label to end up
label.alpha = 0
}
Edit: As mentioned in the comments, you asked for how to create the label at a random point. Try this:
let screenWidth = self.view.frame.width
let screenHeight = self.view.frame.height
let randomX = CGFloat(arc4random_uniform(UInt32(screenWidth)))
let randomY = CGFloat(arc4random_uniform(UInt32(screenHeight)))
let point = CGPoint(x: randomX, y: randomY)
As you will notice, for the width and height, I use the view's frame's width and height. You may want to use the view's bounds. For more on this, check out this SO Post.

Vertically aligning text in an NSTextField using Swift

I have been reading through the various options on how to set the vertical alignment on an NSTextField. I want the text to be displayed in the center and to do it programatically in Swift. Here are the things I have looked so far:
http://www.cocoabuilder.com/archive/cocoa/174994-repositioning-an-nstextfieldcell.html
https://red-sweater.com/blog/148/what-a-difference-a-cell-makes
Vertically Centre Text in NSSecureTextField with subclassing
Get NSTextField contents to scale
vertically align text in a CATextLayer?
One thing I have tried in Swift is to set the following property:
textField.usesSingleLineMode = true
Any tips on the best way to vertically center text would be much appreciated!
This is very hard to do, as Apple makes this very difficult. I achieved it by subclassing NSTextFieldCell and overriding the drawingRectForBounds: method like so:
override func drawingRectForBounds(theRect: NSRect) -> NSRect {
let newRect = NSRect(x: 0, y: (theRect.size.height - 22) / 2, width: theRect.size.width, height: 22)
return super.drawingRectForBounds(newRect)
}
This is just my way to do it, I'm sure there are better ways, which I don't know (yet). And this only works for the standard font size in TextFields (which gives a text height of 22). That's why I hardcoded that. Haven't figured out yet, how to get the height in the cell if you change the font.
Result:
Try this on a playground, it centers the text perfectly, use it on your projects! Hope it helps!
import Cocoa
let cell = NSTableCellView()
cell.frame = NSRect(x: 0, y: 0, width: 100, height: 100)
let tf = NSTextField()
tf.frame = cell.frame
tf.stringValue = "MyTextfield"
tf.alignment = .Center
let stringHeight: CGFloat = tf.attributedStringValue.size().height
let frame = tf.frame
var titleRect: NSRect = tf.cell!.titleRectForBounds(frame)
titleRect.size.height = stringHeight + ( stringHeight - (tf.font!.ascender + tf.font!.descender ) )
titleRect.origin.y = frame.size.height / 2 - tf.lastBaselineOffsetFromBottom - tf.font!.xHeight / 2
tf.frame = titleRect
cell.addSubview(tf)
I have added the NSTextField inside a NSView and centered it.
Another solution was (in an iOS project) to create a UILabel and allow it adjust its size (sizeToFit()) and again embed it inside a UIView.
I personally don't like the calculations in previous answers and the second solution for iOS works for all texts size and row numbers.
I was also facing vertical alignment issue with NSTextField. My requirement involved, rendering a single-line string inside a NSTextField. Additionally,
textfield needed to be resize implying we had programatically resized the font-point-size of the text inside text-field on resize. In this scenario we faced vertical-alignment issues - the mis-alignment was tough to grasp/understand in a straight forward way.
What finally worked:
So, in my scenario a simple,
turn off the "Single Line Mode" in interface builder
for the text-field solved the issue.
The accepted answer works perfectly and here's the Swift3 version.
class VerticallyAlignedTextFieldCell: NSTextFieldCell {
override func drawingRect(forBounds rect: NSRect) -> NSRect {
let newRect = NSRect(x: 0, y: (rect.size.height - 22) / 2, width: rect.size.width, height: 22)
return super.drawingRect(forBounds: newRect)
}
}

How to make image switch positions

How can I make an image start at a predetermined location on screen, and when tapped, appear at a different location, also predetermined. And when tapped then, return to the original location?
Thanks
PS: Working on Xcode 6 - Swift
If you are using an UIImageView, simply change its frame. (Let me know if you're using autolayouts):
let imageView = UIImageView(frame: CGRectMake(0, 0, width, height))
imageView.image = UIImage(named: "assetName")
then when clicked (you can detect by overlaying a clear button over your image, etc):
imageView.frame = CGRectMake(100, 100, width, height)
etc.
Every UIView has a frame property of type CGRect which specifies both its size and position. To change the position of a view, you thus have to modify the x and y values of the frame's origin, the location of the upper-left point of the framing rectangle:
let view = UIView()
// Set location and size
view.frame = CGRectMake(0, 0, width, height)
// Modify location
view.frame.origin = CGPointMake(newX, newY)
Depending on what type your view has, there are different approaches to react to taps on the view. A button, for example, can specify a target function that is called when it's tapped.
Generally speaking, you can attach a UIGestureRecognzier (such as a UITapGestureRecognizer) to detect gestures the user performed on the given UIView. You also need to make sure its userInteractionEnabled property is set to true so that the interaction can be detected in the first place.

UIButton label text is being clipped

I have a UIButton built in Interface Builder that has a default label. In Xcode, I'm changing the label text dynamically like so:
myButton.titleLabel.text = #"this is the new label";
However, when the text updates, the new string is being clipped down to the same size as the original string and ends up looking like:
this...label
Anyone know why this is happening?
You should use setTitle:forState: to change the title of a UIButton. If you change the title yourself, the button has no indication that it needs to resize the label – you'd end up having to do something like this:
myButton.titleLabel.text = #"this is the new label";
[myButton setNeedsLayout];
but I'm not even sure that would work in all cases. Methods like setTitle:forState: are provided so that you can provide titles for multiple states without having to update the button manually, and so that the button knows that it needs to be laid out with a new title.
Try using the button's setTitle method (rather than setting the title directly on the label). It should force the title label to be resized.
Objective C:
[myButton setTitle:#"This is the text" forState:UIControlStateNormal];
Or in Swift:
myButton.setTitle("This is the text", for: .normal)
An alternative solution is to let the UIButton's inner UILabel to shrink the font size, as UILabels can do :
button.titlelabel.minimumFontSize = 8.0; // or some more adequate size
self.buttonWithLongTitle.titleLabel.adjustsFontSizeToFitWidth = YES;
Call sizeToFit on your button. This will resize the button to fit the text.
If that didn't work you can always determine the string size and adjust the button frame width. In that case you are sure it will fit.
// Calculate the size
CGSize buttonSize = [#"My text.." sizeWithFont:[UIFont systemFontOfSize:15.0]
constrainedToSize:someSize lineBreakMode:UILineBreakModeWordWrap];
// Do whatever you want with the "buttonSize", you can for example adjust your button's frame width
Solution in Swift 4.2
yourButton.titleLabel?.minimumScaleFactor = 0.5 //set whatever you want here to scale
yourButton.titleLabel?.adjustsFontSizeToFitWidth = true
Solution for Objective C
[yourButton.titleLabel setMinimumScaleFactor:0.5];
[yourButton.titleLabel setAdjustsFontSizeToFitWidth:YES];
This worked for me while setting my button up programmatically with all other constraints.
yourButton.widthAnchor.constraint(equalToConstant: yourButton.intrinsicContentSize.width).isActive = true
You can also add "padding" like so
yourButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
Use Autoresizing mask if not selected.
None of the solutions above worked for me. What did was sublclassing UIButton and re-setting the frame of the titleLabel:
Context: My font was Josefin Sans and it does clipping the top part of "Ñ". I can imagine it could happen with any other text using a different font.
open class Button: UIButton {
open override func layoutSubviews() {
super.layoutSubviews()
guard let titleLabel = titleLabel else {
return
}
// Play around to get these numbers
let heightToAdd: CGFloat = 15
let widthToAdd: CGFloat = 100
titleLabel.frame = CGRect(
origin: CGPoint(
x: titleLabel.frame.origin.x - widthToAdd / 2,
y: titleLabel.frame.origin.y - heightToAdd / 2),
size: CGSize(
width: titleLabel.frame.width + widthToAdd,
height: titleLabel.frame.height + heightToAdd
)
);
}
}
Play around with the values widthToAdd and heightToAdd or make them injectable when setting a new title.
It is not a superb solution, but it was the only think that worked for me.