Append item horizontally into a tableView cell but make them not fill all the space - ios

I have a specific design that I want to achieve, it doesn't seems to complex to me but I'm struggling a lot to make it happen.
First the design looks like this:
So, I have a table view of items which have a picture, then a title and then a collection of three items which will be ImageViews.
All of this inside a cell and inside a stackView.
I tried to make an horizontal stack view and did manage to append my items correctly but it went horribly wrong in terms of design as my imageviews were stretching all the way horizontally. I guess this is not possible to NOT stretch this items.
I also tried to add a collection view into the table view but figured out that was very complex for a thing this basic (as I guess it should be). And then, I'm here.
Here is my code and where I'm stuck at:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = debateList.dequeueReusableCell(withIdentifier: "itemsBox", for: indexPath) as! ItemBox
// Make a variable with 3 participants
let participants = tableView[indexPath.row].participants?.prefix(3)
// iterate over them and adding them to anything that can be doable
participants?.forEach { participant in
let imageView = UIImageView()
let imageUrl = URL(string: participant.imageURL)
imageView.kf.setImage(with: imageUrl)
// Here add item to something
}
return cell
}
I'm stuck and it's getting too long for something this little. Guess I'm a little bit upset with myself for not figuring out how to do it.

If you are having up to 5 participants, then I would suggest you to add by default 2 subviews in horizontal stack view:
empty view with width constraint >= 5 (call it spaceview)
fixed width for "60 % no" UILabel.
then programmatically insert image views with fixed width and aspect ratio 1:1 in horizontal stack view at index 0.
This way, if there will be only 1-2 participants, then the remaining space will be occupied by spaceview as its width will be greater than 5.
If the participants will be more than 5, then better option is to use collectionview with uilabel in horizontal stack view.

