Start UITableView from the bottom - ios

I'm rather new to Objective-C programming and I'm making an app that requires the Table View to load from the bottom to the top, similar to messaging apps. I've tried searching on Google about this but I'm still a bit confused about the code used. Thanks in advance!

UITableView polls its dataSource for cells based on what is visible on the screen. So, the key to your problem is you want to show the bottom of the table first.
In order to do that, you can call [tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)];, which will scroll the UITableView to the bottom.
Keep in mind that where you place that call may vary based on whether or not you are using Autolayout.
See How to scroll to the bottom of a UITableView on the iPhone before the view appears for more information

Here's what I did when I designed a chatbot:
1 - Add a UItableView in IB and set its constraints.
2 - When I added a new cell (message), I would change the Y position of the UITableView. For example, when the first message was added to the data source array, I would calculate the height of that cell, so if the height of that cell was 50, I would set the Y position of my UITableView as the current height of the UITableView minus the height of the cell that is being added. This makes it look like the messages are being added from the bottom.
3 - Repeat the above cycle in step 2, until the Y position of your UITableView is just below the top of the screen (or the required position), in that case you no longer have to set the subtracted value as the Y position (otherwise the tableview would go off screen). Add a if condition that checks if the calculated values is lower than the required position, if it is then just set the Y position yourself (So the table is pinned at the top).
4 - Also make sure that you always scroll to the last cell of your UITableView using scrollToRowAtIndexPath.
Hope this helps.

An alternative way to solve this is by flipping UITableView’s Y axis
taken from: Igor Kulman
The best solution I found is to flip the UITableView’s Y axis. It gives you all the advantages of the previous solution, but you do not have to handle the scrollbar. It stays in the right place because only the content is flipped.
So flip the UITableView
tableView.transform = CGAffineTransform(scaleX: 1, y: -1)
and flip your cells in the same way
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)

Related

Dynamic height for custom dialog in iOS

I'm trying to create a custom dialog with a UITableView inside.
What I want to achieve is to have the lowest height possible, meaning it should be only wrapping the tableview.
BUT when the tableview has too many items (meaning its height is bigger than the screen), I want the dialog to have 20 px margin from the screen top and bottom.
So if the tableview has 2 items, the height of the dialog should be for example 20 px. But if the tableview has 200 items, the height of the dialog should take almost the entire screen height and have its content scrollable.Dialog with few items
Dialog with multiple items
Currently if the tableview has multiple items, I can only see some items and the top and bottom of the dialog disappear.
Thanks.
EDIT: I forgot to mention I intend to achieve this using the storyboard only, using constraints and changing priority in content hugging and compression.
GOT IT WORKING!
All I had to do was change the top and bottom constraints from "=" to ">=".
So now it allows the dialog to have a smaller height but not bigger than the screen. No code needed.
Thanks everybody for your help.
My answer will include several parts. They are solving a more general question of how to efficiently work with dialogs.
To create dialog use UIViewControllerTransitioningDelegate, UIPresentationController and UIViewControllerAnimatedTransitioning. It's a long way, but it will make your dialogs presentation reusable.
To determine size of the dialog with table inside of it, set peferredContentSize property of your dialog view controller. This property will be used by UIPresentationController to set dialog height. Before setting peferredContentSize you can adjust the height to the margins you like.
To calculate size of table view you can use several options. table.layoutIfNeeded() worked for me.
Update: check out the article I wrote about this approach.
You need to set the tableView height dynamically, so give it two position constraints (ie centerX, centerY), a fixed width constraint, and then a height constraint set to some arbitrary constant (0). Take an outlet to the height constraint. Whenever you update the data that backs the tableview you take the min of the calculated tableview height and the superview height and set the height constraint constant to that value, then call setNeedsLayout on the tableView's superview. This way the tableview will either be the height of its content, or if the content is too big, the height of the superview and it will scroll.
tableViewHeightConstraint.constant = min(superview?.bounds.size.height ?? 0, numberOfCells * heightPerCell + headerAndFooterSize)
superview?.setNeedsLayout()
I guess that you know how many items you have before present the dialog and I guess that you dialog is a custom view (xib)
if this premises are true, you can resolve whit this line.
let dialog = CustomDialog(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: (heighCell * elements) + (heightButtonClose) + (heighTitle))
dialog.center = self.view.center
let me know if you have doubts

iOS for Android View.GONE setVisibility mode

