Reputation:
UIView,SegmentedController & UIContainerView in a ScrollView or something similar?
In my storyboard I have a VC containing a UIView at the top, segmented controller in the middle & 2 ContainerViewControllers at the bottom with embeded segue's to new VC's.
In the new VC's I have a TableView & a CollectionView (For example, the Instagram profile).
My issue is that I need the SegmentedController and UIView to scroll with the ContainerView(TableView/CollectionView), at the moment only the ContainerView part scrolls and the parts above that are fixed.
Now I'm guessing I probably need to put everything into a UIScrollView, so I tried that & placed all the costraints correctly. But when It came to configuring it in the Swift file, I only really now how to set the height of the scroll but oviously the height I need can vary and isn't a fixed height!
If anyone can help me here that would be fantastic, or maybe point me towards a similar question already asked here? I have already looked, but did not find anything unfortunately!
Here's an image below explaining basically what I'm after, if above I wasn't very clear..
here is an example you can see: https://github.com/Jackksun/ScrollIssue
Upvotes: 13
Views: 3198
Reputation:
So as I understood, you want to make your scroll view receive touches outside its bounds. You can achieve this by overriding hitTest:withEvent: method on the view that is actually receiving touches.
Here is an example of what I did in my project. I subclassed UIView and redirected all touches it was receiving to the specific view. In your case, you will redirect all the touches to scroll view.
.h file:
@import UIKit.UIView;
/*!
@class TouchableView
@abstract Touchable view.
*/
@interface TouchableView : UIView
/*!
@property viewToReceiveTouches
@abstract View that receives touches instead of a given view.
*/
@property (nonatomic, weak) IBOutlet UIView *viewToReceiveTouches;
@end
.m file:
@import UIKit.UIButton;
@import UIKit.UITableView;
@import UIKit.UITextField;
#import "TouchableView.h"
@implementation TouchableView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if ( [self shouldViewReceiveTouch:self inPoint:point] )
{
return [super hitTest:point withEvent:event];
}
else if ( CGRectContainsPoint(self.bounds, point) && self.isUserInteractionEnabled )
{
return self.viewToReceiveTouches;
}
return nil;
}
- (BOOL)shouldViewReceiveTouch:(UIView *)view inPoint:(CGPoint)point
{
if ( !CGRectContainsPoint(view.bounds, point) || !view.isUserInteractionEnabled )
{
return NO;
}
if ( [view isKindOfClass:[UIButton class]] ||
[view isKindOfClass:[UITextField class]] ||
[view isKindOfClass:[UITableViewCell class]] ||
[view isKindOfClass:[UITableView class]] )
{
return YES;
}
for ( UIView *subview in view.subviews )
{
if ( [self shouldViewReceiveTouch:subview inPoint:[view convertPoint:point toView:subview]] )
{
return YES;
}
}
return NO;
}
@end
Upvotes: 2
Reputation: 1514
Since your height can vary, the easiest way in my opinion to do what you want is to put everything in a UICollectionView
.
Segue? No problem, implement didSelectRowAtIndexPath
, change your datas and height and reload the UICollectionView
.
You can also add the UICollectionView
to a simple UIView
, that will allow you to put some static content on top of it.
Here is a sample app to demonstrate this : https://github.com/tirrorex/Apps/tree/master/Swift/Sampleapp
You will have to implement a dynamic height, you can find some threads on this (basically you can make a special case for the cell containing your collectionview/tableview so that this cell will be load from nib, that might help you): UICollectionView Self Sizing Cells with Auto Layout
Upvotes: 1
Reputation: 1147
You can set dynamic size for the scrollview content. Here what I did.
dynamicHeight
to store your new TableView/CollectionView height. Take a look at my code (demo here)
@IBAction func selectPage(sender: AnyObject) {
// clear all child controller before load new controller
for controller in childViewControllers {
controller.removeFromParentViewController()
}
for view in pageContainer.subviews {
view.removeFromSuperview()
}
let segment = sender as! UISegmentedControl
if segment.selectedSegmentIndex == 0 {
createImageController()
}
else {
createTextController()
}
updateScrollContentSize()
}
func updateScrollContentSize() {
// 150 is your view and segment height
scrollView.contentSize = CGSize(width: view.frame.size.width, height: dynamicHeight + 150)
}
func createTextController() {
let textController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("TextController") as! TextController
dynamicHeight = textController.getTableContentHeight()
textController.tableView.scrollEnabled = false
self.addChildViewController(textController)
pageContainer.addSubview(textController.view)
textController.view.frame = CGRectMake(0, 0, pageContainer.frame.size.width, dynamicHeight)
}
func createImageController() {
let imageController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ImageShowController") as! ImageShowController
dynamicHeight = imageController.getTableContentHeight()
imageController.tableView.scrollEnabled = false
self.addChildViewController(imageController)
pageContainer.addSubview(imageController.view)
imageController.view.frame = CGRectMake(0, 0, pageContainer.frame.size.width, dynamicHeight * 2)
}
Hope this can help.
Upvotes: 1