I have a UIView in my ViewController that users can move around the screen, rotate and zoom in and out. All with UIGestureRecognizers.
The problem I have is that the UIView contains a UILabel and after zooming the label is very blurry.
Here is the code for the zoom:
#IBAction func handlePinch(recognizer : UIPinchGestureRecognizer) {
recognizer.view!.transform = CGAffineTransformScale(recognizer.view!.transform, recognizer.scale, recognizer.scale)
recognizer.scale = 1
}
Also, when the user leaves the screen I am saving the new location and transformation of the UIView like this:
func saveViewValues() {
var userDefaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(NSStringFromCGPoint(self.theView.center), forKey:kViewCenter)
userDefaults.setObject(NSStringFromCGAffineTransform(self.theView.transform), forKey:kViewTransform)
userDefaults.synchronize()
}
This way when I reload the page I can use these values to reset the UIView to how the user last had it.
All works fine however the UILabel is very blurry if the user zooms in on the view.
Is there a way I can make the text crisp, even when zoomed? And how do I save this value like the others so that it can be put back afterwards and be crisp straight away?
Hope this makes sense.
Related
I'm developing an app showing a 3D human body - in the SceneKit editor, I've set up the camera pointing to the model.
As I did set sceneView.allowsCameraControl = true, the user can move around the object, zoom in and zoom out with simple gestures.
In order to move vertically, I've implemented an UISlider - I don't want the user to pan vertically with two finger gestures.
In the slider action, I do the following:
#IBAction func sliderDidMove(_ sender: UISlider) {
cameraNode = sceneView.scene?.rootNode.childNode(withName: "camera", recursively: true)
let vert = 1.5*(0.5 - sender.value)
cameraNode?.position.y = posY + vert
}
This works fine when I change the slider position just after loading my ViewController. But as soon as I rotate or zoom the model by gestures, the slider no longer shows effect - thus I can no longer change the position of my camera node programmatically.
Has anyone an idea how I can fix this?
I have a horizontal scrollview with an image which I need to rotate as the user scrolls left or right. It needs to rotate as the user moves the scroll across the screen. So if the user scrolls half way and stops the image should rotate halfway etc. I have looked at few examples but nothing seems to be giving me the correct result. Can some one please help.
Thanks in advance
Vertical scrolling and Swift 5:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let topOffset = scrollView.contentOffset.y
let angle = -topOffset * 2 * CGFloat(Double.pi / 180)
self.myImageView.transform = CGAffineTransform(rotationAngle: angle)
}
Don't forget to do this in viewDidLoad:
self.scrollView.delegate = self
You'll need to implement the scrollViewDidScroll method and then apply a rotation matrix to the image. To rotate a UIIMage you can do what they outline here. How to Rotate a UIImage 90 degrees?
However, this would be better accomplished in a pan gesture recognizer. The pan gesture will give you information about how far the user panned, and then you can rotate the image based on that distance.
To rotate image is not good for performance. You'd better set image view's rotate transform as user scrolls. Like this:
imageView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
This is what I currently have:
func handlePinching(recognizer : UIPinchGestureRecognizer) {
self.layer.transform = CATransform3DMakeAffineTransform(CGAffineTransformScale(self.transform, recognizer.scale, recognizer.scale));
recognizer.scale = 1.0;
}
Using self.view.transform for that also makes it bigger. I want to make it zoom "internally" (I really don't know how to explain it).
So I'm not 100% sure to understand the question but I guess I get it.
For example you want to zoom on an image without zooming the other element of the UI (NavBar, Buttons, ...) right?
So I guess in you're example you're in a viewController, which means, when you change the scale of self.view you'll zoom everything. You have to apply the scale on the specific view that you want to zoom in.
In the example below, to zoom on the image, the image is inside of an UIImageView, and this imageView is subView of self.view. And you will just apply a transform on this imageView.
Moreover I think you get a little bit confused on how to zoom, considering the view you want to zoom is imageView you just need to do
imageView.transform = CGAffineTransformMakeScale(recognizer.scale,recognizer.scale)
I hope this answer your question, let me know if something is not clear.
All,
I have studied Gesture Recognisers and I have placed one in Interface builder and I am going to wire it all up. I have also enabled 'User Interaction Enabled' in IB on the UIImage.
How can I make the UIImage larger according to how far the finger is swiped down on the screen.
How can I make the UIImage larger in the UIView that it sites in ?
This code works for me, I'm using UIPinchGestureRecognizer, which is use as a default if you want to scale the view:
#IBAction func handlePinch(recognizer : UIPinchGestureRecognizer) {
recognizer.view!.transform = CGAffineTransformScale(recognizer.view!.transform, recognizer.scale, recognizer.scale)
// Reset recognizer scale
recognizer.scale = 1
}
If you want to use swipe gesture, you need to calculate swipe difference between start point and current swipe point and convert it to scale value you required.
I need to implement a slider control like the below image
Slider will have uneven length steps.
Whenever user slides the slider slider will only stop at one of the step which is near to the current range.
But the real challenge is UISlider with dots at custom points (range) which will be provided initially.
Can anyone help me in achieving this functionality.
I think you are best to step away from trying to mangle UISlider into this configuration
If this was my problem I would build a custom view structured like this
DKCustomSliderView
-> UIImageView (subview for slider head)
which implements an interface like this.
#interface DKCustomSliderView : UIView
-(void)setStopPoints:(NSArray *)stopPoints; //array of NSNumbers between 0-1 which define indents
-(void)setSliderHeadImage:(UIImage *)sliderHeadImage; //image to use as slider head
-(void)setIndentImage:(UIImage *)indentImage; //image to use as indent marker
-(void)setTrackImage:(UIImage *)trackImage; //stretchy image to use on track
#end
I would track a pan gesture on the slider image view.
-(void)handlePanGesture:(UIPanGestureRecogniser *)pgr {
if(pgr.state == UIGestureRecogniserStateChanged) {
//am i near an indent? , if so lock me here and be slightly sticky.
}
}
and the draw rect for DKCustomSliderView would look a little like this.
-(void)drawRect:(CGRect)dirtyRect {
CGRect bounds = self.bounds;
// 1. draw track across width
for(NSNumber *marker in self.stopPoints) {
//draw a instance of self.indentImage at ([marker floatValue]/bounds.size.width)
}
}