I have a scenario where I overlapped a view(pageViewController inside the view) with a uitableview with an offset of 130, and that uitableview is Transparent, only cells will be scrolled and visible.
My requirement is within this offset place of 130, I want to pass touch events to the view(pageViewController) which is below the uitableview and that view is not a superview(It is a sibling view) of table view but I overlapped it with tableview.
So is it possible to pass touch (Horizontal Swiping Event) to the view which is below the uitableview in the transparent area (Offset Area of 130); if yes, what I have to do for this?
There are lots of options for controlling how touch events and scrolling interact in iOS. You can override hitTest, you can use delegate messages sent to gesture recognizers to say which combinations of recognizers should fire when, etc. Without seeing your problem in detail it's hard to say which is best... and even then, you might say it's partly a matter of style. (At first blush, though, I'd guess that overriding hitTest to return different views at different times might be it.)
I'd recommend watching the WWDC 2014 video on Advanced Scrollviews and Touch Handling Techniques. That talk works through solving some problem that sound almost exactly like yours, so you'll almost certainly find a good solution in there. And lots of other tips that might be helpful elsewhere in your app. (Actually, if you have the time, I'd recommend watching the UIScrollView-themed sessions from the past several years' WWDCs... the so-called "Josh & Eliza Show" has always been full of cool demos and useful insights.)
Related
I have a UITableView on didSelectrowAtIndex it pushes to a viewController which shows the detail on UIScrollView which is vertically scrollable.
Now I need that If I tap on any row it would be pushed to the same viewController and shows the detail of selected row,Additionally I need to have the Swipe Functionality to see the data for all rows in tableview instead of go back & select another row.
I know it can be achieved by UIPageControl or [scrollView setPagingEnabled:YES];,But I am wondering If there is any better approach to do the same or I should go with any of these two,If yes then Which one is better?
Please Help Guys.....Any Help would be much appreciated.
Thanks in Advance....:)
Of course, there are plenty of approaches to achieve what you want. You should keep in mind that UIPageControl has limitation on number of items (dots) displayed (over 20 items would overlap). Also, it would be appropriate to have next/previous buttons for the users preferring tapping buttons instead of swiping/panning. I prefer using UISwipeGestureRecognizers and buttons on toolbar for navigating between items.
The key, in my opinion, is to control how many UIKit controls are held in memory at the same time. However you implement this, you want to make sure that you have solution that holds UIKit controls for the currently visible child element only, or perhaps the previous and next ones, too, but not for the full array (especially if you're dealing with UIImageView objects).
One control to consider is UIPageViewController. At first blush, it might look complicated, but in reality it's quite simple and offers a nice way to swipe between various "pages" while not holding all of the pages in memory at the same time. See View Controller Catalog for iOS: Page View Controller.
If you decide to implement a scroll view with paging enabled, I'd suggest specifying the delegate and implementing the UIScrollViewDelegate methods to add and remove subviews as appropriate. This is historically what I've done, but I now lean towards page view controllers.
There are also a ton of third-party implementation of "infinite scrollers", which implement this sort of functionality, though I can't vouch for any particular one.
I'm building a native iOS app that will allow end users to build forms by dragging and dropping from a toolbox of custom controls. A typical scenario would be a power-user dragging some UILabels and UITextField representations around on a UIView. Groups of controls would be supported, allowing several controls to be visually contained within a section. The whole thing will probably be contained in a UIScrollView allowing horizontal scrolling between 'pages'.
'Normal' users will then use the form for data entry.
So, I have two related requirements: to allow different types of UIView/UITableView/UIImageView/UILabelView/UITextField etc to be laid-out and grouped (and probably contained within an outer UIScrollView), and to allow the layout to be adjusted/dragged/dropped by power-users.
My question is rather broad, but is essentially this: what is the most appropriate nested UIView hierarchy to support these two related requirements? Is a basic structure of UITableViews contained within an outer UIScrollView fundamentally sound if I want to drag-drop within nested views within the UITableView? Should I avoid UITableView because it will complicate dragging?
I appreciate this question is borderline subjective in scope, but I'd really appreciate some guidance from people who have tacked this sort of thing before and who have some words of wisdom for me.
Many thanks.
Sounds like an interesting app! I would say that using a UITableView would make the app horribly complicated. A UIScrollView would be a good base to drag and drop controls onto. Perhaps with an "add page" button, the user could tap this it required, and you could extend the contentSize of the UIScrollView to be the width of +1 pages, and then scroll it so the user can drag more controls onto that page.
To drag the controls around, you could use a UIPanGestureRecognizer attached to each control, and when triggered it changes the centre position of the control. You might need to turn off user interaction of some of these controls - e.g. for a UITextField the power user will want to drag it around but not want to enter a value into it.
For grouping controls, you could do something like this:
a "group mode", whereby the user taps a button to enter this mode, then taps a number of controls (would need some visual indication on them to show they are selected) and then taps done.
the selected controls are then be removed from the UIScrollView
a new UIView is created and positioned at the centre point of the selected controls, and is big enough for the controls to fit in at the same distances apart. It is added as a subview of the scroll view
the controls are all added as subviews of this view
the gesture recognizer is added to this view, instead of the individual controls. Then when dragging around, this group of controls will all move as a group with fixed layout.
If you have groups of controls that you think might be commonly used, you could even create them in advance, each in their own nib, and then allow the user to drag them onto the scroll view as a pre-made group.
What you might find, especially if some of your controls are quite large (e.g. I'd expect an image view to be significantly bigger than a label or text field), the pan gesture recognizer gets a bit limiting because when trying to drag views around you'll inadvertently pick the wrong one if they are positioned close together or overlapping. In which case, you might need the extra precision of handling all the touch events yourself - so when a touch starts, you test against all the controls (or groups) to see which has the closest centre to your tap position, and then as you get the touch moved events you can update this centre position.
I've not made anything quite as complex as what you're describing, but I did make an app where the user could drag small images onto a large image to apply as "decorations". They could drag on any number of these decorations, and also scale them with a pinch gesture. In this case, I had a UIImageView as a background which held the main image. Then the decorations were on the edge of the image, and a pan gesture recognizer was used to detect them being dragged onto the image. On drag, I'd actually create a new instance of the decoration (UIImageView) so that there was always another one left in the toolbox. A pinch gesture recognizer was used for the user to scale the decorations. For the user to move around a decoration they had already placed, I had to use manual touch handling to detect the right decoration (since they could easily be overlapping, and ones that looked round to the user are actually square in terms of UIViews, so it was easy for the user to accidentally drag the corner of one when they intended to drag a different one). Mixing an matching gesture recognizers and manual touch handling seemed to work out just fine, which was good because it's much easier to use the gesture recognizers for the more complex behaviour like pinching.
Back to your app, once your power user has set up everything, then when the normal user loads the app, you can just turn off any touch handling code (and remove or don't create the gesture recognizers) and they will get static forms as laid out by the power user. Then make sure user interaction is enabled on all of the controls (e.g. UITextField) and they will be able to enter data into them.
Doing all of the above with controls onto a scroll view will be complex enough I think, and you may end up having to deal with lots of niggly behaviour in trying to get it working nicely for both normal and power users. I think this would be 100x harder if you were also dealing with UITableViews and UITableCells at the same time.
Please let me know if you'd like me to elaborate on any aspect of the app I outlined above, as it does seem to have a fair chunk of functionality in common with your app. Hope to see/hear more about your app in the future!
EDIT
One more thing occurred to me - if you are keen to use a UITableView in your solution, then I would suggest that your power user lays out one UITableViewCell at a time. In fact, they would be dragging UILabels and other controls onto just a basic UIView, which when they've finished you then use to record the positions of the controls. You then use these positions when presenting those controls in a cell - in cellForRowAtIndexPath you would create and init all of the chosen controls, and position all of them in a newly created cell at the positions and layout the power user had chosen. The power user could also have a control to change the height of the cell they are laying out, for more flexibility. They would create a series of cell layouts one after the other (I guess each of these would be a "group" of controls), and then those cells would be presented in order in the table view. You could then give the power user some final tweaking control by letting them put the table into edit mode so they can reorder the cells (or even remove some).
Depending on the application, perhaps the user could also have these cell layouts they've previously created always available, so after they've built up a few common control groups, they can just keep reusing them to very rapidly build up a form. And then occasionally they would create a new cell layout when none of the ones they have created so far are suitable, and again it would be saved as a template for them to use again in future forms.
I would just make an EditView class that is just a UIView with some transparent background color. When you want to drag controls around, then set some type of edit mode where you overlay a bunch of EditViews on all the appropriate controls. The EditView would then support whatever gestures / touch handling you want to resize or move it. Dragging a view onto another view and releasing might prompt something like "Nest view A in view B?" which then you can make the related addSubview calls.
Nesting tableviews inside scrollviews won't be an issue, though I'm not sure what kind of behavior would be expected if you were trying to nest anything inside a tableview...that would have to be specified using standard UITableView methods.
For saving layouts and such, you might need to create your own pseudo-view hierarchy that contains various pieces of meta-data needed to recreate the final layout which you would then be able to store somewhere.
Ok. I HAVE seen a LOT of topics which are similar to what I'm trying to do here, but nothing that quite matches. Maybe my approach is way off base. Here's the deal.
I'm drawing a chart to my UIView subclass in drawRect:. I then use a UIPanGestureRecognizer to translate the chart's offset (internal, not in the view hierarchy) to the right/left. This works great, but my problem is that the recognizer's action gets fired with relatively low frequency. Specifically, the resultant panning is MUCH choppier than, say, in a scrollview or tableview. Particularly when the number of points in my chart goes up. Now, what I'd LIKE to do is not actually trigger drawing from the pan gesture's action, but have a timer firing at something like 30 times per second, interpolating the offset from the moment the pan fired to the current moment. However, this is getting more and more complicated.
Anybody have suggestions? Should I really just be doing this with a UIScrollView? The reason I'd prefer not to is that the data may extend quite far in either direction, and I'd like to not have to draw (or at least store) the whole path at once, but just do the section which is currently displayed. Should I be using CAShapeLayer? I'd like some input before I spend another day playing around with these possibilities...
Any input / experiences would by most welcome.
So, in the end, I DID end up putting these things in a UIScrollView. I had to do quite a bit of work to get this up and running, the complicated part being the creation of a series of PANES which would be added to the scrollview. Each pane asks a delegate for the data it needs to draw, and then they're all stitched together. Fortunately, everything worked great once I put these scroll views containing chart panes into a table view. Still haven't tackled scaling, but I've seen a few posts on here which should make it relatively trivial.
So that's the answer to my original question. DON'T try to pan and draw on each frame, it WILL be choppy, and baring some real hack, there's no good way I could find to smooth it out. Scroll view handles all these problems for you, as long as you can split your view up nicely. I guess I could have used one long view, but then when the data set gets large I'm in trouble.
Now I've got a related problem though -- when offscreen charts scroll into view (they're in UITableViewCells), there's a big hiccup as the new chart gets drawn. I think I will try drawing them into an image asynchronously, so that when the new row scrolls into view, I've already got the image.
My question is essentially what it says in the title--I would like to create a scrolling view similar to the one that appears under the 'Home' tab of the HBO GO iPad application.
I have looked into circular/infinite UIScrollViews, but they only discuss infinite content in one direction (either horizontal OR vertical) and bring up many problems when scroll speed gets too high. So my question is twofold:
A) Could they have created this scrolling view by subclassing UIScrollView? If so, please do let me know how?
B) If not, does anyone have ideas as to a starting point for how they could have created it? It runs very, very smoothly even at fast acceleration, and I'm trying to figure out how they created this.
Thanks in advance!
Reposting to get answer ;-)
The sample is named StreetScroller.
Referenced video is here.
I believe the successful technique will be to apply the techniques in the video in either a 2x2 or 3x3 grid and handle scrolling in both directions.
I have put together a library that provides an infinitely scrolling view in all directions. It allows you to very easily achieve the effect you’re looking for and much more. As the user scrolls around, the framework lays out the tiles and lets the delegate know so it can set up the tiles' presentations. This is indeed done by subclassing UIScrollView and as for performance, the framework introduces no lag: full 60 fps no matter how fast you scroll.
The framework with a sample app that displays Flickr images in an infinitely scrolling wall is here: https://github.com/vovagalchenko/scroll-for-days. Additionally, here's a video of the sample app in action: https://cloud.box.com/s/d6bgvlot175au5a3jeh5
I don't think there is an easy way to do it by sub classing UIScrollView
I have done something similar with a UIView and a custom gesture recognizer, moving views around nice they disappear off the side of the screen.
I hope this helps you.
I'm looking to build a document "selector" screen, similar to Pages and Numbers on the iPad/iPhone:
I come from a WPF background and have some iOS experience. That being said, I'm looking for a good approach to building something like the tile-based interface Apple uses for opening documents in Pages.
I'm not concerned with the Folder animation.
What is the best way to approach building just the tile interface? I'd imagine I'd build some sort of view that sits within a UIScrollView - but it's the nature of that subview that I'm a little confused about. Does iOS have any wrap-panel or grid-like controls I could load a set of tiles (i.e., documents) into?
What do you guys think?
I don't know of any third-party classes to handle this for you, but there might be some out there.
The basic structure will be a UIScrollView containing a set of views, each representing one cell on the grid. You set the scroll view's contentSize based on the total number of tiles. Then you create tile views on demand, and place them inside the scroll view.
The scroll view's delegate object will be responsible for monitoring the scroll position, putting down tile views as they become visible, and (optionally) removing tile views that move out of view. This is basically how UITableView works: there are only about six or so instances of UITableViewCell at any given time, they are recycled as you scroll up and down the view. (Imagine a train where somebody at the back end is pulling out the rails and passing them forward to somebody in the front, putting them down in front of the train. As far as the train knows, the rails go on for miles.)
If you wind up having to place all the views yourself, take some time to learn the CGRect family of methods, including CGRectDivide. They will be useful in laying out the views and also in computing what's visible and what's not.
There are a few third party classes/libraries you can get to produce this functionality, AQGridView comes to mind. But there are no default easy classes for this.
If I was to develop this type of implementation, I would subclass UITableViewController. Expand it to have columns. Then subclass a UITableViewCell to display the image. That way all the container code and everything would already be there, and all you have to do is customize it to f it your needs.