I have an iPad interface where different views can be moved left-right with one finger (as for e.g. like the Twitter iPad interface).
I have a problem with this, as I have a slider on one view and when I start sliding, the UIGestureRecogniser on the main (underlying) view also start acting on the movement.
Is there a way to prevent this? That only the UISlider takes the touch action, and that the underlying view does not act? I mean to remember there is a variable for this with UIGestureRecognisers, but cannot find it for views/sliders.
Thanks in advance!
Set the exclusive touch property:
[view setExclusiveTouch:YES];
I searched for hours and I following trick work for me.
ViewController.h
#property (weak, nonatomic) IBOutlet UIScrollView *yourScrollView;
ViewController.m
- (void)viewDidLoad
{
yourScrollView.delaysContentTouches = NO;
}
Related
Here's the situation, I'm a newb at this - so I could be totally on the wrong path.
I am building an app with multiple views; in one of those views I need the user to select from a dropdown list (UIPickerView) --> for simplicity let's call that view "PC" which has PC.h and PC.m files.
Through IB I was able to drop a UIPickerView object to the PC view, and I initialize that "object" in my ViewController.h and ViewController.m files. Meaning, I'm able to load the view, populate data in the view, etc. etc.
My challenge/problem is - I want the UIPicker to be hidden until the user clicks a button on the PC view, then I want to show the UIPicker and hide it again once the user selects something from the menu.
I've searched and searched and can't find anything, so any help here is appreciated!
assuming that your UIPickerView instance (object) is called pv;
This is how your header-file may look like:
#interface YourViewController : UIViewController
{
IBOutlet UIPickerView *pv;
}
#property (nonatomic, retain) UIPickerView *pv;
#end
You then need to connect the pv-instance within the InterfaceBuilder to your Picker-View.
Trivial Approach:
somewhere in your viewDidLoad of the embedding view-controller:
pv.hidden = YES;
within the button action method (connected to your button-touch-up-instide event):
pv.hidden = NO;
within the action method of your "menu"
pv.hidden = YES;
The context: I have three views. One Introductory view, an Upload view and the Main view. As classes (With their respective headers) I have the rootViewController (SwitchViewController), IntroViewController and UploadViewController. The first view to be shown is IntroView. The user presses a button (declared in SwitchViewController) that takes them to the UploadView, then in the UploadView they get to choose an image and press the button again to go back to IntroView.
The thing is that while the user gets to pick the image with UIImagePickerController the button to switch views won't hide nor a UIImageView I have with a logo on top of the view(screen). The UIImageView and the UIButton are both declared in SwitchViewController's header.
The code used:
UploadViewController.h
#import [...] //Imports
#class SwitchViewController;
#interface UploadViewController :
UIViewController <UIImagePickerControllerDelegate,
UINavigationControllerDelegate,UIActionSheetDelegate> {
UITextField *imageTextField;
UIImageView *uploadedImage;
SwitchViewController *switchViewController;
[...]
}
#property (nonatomic, retain) SwitchViewController *switchViewController;
#property (nonatomic, retain) IBOutlet UITextField *imageTextField;
#property (nonatomic, retain) IBOutlet UIImageView *uploadedImage;
[...]
#end
UploadViewController.m
[...]
- (IBAction) selectImageButtonPressed {
self.switchViewController.submitButton.hidden = YES;
self.switchViewController.imageLogo.hidden = YES;
[...] //continues
I just begun recently programming in objective-c so please forgive me if the question is very essential. I have looked and am following "Beginning iPhone 3 Development" of APRESS. But even if it helps to greatly understand the basics sometimes I get lost.
PS: If it is clearer to answer the question the SwitchViewController.h and .m snippet codes can be provided if asked. But I thought this text is big as it is.
#Joze i think I may have understood your problem switchViewController is a variable of the class UploadViewController so if you do anything with that variable it wont affect the switchViewController view. so when you are calling the switchViewController view at that time you have to do initWithNibName: bundle: and then hide the button and imageView and also you need to do something like switchViewController.delegate = self; and then call the view modally or what ever way you want it.
PS. i m not sure the that spelling is correct. i dont have xcode at my home.
I hope your problem solves with this.
I solved my problem after refactoring the whole code and changing the general structure of the program itself. Now I have 3 views and each with a viewController to control it. All the switching of views occurs in the Delegate since he has access to everyone. That way I can control every property with every controller, without much difficulty. Changing the property of one of the objects present in one view from another view is difficult and rather inconvenient if not sometimes impossible.
The approach I took when asking this question was short sighted for the application that had to be done. I thank all those who tried to help.
As the title says. Reordering within a single UITableView is trivial, but the screen of the iPad is large enough to display multiple UITableViews at the same time. So it seems like there should be a way to drag and drop a UITableViewCell between two UITableViews. Any thoughts on the best approach?
My solution was to use a custom UIGestureRecognizer for tracking the touch events, and a separate view for drawing the dragging operation.
This works because UIGestureRecognizer doesn't block the responder chain.
From the UIGestureRecognizer documentation:
UIGestureRecognizer objects are not in the responder chain, yet observe touches hit-tested to their view and their view's subviews.
Create a custom UIViewController (DragAndDropViewController) and add its view to the parent view of the views you want the drag & drop operation to occur in. Use your custom gesture recognizer class to forward the touch information to your DragAndDropViewController.
The source tells your DragAndDropViewController where the the drag originates from (and any custom info). The controller should also have a delegate reference to the drop destination. When the drop occurs, send the delegate the UITouch event (not recommended according to Apple, but the UITouch object is needed to get the correct location in the destination view).
This is what my DragAndDropViewController looks like:
#protocol DragAndDropDestination
(void)droppedItem:(NSDictionary *)item withTouch:(UITouch *)touch;
#end
#interface DragAndDropViewController : UIViewController
{
id _dropDestination;
NSDictionary *_draggedItem;
UIImageView *_icon;
}
#property (nonatomic, assign) id dropDestination;
#property (nonatomic, retain) NSDictionary *draggedItem;
// Source sends this message
- (void)startDraggingWithItem:(NSDictionary *)item;
#end
Once the destination gets the message, you can use - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event to get the exact view at the drop destination.
Also make sure you disable cancelsTouchesInView in the gesture recognizer if you want other UI operations to happen normally in your table views.
Okay I just typed this whole question out and then managed to delete it. Sigh. Anyway, standard disclosure that I have searched everywhere and banged my head on the keyboard and can't figure this out.
I'm building a basic app based on the utility application template (with a MainViewController and FlipsideViewController). Side note: I still don't understand the purpose of MainView and FlipsideView in this scheme so if someone can explain it that wouldn't be too terrible :D
Anyway, at the bottom of both of these views I want to have a toolbar. It was easy enough to add that to a given view with IB, but I want the toolbar to have its own controller and model because I want to keep its state consistent across the two views. Accordingly I'd like to load that view from a nib but it seems I'm doing something wrong. I followed the advice here: NSViewController and multiple subviews from a Nib but obviously borked it up so more insight would be appreciated.
I did the following things:
I created ToolBarViewController which is basically empty but is the file owner of ToolBar.xib. Inside ToolBar.xib I have a view with a frame the size of the toolbar and inside that a toolbar. In MainView.xib I've got a view element of the same size which is wired up to toolBarView found in the code below...
In MainViewController.h:
#import "ToolBarViewController.h"
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate, MKMapViewDelegate> {
...
ToolBarViewController *toolBarViewController;
IBOutlet UIView *toolBarView;
}
...
#property(nonatomic, retain) ToolBarViewController *toolBarViewController;
#property(nonatomic, retain) IBOutlet UIView *toolBarView;
In MainViewController.m:
#synthesize toolBarViewController;
#synthesize toolBarView;
- (void)loadView
{
[super loadView];
toolBarViewController = [[ToolBarViewController alloc] initWithNibName:#"ToolBar" bundle:nil];
[[toolBarViewController view] setFrame:[toolBarView frame]];
[[self view] replaceSubview:toolBarView with:[toolBarViewController view]];
}
When I build and run I get the warning for the last line above that 'UIView' may not respond to 'replaceSubview:with' and on running it the following exception is thrown:
*** -[MainView replaceSubview:with:]: unrecognized selector sent to instance 0x450c540
Can anyone explain what I'm doing wrong? Thanks!å
There is no such method as [UIView replaceSubview:with:]. That's an NSView method. You should have gotten a warning about this when you compiled.
To do the same thing, you'd need to use [[self view] insertSubview:aboveSubview:] and then [toolbarView removeFromSuperview].
That said, I'm not certain if this is how you want to mess with the toolbar. I'd probably try something more like:
self.toolbarItems = [toolbarViewController toolbarItems];
That's because there's no such UIView's replaceSubview:with: (there's a method like that for NSView on the Mac, though).
Remember that Objective-C warnings are usually errors ;) in general I tend to never leave them without treatment, and I even turn them into errors:
http://akosma.com/2009/07/16/objective-c-compiler-warnings/
Tell me if I am wrong with that:
I made an new class ScrollViewDataSource. That class conforms to an protocol I created within my delegate for the scroll view. Well, it's a very special delegate that does some very complex stuff upon scrolling. So this delegate receives that data source object upon initialization. The datasource object now has a method
(NSArray*)subviewsFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex;
so when the user scrolls, the delegate rings the datasource object lots of times dunring scrolling to ask for data. I'm going to recycle views during scrolling. That means, if the user scrolls down, I remove the views from the top to the bottom, and fill them up with new data.
The NSArray contains UIView objects, which will be positioned appropriately during scrolling. Also, on first launch of the view that contains the scroll view, the data source will deliver the data to display the first visible contents.
Is that a good pattern, or do you have better ideas for that?
BTW: I know a UITableView does something similar. But I want to learn that. It's a practise for me. Thanks!
May,
This is the best pattern that you can make use of. Exclusively followed by Apple in various of their data displaying views like UITableView in iPhone and NSTableView,NSOutlineView in Mac.
All the best.
If your content views are using same layout, I would make ScrollViewDataSource containing only the data that content views needed, so I don't need to alloc/create new UIView for my UIScrollView when asking new data (since MyScrollView hold the content views that I can reuse):
#interface MyScrollView : UIView {
#private
id <MyScrollViewDelegate> _delegate;
id <MyScrollViewDataSource> _dataSource;
UIScrollView *_scrollView;
NSMutableArray *_contentViews; // you need to create/maintain/reuse contentView from here
}
#property (nonatomic, assign) id <MyScrollViewDelegate> delegate;
#property (nonatomic, assign) id <MyScrollViewDataSource> dataSource;
#end
#protocol MyScrollViewDataSource <NSObject>
#optional
- (NSString *)myScrollView:(MyScrollView *)myScrollView requestTitleForContentViewAtIndex:(NSInteger)index;
- (UIImage *)myScrollView:(MyScrollView *)myScrollView requestLogoForContentViewAtIndex:(NSInteger)index;
#end
...
The good about this is, your MyScrollView interface would look clean to superview, and you are dealing all the scrolling, layout, redraw and content updating stuffs within your MyScrollView AND without bothering other views or controllers from outside.
But, if your content views are totally different to each others, I won't use pattern like this.