Change custom UIView to UIScrollView - ios

In general:
I got a custom UIView with a xib file as subview on a UIViewController. I add the subview programmatically in my controller.
In my UIViewController:
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"MyCustomSubView" owner:self options:nil];
mySubView = [subviewArray objectAtIndex:0];
...
[self.view addSubview:mapView];
Because I need to scroll on this subview, which also have an UIImageView on it, I decided to change my custom UIView into an UIScrollView.
I did the following steps:
Changed the MyCustomSubView.xib, added an UIScrollView with Custom Class MyCustomSubView (and an UIImageView on it like before)
Changed my MyCustomSubView class to extend UIScrollView
Changed my MyViewController to implement UIScrollViewDelegate
set mySubView.delegate to self(the controller)
implemented (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView and returned the UIImageView of the subview
enabled user interaction on the imageview and on the uiscrollview
These were my total steps I think. But as example, the viewForZoomingInScrollView method wasn't called. Also I tried to zoom in, but nothing happened.
Anyone an idea, what could be wrong?

Looking briefly at the UIScrollView Class Reference page, I see the following:
The UIScrollView class can have a delegate that must adopt the UIScrollViewDelegate protocol. For zooming and panning to work, the delegate must implement both viewForZoomingInScrollView: and scrollViewDidEndZooming:withView:atScale:; in addition, the maximum (maximumZoomScale) and minimum ( minimumZoomScale) zoom scale must be different.
You mentioned implementing viewForZoomingInScrollView:, but not scrollViewDidEndZooming:atScale:, nor did you mention setting maximumZoomScale or minimumZoomScale. Try doing those things, and check back if you're still having issues.

Related

How to add an UIView from a XIB file as a subview to another Xib file

I am trying to add a custom UIView that I created in XIB, to my view controller in my main.storyboard as a subview. How can I do this?
matchScrollView (tag 1) is the UIScrollView in view controller in main.storyboard, while matchView (tag 2) is the custom UIView I created in another XIB file.
With the press of a button i want to have the custom UIView added to the UIScrollView as a subview. But how can i actually make it show up on display? I guess i have yet to alloc and init it, along with indicate position and such, but how can i do that? I tried different ways without success. I can create UIViews programmatically, but have yet to find a way to just load the UIView from XIB.
-(IBAction) buttonTapped:(id)sender {
UIScrollView *matchScrollView = (UIScrollView *) [self.view viewWithTag:1];
UIView *matchView = (UIView *) [self.view viewWithTag:2];
[matchScrollView addSubview:matchView];
}
The reason that I am creating my custom UIView in another XIB file instead of directly implementing it on my main.storyboard view controller, is because I want to re-use the same view multiple times. So the UIScrollView has a numerous subviews of UIViews.
I was hoping I could create numerous instances of MatchView and add them all to matchScrollView as subviews.
The issue you are having is completely normal. The way Apple designed it doesn't allow to reuse custom views with their own xib into other xibs.
Lets say you have a custom view named HeaderView with a custom xib named HeaderView.xib. And lets say you want to be able to, in another xib named GlobalView.xib, drag a subview and specify its class to be of type HeaderView expecting it to load that view from HeaderView.xib and insert it inplace. You can do it like this:
A) Make sure File's Owner in HeaderView.xib is set to be HeaderView class.
B) Go to your GlobalView.xib, drag the subview and make it of class HeaderView.
C) In HeaverView.m implement initWithCoder, if after loading the view there aren't subviews means it got loaded from GlobalView, then load it manually from the correct nib, connect the IBOutlets and set the frame and autoresizingmasks if you want to use the GlobalView's frame (this is usually what you want).
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self.subviews.count == 0) { //means view got loaded from GlobalView.xib or other external nib, cause there aren't any subviews
HeaverView *viewFromNib = [[NSBundle mainBundle] loadNibNamed:#"HeaverView" owner:self options:nil].firstObject;
//Now connect IBOutlets
self.myLabel1 = viewFromNib.myLabel1;
self.myLabel2 = viewFromNib.myLabel2;
self.myLabel3 = viewFromNib.myLabel3;
[viewFromNib setFrame:self.bounds];
[viewFromNib setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[self addSubview:viewFromNib];
}
return self;
}

UIView in a custom xib

I created a UIView in a separate subclass of UIView and with an xib.
I have a UIViewController with a UIView in storyboard and I want to set custom UIView to this UIView.
I modified class name in storyboard UIView to the class name of custom UIView. I am getting the UIView on the result but with the frame size of custom UIView. I added correct constraints in the custom xib. and some touch gestures not working as desired because of the wrong frame etc.
Please suggest me if anything wrong I did.
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// Load the UIView from Interface Builder
[[NSBundle mainBundle] loadNibNamed:#"TMPhotoEdit" owner:self options:nil];
// Add UIView to current UIView object.
[self addSubview:self.view];
}
return self;
}
self.view is the same view object I created a variable for it.
I want the frame to set as same as the one i am using in storyboard.
Solution to get it work using code also helps me a lot. I mean, without IBOutlet in storyboard, just adding this UIView with some frame set to it.
If I call initWithFrame, I can't set the xib like what I am doing with initWithCoder above and initWithCoder is not being called if I use initWithFrame in code.
Assuming you have an instance of the view you want to resemble in size
self.view.frame = CGRectMake(otherView.frame.x, otherView.frame.y, otherView.frame.width, otherView.frame.height);
Actually what you are doing is not correct but anyway you should load the custom view nib like this
self.view = [[NSBundle mainBundle] loadNibNamed:#"TMPhotoEdit" owner:self options:nil][0];
Again this is not correct, why do you need it anyway? but it shall solve your nib loading issue.

UITableView contentOffset behaving oddly

I have a UIViewController which has multiple UIViews that enter from off the screen. Rather than initializing and designing all those UIViews in the UIViewController, I created separate nib files with corresponding .h/.m files which just get preloaded.
In one of the custom UIViews, I have a UITableView with a header UIView. I'm trying to have this header hidden under another component I have in the original UIViewController that this UIView will slide into. I initially worked this out using a sample project with [self.tableView setContentOffset:CGPointMake(0, 44) animated:NO];, but that was just in a UITableViewController.
For some reason, this does not work for a subclassed UIView. I've tried setting the tableView's content offset in both - (id)initWithCoder:(NSCoder *)aDecoder and - (void)layoutSubviews and I've been checking whether the offset was actually set in tableView:cellForRowAtIndexPath: by
NSLog(#"tableView Content Offset: %#", NSStringFromCGPoint(self.tableView.contentOffset));
but it just returns
tableView Content Offset: {0, 0}
The interesting thing is that if I set the contentOffset in tableView:cellForRowAtIndexPath: it works! But I know I shouldn't be setting it there. Could someone explain to me where and how I should be implementing this when loading a UITableView from a custom nib which is only a subclassed UIView? I can post all the code if you think it'll help.
Additional Info:
Question: how are you loading the view from the nib ? – MAB
UIView *newView = [[[NSBundle mainBundle] loadNibNamed:#"ProfileCostTableViewController" owner:self options:nil] objectAtIndex:0];
I subclassed UITableView to see when the contentOffset is being rest to {0,0}. it seems its a call in ios7 from the private method : _adjustContentOffsetIfNecessary. Since this method is not documented I don't see how to prevent it from changing the offset, so I think the workaround is to change the offset after a delay or in - (int) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section.
You're adding your view using addSubview: which triggers the methods: - (void)willMoveToSuperview:(UIView *)newSuperview I think if you put your code there it should work.

uiscrollview's unusual contentsize property

I am quite new to iOS application development.
I was working with UIScrollView and found very strange behavior. Hope somebody could explain this to me.
I tried the two methods and found the outputs different.
1). UIScrollView is added to my view in the Interface Builder, and a view (UIView) is also added to the scrollview earlier. I set the view's bounds manually in the IB, and set the scrollview's content size in the class file.
Observation : The scrollview doesn't scroll with the setcontentsize, rather takes some unusual content size, independent of anything else, even its own bounds.
2). The same UIScrollView is again added in the Interface Builder, but the view is added this time programmatically.
Observation : This time everything works out quite good.
I don't understand what could have gone wrong.
Can anyone explain and elaborate
I'm not sure exactly what your problem is, but if you want to be able to add views to a UIScrollView in IB, create a UIScrollView subclass and do something like this:
- (void)awakeFromNib
{
[super awakeFromNib];
CGRect bounds = CGRectZero;
for (UIView* view in self.subviews)
{
bounds = CGRectUnion(bounds, view.frame);
}
[self setContentSize:bounds.size];
}

UIScrollView or UIImageView?

I need to place a photo in the screen and it should be able to be scrolled or zoomed,
I know UIScrollView does these, so I alloced one, but how about my photo?
I guess I should not just set the photo as the backgroundColor of my UIScrollView, and I haven't found any property of UIScrollView, in the document, to hold an image, such as "imageView", "contentView", or something like that.
So, what should I do to make a picture in my screen and make it able to respond to finger touches?
Thanks a lot!
Add the UIImageView to the UIScrollView and set the min/max scale value to it.
Then implement the following UIScrollViewDelegate function.
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return yourImageView;
}
If you want to have multiple items scaled, add all the view into a UIView, and put that UIView inside the UIScrollView. Of course you have to change the return view to that UIView in the above function.
Just add your UIImageView as a subview of the UIScrollView. Also, set the scroll view's contentSize property to be equal to the size of the image view's frame.
THe scrollView is the first step.
Then you should add a UIImageView and load an image inside.
You need also to set the max e min zoomScale properties of the scrollview
And you must implement the scrollview delegate method – viewForZoomingInScrollView:

Resources