I have used storyboard with autolayout for my UI design. Basically in android there are three different properties will be there like Visible and Invisible and gone.
For Example:
1) Android
mTextView = (TextView) findViewById(R.id.textview);
mTextView.setVisibility(View.GONE);
2) Objective C
UIView *a = [self.view viewWithTag:2]
I want to process View.GONE...
for act as a gone in IOS i have searched from google but i can't able to find the Solution.
Shin,
Android does not make use of autolayouts to calculate the frame of view components and like CSS (Cascading style sheets) it uses relative values of view components with respect to parent, margin or other peer views to calculate the position of view.
But in iOS when u use auto layouts, you define the constraints which are mathematical expressions and iOS evaluates them to find the actual values for the frames of various components :)
Whats the Significance of it ?
Because auto layout constraints are maths expressions, you will have to provide iOS enough data to calculate the unknown values.
Lets consider,
As you can see the view with pink colour has a fixed horizontal spacing from the green view, so iOS calculates the x position of pink view from the maxX position of green view + horizontal spacing between green and pink view :)
Now assume you call view.GONE on green view and completely remove green view, now iOS will be baffled as it does not know what will be the x position of pink view, now it does not have enough data to calculate the x position of pink view :)
Does that mean I can never achieve View.GONE in iOS ?
You can!! only virtually though :P
HOW??
Two ways :
way 1
You can't remove a view because that will cause it to leave all other view depending on it for their frame calculation un handled. Hence consider setting width and height constraint's constants value of views to "0"
Add height and width constraints to the view which you want to hide and create a IBOutlet to height and width constraints.
Now when you want to hide simply say,
self.greenViewHeightConstraint.constant = 0
self.greenViewWidthConstraint.constant = 0
self.view.layoutIfNeeded()
Yeah!!! Now you have a view whose width and height 0, I mean view exists but does not exist!!
Way 2
But then, You dint remove it really using way 1 did you ??? Nope. You can actually remove the view using Way 2
What I want you to see here that, now I know that if I remove View1, view 2 could not calculate its x position, So I created a Leading constraint from View2 to Parent left margin and set its priority to High and set its constant to 0 :)
Now this constraint will not come into play, as long as required (1000) constraints are good enough to calculate the values, now assume you remove View 1, View 2's frame can't be calculated with Required constraints, hence high constraint kicks in and it says your pink view should be 0 pixel from parents left margin :)
Yeah :) You achieved what you wanted, now you actually removed green view and pink view still not lost its frame :)
How on earth did you remove green view ??
Wasn't that the question ?? Sorry, I got carried away :)
You can say self.greenView.removeFromSuperview()
On iOS, visible and gone are done with hidden = NO and hidden = YES
If you want it to be invisible, set the view alpha to 0.
edit: Making a view hidden doesn't make the layout hierarchy ignore it, unless it is in a stack view.
After some googling, I found this:
View.GONE - This view is invisible, and it doesn't take any space for layout purposes.
View.INVISIBLE - This view is invisible, but it still takes up space for layout purposes.
And its equivalent in ios is :
View.GONE - Uninstalling view. This can be done from storyboard as shown in the below image. You will have to uncheck the checkbox of Installed
View.INVISIBLE - View.hidden = true;

UITableView over the top

I have an UITableViewController with an iAD banner on top, under the top bar.
When banned is loaded and device is in portrait it looks good but, when there's no banners or device turn in landscape, between top bar and the first tableView's row there's an ugly empty space.
The best solution would be to move the TableView up but I can't find a way to do that; the best solution I thought was to try resizing the header of section 0 of table's but I can't go under 0; and 0 is too much!
Is there another way to move table, for example, 10 pixels up?
The table view's content inset property can be used to add a padding around its content view. If you set the top for 10 for example, there will be some padding between the table view's top, and its content's top.
Using Swift, you can set the tableView.contentInset.top property directly. In Objective-C, you can set it like so:
self.tableView.contentInset = UIEdgeInsetsMake(10, 0, 0, 0)

How to vertically center table view in a Table View in Objective C

I have Table View in my Storyboard. So let's so I know I'm going to have a total of 5 rows. Those 5 rows to not take up the entire screen space vertically, so I would like the group of those 5 rows to be centered vertically on the screen, instead of starting from the top and having all the blank space on the button because there are only 5 rows.
How do I accomplish this (1) Using Storyboard or (2) using code?
you could use UIScrollViews contentOffset-property, since UITableView inherits from UIScrollView. Here is a link to the docs:
https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html#//apple_ref/occ/instp/UIScrollView/contentOffset
Essentially you just set a Point to define the X- and Y-Offset. So if you want the TableViews content to be offset by 100pts from the top, you would set
myTableView.contentOffset = CGPointMake(0, -100); //(edited in response to Lavvo's comment)
and thats it!
EDIT: Since its a property, there is a chance that you can set it in Interface Builder, but i cant check that right now. If so, its probably in the "Sizes"-Panel, i would guess.
If your table view has a static height, the easiest thing to do in a storyboard is to set the height constraint of the table view to however tall you want it. For example, if your cells are 44, 5*44 = 220.
Then add a constraint to your table view to have it centered vertically in its container.
This will make it compatable with any screen size as auto layout will automatically center it in the view container no matter what size it changes to.

Modifying a UICollectionViewFlowLayout to change cells positions

I need to slightly change the way FlowLayout draws cells.
I need to set the collection to scroll horizontally and I want to draw cells from left to right, moving to the next line when the width is completely filled and taking into account pagination.
Here some images to clarify my question:
This is the current behaviour of the FlowLayout:
this is what I'd like to obtain:
Some notes:
I need paginationEnabled = YES
I want to fix the rows to a maximum of 2
I have a fixed number of cells too.
Is there a way to achieve this behaviour working with a UICollectionFlowLayout? Or is this the case to create a totally custom UICollectionLayout?
I believe you would have to manually fill the cells checking the indexpath.row and also checking the width of each cell and self.view.frame.size.width

Resources