how to draw multi-day event rectangles across multiple days on a month-view calendar on IOS? - ios

What approach is recommended to draw multi-day event rectangles across multiple days on a month-view calendar on IOS? Keeping in mind the goal to be able to drag/drop the event bars around on the calendar
Two options that come to mind, however I'm not sure which would be best (or if there is another) is:
Use UICollectionView (with UICollectionViewFlowLayout) - but then there wouldn't be one object per multi-day event would there? i.e. Every multiple day event would need to effectively draw a portion of itself separately in each day cell, and ensure the drawing lines up to appear as single bar
Draw the calendar yourself, so you can put multi-day rectangle bars for ease in drag-droppping, but then you wouldn't get the rendering support from the UICollectionView associated with continuing to scroll through the calendar and it creating/removing cells as required?
Any suggestions/direciton welcome.

I would suggest the following:
create your own collectionviewcell representing a day (you might probably
already do this).
add an 'events' property to the cell holding
all events which start, end or include the day (you set this in collectionView:cellForItemAtIndexPath:).
you have to decide if you draw the rectangle by yourself (overriding drawRect) or if you
add a view (eg. imageView, ...). In any case: There are
4 scenarios:
The event starts in the cell but ends in another cell
The event starts in the cell and ends in the cell
The event starts in another cell and ends in this cell
The event starts before the cell and ends after the cell
For each of this scenarios, draw the corresponding graphics or add the corresponding view. If you use a plain colored rectangle / view, this ist very easy, if the rectangle has a border or round corners, you have to draw different rectangles for each scenario.
If you drag the event, just adjust the dates of the event and be sure it is removed / added from / to the corresponding cells and repaint the cells.
An alternative (probably easier) way to the 'events' property might be, that the cell can inquire the corresponding events from somthing like an event manager.

Related

Create event in hourly calendar in table view in Swift

I am trying to create a daily calendar, like the native Apple one, that allows you to add an event that takes up part of a row or multiple rows. What would be the best way to go about doing this? I already have a table view built that displays the times by creating a custom separator line in each cell.
Should I be trying to use CGRect and create multiple prototype cells for each 15 minute interval (events will only be as granular as 15 min most likely)? Or would you layer a CGRect on top of the table view in a certain position? Events will not overlap each other, which should hopefully take some complexity out, e.g., not having to deal with events/blocks that are half the width.
Ideally, a blank row or an event should both be selectable so that an event can be added or edited, respectively.
Add two separate prototype cells one for no event and one for added event. You will of course have the data source array with you (I assume), from which you can detect for event is present on selected row in did select row.
Or else add flag for the same to check if event is added on particular cell index.
P.S. You can use UITableViewAutomaticDimension property for managing height for cells.

how to create multiple button in ios?

I have create one custom cell and I want to create multiple button in that cell in ios. I have created multiple buttons in cell but I have problem on selection.I want to select first button by default.Check image for better understanding
Image
I would make this a collectionView that allows single selection. This is because you are representing sizes/dimensions and they come in notoriously different and arbitrary scales (0-14, XS-XL, 28-44, etc). If you make a it a collection view it very easy to handle arbitrary size scales by modifying the collection view datasource methods. If you make this a fixed set of buttons and someone comes along and changes the size scale, you have a problem.

Design for annotating UICollectionView selections with additional controls

Using UICollectionView and excellent help given on here on StackOverflow, I've been able to build a "Gantt Chart" style control for my iPhone:
Cosmetics aside (I'm doing the functional right now, I've got a graphics designer on tap to look at colors and all that).
Background aside, the spans were relatively straightforward to do with a custom UICollectionViewLayout subclass. Each span is an item.
But I need to add some functionality, and am unsure how to proceed. Where I'm trying to go is illustrated roughly as:
Sketchy cosmetics aside, the point is that I want to "annotate" whatever the currently selected span is with additional information (I promise to find someone to help me look it pretty). And I want them to be active, I'm not sure if it brings up an editing control or does drag, but I want to be able recognize gestures on either the numbers or the bold lines and do things with them, distinct from touching on the span which drives selection.
I can think of (at least) 3 ways to try and implement this:
Use supplementary views. Cause selection to invalidateLayout, detect the selected state in my prepareLayout, and generate additional layout attributes for the two anchors. Implement a subclass of UICollectionReusableView which does the drawing, and adds touchable subviews (or its own gesture recognizers). This feels... wrong. I get the idea that supplementary views are more for headers and footers, not for controls that come and go as the selection state changes. But maybe it's an appropriate extension of the facility?
Use the backgroundView (or selectedBackgroundView, not sure it matters) of my current SpanCell class (which is a subclass of UICollectionViewCell). As long as I disable clipsToBounds, I can draw the annotation around the bounds of the span. I'll have to give it some knowledge of the big picture to find the endpoints, but that's not too offensive. I would just show/hide this view in response to selection changes. This seems like the best way to do it.
Do it in the main backgroundView of the entire UICollectionView. As shown, I've already got a specialized backgroundView which shows the the current time grid, strip style. I could further extend this view to draw annotations and manage touchable sub controls in response to selection changes. This would give me most direct implementation, but it feels like I'll end up with a big monster "doing too many jobs" object for the background.
Question then, for those who have more experience, is which route would you go? Would it be one of the above 3? Or something different? And why?
While your question is very technical with UICollectionView implementation, which I am not very familiar with, this seems like a job for the container (in this case, the collection view). Imagine you need your annotation to consider, in addition to the selected item, other items? Like for example, avoiding collision between annotation lines and another item?
For me, option number 3 seems like the most correct one. If you fear a large class, you can extern it to an annotation controller class, which should be notified whenever the annotations should be updated.

how to drag or drop multi uitableveiwcells on ios?

I want do drag a lot of selected cells and recorder them in my app.But I don't know how to do it.It seems apple just let u to drag one that what I have done it.
idea?
If it is ok to require that the selected cells are contiguous, then you can cheat by replacing them with a single tall cell.
EDIT:
For noncontiguous, the lazy solution would be to let the user select any cells, then after they drag and drop one of them, just move all the other selected cells right below it.
You could experiment with UITableView and see if it will let you animate out the other selected cells (with deleteRowsAtIndexPaths:withRowAnimation:) as soon as dragging is detected (possibly with UITableViewDelegate's tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:). You could also see if it will let you redraw/resize the cell when it begins dragging - then you could make it look like a z-layered stack or totem pole them into a tall cell while dragging.
Of course I'm assuming all the selected cells will share the same destination position. I can't wrap my head around noncontiguous sources to noncontiguous destinations in one drag-n-drop. If the user drags down 3 slots, does that mean you add 3 to the positions of all the selected cells? What if that takes a cell out of bounds? Even if you decided on some rules for odd cases like those and actually implemented this monstrosity, it could never be user friendly.
There is no easy way out. You need to handle the animation and movement by yourself.
Maybe you can take a copy of the cells you want to move and show an animation of moving to the destination.
When animation stops change the datasource.

iOS Nested View Hierarchy to support drag drop functionality to allow end-user to configure forms

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.

Resources