UIView position relative to another UIView - ios

I'm trying to create a custom accordion-list. On tap it should expand the tapped line and the next lines should change their position relative to the expanded one. By tapping it again it should contract. By tapping another non-expanded line, the expanded line should contract and the tapped one should expand.
I tried to solve this by using subviews with TapGestureRecognizers. I have a undefined number of lines. On tap I change the height of the tapped line and rearrange the position of the following lines manually. Now, it's getting really confusing to handle all possibilities of expanding/contraction/positioning. I'm looking for a more comfortable way to handle this.
Is there any way to align the subviews vertically so that the positions of the lines change automatically if one height changes?

I think a better solution is to use the tableView where the cells will contribute your custom view.Positioning and all will be handled by tableview itself.

If you are working with iOS 6, this should be pretty easy with constraints. Specify that each view is to be located a certain distance from the bottom of the one above it, and when the ones above it move or expand or contract, that constraint should force everything else to move to keep the gap you specified.
EDIT: I just realized that you mentioned in your OP that you may not know for sure how many views you are going to need ahead of time. That probably makes the table view method others have suggested more favorable. It is still possible to do with constraints though (and I found a pretty detailed tutorial here that goes over everything).

Related

Stack button fail

Swift 2.2 Xcode 7.3.1. iOS 9. Storyboard. I have 7 rows of four labels across. I was intending to select each row to place it in a stack. Saw this technique in Hagerty's iTunes U (Stanford). Each time I select a row and press the button to add the four across to a stack, it makes these huge rectangles... They have a width of 127,000,000. I keep trying different things, adding all suggested constraints, getting rid of all contstraints, etc.
Any idea what I am doing wrong? TIA
Sorry, I'm apparently not allowed to add images as yet here... The rectangles on the View Controller are all UILabels. When I select a row of them and press the Stack button, next to pin, etc., it appears to make one wide rectangle, all 4 on top of each other, this last time is was 27,216,026 pixels across. I think the comment about not using "suggested" constraints is probably a clue... there certainly seem to be more than necessary. There are also some where I tried to delete a constraint where the constraint item appears to be dimmed. There are one or two where the dimmed one, and an exact copy of the dimmed are both there...
There are no images on the view... the only button is up top, a "Back" button.
Someone gave me the clue. It turns out that there are some bugs in the constraints setup, especially when using "suggested" constraints. I deleted all the constraints, then added just the minimum needed, made sure they were all perfect, and I got one row to work properly. Now I can do the others.
After I do this enough times I am sure it will make sense, there is probably one constraint mechanism that doesn't work as it should - an Xcode bug. One adds size constraints both in the size inspector, and potentially the constraint mechanism, and sometimes they do not match. Those things have to be fuddled with until they do... and then Stacking works...

Best approach to showing or hiding dynamic content in iOS

I've been doing iOS for a while now, but when it comes to dynamically hiding / showing elements, I'm a bit lost.
Coming from Android, I'm used to being able to simply set views to visibility gone, but this doesn't exist on iOS.
So let's say I have the following scenario:
Basically I want to have a table, but the table should not fill the entire view controller. Instead it should leave place for optionally either a button, a multiline label, or possibly both at the bottom (if visible, these should be fixed, not scroll).
One way to solve this would be to use auto layout and modify constraints, like adding a zero height constraint. But that would make iOS kill one of the other constraints, which would make it hard to change it again. For the label, I wouldn't always want to have a height constraint, because it could be multiline, and should take the size it needs.
Maybe it's easier to skip autolayout here and modify frames instead, I don't know.
My question is: What approach would be best here?
Is there some other way of doing this I haven't thought of, or do I have to try to do what I described above?
I'm not primarily looking for code (code can be ok), but I'm more interested in a description of how it can be done.
I'd like to support iOS 7.
This problem had a variety of solutions, and opinion based, but I'm facing such questions a lot, when I don't know what to choose and what would be the "right thing".
So, I my opinion, the best solution here is using autolayout, you need to set height of label manually, but you have a few methods for this, at least you can play with it and if you don't succeed ask question about it. Using frames, you'll face same problem of calculating height, right? But with auto layout, you only need to set height, vertical space to 0, when you need to hide message.
You can also use constrains with priority lower 1000, and remove completely constraints from message (button, label) if you don't need it at all anymore.
For example, taking your layout image, you can make UIView with subviews: button, label. Top constraint connect to the UITableView, other constraints to the sides.Label and button will calculate the view's height. The only question here is label height.
So in ios assuming that the background of both these objects is opaque only the front most view in the Heirarchy will be visible and interactable, An easy solution would be to change the different frames of these two things you need and make sure they are in the back of your view heirachy, and when you need them to appear use view.bringSubviewToFront(mySubview) and view.pushSubviewToBack(mySubview) to make it disappear again. View obviously would be referring to main view of your view controller.

Laying out subviews in a UITableViewCell dynamically

