fading scrollMenu with labels - ios

i've created a paged UIScrollView which contains labels on every page. How can i lower the margin between the labels like in the picture and then still being able to scroll?
At the moment my navigationBar look like following. Where u can swipe to next page to the right and get the next label.
What i want is something like this with a small margin and still being able to swipe.
viewDidLoad code
//Category ScrollView
categoryScrollView = UIScrollView(frame: CGRectMake(0, self.navigationController!.navigationBar.frame.height-38, self.view.frame.width, 38))
categoryScrollView?.contentSize = CGSizeMake(self.view.frame.width, 38)
categoryScrollView?.delegate = self
categoryScrollView?.pagingEnabled = true
self.navigationController?.navigationBar.addSubview(categoryScrollView!)
categoryArray = NSArray(objects: "Book", "Elektronik")
var textWidth = 0
for val in categoryArray!
{
var textLabel: UILabel = UILabel()
textLabel.textAlignment = NSTextAlignment.Center
textLabel.text = val as NSString
textLabel.frame = CGRectMake(CGFloat(textWidth), 0, categoryScrollView!.frame.width, categoryScrollView!.frame.height)
categoryScrollView?.addSubview(textLabel)
textWidth = textWidth + Int(textLabel.frame.size.width)
if textWidth > Int(self.view.frame.width) {
categoryScrollView?.contentSize = CGSizeMake(CGFloat(textWidth), categoryScrollView!.frame.height);
}
}

The default width of the "page" when pagingEnabled is switched on is the width of the scroll view. You could reduce the width and let the contained views be visible beyond the edges of the view by setting clipsToBounds to false.
If this does not work for you there also the option to adjust the paging width by intercepting the end of the drag via the UIScrollViewDelegate method scrollViewWillEndDragging(...) where you can adjust the targetContentOffset to fit your needs (see an example here).

Related

clipsToBounds on UILabel not working

I have a UILabel, that I am setting up like this:
class someSuperclass {
var firstLetterLabel = UILabel(frame: CGRect(x: 58, y: 0, width: 81, height: 120))
func commonInit() {
firstLetterLabel.font = UIFont(name: "MuseoSans-500", size: 110.0)
firstLetterLabel.textColor = UIColor.museumRed
firstLetterLabel.textAlignment = .center
firstLetterLabel.numberOfLines = 1
firstLetterLabel.lineBreakMode = .byClipping
firstLetterLabel.clipsToBounds = false
addSubview(firstLetterLabel)
}
}
But it is still being clipped by its bounds
Since clipsToBounds does not seem to apply to the content of a label. How can I stop label content from being clipped by it's frame/bounds?
ClipsToBounds allows subviews or sub layers to spill out of a view or prevent that but it does not do that for drawn content by a view and in this case it is a UILabel. You cannot draw past the bounds of the view/label. That is why it is clipped. This difference always clips drawn content.
possible solutions
1) let intrinsic size of the single letter labels keep it from clipping. Place all the the labels in a horizontal stack view.
2) enable minimum font scale on the label to allow it to fit.
3) lastly it appears it is not drawing centered. Not really sure why as you have given very little to look at.
You can use UIButton instead, and setting button.userInteractionEnabled = false.

How to create horizontally dynamic UICollectionView cells? Swift

