I have a UIImageView contained within a UIScrollView. The image is (usually) big, so the user can zoom it out in order to see the whole thing.
Upon zooming out, though, UIScrollView snaps the ImageView to the top-left of the scrollview. I want this to be positionable by the user, and haven't found a way to "turn it off" yet.
It's kinda like always allowing scrolling, rather then only allowing scrolling when the image is zoomed in. Maybe it's too major of a change?
Anyone know of a way? Originally, I was just going to create this functionality manually. But UIImageViews don't like to adjust to new sizes (I've tried about everything and can't get UIImageView to resize UNLESS I remove the picture from the imageView, change the frame, and re-add it).
I ended up disabling the UIScrollView's panGestureRecognizer and subbing in a custom one.
Here's a quick snippet on how to disable it:
// Disable our GestureRecognizer
for (UIGestureRecognizer *gesture in scrollView.gestureRecognizers){
if ([[NSString stringWithFormat:#"%#",[gesture class]] isEqualToString:#"UIScrollViewPanGestureRecognizer"]){
[gesture setEnabled:NO];
break;
}
}
A bit of a hack-job there, but it's due to the fact that UIScrollViews have changed the class of the GestureRecognizer to "UIScrollViewPanGestureRecognizer." The compiler will yell at you if you try to use that class (there's probably a better solution out there).
If you locate the UIImageView at location 0,0 in the UIScrollView, then that's always going to be the upper-left. If you want it to be centered in the scrollview when it's smaller than the view, you need to position it there. Check whether its -size is bigger or smaller than the scrollview's. If it's smaller than the scrollview, set its -center to be the same as the scrollview's.
Related
I have falling UIImageViews falling on the screen and going back to the top in my game. I have another two image views on the bottom of the screen that their images change every so often. When those two bottom images change, the falling UIImageViews jump around the screen to their original position of when the game app opens, then they fall again. The same thing happens when the score label changes.
I have constraints on almost everything so im thinking that might have something to do with it but I don't know why.
Thank you very much for your help
OK so I'm sure you're aware of layout constraints and the NSLayoutConstraint class. (If not read this). Basically Apple uses these classes which are represented in the IB to position and resize subviews e.t.c.
Because of this you need to adjust the layout constraints of any view you want to move. To animate a UIView it used to be a case of changing the frame property and then getting the superview to redraw it's subviews; however, now you need to change the constant property of a view's layout constraints and then call layoutIfNeeded on the superview like so:
myImageViewConstraint.constant += 100;
[UIView animateWithDuration:1 animations:^{
[superview layoutIfNeeded];
}];
Then because you have changed the constraint, the view won't jump around.
Note: you should research this before jumping on Stack Overflow because this is readily available in the Apple Developer Resources.
I am developing a iOS-6 app. I have a UIViewController with a view that needs fixed orientation (portrait mode). But when the phone is rotated, one control on that view needs to be moved and rotated (so that it will always be in the upper left corner, and its text will be readable).
I am achieving this by shifting the control(a UIView) using the frame-property of my control (it is a custom view, more on that later), and then using CGAffineTRansformMakeRotate() afterwards, since I know that it's not advisable to use the frame after rotating a view. Everything is fine so far, but here's the thing: That custom view has three UIButtons of type UIButtonTypeCustom as its subviews. Because I rotated the View, but cannot rotate the buttons inside the view (they are not squares), I need to rotate the titleLabels of the Buttons for the text to be readable in the new deviceOrientation.
But it won't work very well. The text will be rotated, as I intended, but it will be clipped by the titleLabel, because the titleLabel has the wrong frame. I checked this by applying borders to the label. So I need to change the titleLabels frame, right? But how can I do that? I tried setting it using [titleLabel setFrame: frameThatFits];, but to no avail. (frameThatFits is a CGRect I created). Also, calling [button.titleLabel sizeToFit]; has no effect that I could see.
I am using [button setTitle:title forControlState: UIControlStateNormal];to set the title.
TL;DR: I'm trying to change the frame/bounds of a UIButtons titleLabel after rotating it using an affine transformation. Any help?
Thanks.
PS: I can supply code when needed, but I wouldn't know what to show you. Tell me what you need, I'll post it.
OK, first of all, thanks to everyone who tried to help. Im posting an alternative solution for my problem, and although it doesnt really address the problem of changing the titleLabels dimensions, it will result in the proper display of my ViewController.
It turns out using the frame is a bad idea. I initially used the frame to reposition the view and i figured that this couldnt be a problem because i only ever applied transformations afterwards, but i was wrong. Because OBVIOUSLY i tried to change the titleLabels frame. AFTER the rotation. And that didnt work.
So the way to go here is using the center-property and the bouds of the view consistently throughout the code. It will result in properly rotated Buttons, that do not need any fidgeting afterwards.
My takeaway here is that i will never ever again use the frame-property outside of a NSLog-statement. But why [button sizeToFit];wouldnt yield any results is still beyond me. If i ever figure it out, i might post it if i remember.
EDIT:
#ZevEisenberg nailed it with this comment:
“Warning: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.” So you are right to use the center and bounds here, but if you do not have a transform, the frame is perfectly safe to use.
NEXT EDIT:
Heres how i ended up repositioning the Buttons:
-(CGPoint)centerForView:(UIView *)view{
//calculate a suitableposition for the view
//depending on the current orientation and the device type (iphone 4S/5, etc)
return point;
}
Then, as a reaction to the deviceOrientation change notification, i apply CGAffineTransformIdentity to all the views, reposition them using my centerForView shown above, and apply the correct rotation transformation to the View. I do this for all the subviews every time the divice rotates, like so:
-(void)setRightRotationTransformations{
[self resetAllTransformations];
self.someSubview.transform = CGAffineTransformRotate(self.someSubview.transform, -M_PI_2);
}
In my case works such hack:
set Line Break mode to Word Wrap
Add extra line to title (even for one line title)
I have an image inside a UIScrollView. What I want to happen is if I zoomed in to a particular position, I want to disable the scrolling (both vertical and horizontal) so that it will remain on the zoomed area. Can you give me any ideas on how to do this?
Two things to keep in mind:
Make sure you are exactly where you want when you need to disable the scroll. (you can use some methods from the UIScrollViewDelegate to accomplish that).
Make the contentSize of your UIScrollView the same size of your frame. This way both the horizontal and the vertical scroll will be disable.
CGRect myScrollViewRect = myScrollView.frame;
CGSize myScrollViewFrameSize = CGSizeMake(myScrollViewRect.frame.size.width, myScrollViewRect.frame.size.height);
myScrollView.contentSize = myScrollViewFrameSize;
For clarity I putted more code than you would normally need to.
I need to create a scrollable composite view on iOS. That is to say, the view will contain at least one image, possibly a button, and some text (that we may wish to format with bold fonts, etc). The amount of data, and particularly the amount of text, is variable, from maybe 4 lines to maybe 100. The data is "variable" to a degree, and in particular the image and text do not come joined at the hip.
This all needs to fit in a "pane" of about 280h x 115w pixels in a portrait-only layout.
A single UITextView doesn't provide the facilities to display an image or format the text.
A UIWebView provides the ability to display the image and formatted text, but the button is a problem (not even sure if it's doable).
A UIScrollView would easily allow the image and button, and then a UIWebView could be embedded in the scroll view for the text, but then scrolling becomes a problem -- I'd like the entire view to scroll as one, without having to resize the web view to contain it's content, and without the confusion of a scrollable within a scrollable (the doc warns of "unexpected behavior").
(I'm guessing your thoughts at this point are that I want too much.)
So, any suggestions? What's the best way to get close to what I need here?
In iOS5 the UIWebView has a scrollView property, which is a normal UIScrollView. You should be able to add a UIButton as a subview of the scrollView to achieve what you want, although positioning it correctly may be a challenge. Prior to iOS5 you could cycle through the subviews of the UIWebView to find the UIScrollView with isKindOfClass...
I suggest testing with a UIWebView inside your UIScrollView. I don't see any interference in the iOS 5.0 simulator. I don't know if there are problems in iOS 4.0.
If you find that there is interference, you can prevent it by setting the web view's userInteractionEnabled property to NO, either in the nib or in code. This will prevent the web view from receiving any touches, so the user also won't be able to pinch-zoom it, follow links in it, or copy text from it.
In the web view's delegate, implement webViewDidFinishLoad: to set the web view's size and the scroll view's contentSize. For example:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGRect frame = self.webView.frame;
frame.size = [self.webView sizeThatFits:CGSizeMake(frame.size.width, HUGE_VALF)];
self.webView.frame = frame;
self.scrollView.contentSize = CGSizeMake(CGRectGetMaxX(frame), CGRectGetMaxY(frame));
}
When I did a similar thing, I had a dozen of views which I added to the UIScrollView and then calculated the frames of all the views. Granted, it was an extremely tedious work, given that some views could get hidden under various conditions. The layout code was actually pretty simple, laying out views from top to bottom, but ugly. The upshot is that it works like a charm, fast and reliably. You can even trivially wrap it in an animation block.
I have a NSScrollView with a custom view inside and when I resize the NSScrollView, the height grows and it scrolls upward. Unless there is an easier way, I'll probably have to register a notification to see if the view changes size and then adjust the scrollPoint: to a new point. I'm having trouble getting method to work smoothly.
Thanks!
This question comes up from time to time, because it's not obvious.
The content will pin to the top left if [contentView isFlipped] == YES.