Getting details about the pinch gesture in ARKit - ios

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
}

Related

swift pan a imageView that is behind a view

Is it possible to pan an object that is behind another object?
Currently I have a imageview and a view with clear color and only a border around, that I can see the imageview. I want to achieve that the view with the border is always on top. Trough the view I want to pan the image view with pan gesture.
You can add Pan gesture to the view and apply the transformation to the imageView.
var translation = panGesture.translationInView(imageView)
panGesture.setTranslation(CGPointZero, inView: imageView)
Just set isUserInteractionEnabled false for upper view.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let bottomView = UIView.init(frame: .init(x: 100, y: 100, width: 300, height: 300))
bottomView.backgroundColor = .yellow
let upperView = UIView.init(frame: .init(x: 100, y: 100, width: 300, height: 300))
upperView.backgroundColor = .clear
upperView.layer.borderWidth = 1
upperView.layer.borderColor = UIColor.red.cgColor
upperView.isUserInteractionEnabled = false //<------------
view.addSubview(bottomView)
view.addSubview(upperView)
bottomView.addGestureRecognizer(UIPanGestureRecognizer.init(target: self, action: #selector(handle)))
}
#objc func handle() {
print("handletapgesture")
}
}

Programmatically adding UILabel is not visible

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

Limited Area Pinchview in Swift

I have a label on a imageview and both of them are in one view. The label is pinch-able via below code. However, it is pinch-able also out of image view. I want the areas outside of the imageview not seen (like in whatsapp or snapchat. The texts outside of the screen is not seen, i want that for only imageview area). I'm not sure but i guess somehow it will be done with bring view to front function. Just i don't know how to do it
func handlePinch(recognizer: UIPinchGestureRecognizer) {
if let view = recognizer.view as? UILabel {
let pinchScale: CGFloat = recognizer.scale
view.transform = view.transform.scaledBy(x: pinchScale, y: pinchScale)
recognizer.scale = 1.0
}
}
I done it with creating views out of imageview (left, right upper and bottom side) and set all views to the front except the view which has imageview. I created the first three view in (left, right and the bottomside) in the storyboard and last one (the upper one) in the code because i needed to hide status bar first then create a view on top of it.
customView = UIView(frame: CGRect(x: 0, y: 0, width: 440, height: 20))
customView.backgroundColor = UIColor.white
self.view.addSubview(customView)
self.view.bringSubview(toFront: view_main)
self.view.bringSubview(toFront: view2)
self.view.bringSubview(toFront: view3)
self.view.bringSubview(toFront: customView)

Frame on ViewController

I have this class:
extension UIViewController {
func waiting() -> UIView{
let strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 200, height: 50))
strLabel.text = "Aguarde..."
strLabel.textColor = UIColor.whiteColor()
let messageFrame = UIView(frame: CGRect(x: view.frame.midX - 90, y: view.frame.midY - 25 , width: 180, height: 50))
messageFrame.layer.cornerRadius = 15
messageFrame.backgroundColor = UIColor(white: 0, alpha: 0.40)
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityIndicator.startAnimating()
messageFrame.addSubview(activityIndicator)
messageFrame.addSubview(strLabel)
view.addSubview(messageFrame)
return messageFrame
}
}
When I need use this class I use:
class MyController: UIViewController{
....
func x(){
let messageFrame = waiting()
//my code
messageFrame.removeFromSuperview()
}
}
The problem is when the frame is showed if I touch anywhere on my app this frame is hidden. I need that when this frame is showed other options staying disabled, when I finish the frame, the options of app is enabled again. How can I do it?
Change the view that you are returning a bit:
Make a "container" view that has the same frame as the view controller's view. Give this view a "clear" background.
Make a "background" view, same size as the "container" view and add it to the container. Give this view a black background and an alpha of, say, 0.4.
Now put the view that you are currently building in your "waiting" method, and add it to the "container" view (NOT to the background view, this should be a sibling of the background view, otherwise your alert will also be transparent).
Make sure all user interaction is disabled on your views (might only need it disabled on the "container" view).
This gives you a container view that covers the entire screen, and it has 2 children: a transparent background of the same size, and your current "waiting" alert thing.
Now if you add the "container" view to your view controller's view, the user can only touch on the container view which does nothing.
(Keep in mind that this doesn't handle screen rotation...you will have to do that yourself if needed.)

Position of rightView UITextField

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

Resources