Hey I'm trying display a set of "tags" in a view controller using collection view cells but I'm having trouble finding a way to make them be able to dynamically resizable depending on the length of the string.
Right now the individual cells are statically sized so whenever a String that populates the cell with characters exceeding the size of the cell, it goes into the second line. I want it so that the cell can change length depending on the length of the String. So if it's the tag "#Vegan", it will automatically resize so that the tag isn't that big. Likewise, if it's a longer string like "#LaptopFriendly", it will become horizontally longer to accommodate the string and not use the second line. The vertical length can stay fixed. Thank you!
UPDATE (interface builder settings when I run into errors using Rob's code):
Simulator screenshot:
You need unambiguous constraints between your label and the cell (e.g. leading, trailing, top, and bottom constraints):
Then you can use UICollectionViewFlowLayoutAutomaticSize for the itemSize of your collectionViewLayout. Don't forget to set estimatedItemSize, too, which enables automatically resizing cells:
override func viewDidLoad() {
super.viewDidLoad()
let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = UICollectionViewFlowLayoutAutomaticSize
layout.estimatedItemSize = CGSize(width: 100, height: 40)
}
That yields:
You can calculate the lengths of the texts ahead of time, feed them into an array accessible by your collectionView and use them them to construct the size of the cell.
//Create vars
NSArray * texts = #[#"Short",#"Something Long",#"Something Really Long"];
NSMutableArray * lengths = [NSMutableArray new];
float padding = 30.0f;
//Create dummy label
UILabel * label = [UILabel new];
label.frame = CGRectZero;
label.font = [UIFont systemFontOfSize:20.0f weight:UIFontWeightBold];
//loop through the texts
for (NSString * string in texts){
//set text
label.text = string;
//calculate length + add padding
float length = [label.text boundingRectWithSize:label.frame.size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:label.font}
context:nil].size.width + padding;
//save value into array as NSNumber
[lengths addObject:#(length)];
}
//drop label
label = nil;
Create the size of the cell using some code like this:
return CGSizeMake(lengths[indexPath.row], 100.0f);

Calculate where text starts on centre alignment

I have a UILabel that I want to add a UIView exactly where the text starts.
The problem is that the text in the label is aligned to the centre so I don't know how to determinate where the actual text starts and where to position this UIView.
Any idea how can I calculate this thing?
Thank you!
You can use a UIView container which will wrap the UILabel and your new UIView. Then you can let the UILabel decides the width depending on its content and set it in the center of the container. Once you have this working you can just read the UILabel x to understand where it starts.
so the UILabel will have the constraints to top, bottom, the height you want and at center to horizontal whereas the little UIView to top, bottom, height, width and leading equal to UILabel
From :How to find the position(x,y) of a letter in UILabel
NSRange range = [#"Good,Morning" rangeOfString:#","];
NSString *prefix = [#"Good,Morning" substringToIndex:range.location];
CGSize size = [prefix sizeWithFont:[UIFont systemFontOfSize:18]];
CGPoint p = CGPointMake(size.width, 0);
NSLog(#"p.x: %f",p.x);
NSLog(#"p.y: %f",p.y);
you can modify it for your purpose
you can get text size using "nsattributedstring"
let label = UILabel(frame: CGRectMake(0, 0, 100, 100))
label.text = "dshfk,j"
label.textAlignment = .Center
label.textColor = UIColor.redColor()
let string = label.attributedText
let width = string!.size().width
let height = string!.size().height
let view = UIView(frame: CGRectMake(width, height, width, height))
view.backgroundColor = UIColor.blackColor()
then you can find rect using this ..
sample view
You could also use
yourLabel.sizeToFit()
to automatically resize your label for the space it needs. And then read out the frame of your label with:
yourLabel.frame.size (width or height)

Managing autolayout constraints for a chat view

I'm creating a chat view, and currently trying to design the cell based on autolayout. My main problem is that, there is an image view and just below there's a label for chat text which go multiple line, and if there's no image only text should display and if there's no text only image should display. Image should be 60% of cell width and 40% in height. Below is my cell design, I've added background color to each view for clarity.
But by giving proportional height, I'm not able to set its height programatically. So currently I tried giving a fixed height for image view and manage it programmatically in the code. Below is my code where I adjust imageview and chat text height.
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell : ChatViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("chatCell", forIndexPath: indexPath) as! ChatViewCell
cell.fullNameLabel.text = tempArray[indexPath.row].0
cell.fullDateLabel.text = tempArray[indexPath.row].1
cell.chatSentStatusLabel.text = tempArray[indexPath.row].2
cell.chatTimeLabel.text = tempArray[indexPath.row].3
let chatBubbleData1 = tempArray[indexPath.row].4
if (chatBubbleData1.image == nil)
{
cell.chatImageHeightConstraint.constant = 0
}
else
{
cell.chatImageHeightConstraint.constant = 150
}
cell.chatTextContainerView?.layer.cornerRadius = 10.0
cell.chatTextContainerView?.layer.masksToBounds = true
cell.chatBubbleView?.layer.cornerRadius = 10.0
cell.chatBubbleView?.layer.masksToBounds = true
cell.chatImageView.image = chatBubbleData1.image
cell.userPointerView.colors = (0.0, 0.0, 1.0, 1.0)
cell.userPointerView.backgroundColor = .clearColor()
cell.chatImageView?.layer.cornerRadius = 10.0
cell.chatImageView?.layer.masksToBounds = true
if (chatBubbleData1.text?.characters.count > 0)
{
cell.chatText?.numberOfLines = 0 // Making it multiline
cell.chatText?.text = chatBubbleData1.text
cell.chatText?.sizeToFit()
cell.chatTextContainerHeightConstraint.constant = CGRectGetHeight(cell.chatText.frame)+20
}
else
{
cell.chatText?.text = ""
cell.chatTextContainerHeightConstraint.constant = 0
}
cell.setNeedsDisplay()
return cell
}
This is the result now
The multiline doesn't seems to work. I'm not sure if I'm following the best approach. If anybody has any solutions or any suggestions, please let me know.
PS: Please don't suggest any third parties like JSQMessagesViewController. I'm already aware of those. I'm doing this as part of learning.
You just put a bottom constraint for all the components in the cell.
and call delegate methods of table view (EstimatedRowHight and HightForRow).
it will return the exact hight of the cell.and you can also customise whether it display or not..
remember that text labels should had the bottom constrain property with respect the other components.Hope you get what i meant.
If UIImageView and UILabel will never be shown both in the same cell, you could remove all constraints relations between them and make each in relation only with superview. Then with some code you can manage UIImageView or UILabel visibility and calculate proper height for each cell in CollectionView/TableView delegate method.
I think problem is in your line
cell.chatTextContainerHeightConstraint.constant = CGRectGetHeight(cell.chatText.frame)+20
Instead of getting chatText.frame height your should manually calculate the height. I used following function to calculate cell height:
+ (CGFloat)calculateCellHeightForText:(NSString *)text cellWidth:(CGFloat)cellWidth {
CGFloat maxWidth = cellWidth;
CGSize textSize = [text boundingRectWithSize:CGSizeMake(maxWidth, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName : [UIFont fontWithName:#"CALIBRI" size:17]}
context:nil].size;
return textSize.height;
}

UIScrollview Dynamic content size is very off based on number of items

I have a vertical scrollview with thumbnail images to act as a "side panel" for specific items on an ipad app.
Here's my code to set the content size:
- (void)setScrollViewContentSize:(UIScrollView*)scrollView{
NSInteger viewCount = [scrollView.subviews count];
NSLog(#"viewCount: %d", viewCount);
NSLog(#"height: %f", (viewCount * 190.0f));
scrollView.contentSize = CGSizeMake( scrollView.superview.frame.size.width, (viewCount * 190.0f));
}
When I run my app, there's one menu that has 57 items, so the viewCount log shows up as 57 and the height shows up as 10830. On another menu, I have 13 items and thus, the height is 2470.
Everything seems fine here, but when I scroll to the end of the view, the menu with 57 icons has way too much white space left over whereas the menu with 13 items ends perfectly on the last item with a little margin (each thumbnail is 183px). I'm trying to find out what the cause is, but it seems like the more menu items I have, the bigger the scroll view's spacing at the last item gets.
I tried calling scrollView sizeToFit and even trying to create a CGRect of a visible region to apple to my frame, but none of those worked. Any ideas?
thank you.
from https://stackoverflow.com/a/14852596/1363779
float sizeOfContent = 0;
UIView *lLast = [scrollView.subviews lastObject];
NSInteger wd = lLast.frame.origin.y;
NSInteger ht = lLast.frame.size.height;
sizeOfContent = wd+ht;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);
This is a nice and easy way to do it.
Swift 2.0 version
var sizeOfContent: CGFloat = 0
let lLast: UIView = scrollView.subviews.last!
let wd: CGFloat = lLast.frame.origin.y
let ht: CGFloat = lLast.frame.size.height
sizeOfContent = wd + ht
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent)

Resources