This is the most complicated UI related problem I've come across yet. I've been trying to find a solution for literally weeks but no avail. Let em explain.
In this app I'm working on, I need to display a certain list. It's actually a schedule. Here's how it should look like,
The fields circled by red circles don't change. To explain what change means I have to show you this.
Its a set of filters which the user can show/hide certain fields and the ones that are circled in the first image are static ones. They can't be toggled on and off.
Now the problem arises with the ones that can be toggled. Here's what it looks like if you turn off the Show Actions flag.
A new label with a blue background replaces the bottom one you can see in the first image.
Here's another one where you disable Show Time option and the time labels are gone (yes it affects only for some. Its expected).
If this filter list were an option list, it would have been easy. Just create a custom cell for each option and you're good to go. But unfortunately the user is able to toggle multiple filters! For example the user can turn off both Show Actions and Show Time and it'd look like the last image but the bottom label would have the blue label in the third image.
To top it all off, the cells' height is dynamic. In iOS 8 creating self resizing cells are easy enough from the IB when you could just add auto layout constraints and done.
But it seems to me that creating these cells from the IB isn't an available option to me. Simply because there are way too many filter combinations a user can make. So the cell's subviews need to adjust to it.
My question is how can I create a dynamic cell like that? My best guess is through code, right? I haven't written my UI in code before so I tried creating a test project to familiarize myself with it. But the problems I'm facing is setting fixed frame sizes makes the dynamic nature obsolete. And how can I move a view to fill up a removed view's space (Last image. Time labels are gone so the name and the id labels move to the left to fill that space).
I know this question is a little too broad. I'm not asking for a straight answer either. I'd really appreciate some pointers, or even a better suggestion on how to approach this because I'm truly at the rock bottom on this issue.
Thank you.
It's hard to give you any precise help since your question is so broad. First, I would recommend watching the 3 videos on Auto Layout from the WWDC 2012 (sessions 202, 228, and 232).
To answer your one example, how to move a view to replace a view that's removed. You would need to make two left edge constraints from the view with the text (Kund Alof...). One with a constant of 0 to the time label with a priority of 1000 (that's the default), and another to the left edge of the cell, also with a constant of 0, but with a lower priority, say 900. As long as the time label is present, the constraint to it will determine the position of the text label, but when it's removed, the lower priority constraint to the left edge will take over and move the label over to the left edge.

UITableViewCell incorrect X positions

I've been searching through here and googling like crazy for a possible solution to this problem. Thus far I'm turning up exactly nothing that actually fixes it so I'm hoping someone can help.
I'm working on the UI for a iPad app. I'm doing it using interface builder. I worked with storyboards briefly but I don't like them all that much so I'm sticking with IB for now. Unfortunately I'm not very experienced with the workings of IOS Ui but it's been going relatively smoothly so far. In my app, I have a view controller, which holds a view containing a pair of sub views. One subview contains a rather windows like header bar (i like the look). The second contains a UITableView. The UITableView is set up properly as far as I can tell, and feeds it's info from a data source using custom UITableViewCells. The UITableView is set to grouped though currently there is only one section. The table is in edit mode by default because I want the user to be able to add new items and use the VC as a selection dialog. The view controller is presented (rather than pushed) using UIModalPresentationFormSheet (again, because I like the view) but I don't know that has any bearing on the problem. The cell border is flush with the X origin, the only reason the text isn't currently starting there is because I went into my cell and move the label over, leaving a gap between the edge of the cell and the label containing my text.
The Offending View http://bit.ly/144cbjT
The Problem: The UITableViewCells, for some reason are positioning themselves at X: 0. This puts them outside the border drawn on the UITablewView when you set it to grouped style. I could probably just turn off the border and get away with it, but I like the look so i want to keep it. I've tried messing around with constraints and anchor points on the cells, the content of the cells, the table itself, the view... I've tried simply moving my cell's labels over a bit. I've also had clipping subviews turned on and off. I've made sure the controls are being loaded properly from the XIB. I've made sure everything is added as a subview where needed. I've made sure I've tried everything I could think of short of setting the cell's X position in code. But since I'm not sure how to tell where the border is, I'd rather have the tableview or the cell do the work itself.
The question: How do I fix this? The selection accessory should be outside the grouping box. The text should be inside, not bleeding out onto the background like it is.I believe the content of the cell should be displayed inside the border within the yellow area.
The odd thing is, this is my fifth or sixth table in this app and I've been doing them all basically the same. Thus far this is the only one I've had trouble with.
Can anyone shed some light as to what's going on?
Thanks in advance
I think that to get this in code, you'd have to do something explicit, so the most likely candidate is a messed up IB file.
Since it doesn't cost anything, I'd just delete the tableView from the IB and then re-add it. If that doesn't work, try recreating the complete IB.
Hope that helps

uitableview custom transparent header

I am using section headers to show a small image 'floating' next to cells from appropriate sections. The section header is transparent and contains only a imageview.
The initial problem with this solution was that the section header takes up height, which looked strange (there was unnecessary empty space in the beginning of each section + the image should be aligned with the top of the first cell when tableview is scrolled to the beginning of the section). The fix for this was to set section header height to 1px. The image was still in place, but the header didn't use any height and everything looked great.
However now I need to add a UIButton on top of that image, and unfortunately it doesn't work when the header has 1px of height. It is not hidden or covered by anything and it is drawn correctly, but the set selector doesn't get called. If I set some height, the button works.
In short - how to achieve either a working button in a section header that has virtually no height, or how to achieve a section header that has normal height but always overlaps cells (doesn't use any space when the tableview is scrolled to the top of the section)?
Any help will be greatly appreciated.
One way you may be able to get this to work is to add a transparent view over the table. You would intercept touchDown and touchUp. You could calculate whether they were over one of your buttons, and if so send them directly to the button, otherwise just forward them. the reason you don't get the touch events is probably since the touch does not fall into the header frame.
David H suggestion was my initial idea as well but I was hoping to find a more elegant solution. Anyway, that's how I ended up implementing this feature.
I kept the code as simple as possible (I'm sure it can be done in a more optimized fashion, works fast enough for my needs) - each image added to a section (no need for overlaying buttons anymore) was also added to a dictionary with section numbers as keys.
When my mask layer view (the transparent one added over my tableview) is being touched I simply check with CGRectContainsPoint if the touch corresponds to any of the views in my dictionary.

Resources