I'd like to have a UITableView with cells wider than 320 points. The user should be able to scroll sideways to be able to view different parts of a UITableViewCell. Is this kind of behavior possible with a UITableView, or should I go and try to implement a tiling UIScrollView?
I tried wrapping a UITableView within a UIScrollView, and the results are terrible - they compete for the scroll gestures and most of the time the scroll view wins, preventing the table from being traversed vertically.
Any input is appreciated!
Thank you!
Update: I tried the proposed solution and it scrolls properly, but the tableview is still only 320 pixels wide. Is tableView's width linked to the window bounds ?
Wrapping the table view with the scroll view is the right way.
UIScrollView with
Show horizontal scrollers
scrolling enabled
autosize to full screen
Inside that, a UITableView
shows vertical scrollers
scrolling enabled
Then I set the table view's frame, with w, being the calculated width of the table view with all columns, whatever your width, and kTableScrollViewHeight being the fixed height of both the table view and the scroll view, in my case, for example 367 points (screen minus status, navbar and tabbar):
tv.frame = CGRectMake(0, 0, w, kTableScrollViewHeight);
and the scroll view's content size
scrollView.contentSize = CGSizeMake(w, kTableScrollViewHeight);
If you want the scroll-to-top behavior when the user taps the status bar, you might want to set
scrollView.scrollsToTop = NO;
because otherwise the scroll view will take away the tap from the table view.
Related
I'm creating a UITableViewController in code and pushing it on top of the navigation stack.
It's table view is intended to just show a simple list of text items.
I need to add some contentInset to my table view which I add in the init method of my UITableViewController
self.tableView.contentInset = UIEdgeInsetsMake(7.0f, 5.0f, 7.0f, 5.0f);
However, when I load the table view it seems the left and right contentInset have actually stretched the width of my table view by 10. I'm now seeing a small horizontal scrollable area. I don't want any sort of horizontal scrolling on my table view. If I remove the contentInset code, my table view behaves plainly i.e. simply provides for vertical scrolling. How I can keep just like that but with my contentInset in place? I tried reducing my contentSize.width by 10 in viewWillAppear, it had no effect.
This seems to be a duplicate but with no acceptable answer: UITableView ContentInsets scrolling content horizontally
In the mock I have marked the desired contentInset with dashed line ---
Thanks.
I ended up setting just the top and bottom insets. To achieve the left and right inset look and feel, I created custom cell as wide as the screen. But the actual cell content was restricted to a slightly narrower subview within the custom cell. Thus, there was space leftover on the left and right of the subview.
Looks like you need to do 2 things:
Add the table view to a container view and make the table view frame thinner (to add the left and right borders).
Add thecontentInset only for the top and bottom.
Maybe you should set the bounces property of the scrollView to YES.
And do not set the contentInset.
Another way that could work, is that, instead of setting the tableView frame, you can set the frame for cell's contentView , something like this,
- (void) layoutSubviews
{
[super layoutSubviews];
CGRect frame = self.contentView.frame;
frame.size.width = frame.size.width * 0.9; //90% of total width
frame.origin.x = self.center.x - (frame.size.width/2); //center the contentView
self.contentView.frame = frame;
}
The using the above, u can add any left or right or left padding u need for the cell. and all the subViews will be added to the contentView , hence no problems there.
happy coding..!
I have a UITableView within a UIScrollView. It took me quite a lot of work to make it work.
The tableView is 640x350, I use the scroll view to scroll from one end of the cell to the next.
The scroll view is 320x350.
The scroll view's content size is 640x350
I'm running into this problem:
if I set scrollView's minimum zoom scale to 0.5, the tableview's width now fills the screen, but it's height is only half the screen. I would like the tableview to show more rows when I zoom out to 0.5.
First of all I would like to understand if this is the correct behavior, or the result of my tableView's content size and frame manipulations. The tableview has all springs and struts set in interface builder and should fill the frame available. This is my first attempt at zooming in months, and I don't remember how it works with zooming.
Can someone help me understand where and what do I need to adjust?
As far as I understand, I need to put the code into scrollViewDidZoom: that will manipulate the tableView's frame and content size.
PS. I"m returning the tableview from the viewForZooming: method of UIScrollView
What you are trying to achieve is pretty hard.
Solution 1 This solution uses the exact setup you have (UITableView inside UIScrollView).
You say that when you set the zoomScale to 0.5, you want your table view to fill the scrollView vertically. At 0.5, your table view must be 640x700 in order to fill the UIScrollView as you wish. For this to happen, on scrollViewDidZoom: you must resize the frame of the table view to 640x700
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
// No matter what the zoomScale is, the tableView will be zoomed accordingly
// Only zoom the height of the table
tableView.frame = CGRectMake(0, 0, 640, 350 / zoomScale);
// Also, update the contentSize
scrollView.contentSize = CGSizeMake(640, 350 / zoomScale);
}
If you run the code above for zoomScale = 0.5 you will get a frame size of 640x700.
This only changes the frame of the table and doesn't change the heights of the cells. This means that as you zoom out, you will also see more cells in the tableview.
Solution 2 Use only UITableView
UITableView is a subclass of UIScrollView. This means it has the ability to zoom and scroll around.
Start with a UITableView with the size that you want on the screen. Then, after the content is loaded modify the contentSize and make it wider than your frame width. This should enable horizontal scrolling.
However, UITableViewCells have their frame set automatically to the width of the tableview frame. You can bypass this by using a custom UITableViewCell, with clipsToBounds=false. Inside it you will insert a UIView with the frame set to the width&height you desire and with no autoresizingMask. When the tableview will resize UITableViewCell frame, this will not affect your inner UIView.
I have a UIScrollView in which vertical only scrolling is enabled. I'm displaying a grid of buttons (similar to the photo viewer image grid). The grid has to be drawn differently based on screen orientation, so that all of the screen real estate is used. Given the size of my buttons, I can fit 3 per row in portrait, and 4 per row in landscape.
I reposition all of the buttons in: willRotateToInterfaceOrientation:duration and then call: setContentSize: on my UIScrollView. Everything seems to work just fine, with the exception of the auto-scrolling that occurs after the call to SetContentSize:. In other words, let's say I was in portrait, and scrolled 3/4 of the way down the list, when I rotate to landscape, it auto-scrolls all the back up to the top.
The interesting thing is, in the same scenario, if I were to do a small flick scroll up or down, and then immediately rotate the device, the scroll view redraws correctly, and retains the current scroll position!
So, to be clear, the culprit here seems to be SetContentSize:, but obviously I have to call that for the scroll view to scroll correctly.
Any ideas on how I can retain the current scroll position?
Thanks!
You might try implementing the UIScrollViewDelegate method scrollViewShouldScrollToTop:, which tells the caller whether to scroll to the top or not. You may have to have some flag in your delegate that indicates if a rotation is underway or not, because under normal conditions you may actually want the ability to tap the status bar and have the scroll view scroll to the top.
If, on the other hand, you don't ever want the scroll view to scroll to the top automaticlly, simply implement that delegate method and have it return NO.
I had this problem, just did this and it works well for me
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//calculate percentage down scrollview currently at
float c = self.scrollView.contentOffset.y / self.scrollView.contentSize.height;
//reposition subviews in the scrollview
[self positionThumbnails:toInterfaceOrientation];
//set the new scrollview offset to the same percentage,
// using the new scrollview height to calculate
self.scrollView.contentOffset =
CGPointMake(0, c * self.scrollView.contentSize.height);
}
In my case, I have a scrollview with a fixed width to device size, and variable height
In IB I have my UIView. Then I have a sub-UIView with a UIScrollView as a sub view. Then the UIScrollView has a sub-UIImageView. The UIScrollView and UIImageView are the same size. They're much bigger than the UIView of which they are subviews. I assumed this would make scrolling work. It doesn't. Is some sort of code required for scroll views to work?
You need to set UIScrollView.contentSize to match the total scrollable size, which is your subview frame size in this case.
As mentioned in the accepted answer, you must set the UIScrollView's contentSize property.
This can be done in Interface Builder.
Select the scroll view
Select the 'identity inspect' in Utilities pane on the right
Under 'User Defined Runtime Attributes' click the '+' button
Set the 'Key Path' value to 'contentSize'
Set the 'Type' value to 'Size'
Set the 'Value' value to '{width, height}' (eg: '{320, 600}')
Build and run and your scroll view will scroll.
The content inset does not affect scrolling. See What's the UIScrollView contentInset property for?
To scroll, you have to make the scrollview's frame smaller than its content, the contained image or view.
This might be obvious to most, but I spent ages wondering why my UIScrollView wouldn't scroll so I'm posting what was stopping me in case it helps anyone else:
The UIScrollView has to be of the dimensions of the visible area in which you wish it to be presented and not the size of it's contents.
Ridiculous on my behalf I know, but just in case it helps someone.
I placed all the content of my scrollview in IB. (buttons, labels, text fields, etc). The full size is 500 tall.
I then resized it to 436 tall in IB.
Then in code, I put this is viewDidLoad:
optionsScrollView.contentSize = CGSizeMake(320,500);
So that leaves 64 pixels that I can scroll. It works perfectly.
I also placed "UIScrollViewDelegate" in the <> braces of #interface for my .h file and tied the delegate outlet of the scrollview to File's owner in IB.
I could solve the scrolling problem with the following answer:
https://stackoverflow.com/a/39945124/5056173
By me the trick was:
You now need to set the height of the content UIView. You can then either specify the height of the content view (blech) or use the
height of the controls contained within by making sure the bottom
control is constrained to the bottom of the content view.
I have set the height and width of the view inside the scrollView with center vertical and horizontal alignment and that was the reason, why it did not work!
After deleting this constraints, I need to add equal width (scrollView and the view inside the scrollView) AND I set the height of the view inside the scrollView directly with the content. Which means: The last element in the view must have a bottom constraint to the view!!
The other important thing that I don't see mentioned here is that UIScrollView does not play nicely with AutoLayout. If it seems like you've done everything correctly, check if your ViewController has autolayout turned on and, if so, turn it off.
(Every time you scroll, the views are re-laid-out. Gak!)
So:
Make sure scrollview's contentSize is bigger than its frame.size
Make sure AutoLayout for the ViewController is turned off.
more, did you enable scrolling?
look at the property
#property(nonatomic, getter=isScrollEnabled) BOOL scrollEnabled
Make sure 3 things,
checking scrollView frame & contentView frame, u may find the answer
scrollView.isScrollEnabled = true
contentView of scrollView height didn't constraint with scroll view height
UIScrollView won't scroll!
reason: contentSize is same as (sub) view
should: contentSize is large than (sub) view
-> UIScrollView can scroll
how set UIScrollView contentSize?
two method:
in code
- (void)viewDidLoad {
[super viewDidLoad];
。。。
//[(UIScrollView *)self.view setContentSize:CGSizeMake(375, 1000)];
CGSize curScreenSize = UIScreen.mainScreen.bounds.size;
CGFloat scrollWidth = curScreenSize.width;
CGFloat scrollHeight = curScreenSize.height * 2;
[(UIScrollView *)self.view setContentSize:CGSizeMake(scrollWidth, scrollHeight)];
in UI (Storyboard)
Storyboard-》Identity Inspector-》User Defined Runtime Attributes-》 add new attribute:
contentSize
Type:Size
Value:{375, 1000}
Scroll view works with this:
Frame
then
contentSize
views or objects etc...
If your frame is set to your content size then it won't scroll.
So set your frame ( in IB right panel -> second last tab 'Size Inspector") to the length of your app ( in my case it is 367 as i have a navbar and a tab bar) then programatically set the contentSize to - yup you guessed it ... more than your frame so it can scroll.
Happy days!!
When you have a sectioned, plain-style tableview on the iPhone, such as in the Contacts app, the section headers remain visible when you scroll past them until they are pushed offscreen by the next section header.
Does anyone know how to achieve something like this in an ordinary scrollview? I already have one scrollview nested in another to get horizontal paging with vertical smooth-scrolling, so I'm reluctant to add a third scrollview.
Cheers
Basically I did a bunch of maths in scrollViewDidScroll: and set the frame of the subview.
Edit:
Well my exact requirements were a bit different than the question I asked, I have a footer view as opposed to a header view. Basically in scrollViewDidScroll I have:
CGRect frame = self.footerView.frame;
frame.origin.y = MIN(self.bounds.size.height -
self.footerView.frame.size.height +
self.contentOffset.y,
self.contentSize.height);
self.footerView.frame = frame;
This ensures the footer view, which is a subview of the scroll view, is always visible at the bottom of the scroll view, and there is never a gap between the footer view and the bottom of the content view.