I'm writing a custom UIButton that can draggable around the screen. When I press this button, a uiview will bee added into superview. I've adding pan gesture for this view so it's can draggable too.
And now I wanna make both uiview and button can draggable at the same time. How can I do that?For example:
If I drag the uiview or the button to a point, the other will move too. You can see the picture below for more information.
I would encapsulate the button and the view in a parent transparent UIView. Add the pan gesture to it and move it around... both will then move.
I tried the sample code for your application.It works perfectly.When you drag button,the view also moves simultaneously.
First I created button and UIView.I hooked up that.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIButton *btnDragg;
- (IBAction)actionDragg:(id)sender;
#property (strong, nonatomic) IBOutlet UIView *viewDrag;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize btnDragg,viewDrag;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIPanGestureRecognizer *panRecognizer;
panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(wasDragged:)];
panRecognizer.cancelsTouchesInView = YES;
[btnDragg addGestureRecognizer:panRecognizer];
}
- (void)wasDragged:(UIPanGestureRecognizer *)recognizer
{
UIButton *button = (UIButton *)recognizer.view;
CGPoint translation = [recognizer translationInView:button];
CGPoint translationView = [recognizer translationInView:viewDrag];
button.center = CGPointMake(button.center.x + translation.x, button.center.y + translation.y);
viewDrag.center = CGPointMake(viewDrag.center.x + translationView.x, viewDrag.center.y + translationView.y);
[recognizer setTranslation:CGPointZero inView:button];
[recognizer setTranslation:CGPointZero inView:viewDrag];
}
Before I drag the button,it is in original position
Then When I drag the button,the view also moves with button.Now it changes the position after the I drag the button.
Related
I'm relatively new to Xcode, and am in the process of making an app in Objective C with several viewControllers each with a single UIScrollView containing a single UIImage that can be zoomed and scrolled.
This code works for the first image (dermatomes), but I can't figure out how to tweak the UIView to enable zooming and scrolling on the second image (anatomicPlanes). Currently the second image imports correctly to the second UIScrollView, but when I try to zoom it just jumps down and right and remains static there.
The size of the UIScrollViews were set using Interface Builder, no problems there.
viewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIScrollViewDelegate> {
IBOutlet UIScrollView *dermatomeScrollView;
UIImageView *dermatomesImageView;
IBOutlet UIScrollView *anatomicPlaneScrollView;
UIImageView *anatomicPlanesImageView;
}
#property (strong, nonatomic) IBOutlet UIScrollView *dermatomeScrollView;
#property (strong, nonatomic) IBOutlet UIImageView *dermatomesImageView;
#property (strong, nonatomic) IBOutlet UIImageView *anatomicPlanesImageView;
#property (strong, nonatomic) IBOutlet UIScrollView *anatomicPlaneScrollView;
#end
viewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize dermatomeScrollView, anatomicPlanesImageView, dermatomesImageView, anatomicPlaneScrollView;
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return dermatomesImageView;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *dermatomes = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"dermatomes.jpg"]];
self.dermatomesImageView = dermatomes;
dermatomeScrollView. maximumZoomScale = 1.2;
dermatomeScrollView. minimumZoomScale = 0.4;
dermatomeScrollView. delegate = self;
[dermatomeScrollView addSubview:dermatomesImageView];
dermatomeScrollView.zoomScale = 0.6;
UIImageView *planes = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"anatomic planes.jpg"]];
self.anatomicPlanesImageView = planes;
anatomicPlaneScrollView. maximumZoomScale = 1.2;
anatomicPlaneScrollView. minimumZoomScale = 0.4;
anatomicPlaneScrollView. delegate = self;
[anatomicPlaneScrollView addSubview:anatomicPlanesImageView];
anatomicPlaneScrollView.zoomScale = 0.6;
}
Any help is appreciated!
You need to return the correct view based on the scroll view that is requesting. Every method in the delegate pattern is passed a reference to the originator of the method call, so your delegate implementation can handle it differently. In this case, the originator of the delegate method call is the scroll view:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
if (scrollView == dermatomeScrollView) {
return dermatomesImageView;
}
return anatomicPlanesImageView;
}
If you add more scrollviews, you'll have to extend this method further.
i Am using Mb Progress Bar. in which the progress bar is sccessing automatically. here i want to move the progress bar with my mouse cursor.
i am using Github Library
https://github.com/matibot/MBCircularProgressBar
This library gives me animated progress bar which runs automatically on button click. i want exactly this one. but it should not be automatically. i want to move it by my cursor like hand moment.
this is my code:::
#property (weak, nonatomic) IBOutlet MBCircularProgressBarView *progressBar;
#property (weak, nonatomic) IBOutlet UISwitch *animatedSwitch;
#end
#implementation MBViewController
- (void)viewDidLoad {
[super viewDidLoad];
// pan gesture detects circle dragging
UIPanGestureRecognizer *pv = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
//[self addGestureRecognizer:pv];
[self.progressBar addGestureRecognizer:pv];
}
- (IBAction)animate:(UIButton *)sender {
[UIView animateWithDuration:self.animatedSwitch.on * 1.f animations:^{
self.progressBar.value = 100.f - self.progressBar.value;
}];
}
# pragma mark detect pan and determine angle of pan location vs. center of circular revolution
- (void) handlePan:(UIPanGestureRecognizer *)pv {
self.progressBar.value = 100.f - self.progressBar.value;
}
Anyone can have idea. please help me for this::
I have a xib file which contains a UIButton. I control + dragged the button to create an action. The position of the button has to be set dynamically. The method below is called from drawRect: method which updates the button position.
-(void)updateButtonPosition {
CGFloat xPos = self.label.frame.origin.x + self.label.frame.size.width;
CGFloat yPos = self.label.frame.origin.y + self.label.frame.size.height - 25;
CGRect frame = CGRectMake(xPos, yPos, self.button.frame.size.width, self.button.frame.size.height);
self.button.frame = frame;
}
But I noticed that calling this function disconnects the UIButton from the action I created by control + dragging (i.e. nothing happens when I click the button when the app is running). I commented the part where this function was called. And now the button started working and the action method was called. So changing the frame disconnected the UIButton from its action method.
EDIT: User Interaction is enabled for all its superview. I'm not using auto layout. The project is like that.
How can I change the frame of the button so that the action is also called when I click the button?
Check the button's frame with it's superview frame. The button receives touch events only when it resides inside it's superview frame.
Can't reproduce your problem, I dragged an action named "btnAction" and a outlet named "btnTest".
This is ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
- (IBAction)btnAction:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *btnTest;
#end
And this is ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
// [super viewDidLoad];
// // Do any additional setup after loading the view, typically from a nib.
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(grHandler)]];
}
-(void)grHandler{
NSLog(#"grHandler actived.");
[self updateButtonPosition];
}
- (IBAction)btnAction:(id)sender {
NSLog(#"btn actived.");
}
-(void)updateButtonPosition {
CGFloat xPos = 20;
CGFloat yPos = 30;
CGRect frame = CGRectMake(xPos, yPos, self.btnTest.frame.size.width, self.btnTest.frame.size.height);
self.btnTest.frame = frame;
}
#end
Try to use my code and tell me where is the problem?
Then I can help you.
My button's frame was outside the frame of its parent view. Hence it was not tap able.
For more info refer UIButton not responding after set frame within UIScrollview
I'm Making a game, with level select Ive got 3 levels and 3 views on 3 different controllers
Now I've placed 2 - 1/4 of the button on each side of my scroll view, on on the left and one on the right!
When the user of the game is on level 1 "thats View1" The button on the left needs to be hidden and only show when its on View2 and View 3 - same goes for the button on View3 on the right!
How is this done?
Outlets for those buttons are leftIllusion & rightIllusion
code for UIViews:
#implementation ViewController
#synthesize View1;
#synthesize View2;
#synthesize View3;
- (void)viewDidLoad
{
// Do any additional setup after loading the view, typically from a nib.
[super viewDidLoad];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"View1"]];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"View2"]];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"View3"]];
}
code from that imports scroll file .h:
#import "PagerViewController.h"
#interface ViewController : PagerViewController {
}
#property (strong, nonatomic) IBOutlet UIView *View1;
#property (strong, nonatomic) IBOutlet UIView *View2;
#property (strong, nonatomic) IBOutlet UIView *View3;
#end
UIScrollView instance has property contentOffset, which can help you to detect what view is being displayed now (view1, view2, view3). I am posting example code-snippet, which helps me to determine the page number of scrollView.
- (NSInteger)pageNumber
{
static NSInteger previousPage = 0;
CGFloat pageWidth = self.scrollView.frame.size.width;
float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
NSLog(#"page number %d",page);
if (previousPage != page) {
previousPage = page;
/* Page did change */
//put here your hide/show buttons logics
}
return page;
}
The best place to insert these lines is scrollView delegate's method -(void)scrollViewDidEndDecelerating:. The scroll view calls this method each time when the scrolling movement comes to a halt.
So your final version will look like:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender
{
[self pageNumber];
}
I have UITextFields in tableviewcells. When you swipe over the cell not part of the textfield, the delete action comes up as expected. If you swipe over the textfield, it stops the delete from popping up.
How do I fix this so that you can swipe over the inputs and the cell will trigger the delete action?
I think the issue here is that the touch on the text field is interfering with your swipe gesture recognizer (presumably attached to the parent view). I had a similar problem with a text field that was placed in a UIScrollView.
I got around this problem by overlaying a clear UIView on top of my UITextField. I then assigned a UITapGestureRecognizer to this clear view to set the text field as the first responder when the user taps on the field. Otherwise, the swiped is sent to the parent view (a scroll view) which recognizes the swipe without any issues. It's kind of lame but it works.
This scenario is a bit different from yours, but I think it's the same problem. Here is what my code looks like, hopefully it helps:
// UIView subclass header
#interface LSAddPageView : UIView
#property (weak, nonatomic) IBOutlet UITextField *textField; // Connected to the UITextField in question
#property (strong, nonatomic) UIView *textFieldMask;
#property (assign, nonatomic) BOOL textFieldMaskEnabled;
#end
// UIView subclass implementation
#implementation LSAddPageView
- (void)awakeFromNib
{
[super awakeFromNib];
_textFieldMask = [UIView new];
_textFieldMask.backgroundColor = [UIColor clearColor];
[self insertSubview:_textFieldMask aboveSubview:self.textField];
}
- (void)layoutSubviews
{
[super layoutSubviews];
_textFieldMask.frame = self.textField.frame;
}
- (BOOL)textFieldMaskEnabled
{
return _textFieldMask.hidden == NO;
}
- (void)setTextFieldMaskEnabled:(BOOL)textFieldMaskEnabled
{
_textFieldMask.hidden = !textFieldMaskEnabled;
}
#end
And then in the controller:
- (void)viewDidLoad
{
[super viewDidLoad];
_addPageView = (LSAddPageView*)self.view;
_maskGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTapMask:)];
_maskGestureRecognizer.numberOfTapsRequired = 1;
_maskGestureRecognizer.numberOfTouchesRequired = 1;
[_addPageView.textFieldMask addGestureRecognizer:_maskGestureRecognizer];
self.textField.delegate = self; // Set delegate to be notified when text field resigns first responder
}
- (void)didTapMask:(UIGestureRecognizer*)recognizer
{
_addPageView.textFieldMaskEnabled = NO;
[self.textField becomeFirstResponder];
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
_addPageView.textFieldMaskEnabled = YES;
return YES;
}
Sounds like you need to set the cancelsTouchesInView property
yourGestureRecognizer.cancelsTouchesInView = NO;
from UIButton & UITextField will block UITableViewCell being swipe to delete
self.tableView.panGestureRecognizer.delaysTouchesBegan = YES;
this will make the textfield not stop left swipe guestures