I am developing an app in which user can add some icons like hat, hair on the captured picture.For this I have a image view on the screen to hold the captured image and below this I have a scrollview to display various icons that user can apply.
When I tap any icon placed inside the scroll view, I need to move this icon to the center captured picture, but when I tried it with code this sets the image to the center of the scroll view not the entire view.
But when I remove the scroll view and put the image outside the image view this works. Please suggest.
//In view Did Load
//*************************************adding gusture******************************
//SINGLETAP
UITapGestureRecognizer *singleTapGestureRecognizer_For_image15 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTapAction_For_Image_15:)];
singleTapGestureRecognizer_For_image15.numberOfTapsRequired = 1;
[self.image_15 addGestureRecognizer:singleTapGestureRecognizer_For_image15];
//DOUBLE TAP
UITapGestureRecognizer *doubleTapGestureRecognizer_For_image15 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTapAction_For_Image_15:)];
doubleTapGestureRecognizer_For_image15.numberOfTapsRequired = 2;
[self.image_15 addGestureRecognizer:doubleTapGestureRecognizer_For_image15];
//End Image 15
//***********************************Handling Tap
//SIngle TAP
-(void)handleSingleTapAction_For_Image_15:(UITapGestureRecognizer *)handleSingleTapAction_For_Image_15{
CGSize newSize = CGSizeMake(250.0, 250.0);
CGPoint currentCenter = self.view.center;
self.image_15.frame = CGRectMake(self.image_15.frame.origin.x, self.image_15.frame.origin.y, newSize.width, newSize.height);
self.image_15.center = currentCenter;
}
//Double Tap
-(void)handleDoubleTapAction_For_Image_15:(UITapGestureRecognizer *)doubleTapGestureRecognizer_For_image15
{
CGSize newSize = CGSizeMake(40.0, 40.0);
CGPoint currentCenter = self.view.center;
self.image_15.frame = CGRectMake(self.image_15.frame.origin.x, self.image_15.frame.origin.y, newSize.width, newSize.height);
self.image_15.center = currentCenter;
}
You are setting the center of the image from the self.view's center but I think you also have to take care of the scrollview frame offset from origin. So your image_15 center should be set like
self.image_15.center = CGPointMake(currentCenter.x-yourScrollView.frame.origin.x, currentCenter.y-yourScrollView.frame.origin.y);
(provided scrollview is also a direct subview of self.view)
I can refine my answer if you provide me details about your view hierarchy incode.
Related
I would like to emulate the swipe to left to show next picture seen in the photos app, among other places so that the new picture slides in from right to left using animation.
However, in my case, the view has more than one photo. It has a caption as well.
I am able to do this without animation by just updating the photo and text upon swipe. This just changes the photo and caption on screen, however, without the right to left animation technique.
Is there a way to show the old view moving to the left while the new updated view moves in from the right.
The following moves the view to the left but renders the screen black as nothing is put in its place.
//In handleSwipe called by gesture recognizer
CGRect topFrame = self.view.frame;
topFrame.origin.x = -320;
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.view.frame = topFrame; _myImage=newImage;
_mycaption=newcaption;} completion:^(BOOL finished){ }];
Thanks for any suggestions.
Edit:
The view in question is a detail view that you get to from a tableview through a segue. It currently already uses a scrollview for vertical scrolling as the content can exceed a single screen in the vertical dimension.
I have found a way to get the old photo and caption to move left and the new to come in from right using a completion block, however, it is less than satisfactory, because there is a gap between the two actions when the screen is black. This seems endemic to completion approach because new image does not start to move until old image has completed moving.
- (IBAction)swipedLeft:(id)sender
{
CGRect initialViewFrame = self.view.frame;
CGRect movedToLeftViewFrame = CGRectMake(initialViewFrame.origin.x - 375, initialViewFrame.origin.y, initialViewFrame.size.width, initialViewFrame.size.height);
CGRect movedToRightViewFrame = CGRectMake(initialViewFrame.origin.x + 375, initialViewFrame.origin.y, initialViewFrame.size.width, initialViewFrame.size.height);
[UIView animateWithDuration:0.1
animations:^{self.view.frame = movedToLeftViewFrame;
//above moves old image out of view.
}
completion:^(BOOL finished)
{
self.view.frame = movedToRightViewFrame;
[self loadNextItem];//changes pic and text.
[UIView animateWithDuration:0.1
animations:^{self.view.frame = initialViewFrame;
//moves new one in
}
completion:nil];
}];
}
I suggest using a UIPageViewController, and manage each image/set of images as a separate view controller.
A page view controller supports either a page curl style transition or a slide transition. You'd want the slide transition.
Three ways to build this using existing components:
UIPageViewController (see DuncanC's answer).
UICollectionView with pagingEnabled set to true. Use a full-screen-sized cell and a UICollectionViewFlowLayout with scrollDirection set to horizontal.
UICollectionView as above, but instead of setting pagingEnabled to true, implement scrollViewWillEndDragging:withVelocity:targetContentOffset: in your delegate. This allows you to have a gutter between each cell while still having each cell fill the screen. See this answer.
It's ScrollView+PageControl
I hope it can help you.
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.delegate =self;
self.scrollView.translatesAutoresizingMaskIntoConstraints =NO;
self.scrollView.pagingEnabled =YES;
self.scrollView.contentSize =CGSizeMake(ViewWidth*VIewCount, ViewHeight);
[self.view addSubview:self.scrollView];
self.pageControl = [[UIPageControl alloc] init];
self. pageControl.translatesAutoresizingMaskIntoConstraints =NO;
[self.view addSubview:self.pageControl];
self. pageControl.numberOfPages = VIewCount;
self.pageControl.currentPage = 0;
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0f
constant:0.0f]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"[self.scrollView(width)]"
options:0
metrics:#{#"width":#(ViewWidth)}
views:NSDictionaryOfVariableBindings(self.scrollView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[self.scrollView(height)]"
options:0
metrics:#{#"height":#(HEIGHT_VIEW)}
views:NSDictionaryOfVariableBindings(self.scrollView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[_scrollView]-5-[pageControl(15)]"
options:NSLayoutFormatAlignAllCenterX
metrics:nil
views:NSDictionaryOfVariableBindings(self.scrollView, self.pageControl)]];
//[imgArr addObject:[UIImage imageNamed:...]];
for (NSInteger index = 0; index<ViewCount; index++) {
UIImageView *addSubview = [[UIImageView alloc] initWithFrame:CGRectMake(index*ViewWidth, 0, ViewWidth, ViewHeight)];
// addSubView.image = [imgArr objectAtIndex:index];
[self.scrollView addSubview:addSubview];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSInteger currentOffset = scrollView.contentOffset.x;
NSInteger index = currentOffset / ViewWidth;
if (currentOffset % ViewWidth == 0) {
pageControl.currentPage = index;
}
}
I am having some problems placing a UIActivityIndicator inside a UIButton.
Here is how it looks like:
And this is what i always get:
with this code:
self.activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
CGFloat halfButtonHeight = self.updateEventButton.bounds.size.height / 2;
CGFloat buttonWidth = self.updateEventButton.bounds.size.width;
self.activityView.center = CGPointMake(buttonWidth - halfButtonHeight , halfButtonHeight);
[self.subSubView addSubview:self.activityView];
[self.activityView startAnimating];
I want the indicator to be in the buttom of the right corner. Just look where the indicator is right now and think if you dragged it down to the button and then a little to the right.
Here is how my view is setup:
You are calculating indicator position in coordinate system tied to the button, but then add it as a subview to the different view so coordinates are incorrect. To fix that you can add indicator view to the button directly:
[self.updateEventButton addSubview:self.activityView];
Or convert point in button's coordinate system to the coordinate system of self.subSubView before setting it to activityView:
CGPoint centerInButton = CGPointMake(buttonWidth - halfButtonHeight, halfButtonHeight);
self.activityView.center = [self.updateEventButton convertPoint:centerInButton
toView:self.subSubView];
What I am trying to do is: I have an UIImageView inside a UIScrollView for Zooming purposes. Now when I zoom out, I should be able to move/pan the image anywhere on the screen. For this I have a UIscrollView (parent) which has the UIScrollview(child) with the Image.
The code I used is:
void SetTestImageSettings()
{
//mainScrollView is Parent scrollview.
mainScrollView = new UIScrollView (
new RectangleF (this.mainImgView.Frame.X, this.mainImgView.Frame.Y, this.mainImgView.Frame.Width +50
, this.mainImgView.Frame.Height +50));
mainScrollView.ContentSize = new SizeF (mainScrollView.Frame.Width + 500, mainScrollView.Frame.Height + 500);
mainScrollView.BackgroundColor = UIColor.Red;
mainScrollView.ContentMode = UIViewContentMode.Center;
//I tried implementing these events, but I am not sure, what to set, I mean I know I should add contentOffset, but what value?
mainScrollView.WillEndDragging += HandleWillEndDragging;
mainScrollView.DraggingEnded += HandleDraggingEnded;
// create our scroll view that has Image
scrollView = new UIScrollView (
new RectangleF (this.mainImgView.Frame.X, this.mainImgView.Frame.Y, this.mainImgView.Frame.Width
, this.mainImgView.Frame.Height - toolBar.Frame.Height));
mainScrollView.AddSubview (scrollView);
View.AddSubview (mainScrollView);
// create our image view
imageView = new UIImageView (mainImage);
scrollView.ContentSize = imageView.Image.Size;
scrollView.ContentMode = UIViewContentMode.Center;
scrollView.ShowsHorizontalScrollIndicator = false;
scrollView.ShowsVerticalScrollIndicator = false;
scrollView.AddSubview (imageView);
// set allow zooming
scrollView.MaximumZoomScale = 3f;
scrollView.MinimumZoomScale = .1f;
scrollView.ViewForZoomingInScrollView += (UIScrollView sv) => { return imageView; };
}
Now every time, I drag ends, the child crollview(with image) bounces back at top left corner.
Any help would be appreciated. Also any Objective-C developer's help too would be appreciated. I hope I sound sane and clear with my issue.
Thanks in advance.
The alternative I used is: I got rid of the UIScrollview and added gestures on the UIImageView itself. Pan, and Pinch gesture, where I can zoom, and also Pan/move my image on the screen. It is simpler now, and also under my control :)
I would like to replicate the exact same didSelect animation / segue when you tap a photo in the iPhone's photo app (or in almost every so other app) where the photo enlarges from the cell itself into a modal view controller, and minimizes to wherever it belongs to in the grid when dismissed.
I tried googling but couldn't find any articles about this.
There are many public repos on git that could probably do what you want. Some stuff I've found:
https://github.com/mariohahn/MHVideoPhotoGallery
https://github.com/mwaterfall/MWPhotoBrowser
Those may be overly complicated. Another option is creating a UIImageView at the same place as the cell and then animating it to fill the screen. This code assumes the collectionView has an origin at (0,0), if not then simply add the collectionView's offset when calculating the initial frame.
collectionView.scrollEnabled = false; // disable scrolling so view won't move
CGPoint innerOffset = collectionView.contentOffset; // offset of content view due to scrolling
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0] ];
CGRect cellRect = attributes.frame; // frame of cell in contentView
UIImageView *v = [[UIImageView alloc] initWithFrame:CGRectMake(cellRect.origin.x - innerOffset.x, cellRect.origin.y - innerOffset.y, cellRect.size.width, cellRect.size.height)];
[self.view addSubview:v]; // or add to whatever view you want
v.image = image; // set your image
v.contentMode = UIViewContentModeScaleAspectFit; // don't get stupid scaling
// animate
[UIView animateWithDuration:0.5 animations:^{
[v setFrame:[[UIScreen mainScreen] bounds]]; // assume filling the whole screen
}];
It's not the nice popping animation but it should still look ok.
I design the scrollview in interface builder like this
It looks good here. But unfortunately when I run it on emulator or device
it becomes
The content in scrollview is expand outside scrollview itself and even though outside UIView that contains this scrollView.
In my viewDidLoad (panel is the container of scrollView )
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat adjustPanelHeight = [PTTScreenScaleUtil getAdjustHeight:self.panel.frame.size.height];
CGRect panelRect = self.panel.frame;
panelRect.size.height = adjustPanelHeight;
self.panel.frame = panelRect;
UIImage *image = [UIImage imageNamed:#"panel-background"];
UIGraphicsBeginImageContext(self.panel.frame.size);
[image drawInRect:CGRectMake(0, 0, self.panel.frame.size.width, adjustPanelHeight)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.panel setBackgroundColor:[UIColor colorWithPatternImage:newImage]];
NSLog(#"scrollView Height : %f", self.scrollView.frame.size.height);
NSLog(#"scrollView contentSize Height : %f", self.scrollView.contentSize.height);
// CGRect scrollViewRect = self.scrollView.frame;
// CGRect scrollViewContentRect = self.scrollView.frame;
// NSLog(#"ScrollView Height Before : %f , After : %f", self.scrollView.frame.size.height, [PTTScreenScaleUtil getAdjustHeight:self.scrollView.frame.size.height]);
// scrollViewRect.size.width = 280;
// scrollViewRect.size.height = [PTTScreenScaleUtil getAdjustHeight:270];
// self.scrollView.frame = scrollViewRect;
// [self.detailsLabel sizeToFit];
UIView *view = [[self.scrollView subviews] objectAtIndex:0];
// [view sizeToFit];
// [self.scrollView setContentMode:UIViewContentModeScaleAspectFit];
// NSLog(#"ContentSize Height : %f", view.frame.size.height);
// scrollViewContentRect.size.height = view.frame.size.height;
NSLog(#"Bounds : %f", view.bounds.size.height);
self.scrollView.frame = CGRectMake(10, 10, 280, 270);
self.scrollView.contentSize = CGSizeMake(280, 500);
NSLog(#"Frame Height %f", self.scrollView.frame.size.height);
//[self.scrollView setContentSize: CGSizeMake(280, 1000)];
CGRect termBtnRect = self.termBtn.frame;
CGRect mailBtnRect = self.mailBtn.frame;
CGRect twitterBtnRect = self.twitterBtn.frame;
CGRect fbBtnRect = self.fbBtn.frame;
termBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
mailBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
twitterBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
fbBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
self.termBtn.frame = termBtnRect;
self.mailBtn.frame = mailBtnRect;
self.twitterBtn.frame = twitterBtnRect;
self.fbBtn.frame = fbBtnRect;
}
All the log return 270.0
PS. the scroll bar is correct even though the content goes outside but the scroll bar is working correctly (stay in the scrollview's frame as arrange in interface builder)
I have no idea how can I solve this.
Anyone help me please.
Thanks you.
Solve it by creating new view controller in interface builder and redo the same process with careful and bingo. It works.
When I compare both two view controller I realise that the wrong one UIScrollView Clip Subviews is unchecked. When check it the problem solve.
I just struggled with this for an hour and had a head smack moment.
In my case, I had a UIView on the scene in the Storyboard. At some point I decided I needed it to be a UIScrollView instead (as opposed to the original plan which was to embed the UIScrollView in a UIView)
I went ahead and changed the class on the UIView to UIScrollView. IB changed it to Scroll View in the Document Outline, I figure I'm good, right?
And then I see the behavior you describe.
At some point it hits me that this isn't sufficient. Apparently adding a UIScrollView via IB does some things differently than adding a UIView and just changing class isn't enough. And this is probably the reason re-doing it from scratch fixed it for you.
So for anyone who runs into this in the future, make sure you added the UIScrollView via IB instead of a UIView
I was having the same problem as described in this post. I tried multiple combinations of solutions that did not work, including:
putting the scroll view inside a view with Clip To Bounds = YES
putting a view inside the scroll view with Clip To Bounds = YES, that then contained my child view
putting a Container View inside the scroll view, and then embedding my subview
rebuilding the Interface Builder files completely
every combination of autosizing mask options systematcially for both the scroll view and container view
clip to bounds enabled or disabled for every single element systematically
The child view in question had previously worked inside a scroll view, but wouldn't in this one case where the content blew outside the bounds of the scroll view.
In the end, I implemented the solution in code as I could find no way to get Interface Builder to co-operate:
// There are two scroll areas on the screen, the left view and the right view.
// We want the right view to contain a scrollable area with another child view controller
// we designed in Interface Builder.
// create a scroll view to fill the right view with a scrollable area
CGSize rightFrameSize = self.rightView.bounds.size;
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake (0, 0, rightFrameSize.width, rightFrameSize.height)];
scrollView.contentSize = CGSizeMake(640, 1352);
[self.rightView addSubview:scrollView];
// now create our child view controller from Interface Builder and add it to the scroll view
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"CustomerAddress" bundle:[NSBundle mainBundle]];
detailsView = [sb instantiateViewControllerWithIdentifier:#"CustomerDetailsView"];
detailsView.delegate = self;
detailsView.customer = _customer;
[scrollView addSubview:detailsView.view];
You could of course get the scrollView.contentSize from the child view controller you constructed in Interface Builder using scrollView.contentSize = detailsView.view.frame.size.
I have a love/hate relationship with Interface Builder... most days I love it, but some days we argue and I wish we'd never met... :)
only make cliptobound=YES in storyboard if you changed UIView to UIScrollView