I'm trying to practice here, I have a SearchBar in my view and i've used
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
Once the user starts writing, I hide on of my views, and make another one programmatically
Here's my concept, Once i start writing, my 2nd view comes in:
But once i get the second view properly added, i'd like to add a UILabel to it. Here's my code:
self.word_of_the_day_view.isHidden = true // main view
self.popularView.frame = CGRect(x: self.searcy_bar_view.frame.minX, y: self.searcy_bar_view.frame.maxY + 15, width: self.searcy_bar_view.frame.width, height: self.searcy_bar_view.frame.height) // don't mind the height and width
self.popularView.backgroundColor = .white
self.popularView.layer.cornerRadius = self.searcy_bar_view.layer.cornerRadius
self.popularView.popIn() // just an animation
is_popular_added = true
self.view.addSubview(popularView)
let label_1 = UILabel()
label_1.frame = CGRect(x: self.popularView.frame.minX + 3, y: self.popularView.frame.minY, width: self.popularView.frame.width, height: 20)
label_1.font = UIFont(name: "avenirnext-regular", size: 13)
label_1.text = "Hello World!"
label_1.layer.borderColor = UIColor.red.cgColor
popularView.addSubview(label_1)
But on runtime, the UILabel isn't even added.
Thank you so much for even reading the question!
You need to understand the difference between Frame and Bounds.
The Frame of the view is the position of the view in it's super view, so his origin can have any value of a CGPoint.
The Bounds are just the view itself, so it always have an origin of (0,0)
I think the problem is
label_1.frame = CGRect(x: self.popularView.frame.minX + 3, y: self.popularView.frame.minY, width: self.popularView.frame.width, height: 20)
try to change in
label_1.frame = CGRect(x: self.popularView.bounds.minX + 3, y: self.popularView.bounds.minY, width: self.popularView.frame.width, height: 20)
or
label_1.frame = CGRect(x: 3, y: 0, width: self.popularView.frame.width, height: 20)
In your code
label_1.frame = CGRect(x: self.popularView.frame.minX + 3, y: self.popularView.frame.minY, width: self.popularView.frame.width, height: 20)
This is because self.popularView.frame.minX and self.popularView.frame.minY have some +value that crosses the boundary of the current view on which you are trying to add label_1.
you should use self.popularView.bounds.origin.x and self.popularView.bounds.origin.y
Difference between bounds and frame
frame = a view's location and size with respect to the parent view's coordinate system
bounds = a view's size using its own coordinate system
This issues is due to confusion between frames and bounds. I also got similar issue in on of my app.
The bounds of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to its own coordinate system (0,0).
The frame of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to the superview it is contained within.
you should use self.popularView.bounds.origin.x and self.popularView.bounds.origin.y in place of self.popularView.frame.minX and self.popularView.frame.minY
Related
I have a color palette imageview, in that I want to place a plus icon(imageView) according to the x and y-axis I am getting from the backend. If I get x = 0 and y = 0 the frame of the plus is placing correctly
For y axis if I set height of the color palette imageView to the plus icon's frame's y axis, the icon is not going to the actual (0,0)
.
The code I used is below
let cWidth = self.colorPalleteImageView.frame.size.width // 348
let cHeight = self.colorPalleteImageView.frame.size.height // 378.5
let imageView = UIImageView(image: appImages.roundPlusIcon.image)
imageView.frame = CGRect(x: 0, y: cHeight, width: 22, height: 22)
colorPalleteImageView.addSubview(imageView)
I am checking this with iPad 12.9 inch simulator. Am I missing anything to achieve that x=0 and y=0, If I give the width of the colorPaletteImage to the x-axis of plusIconImageView it is not going to end fo the x-axis, It stays before the end of the width of the imageview, I don't know why it is happening, Need help
You're using frame sizes before the frames are finished being set by auto-layout.
I'd suggest using constraints, but if you want to stick to frame coordinates...
add the "round plus" icon imageView in viewDidLoad()
set its frame.origin in viewDidLayoutSubviews() or viewDidAppear()
imageView.frame = CGRect(x: cWidth, y: cHeight, width: 22, height: 22)
mast be:
imageView.frame = CGRect(x: 0, y: 0, width: 22, height: 22)
as axes are:
0,0-----------------> x
| ▢
|
|
|
V
with 0,0 you put top left of little image to to top left of big.
You can fix this issue by modifying the height property to the super view's bound's height. You need to know the difference between frame and bounds to understand why this is happening. In simple words frame is the CGRect with respect to it's super view and bounds is the CGRect with respect to it's own coordinates.
Plenty of detailed explanations are available online just need to google frame vs bounds and you'll get used to both of these after you play with it many times.
Here's how you fix this issue.
let cHeight = self.colorPalleteImageView.bounds.size.height
sorry.. I am back
I did (to follow your code I forced values..)
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var colorPalleteImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let v = self.view
print(v!.frame)
let cHeight = CGFloat(378.5)
colorPalleteImageView.frame.size.width = 348
colorPalleteImageView.frame.size.height = cHeight
let plusImg = UIImage(named: "plus")
let imageView = UIImageView(image: plusImg)
imageView.frame = CGRect(x: 0, y: cHeight-22, width: 22, height: 22)
colorPalleteImageView.addSubview(imageView)
}
}
and I got: (on iPad)
What´s the difference between view and superview?
let fromViewController = self.source
let containerView = fromViewController.view.superview
Suppose that
let v1 = UIView()
parent.addSubview(v1)
here
v1 ----- >>> v1 ( The view itself )
v1.superview ------- >>> parent
Views are the fundamental building blocks of your app's user interface, and the UIView class defines the behaviors that are common to all views. A view object renders content within its bounds rectangle and handles any interactions with that content.
let rect = CGRect(x: 10, y: 10, width: 100, height: 100)
let myView = UIView(frame: rect)
The superview is the immediate ancestor of the current view. The value of this property is nil when the view is not installed in a view hierarchy. To set the value of this property, use the addSubview(_:) method to embed the current view inside another view.
let rect = CGRect(x: 10, y: 10, width: 100, height: 100)
let myView = self.view.addSubview( UIView(frame: rect))
In my project I have a pinch to resize option for the object that has been placed in scene view. But when someone pinch the screen to reduce or enlarge the actual size of the object I need to get that scale. I need to display the scale in which the object is being changed in the screen. How do I get the scale when the action is being performed?
Thank you
Within your main ViewController Class for the ARSCNView
declare the label view, and the label itself at the top.
let scaleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 300, 70))
let labelView = UIView(frame: CGRect(x: 300, y: 300, width: 300, height: 70))
Now within LoadView or ViewDidLoad you can set the attributes for the label such backgroundColor, textColor etc... and also add the view and label to sceneView.
// add your attributes for label,view
labelView.backgroundColor = .clear
scaleLabel.textColor = .white
scaleLabel.adjustsFontSizeToFitWidth
// add you views to sceneView
labelView.addSubview(scaleLabel)
sceneView.addSubview(labelView)
Lastly, with the pinch gesture function for scaling.. which should look something like this.
#objc func pinchGesture(_ gesture: UIPinchGestureRecognizer) {
if nodeYouScale != nil {
let action = SCNAction.scale(by: gesture.scale, duration: 0.1)
nodeYouScale.runAction(action)
gesture.scale = 1
// this part updates the label with the current scale factor
scaleLabel.text = "X: \(nodeYouScale.scale.x) Y: \(nodeYouScale.scale.y) Z:\(nodeYouScale.scale.z)"
} else {
return
}
I want to know if there is a way to determine if a UILabel is full of text.
For example, if a have a label with size of:
| |
I want to know when the label is full of text, such as:
|.........|
I need to fill its with dots until it reaches the textFields width.
Well, If I got it right, probably what are you looking for is Label intrinsicContentSize:
The natural size for the receiving view, considering only properties
of the view itself.
the width of the label intrinsicContentSize should be the actual width of the label, doesn't matter what's the frame.size.width value.
Based on that, you simply implement:
let lbl = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 21))
print(lbl.frame.size.width)
// 150.0
lbl.text = ""
let intrinsicSizeWidth = lbl.intrinsicContentSize.width
// since the label text is still empty, its value should be 0.0
print(intrinsicSizeWidth)
while lbl.intrinsicContentSize.width < lbl.frame.size.width {
lbl.text?.append(".")
}
print(lbl.text!)
// ................................
Note that increasing your label width would leads to contains more dots:
let lbl = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
.
.
.
print(lbl.text!)
// ...........................................
Obviously, if you would like to compare it with a UITextField -for instance- (as you mentioned in the question), it should be:
// "textField" the name of your text field...
while lbl.intrinsicContentSize.width < textField.frame.size.width {
lbl.text?.append(".")
}
Create label with frame and default text
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 100))
label.text = ""
Populate text with dots until text's width reaches label's width
while label.sizeThatFits(label.frame.size).width <= label.frame.width {
label.text = label.text! + "."
}
Is there a way to adjust the position of a rightView on UITextField? I tried setting the frame on the view (set as rightView) but it didn't change anything.
I'd like to avoid making two views, one as the rightView and one as the rightView's subview where I change the subview's position, if possible.
The right overlay view is placed in the rectangle returned by the rightViewRectForBounds: method of the receiver.
So I suggest you subclass UITextField and override this method, something like this:
#interface CustomTextField: UITextField
#end
#implementation CustomTextField
// override rightViewRectForBounds method:
- (CGRect)rightViewRectForBounds:(CGRect)bounds{
CGRect rightBounds = CGRectMake(bounds.origin.x + 10, 0, 30, 44);
return rightBounds ;
}
#Puneet Sharma's answer was great but that would give the need to create a class that would subclass UITextField, what I did instead was create a UIView that would act as a padding.
This code works without the need to subclass
Here's my code, although it's written in Swift 3
// this is the view I want to see on the rightView
let checkImageView = UIImageView(image: UIImage(named: "check24.png"))
checkImageView.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
checkImageView.curveEdges(12)
checkImageView.contentMode = .scaleAspectFit
// declare how much padding I want to have
let padding: CGFloat = 6
// create the view that would act as the padding
let rightView = UIView(frame: CGRect(
x: 0, y: 0, // keep this as 0, 0
width: checkImageView.frame.width + padding, // add the padding
height: checkImageView.frame.height))
rightView.addSubview(checkImageView)
// set the rightView UIView as the textField's rightView
self.textField.rightViewMode = .whileEditing
self.textField.rightView = rightView
What happened here is, that the rightView which is a UIView that has a transparent colored background which then gave the illusion that there is a padding whereas there is not.
Right Padding you can use as
let imageview = UIImageView(image: UIImage(named: "image name"))
imageview.contentMode = .center
let rightPadding: CGFloat = 14 //--- change right padding
imageview.frame = CGRect(x: 0, y: 0, width: imageview.frame.size.width + rightPadding , height:imageview.frame.size.height)
textField.rightViewMode = .always
textFieldd.rightView = imageview