Is there a way to stop an object in a UIScrollView from moving as a result of the UIScrollView responding from user interaction? Essentially I want some things in the scrollview to move but others to remain frozen in place. They all need to be within the scrollview, so moving them to a different view is not an option.
For anyone else having the same problem, I found an answer. I put the objects which I wanted to remain still in a UIView. I then used the UIScrollView delegates to get the initial content offset when the scroll was about to begin and subtracted the current content offset as the scroll view was scrolling to get the change in the content offset. Afterwards, I sent that content offset to the container view I put all my objects in and subtracted the change in content offset from the container view's position. The result is everything in the container view remaining perfectly still.
add to the desired fixed object a constraint in relation to the main view. This would pin it to that view.
Related
I want to set center the content inside a UICollectionView according to ring image in the center of the whole screen. Please check the image below. Any Suggestions?
The function you need is this one... https://developer.apple.com/documentation/uikit/uicollectionviewdelegate/1618007-collectionview
This function is called by the collection view when the user finishes scrolling. It provides the content offset of where the collection view will stop scrolling. (The proposed content offset).
You then need to take that offset and work out the nearest offset to place your cell in the middle of the screen.
Something like, find the item that will be closest to the middle. Work out how far away from the middle it is so you know how much to shift it by. Then apply that shift to the proposed content offset.
This will allow your collection view to decelerate naturally but always stop at the point that you want it to stop.
In my iOS app, my parent view has a child view which, in turn, has a number of UIButtons as children. Without constraints, touches on the buttons are recognized by the topmost view controller. However, when I add a constraint to center the child view (the one containing the UIButtons) horizontally within the parent, the parent stops recognizing the touches.
First of all, is this the correct/preferred way to do this (centering a group of views - e.g. buttons - by putting them in a View)? Should I be using a Container View, or stacked Stack Views, instead? (I tried a Container View, but (a) it generated its own controller, and (b) for some reason, I couldn't move the buttons into the container.)
Second, how do I get the view to recognize the touches while maintaining the constraint?
Apparently, the problem was, I needed to set a fixed width and height as well in order to get the layout set up correctly. Once I did that, it worked correctly.
EDIT: The crux of this problem is that scroll indicators do not show during programmatic scrolling, but I would like them to. My original question (provided below) assumed this had something to do with userInteractionEnabled, but it does not. The mention of a master and slave UIScrollView is also possibly distracting from my core problem (the need to show scroll indicators during a programmatic scroll). Apologies to those of you who answered or commented based on my misleading assumptions/info.
Possible Solution: The only way I found to do this was to use the fact that scroll indicators are instances of UIImageView and use a category on it to hack the alpha. This article shows the approach. It was then a case of using tags and scroll view delegate methods to turn the alpha permanently on prior to a programmatic scroll, and permanently off when the scroll is finished. This feels hacky though, so any further suggestions would be welcome!
Everything below this line is the original unedited question to provide context to users' answers and comments
Setting userInteractionEnabled in a UIScrollView object to NO appears to disable the scroll indicators upon programmatic scrolling. This happens even if you have self.showsVerticalScrollIndicator = self.showsHorizontalScrollIndicator = YES;
Is there any way to programmatically scroll the scroll view but still show the indicators?
(To provide some context: I have a slave scrollview that mimics a master scrollview by hooking up the scrollview delegate callbacks and passing the content offset to the slave scrollview. However, I don't want the user to be able to directly manipulate the slave scrollview, but I do want scroll indicators).
Instead of setting userInteractionEnabled to false try setting the UIScrollView's scrollEnabled property to false. The doc. says "When scrolling is disabled, the scroll view does not accept touch events" that should mean that you should still be able to programmatically scroll the UIScrollView. Hope this helps - Did not test it out let me know.
You could try putting a transparent UIView (alpha == 0.0) over your scroll view (but as a sibling in the view hierarchy, not as a subview). Set touchesEnabled to YES on the transparent view, and it will intercept touches heading for the scroll view.
I've got a scrollview that allows the user to scroll between different pages and then tap on one to have it expand so that they can read the page in full, a little like how one changes tabs in Safari on the iPhone. Changing the frame size of each sub view is a bit of a pain when rotating as the scroll position is getting lost as the content size of the sub view has to change too. I was wondering if there was a more effective way of
resizing the views for entering 'viewing' mode or rotating the device.
The solution to your first problem is when you want to expand the view, pull it out of the scrollView then add it to self.view.subviews with an appropriate frame, then animate the frame to fill the screen. When done with it do the reverse, shrink it, then when its back to the appropriate size stick it back in the scrollView.
If for some reason this does not work - the scrollview is showing other stuff that gets moved when you remove the view, then instead of just removing your view from it, create a simple UIView of the same size as the view you will expand, and essentially replace the view you pull out with the "placeholder" view.
I realize I can rotate the cells and move the indicator by displaying the scroll view "upside down" but that requires a lot of other rotations, and manipulating of information to make the Table scroll properly.
Thanks for the time
Actually, it is possible by changing the scrollIndicatorInsets property to restrict the indicator to a small area on the left side:
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,0,tableView.bounds.size.width-10);
I like Jeremy Jay's solution (though I haven't tested it), but just to thoroughly explore the idea... here's another that might be worth trying (though it's also untested):
Use two scroll views.
One scroll view (we'll call this the "real" one) contains your content but has its indicators hidden. Another scroll view contains no content but has its contentSize set to match that of the "real" scroll view's. When the "real" scroll view's contentOffset changes (as observed via delegate messages), change the "fake" scroll view's offset to match. (Check out the scroll views session from WWDC 2012 for more on the idea of using a scroll view without a content view.)
In theory (again, I haven't tested this), you now have a scroll indicator view that's separate from your original scroll view, and you can place it wherever you like in relation to the original. Layer it on top of the original and move/size it so it occupies a narrow sliver on the left, and you have a left-side scroll indicator. (Alternately, layer it atop the original and flip it horizontally with an affine transform.) Put it somewhere else entirely to take your UI on a trip to crazy town. (Or don't.) Make sure you make it ignore touches if it's layered on top, though.
A quick way to achieve this (if you're not using row actions) without having to calculate insets or messing with additional table views, would be to transform the table view across the Y-axis (flip) and then transform the cells back when you get them.
tableView.transform = CGAffineTransformMakeScale(1, -1);
and then
cell.transform = CGAffineTransformMakeScale(1, -1);