UIVIew Resizes on UIScrollView Scroll - ios

I am developing app in which my parent view is UIScrollView and child views are UIView and UIButton.
When i click on UIButton i am increasing the height of UIView programatically(this works fine)
But after when i scroll my scrollView my UIView resizes to its original height, i also tried changing height of UIView in scrollViewDidScroll method but it doesn't work :(
Please help..
Here is my code snippet:
- (IBAction)ButtonClicked:(id)sender {
[UIView animateWithDuration:0.8f delay:0.0f options:UIViewAnimationOptionTransitionNone animations: ^{
MyView.frame = CGRectMake(8, 243, 304, 400);
} completion:nil];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
MyView.frame = CGRectMake(8, 243, 304, 400);
}
Thanks in advance !!

You should connect left(top, width or height) constraints as IBOutlets and should change them.
Because view is re-layouted with auto layout constraints when you scroll scrollview.
So
myViewLeftConstraint.constant = 8
myViewTopConstraint.constant = 243
myViewWidthConstraint.constant = 304
myViewHeightConstraint.constant = 400
like this.

Related

Set content inset in PDFView

I am using the new PDFKit framework (https://developer.apple.com/documentation/pdfkit).
I would like, like in UIScrollView, to change the contentInset of my PDFView.
Sadly, PDFView doesn't have a property scrollView or contentInset.
Thanks a lot.
PDFView doesn't have a publicly exposed UIScrollView property, but if you iterate the subviews you should find the that first subview is a PDFScrollView (UIScrollView subclass):
UIView *firstSubview = pdfView.subviews.firstObject;
if ([firstSubview isKindOfClass:[UIScrollView class]]) {
UIScrollView *pdfScrollView = (UIScrollView *)firstSubview;
pdfScrollView.contentInset = UIEdgeInsetsMake(0, 20.0f, 0, 20.0f);
}
Otherwise the only other option I can think of is to inset the view itself:
pdfView.frame = CGRectInset(pdfView.frame, 10.0f, 10.0f);

scroll view resizing issue

I have a UIView of 320 x 900 with a scrollview in it and when keyboard shows my scroll view shrinks to 320x300 ! so far so good but when i go from a text field to another the scroll view goes back to 900 by it self. anyone can tell me what is going on ?
The keyboard will hide method works just fine as well
thank you
-(void)keyboardWasShown:(NSNotification *)notification{
NSLog(#"Keyboard is shown.");
self.scrollView.frame = CGRectMake(0, 0, 320, 300);
}
-(void)keyboardWillHide:(NSNotification *)notification{
NSLog(#"Keyboard is hidden.");
self.scrollView.frame = CGRectMake(0, 0, 320, 900);
}

layoutSubviews and animations

I am experiencing animation problems.
This is my current setup so far
I have initialized my objects (UIViews) in the
- (id)initWithFrame:(CGRect)frame method
I adjust and layer the frames of views as well as added subviews in the - (void)layoutSubviews method.
When I try to animate the views/subviews, nothing happens. Everything worked well until I moved the layering to the "initWithFrame" method, it works good.
Could somebody explain what the the cause could be and why the layered views in layoutSubviews can't be animated well?
I believe that it might be due to the hierarchy of calling methods, am I right in thinking that?
Code (subclass of UIView):
- (id)initWithFrame:(CGRect)frame
{
(...)
backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
backgroundView.backgroundColor = [UIColor whiteColor];
(...)
}
- (void)layoutSubviews
{
CGRect frame = CGRectZero;
(...)
frame = (CGRect){ 100, 100, 200, 200 };
[backgroundView setFrame:frame];
(...)
[self addSubview:backgroundView];
}
- (void)animate
{
[UIView animateWithDuration:1.0f animations:^{
backgroundView.frame = CGRectMake(100, 100, 300, 300);
} completion:^{BOOL f){
NSLog(#"w: %f h: %f", backgroundView.frame.size.width, backgroundView.frame.size.height);
}];
}
Tried to call "animate" from subview (by using [(MyClass *)self.superview animate]) as well as send notification.
Always log was
w: 200 h: 200

UIScrollView setContentSize doesn't work

I have a really big problem with UIScrollView. To make sure it wasn't my actual project, I created a NEW project, iPhone only, for iOS 6 and 7. I disabled autolayout.
I created a Tab Bar project
I created a view controller,
embedded it in a navigation controller and connected it as Tab bar
item #0
I put a UIScrollView in my view.
I connected the scrollview in the custom UIViewController created for this view.
I synthesized my IBOutlet and set the delegate to self. I also
implemented delegate in .h
Here is my code (ViewDidLoad):
self.scrollView.delegate = self;
[self.scrollView setScrollEnabled:YES];
[self.scrollView setContentSize:CGSizeMake(self.view.frame.size.width, 20000)];
NSLog(#"contentSize width %f", self.scrollView.contentSize.width);
NSLog(#"contentSize height %f", self.scrollView.contentSize.height);
NSLog(#"%#", NSStringFromCGAffineTransform(self.scrollView.transform));
It returns me "contentSize width 20000.000000", "contentSize height 0.000000
" and "[1, 0, 0, 1, 0, 0]". It scrolls left-right where it should scroll up-down
Please help!
I had the same issue until I realized I hadn't set the UIScrollView delegate. Also, if you're using auto layout, you need to wait for the layout to be applied to the UIScrollView. This means you should set the Content Size in "viewDidLayoutSubviews".
In viewDidLoad method, frame may not be correct, move the code to this method:
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
// Your code
}
Use this code. ScrollView setContentSize should be called async in main thread.
Swift:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
DispatchQueue.main.async {
var contentRect = CGRect.zero
for view in self.scrollView.subviews {
contentRect = contentRect.union(view.frame)
}
self.scrollView.contentSize = contentRect.size
}
}
Objective C:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
dispatch_async(dispatch_get_main_queue(), ^ {
CGRect contentRect = CGRectZero;
for(UIView *view in scrollView.subviews)
contentRect = CGRectUnion(contentRect,view.frame);
scrollView.contentSize = contentRect.size;
});
}
Okay, there is absolutely nothing wrong with your code. So some suggestions:
Make sure you added to your .h file like so:
#interface yourViewController : UIViewController <UIScrollViewDelegate> {
}
Try moving this snippet of code to the "viewWillLoad" method:
- (void)viewWillAppear:(BOOL)animated {
self.scrollView.delegate = self;
[self.scrollView setScrollEnabled:YES];
[self.scrollView setContentSize:CGSizeMake(self.view.frame.size.width, 20000)];
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var contentRect = CGRect.zero
for view: UIView in scrollView.subviews {
if !view.isHidden {
contentRect = contentRect.union(view.frame)
}
}
scrollView.contentSize = contentRect.size
scrollView.contentSize.width = self.view.frame.width
}
Working Swift 3.X code. Converted #Karen Hovhannisyan's answer.

UIScrollView paging enabled with content inset is working strange

I created the UIScrollView with content insets.
scrollView.frame = CGRectMake(-80, 180, 480, 190)
self.scrollView.contentInset = UIEdgeInsetsMake(0, 160, 0, 160);
self.scrollView.pagingEnabled = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];
// Add three Views
[self.scrollView addSubview:view1];
[self.scrollView addSubview:view2];
[self.scrollView addSubview:view3];
[view1 setFrame:CGRectMake(0, 0, 160, 190)];
[view2 setFrame:CGRectMake(160, 0, 160, 190)];
[view3 setFrame:CGRectMake(320, 0, 160, 190)];
At first time, scrollView.contentOffset.x was -160.0
But the weird problem is when I tap on scrollView(Yellow Area), content offset x value is resetting to 0 and shown like this.
I tried several times, but tapping on Scroll View resets the content offset to 0.
How can I prevent this?
UIScrollView paging works by scrolling pages with the same width of the scrollView (in your case pages of 480 width). This means that you have 1 single page (you'd still be able to scroll left and right due to the 160 content inset).
One way to make this work would be:
self.scrollView.frame = CGRectMake(80, 180, 160, 190);
self.scrollView.clipsToBounds = NO;
self.scrollView.contentInset = UIEdgeInsetsZero;
self.scrollView.pagingEnabled = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];
This will draw and scroll correctly, however, the sides of the screen will not be interactive (80 pixels on each side, since the control starts at frame.origin.x=80 and ends at 80+160=240).
Second option would be to handle paging yourself, by using methods provided by UIScrollViewDelegate.
- (void)viewDidLoad
{
[super viewDidLoad];
// pageIndex must be declared as a class member - this is used to prevent skipping pages during scroll
pageIndex = 0;
self.scrollView.frame = CGRectMake(0, 180, 320, 190);
self.scrollView.contentInset = UIEdgeInsetsMake(0, 80, 0, 80);
self.scrollView.pagingEnabled = NO;
self.scrollView.clipsToBounds = YES;
[self.scrollView setContentSize:CGSizeMake(480, 190)];
self.scrollView.delegate = self;
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
int pageWidth = 160;
int pageX = pageIndex*pageWidth-scrollView.contentInset.left;
if (targetContentOffset->x<pageX) {
if (pageIndex>0) {
pageIndex--;
}
}
else if(targetContentOffset->x>pageX){
if (pageIndex<3) {
pageIndex++;
}
}
targetContentOffset->x = pageIndex*pageWidth-scrollView.contentInset.left;
NSLog(#"%d %d", pageIndex, (int)targetContentOffset->x);
}
In addition to alex's first approach with setting clipsToBounds to NO, I need to react to the scroll outside of the scroll view bounds. So I created ScrollForwarderView class which is subclass of UIView.
ScrollForwarderView.h
#import <UIKit/UIKit.h>
#interface ScrollForwarderView : UIView
#property (nonatomic, weak) UIScrollView *scrollView;
#end
ScrollForwarderView.m
...
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([self pointInside:point withEvent:event]) {
return _scrollView;
}
return nil;
}
Then place UIView with custom class ScrollForwarderView above the scroll view, link scrollView property to my scroll view and it nicely forwarded the user events to scrollview.

Resources