What I want to achieve: I want to create a copy of selected view.
I have two UIImageViews on UIView. I am selecting both the views and want to clone both the views.
Everything is working fine until I am not rotating the UIImageView. If am rotating the view UIImageView changing its frame.
UIView *viewClone = [[UIView alloc]initWithFrame:CGRectMake(fltLeadingMin, fltTopMin, fltCloneViewWidth, fltCloneViewHeight)];
viewClone.backgroundColor = [UIColor redColor];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(handlePan:)];
[viewClone addGestureRecognizer:panGesture];
for (UIImageView *imgView in arrSelectedViews) {
NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:imgView];
UIImageView *imgViewClone = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
imgViewClone.frame = CGRectMake(imgViewClone.frame.origin.x - viewClone.frame.origin.x, imgViewClone.frame.origin.y - viewClone.frame.origin.y, imgView.frame.size.width, imgView.frame.size.height);
imgViewClone.backgroundColor = UIColor.blueColor;
[viewClone addSubview:imgViewClone];
}
Here is a screenshot of how it looks like now:
After rotating the image, its frame won't work anymore and that's the reason for your issue.
You can take a look at Apple document for UIView's transform property
When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.
The solution for this situation is using center and transform properties instead of frame.
UIView *viewClone = [[UIView alloc]initWithFrame:CGRectMake(fltLeadingMin, fltTopMin, fltCloneViewWidth, fltCloneViewHeight)];
viewClone.backgroundColor = [UIColor redColor];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(handlePan:)];
[viewClone addGestureRecognizer:panGesture];
for (UIImageView *imgView in arrSelectedViews) {
NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:imgView];
UIImageView *imgViewClone = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
// This is the frame before you rotate image, can be replace with another size
CGRect originalFrame = CGRectMake(0, 0, 200, 200);
imgViewClone.frame = originalFrame
// Using center and transform instead of current frame
imgViewClone.center = imgView.center;
imgViewClone.transform = imgView.transform;
imgViewClone.backgroundColor = UIColor.blueColor;
[viewClone addSubview:imgViewClone];
}
Related
I created arrays of imageViews in UIScrollView programmatically and made then user interacted by assigning them tap gesture. Now, I want to differentiate, which image view is clicked so that I can get images from clicked imageView. However, I was unable to assign them different tag. Here is my code. I am adding 15 images Views.
for (int i = 0; i < 15; i++) {
originx = ((_imageView.frame.size.width+5)*i); //Calculate origin x for each image view.
_imageView = [[UIImageView alloc]initWithFrame:CGRectMake(originx, self.view.frame.origin.y+5, imageViewHeightWidth, imageViewHeightWidth)];
[_imageView setBackgroundColor:[ UIColor colorWithRed:191.0/255.0 green:65.0/255.0 blue:78.0/255.0 alpha:0.5]];
//_imageView.layer.cornerRadius = 10.0;
_imageView.image = [UIImage imageNamed:[_imgArray objectAtIndex:i]];
//Enabling user interaction for gesture.
[_imageView setUserInteractionEnabled:YES];
[_imageView setMultipleTouchEnabled:YES];
//Tap Gesture enabled.
_gesture =[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapTheImage:)];
_gesture.numberOfTapsRequired = 1;
//Add a tap gesture.
[_imageView addGestureRecognizer:_gesture];
//Assigning the tag to image View.
_imageView.tag = 200+i;
//Adding image in to scroll view.
[_gallaryScrollView addSubview:_imageView];
}
//Here i am getting same tag value for every imageView. i.e. "214".
-(void)tapTheImage:(id)sender
{
NSLog(#"The tag value of imagView is%ld",(long)[_imageView tag]);
}
Change TapTheImage method
-(void) TapTheImage:(UITapGestureRecognizer *)gestureRecognizer{
//Get the View
UIImageView *tableGridImage = (UIImageView*)gestureRecognizer.view;
NSLog(#"%d",tableGridImage.tag);
}
You are not creating a new object of UIImageView.
Change the line
_imageView = [[UIImageView alloc]initWithFrame:CGRectMake(originx, self.view.frame.origin.y+5, imageViewHeightWidth, imageViewHeightWidth)];
to
UIImageView *_imageView = [[UIImageView alloc]initWithFrame:CGRectMake(originx, self.view.frame.origin.y+5, imageViewHeightWidth, imageViewHeightWidth)];
I'm new to the iOS UI development and I need some help to figure out, what is the best way to implement image belt (sequence of images in horizontal belt). I don't need details (someone to write me the code), just guidance what I should focus on learning as a libraries and most important design patterns (by design patters I mean software design for iOS UI).
The task details:
1. I will have image belt - sequence of few related images. This will be my horizontal transition. The transition animation will be simple push animation (something like push CATransion), initiated by swipe left/right. On top of the images there will be overlay with some text, icon info and etc. The overlay info will be the same for all images in the current belt.
2. I will have multiple image belts - this will be my vertical transition. The transition between belts will be triggered by swipe up/down. The different belts will contain unrelated information, so the information shown in overlays from point 1 must be also changed. The animation will be also simple push animation as in point 1.
I probably should inherit UIView and implement my belt as one object, which will consist of different UIView(overlay) and UIImageViews(for the images). Am I on the right track?
Some helpful brainstorm will be highly appreciated.
Yes - I've done many of these. You add a UIView above the top view. I usually use a full-screen one with some alpha so they can see through the core content a little. Then add stuff on top of that which won't change: things like your text, icons, etc... Then on top of that you put the image you want to swipe and add a swipe gesture recognizer, typically one for left and one for right. When they swipe you init a new UIView off the edge of the device, init it with the image, and animate the frames of both left or right, depending on which way they've swiped. Mine are help tutorials showing how to use my app step-by-step so I also init multi-part animations on some of the frames that fly in; that's a nice looking optional effect. Here's the one I use (with the animation support stripped out or it'd be too much code) and there's lots of variations. Edited to note my app doesn't support rotation but if yours does you have to adjust the frames after a rotation.
- (void)init
{
currentPanelNumber = 10;
self = [super initWithNibName:nil bundle:nil];
if (self)
{
[self.view setBackgroundColor:[UIColor clearColor]];
currentPanelNumber = 10;
overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
overlay.backgroundColor = [UIColor colorWithRed:.9 green:.9 blue:.9 alpha:.9];
[self.view addSubview:overlay];
CGRect currentPanelFrame = CGRectMake(267, 175, 494, 444);
currentPanel =
[[HelpView alloc] initWithFrame:currentPanelFrame withImage:[UIImage imageNamed:#"10"]];
currentPanel.frame = currentPanelFrame;
[overlay addSubview:currentPanel];
// ----------------------------------
// Gesture swipes go here
swipeLeftRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft:)];
[swipeLeftRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[overlay addGestureRecognizer:swipeLeftRecognizer];
swipeRightRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
[swipeRightRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
[overlay addGestureRecognizer:swipeRightRecognizer];
swipeDownRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDown:)];
[swipeDownRecognizer setDirection:UISwipeGestureRecognizerDirectionDown];
[overlay addGestureRecognizer:swipeDownRecognizer];
UITapGestureRecognizer *tapRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[overlay addGestureRecognizer:tapRecognizer];
skipIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"SkipAndStartIcon"]];
CGSize size = CGSizeMake(84, 124);
skipIcon.frame = CGRectMake((self.view.frame.size.width/2)-(size.width/2), self.view.frame.size.height-size.height-25, size.width, size.height);
[self.view addSubview:skipIcon];
}
- (void)goNext
{
// Clear out all subviews to remove lingering animations
[[currentPanel subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
if(currentPanelNumber>=80)
{
[self closeHelp];
return;
}
NSString *nextImage = [NSString stringWithFormat:#"%i", currentPanelNumber+10];
CGRect nextPanelFrame = CGRectMake(765, 175, 494, 444);
nextPanel = [[HelpView alloc] initWithFrame:nextPanelFrame withImage:[UIImage imageNamed:nextImage]];
nextPanel.frame = nextPanelFrame;
[overlay addSubview:nextPanel];
[UIView animateWithDuration:.2 animations:^
{
nextPanel.frame = currentPanel.frame;
}
completion:^(BOOL finished)
{
currentPanel.image = nextPanel.image;
nextPanel.alpha = 0;
currentPanelNumber += 10;
}
- (void)goPrevious
{
if(currentPanelNumber<=10)
{
return;
}
// Clear out all subviews to remove lingering animations
[[currentPanel subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
NSString *nextImage = [NSString stringWithFormat:#"%i", currentPanelNumber-10];
CGRect nextPanelFrame = CGRectMake(-230, 175, 494, 444);
// nextPanel = [[UIImageView alloc] initWithImage:[UIImage imageNamed:nextImage]];
nextPanel = [[HelpView alloc] initWithFrame:nextPanelFrame withImage:[UIImage imageNamed:nextImage]];
nextPanel.frame = nextPanelFrame;
[overlay addSubview:nextPanel];
[UIView animateWithDuration:.2 animations:^
{
nextPanel.frame = currentPanel.frame;
}
completion:^(BOOL finished)
{
currentPanel.image = nextPanel.image;
nextPanel.alpha = 0;
currentPanelNumber -= 10;
}];
}
I have a UIScrollView with many other subviews inside it. Most of the subviews are UITextView's and when they are all loaded, the scrolling and everything is fine. But for one of the views, I am loading a UIView with a MKMapView and a UITextView inside of it. When the user wants to scroll the UIScrollView, they cannot touch the UIView or its contents. I cannot set setUserInteractionEnabled to NO because I need the user to be able to click on the MKMapView and then go to another UIViewController for the map. Are there any suggestions regarding this? I have my code for the above below:
CGRect dealDescRect = CGRectMake(10, 10, delegate.scrollView.frame.size.width - 22 - 20, 120);
mapView = [[MKMapView alloc] initWithFrame:dealDescRect];
mapView.layer.cornerRadius = cornerRadius;
mapView.scrollEnabled = NO;
mapView.zoomEnabled = NO;
BOOL result = [self loadAddressIntoMap];
if (result == TRUE) {
UITapGestureRecognizer* recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[mapView addGestureRecognizer:recognizer];
}
UITextView *addressTextView = [self generateTextView:addressText :5];
addressTextView.editable = NO;
[addressTextView setFont:[UIFont systemFontOfSize:fontSize]];
[addressTextView setUserInteractionEnabled:NO];
CGRect addressTextViewFrame = addressTextView.frame;
addressTextViewFrame.origin.x = 0;
addressTextViewFrame.origin.y = 130;
addressTextViewFrame.size.height = addressTextView.contentSize.height + 15;
addressTextView.frame = addressTextViewFrame;
CGRect viewRect = CGRectMake(10, 145, delegate.scrollView.frame.size.width - 22, addressTextView.contentSize.height + 135);
viewRect.origin.x = 11;
viewRect.origin.y = startTop;
UIView *view = [[UIView alloc] initWithFrame:viewRect];
view.layer.cornerRadius = cornerRadius;
[view setBackgroundColor:[UIColor whiteColor]];
[view addSubview:mapView];
[view addSubview:addressTextView];
EDIT
For some weird reason, if I change the UIView to a UITextView, it works! Not sure what the real solution here is though. I just disable editing.
If it were me, instead of using gesture recognizers to watch for a tap on the map I'd create a UIButton of a custom type (UIButtonTypeCustom) and give it no background and no text, and place it on top of the map with the same frame as the map.
This has the benefit of preventing the user from interacting with the map, moving to the next page as you want and if the user starts scrolling even when over the map they are able to.
I'm trying to modify Apple's PhotoScroller example to make the scrollview that is created into a subview instead of it being a view that takes up the entire screen. Any ideas on how this can be accomplished?
- (void)loadView
{
// Step 1: make the outer paging scroll view
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = [self contentSizeForPagingScrollView];
pagingScrollView.delegate = self;
// When I do this it fails
[self.view addSubview:pagingScrollView];
// Step 2: prepare to tile content
recycledPages = [[NSMutableSet alloc] init];
visiblePages = [[NSMutableSet alloc] init];
[self tilePages];
}
You just need to modify the frame of the scrollview to be positioned and sized how you want:
This is the line in the view controller that sets it up in the example
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
As an example here is a sample frame with some hardcoded values:
CGRect scrollFrame = CGRectMake(100,100,100,100);
pagingScrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
So, I found out that I was able to add the scrollView as a subview by changing the method from loadView to viewDidLoad.
I have no clue why that works, but it does. I'd love to know why that's the case however...
1) I have a UIView with a UIImageView on it, i load pictures from the image gallery. I want to know how I would "center" the picture on the screen and make that the aspect ratio isn't changed. For instance if I load a picture that is on landscape mode, how do I make sure that the picture isn't stretched all over the screen? My app is working in portrait mode.
2) In that same view I want to add the effect that when the user touches the screen the botton menu fades out and back in when he presses again. I'm not sure what that is called and I couldn't get the tap gesture recognizer to work.
EDIT:
I set the UIImageView on page load
- (void)viewDidLoad
{
[super viewDidLoad];
xlabel = [[UILabel alloc] initWithFrame:self.setLablePosition];
xlabel.backgroundColor = [UIColor clearColor];
imgView.image = self.appDelegate.theImg; // now the image is put on a UIImageView that is "full screen"
xlabel.text = #"Some text";
[imgView addSubview:xlabel];
// Do any additional setup after loading the view.
}
and as for Tap gesture :
-(IBAction)screenTapped{
NSLog(#"screen Tapped");
}
the IBAction is linked to the tap gesture recognizer.
For centering the UIImageView in the view you would do the following
//First give imgView the correct size
//You may need to divide the size by some constant if the image is too big
imgView.frame = CGRectMake(0, 0, self.appDelegate.theImg.size.width, self.appDelegate.theImg.size.width);
//Then center it
imgView.center = self.view.center;
For adding the tap gesture recognizer do the following
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(screenTapped)];
//By deafualt interaction is disabled
imgView.userInteractionEnabled = YES;
[imgView addGestureRecognizer:recognizer];
My solution was
1) add imgView.contentMode = UIViewContentModeScaleAspectFit;
2) like Omar Abdelhafith said i added imgView.userInteractionEnabled = YES;, the UITapGestureRecognizer for me was created it the storyboard.