First if they are 3 static number of images then it's better to make them inside design and assign the image urls to their outlets respectively
Second for your current work you need to add a width constraint (regarding height they will fit all the stack height when it's a horizontal stack ) like
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.widthAnchor.constraint(equalToConstant: 50).isActive = true

Related

Slide view together with UICollectionView cell

i have this structure. Scrollview -> UICollectionview + Label
This viewcontroller has array of items (BlockItem). On scrollViewDidScroll i change current test label (description)
func scrollViewDidScroll(_ scrollView:UIScrollView)
{
let midX:CGFloat = scrollView.bounds.midX
let midY:CGFloat = scrollView.bounds.midY
let point:CGPoint = CGPoint(x:midX, y:midY)
guard
let indexPath:IndexPath = collectionView.indexPathForItem(at:point)
else
{
return
}
let currentPage:Int = indexPath.item
if let found = items.first(where: {$0.id == String(block[currentPage])}) {
description.text = found.description
}
}
The main issue that i want my description label will be moving together when i move my collectionview cell and appear from the next cell. In other words, if I scroll to the left my description should move along with the cell, i.e. go to the left and appear on the right of the screen.
How can i do this? I know i could make a big collectionview but i need that only image part should be scrollable, not the entire block.
Here is what i want to achieve
Here is video example: scroll works only if i swipe on the image area, and doesn't work when i scroll down the page
https://drive.google.com/file/d/1kl1GYgXvK4bL3toTfOvpxF2WqS56pQO9/view?usp=sharing
You exactly said this:
"The main issue that I want my description label will be moving together when I move my collection view cell and appear from the next cell."
If you want your description label moving together, just include them into your collection cell. It's very clear from your point there
I don't understand why u need to separate it, but you want it to slide from new cell.
If you insisted that you want to archive the label, not in a scroll view, then use 2 label
One label for this cell and one label will come from scroll direction, u can archive this by creating manually. This is a simple code for a swipe left to scroll
UIView.animate(withDuration: 0.5) {
//insert your label animation
//current label moved with the scroll to left
//create a new label from the outer right of the current view, scroll it to the middle of your view
}
But it will be hard work for good animation or scroll support.

How to equally space labels in a UIStackView?

As a technical assessment for a job I'm interviewing for, I'm making a basic word search game, where the user looks for translations of a given word in a given language. I've got a fair amount of iOS experience, but I've never done dynamically-generated views with run-time-determined text labels, etc. before.
To be clear, I know this is a job assessment, but regardless of whether I get the job, or whether I'm even able to finish the assessment in time, I think this is an interesting problem and I'd like to learn how to do this, so I'll be finishing this as an app to run in the simulator or on my own phone.
So. I have a view embedded in/controlled by a UINavigationController. I have a couple of informational labels at the top, a set of buttons to perform actions across the bottom of the view, and the main view area needs to contain a 2D grid of characters. I'd like to be able to take an action when a character is tapped, such as highlight the character if it's part of a valid word. I'd like to be able to support grids of different sizes, so I can't just create an autolayout-constrained grid of labels or buttons in Interface Builder.
I've tried various methods for displaying the 2D grid of characters, but the one I thought had the most promise was as follows:
Use a UITableView to represent the rows of characters. Inside each table view cell, use a UIStackView with a dynamically generated collection of UILabels.
To fill my UITableView, I have the following:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = gameGrid.dequeueReusableCell(withIdentifier: "GameGridCell") as! TWSGameGridCell
if indexPath.row < word.grid.count {
cell.characters = word.grid[indexPath.row]
cell.configureCell()
return cell
}
return cell
}
The function in the custom table cell class that configures the cell (ideally to create and display the row of characters) is this:
func configureCell()
{
self.stackView = UIStackView(arrangedSubviews: [UILabel]())
self.stackView.backgroundColor = (UIApplication.shared.delegate as! TWSAppDelegate).appBackgroundColor()
self.stackView.distribution = .fillEqually
let myRect = self.frame
self.stackView.frame = myRect
let characterGridWidth = myRect.width / CGFloat(characters.count)
for cIndex in 0..<characters.count {
let labelRect = CGRect(x: myRect.origin.x + (CGFloat(cIndex) * characterGridWidth), y: myRect.origin.y, width: CGFloat(characterGridWidth), height: myRect.height)
let currentLabel = UILabel(frame: labelRect)
currentLabel.backgroundColor = (UIApplication.shared.delegate as! TWSAppDelegate).appBackgroundColor()
currentLabel.textColor = (UIApplication.shared.delegate as! TWSAppDelegate).appTextColor()
currentLabel.font = UIFont(name: "Palatino", size: 24)
currentLabel.text = characters[cIndex]
self.stackView.addArrangedSubview(currentLabel)
}
}
My guess is that it's running into trouble in that the labels have no visible rect when they're created, so they don't display anywhere.
The resulting view when run in the simulator is a white box covering as many rows of the table view as should be filled with rows of characters, and the rest of the table view shows with the custom background color I'm using), as per this image:
What I'm trying for is for that white box to have the same background color as everything else, and be filled with rows of characters. What am I missing?
Problem might be about adding 'labelRect', you already specify the rect of your stackView. I think regardless of the frame of labels, stackView should naturally be able to create it's inner labels and distribute them inside of itself.
Also can you add the following, after you initialize your stackView, inside your configureCell method:
self.stackView.axis = .horizontal
Edit: from the comment below, the solution was to create the labels (though I switched to buttons for further functionality), add them all to a [UIButton], then use that to create the UIStackView (self.stackView = UIStackView(arrangedSubviews: buttons)).

Swift Dynamically growing a cell depending on the text length

I have a TableViewController which contains 2 sections:
Section 1 - is a cell which is loaded from a xib file. This cell just contains a TextView.
Section 2 - Contains multiple cells populated from an Array.
The section 1 only exists if the master (previous) UITableView cell you select contains a certain piece of data.
All of the above works as expected, below is the parent view. The list of items come from a database, some items have a description, and some do not. For example below this image, you'll see the view is 'Classic Starters' is selected. Then below that, you'll see the view if 'Stir Frys' is selected. Stri Frys contains a description:
Now, what I want is, the description cell which is shows on the Stir Frys page, to automatically grow depending on the length of the text inside it. So if a description is 10 lines long, it will grow to show all 10 lines.
Does this have to be done programmatically, or is their a feature in XCode I'm missing ?
You can use UITableViewAutomaticDimension.
1)
Set properties estimatedRowHeight and rowHeight of your tableview, in viewDidLoad for example. Like this :
self.tableView.estimatedRowHeight = 50
self.tableView.rowHeight = UITableViewAutomaticDimension
2) Return UITableViewAutomaticDimension in your heightForRowAt delegate method :
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
First you need to do is to set estimatedRowSize to a value that best estimates most common size, and rowSize to UITableViewAutomaticDimension:
self.tableView.estimatedRowHeight = 44
self.tableView.rowHeight = UITableViewAutomaticDimension
In your case, since except the first one all the other cells are supposed to be the same, you can use the height of the rest of the cells as the estimatedRowHeight.
You don't have to implement heightForRowAt at all.
The second step you need to do is to setup proper constraints on the cells. That means you have to constrain the contents of the cell to the left, right, top and bottom of the cell, so that when contents grow, the cell will need to grow, too. Common mistake is to forget to constrain bottom, so then the cell does not grow and the contents leak through the bottom of the cell.
Third, since your dynamic cell contains UITextView, you need to make sure that it will grow with its text. That is not automatic. To achieve that, based on this answer, this should suffice (in the cell):
textView.isScrollEnabled = false
If you are using storyboard, just uncheck scroll enabled.

