I would like to make a menu which will have horizontal scrolling.
The menu contains total 16 categories. So I am planning to take 8 on first part and rest 8 on another part.
Can some-one give me insight of what needs to be done?
I believe I need to use below.
UIScrollView
Add buttons in this scrollview
That's it?
What I want is on first screen 8 buttons where first screen will have two rows with 4 buttons set on each row.
Menu sample can be seen at http://www.shoutem.com/
If all you're doing is adding buttons to a horizontal scroll view you would do something like follows...
- (void)createScrollMenu
{
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 100)];
int x = 0;
for (int i = 0; i < 8; i++) {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(x, 0, 100, 100)];
[button setTitle:[NSString stringWithFormat:#"Button %d", i] forState:UIControlStateNormal];
[scrollView addSubview:button];
x += button.frame.size.width;
}
scrollView.contentSize = CGSizeMake(x, scrollView.frame.size.height);
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];
}
This will create a scrollview with a height of 100, width as big as its parent, and add 8 buttons to it.
You can accomplish you're goal using a UIScrollView and your UIButton objects, it would involve setting each button's frame / layout properties depending on what iOS version you're targeting. (As in Eric's answer).
However, if you're targeting iOS 6 and above, using a UICollectionView where your items/cells are the buttons, then you can get the horizontal scrolling "menu bar" for free. There are plenty of SO posts on this, but the main idea is to use a flow layout where the item size has a height such that there will only be one row of items (just make the item height the same as the collection view's height).
EDIT:
I should say, this might seem like overkill (and maybe it is), but you will end up with a much more flexible component in case requirements change in the future. It also doesn't result in much extra code and abstracts away tedious layout details.
Related
After 2 days behind the implementation of a UIScrollView, I give up to do it by myself, despite It should be simple but I am not able to make it.
I need a vertical scrollview with Autolayout (I have 2 backgrounds images that need to scale), I have Xcode 7.2, iOs deployment target 9.0 and I am using the storyboard
The scrollview is a "new account" form with a lot of content, So it can have a fixed height
I tried lots of options but no one of them work, at the momment I have a scrollview with a "content view" with all of the components.
Problems:
1.- How can I put more content in the scrollview? If I try to put more compoments(more than the height of ViewControler), it automatically moves my components to be inside the ViewController rectangle
2.- How I can make it scrollable? If I pin the content view to the top, bottom, left, right and make it with fixed height (like 1000) it doesn't scroll
Any help would be appreciated
Scrollview will scroll until the end of last UI object. But this is not the default behaviour of the scrollview. You should explicitly set the contentSize on your scrollview. Check below example.
-(void)addImage {
int count = 20;
UIScrollView * scView = [[UIScrollView alloc] init];
scView.frame = CGRectMake(30, 60, self.view.frame.size.width, 60);
UIButton * btn;
UIImageView * imgV;
float imgWidth = 44;
for(int i=0;i<count;i++) {
imgV = [[UIImageView alloc] init];
imgV.frame = CGRectMake(i*imgWidth, 0, imgWidth, 44);
imgV.image = [UIImage imageNamed:#"gitar"];
[scView addSubview:imgV];
}
[scView setContentSize:CGSizeMake(imgWidth*count, 50)];
[scView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:scView];
}
What the above method does is, it will add 20 images in scrollview and at the end after adding all the images to scrollview in for loop I set contentSize to Scrollview. This step makes my scrollview to scroll until the content available. My example showing for Horizontal scroll, you have to change this behaviour to vertical scroll.
I want to custom the separator line view like that, but I'm still stuck here. Facebook app make the separator line view is a good looking. I want to archive something like that. Can any one help me?
I try with set frame and update constraint, but it does not work on all devices (iPhone 4s, iPhone 5, iPhone 6, iPhone 6 Plus).
I use both constraints and custom frame for UIView to make it works like a separator line view, the height is 0.5 for constraint's constant or frame's height. But it does not like the UITableView separator. The height is not really thin like Facebook app does and sometimes it does not show.
Thanks
UIView * separtor = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.contentView.frame.size.width, 1)];
separtor.backgroundColor = [UIColor whiteColor];
[cell.contentView addSubview:separtor];
Hi there,
You can still add a really thin and empty UIView with a background color you desire.
Create a custom cell / Prototype cell and design it according to the requirement.
At the bottom of the designed custom cell, add a view(with minimum constant height) and set its size colour and other parameters according to the UI need.
Set constraint to it (Prefer giving predefined height to the separator view) so that visual will be same and adopt the width for different devices.
Finally, remove the default separator which will be set by the table view.
i.e: Set 'separator' property to 'None' for table view.
Try this
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 3)];/// change size as you need.
separatorLineView.backgroundColor = [UIColor whiteColor];// you can also put image here
[cell.contentView addSubview:separatorLineView];
Hope it helps
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, 3)];/// change height as you need.
separatorLineView.backgroundColor = [UIColor whiteColor];// you can also put image here
[cell.contentView addSubview:separatorLineView];
I've just started working with XCode 5.1 and iOS 7.1.
Im having some problems with PartialViews containing a scrollview. I have this ). I marked in red the space the scrollview should occupy but its taking more space vertically and horizontally. The viewcontroller and view are defined in the storyboard as freeform of 500x500 and the scrollview is defined like:
scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, rowHeight*[lstMatches count])];
scroll.contentSize = CGSizeMake(self.view.frame.size.width, rowHeight*[lstMatches count]);
//.....more elements here, added as subviews of scrollview
[self.view addSubview:scroll];
The problem is the next:
1) The scrollview is wider than its container so I can't click over right buttons. I tried changing the width of the viewcontroller and view to 800 (max width is about 750), but i cant click them.
Thanks for your help
try:
scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height])];
scroll.contentSize = CGSizeMake(5000, rowHeight*[lstMatches count]);
[self.view addSubview:scroll];
PS: Change the contentSize.width of 5000 to something that suits your needs
I've been messing around and trying to make my own messaging application (for practice).
I'm adding a custom UIView to a standard UIScrollView based on an IBAction.
Each time the user presses a button, I do the following (in order):
Enumerate the subviews in the scrollView and increase the value of an
integer. I use this int to set the y-position of the new custom
view
Create a custom UIView with a frame size that varies only in width. The view has a UILabel on top of it that has the text.
Create a new CGSize that I use to set the contentSize of the
UIScrollView. The new CGSize is the width of the scrollView + the
height of the custom view + some padding.
I then set the contentSize of the scrollView.
I then add the custom view as a subview of the scrollView.
I created a timer that adds a new message/subview every two seconds to test multiple messages and the issue I am seeing is that once the subviews are added outside the viewable area of the UIScrollView, they stop being added. They are only added once I bring the messages back into the viewable area, and even so, they are added overlaying at times.
Now, I am aware of a few things: I need to add the subviews on a separate thread since they won't be added while the user is scrolling. I know that I will need to "clean up" subviews as they build up since my app will keep eating memory as more subviews are added. I am also aware that I should reposition the UIScrollView as messages are added since it doesn't make sense to add them outside of the viewable area. Finally, I don't think enumerating the subviews is very elegant... so I will change that later... nor is the temp UILabel I make... Now for some code:
- (void)pushMyMessage:(NSString *)message
{
UILabel *tempLabel = [[UILabel alloc]init];
tempLabel.text = message;
[tempLabel sizeToFit];
//adding the new message as a subview below any previous messages
if (self.messageView.subviews.count > 0)
{
int yIndex = 0;
for (SDMessageView *view in self.messageView.subviews)
{
//increase the y value for the frame of the next message
yIndex += view.frame.size.height;
//add a little padding
yIndex += 5;
}
SDMessageView *newMessage = [[SDMessageView alloc]initWithFrame:CGRectMake(20, yIndex, tempLabel.frame.size.width + 8, tempLabel.frame.size.height) setMessage:message];
CGSize newSize = CGSizeMake(self.messageView.frame.size.width, self.messageView.contentSize.height + newMessage.frame.size.height + 30);
[self.messageView setContentSize:newSize];
[self.messageView addSubview:newMessage];
}
else
{
//initial message
SDMessageView *newMessage = [[SDMessageView alloc]initWithFrame:CGRectMake(20, 20, tempLabel.frame.size.width + 8, tempLabel.frame.size.height) setMessage:message];
CGSize newSize = CGSizeMake(self.messageView.frame.size.width, self.messageView.contentSize.height + newMessage.frame.size.height + 30);
[self.messageView setContentSize:newSize];
[self.messageView addSubview:newMessage];
}
}
Any ideas on why the subviews are only added while in view? Also, any ideas on how I can do this efficiently?
Thanks for any help in advance!
Few things I noticed while reading your post:
You should not make any UI interface changes (like adding subviews) on secondary thread, this should be done on main thread.
Why don't you use UITableView for displaying messages? If you use table view, you don't have to calculate all the frames, content sizes and etc., just need to give correct height to the cell, and this would efficient way of solving what you are trying to achieve.
I didn't really understand, why your subviews are not added to the hidden area of the scroll view, in my practice, I didn't notice such a behaviour of the scroll view (I used it a lot), there should be some other issue with your code (are you adding subviews on secondary thread?).
Hope this was helpful, Good Luck!
How would I get the actual dimensions of a view or subview that I'm controlling? For example:
UIView *firstView = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,100)];
[self addSubview:firstView];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 20, 230, 120)];
[firstView addSubview:button];
As you can see, my button object exceeds the dimensions of the view it is being added to.
With this is mind (assuming there are many objects being added as subviews), how can I determine the actual width and height of firstView?
If you would like to have the button have the same width and height as firstView you should use the bounds property of UIView like this:
UIView *firstView = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,100)];
[self addSubview:firstView];
UIButton *button = [[UIButton alloc] initWithFrame:firstView.bounds];
[firstView addSubview:button];
To just get the width/height of firstView you could do something like this:
CGSize size = firstView.bounds.size;
NSInteger width = size.width;
NSInteger height = size.height;
The first view really is 200 x 100. However, the views inside are not clipped unless you use clipsToBounds.
A preferable solution to your problem is to stop adding views that exceed the dimensions or to stop resizing views so that they overflow the available space, as appropriate.
(To actually calculate the full bounds including all subviews in the hierarchy is not hard, just a lot of work that won't actually get you anywhere. UIView happens to allow views to be larger than their containers, but it doesn't necessarily give any guarantees about what will work correctly and is likely to be a source of bugs if taken advantage of. The reason for clipsToBounds is probably that clipping is expensive but necessary during animation where subviews may be temporarily moved out of bounds for the purposes of an effect before they are removed from the view.)
firstview.frame.size.width
firstview.frame.size.height