Insert in a tableView set to Autoresize cause a scroll issue

I've an issue for few days and really I can't explain why it goes like that.
I'm doing a chat, set up with a tableView, printing message into cell. These cells are designed with prototypes, there are 3 different type (but anyway it doesn't matter). Text is typed, message is send, cell is inserted in table and then we scroll to the bottom of the tableView.
As you know, in a chat view the container of the message has to fit this text (which is a view), and then the cell has to fit to this container (Label in orange, container in purple).
This container has a variable height and grow along the text, changing cell height.
I've set many constraint for auto-layout display but I didn't have different cell height than the height I initially set for it in the project (no adaptative behaviour). Chat Message were cut.
So, I've tried to set each rowHeight by myself using the method heightForRowAtIndexPath, calculating constraint along text size but it create a real bad behaviour (changing cells when scrolling for example). The size was often wrong calculated/recalculated.
That's why I'm finally using estimatedRowHeight set to 44 combine with UITableViewAutomaticDimension. Here it does the trick ! Waouh ! But it's not as good as expected..
When the table view appears all is good. Containers fit to their label, rows' height fit to their container and it's beautiful. The problem appears during an insert.
After many tests, I notice that this bad behaviour only appears when multilines label remains in the table view.
During an insert, each cell seems to resize to 44 before adapt its height to content, and then create a gap compared to previous state which create a strange scroll of the table view :
If I change the estimatedRowHeight it made this worst.
I can show my code if you want, but I don't think it will be very useful here because I'm not using complicated function.. only insert, automatic height for cells and scroll down which are functions delegate for tableView.
Can you help me please ? Really I don't know how to change that.. every chat application does the trick but I can't found out the way.
Thank you for answer, excuse my english level I'm a poor french student..
If you need some code comment I'll give it.
I think you can cache height value for every cell in cellForRowAtIndex method and in HeightForRowAtIndex set the corresponding height for that cell.
You can just do this way :
var cellCached = Dictionary<Int,AnyObject>()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
table.rowHeight = yourCell.yourLabel.frame.origin.y + yourCell.yourLabel.frame.height + 10
cellCached[indexPath.row] = yourTable.rowHeight
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(tableView == yourTable)
{
if(cellCached[indexPath.row] != nil)
{
return cellCached[indexPath.row] as! CGFloat
}
else
{
return 200
}
}
else
{
return UITableViewAutomaticDimension
}
}

How do I create dynamic views in swift?

I am making an IOS app where the main layout is a UITableView, and cells are completely dynamic and loaded from server. Each tableview item is a different layout.
For example, lets take first item of the tableview:
Server tells it should have a label, 2 buttons and a textbox, it should be created by code. I figured out how to create those elements themselves, the problem is how do I position them?
Ideally I would like to add each layout item under the previous one. And tableviewcell should wrap those, grow or collapse according to views.
I am fairly new to IOS/Swift. Is there any way to implment this easily? In android I just used a linearlayout and added views one by one. Does IOS have something like that? Or do I have to manually set heights, widths, and coordinates of all items?
Thanks in advance.
Here is some code:
if let Actions = AppData["Forms"][0]["AvailableActions"].array{
for var i = 0 ; i < Actions.count ; ++i {
if Actions[i].int == 1{
let actionButton1 = UIButton(frame: CGRectMake(0, 0, 96, 30))
actionButton1.setTitle("View", forState: .Normal)
actionButton1.setTitleColor(UIColor.redColor(), forState: .Normal)
cell.actionsLayout.addSubview(actionButton1)
}
}
}
You can do with self-sizing cells, in this case you just need to
Give proper constraints to your table view cell subviews,(i.e all
your subviews should be connected to each other and topmost
subview should have top-space constraints and bottommost subview should have bottom-space constraints).
Specify the estimatedRowHeight of your table view.
Set the rowHeight of your table view to UITableViewAutomaticDimension
For step 2-3 steps mentioned above,just add following code in your viewDidLoad -
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
For understanding of self-sizing cells you can follow this link
http://www.appcoda.com/self-sizing-cells/

Resources