I have an CCMenuItem and I want to disable it until an animation is finished, but I don't want to disable all touches with:
[CCDirector sharedDirector].touchDispatcher.dispatchEvents = NO;
Any easy solution?
Use CCSequence to first use the animation action and when that is done you create an action that calls a function with the CCMenuItem as parameter and in that function make it enabled.
Code example: (PS: It was a long time since I used cocos2d.)
{
...
CCMenuItem *menuItem = [CCMenuItem itemWith...];
menuItem.isEnable = NO;
CCMenu *menu = [CCMenu menuWithItems:menuItem, nil];
[self addChild:menu];
[menuItem runAction:[CCSequence actions:[CCAction actionWith...], [CCCallFunc actionWithTarget:self selector:#selector(enable:)], nil]];
...
}
-(void)enable:(CCMenuItem *)item {
item.isEnable = YES;
}
You can disable the CCMenuItem with
CCMenuItem *item = [[CCMenuItem alloc] initWith...];
item.isEnabled = YES;
and enable it afterwards.
Related
I am subclassing NSTabView to customise the appearance. I want to use an NSMatrix of NSButtonCells to select the tabs. I managed to add the NSMatrix with buttons in the initWithFrame: method of my NSTabView subclass. What I can not get to work is setting the target and action programmatically. Here is what I tried:
define TAB_WIDTH 24.0f
define TAB_HEIGHT 24.0f
- (id)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self) {
NSInteger numberOfTabs = 5;
NSInteger tabSpacing = 8;
NSSize cellSize = NSMakeSize(TAB_WIDTH, TAB_HEIGHT);
NSSize interCellSpacing = NSMakeSize(tabSpacing, 0);
CGFloat tabSelectorWidth = TAB_WIDTH * numberOfTabs + tabSpacing * numberOfTabs - 1;
CGFloat xOrigin = (frameRect.size.width - tabSelectorWidth) / 2;
NSRect tabSelectorFrame = NSMakeRect(xOrigin, 0, tabSelectorWidth, TAB_HEIGHT);
NSButtonCell *cellPrototype = [[NSButtonCell alloc] init];
[cellPrototype setBordered:NO];
_tabSelector = [[NSMatrix alloc] initWithFrame:tabSelectorFrame
mode:NSRadioModeMatrix
prototype:cellPrototype
numberOfRows:1
numberOfColumns:5];
[_tabSelector setTarget:self];
[_tabSelector setAction:#selector(selectedTab)];
[_tabSelector setCellSize:cellSize];
[_tabSelector setIntercellSpacing:interCellSpacing];
NSArray *theCells = [_tabSelector cells];
[theCells[0] setImage:[NSImage imageNamed:#"tab1"]];
[theCells[1] setImage:[NSImage imageNamed:#"tab2"]];
[theCells[2] setImage:[NSImage imageNamed:#"tab3"]];
[theCells[3] setImage:[NSImage imageNamed:#"tab4"]];
[theCells[4] setImage:[NSImage imageNamed:#"tab5"]];
[self addSubview:_tabSelector];
[self setDrawsBackground:NO];
[self setTabViewType:NSNoTabsNoBorder];
}
return self;
}
- (void)selectTab:(NSMatrix *)sender
{
NSLog(#"selected tab");
}
The view is drawn as desired, but clicking the buttons does not call the target method.
I have tried to add buttons programmatically to a standard IB view as described here Programatically create and position an NSButton in an OS X app?
That works, but things fall apart in my custom view. Can anybody give me a hint what I am missing?
Martin
Try changing
` [_tabSelector setAction:#selector(selectedTab)];`
To
` [_tabSelector setAction:#selector(selectedTab:)];`
I tried this code it didn't work, I want the button to play sound when it is clicked.
-(void)starButtonsound:(id)sender
{
[[SimpleAudioEngine sharedEngine] playEffect:#"fire_truck_1.wav"];
}
In init
starMenuItemsound = [CCMenuItemImage
itemWithNormalImage:#"play.png" selectedImage:#"play.png"
target:self selector:#selector(starButtonsound:)];
starMenuItemsound.position = ccp(525, 500);
[self addChild:starMenuItemsound z: 4];
starMenuItemsound.scale = 0.75;
Whats wrong?
in init
{
// Using SpriteSheet ? Use spriteWithSpriteFrameName in place of spriteWithFile
CCSprite *spriteNormal = [CCSprite spriteWithFile:#"play.png"];
CCSprite *spriteSelected = [CCSprite spriteWithFile:#"play.png"];
ccColor3B color = {128,128,128};
spriteSelected.color = color;
starMenuItemsound = [CCMenuItemImage
itemWithNormalSprite: spriteNormal selectedImage: spriteSelected
target:self selector:#selector(starButtonsound:)];
starMenuItemsound.position = ccp(525, 500);
starMenuItemsound.scale = 0.75;
CCMenu *menu = [CCMenu menuWithItems: starMenuItemsound, nil];
menu.position = ccp(0.0f,0.0f);
[self addChild: menu z:4];
}
Call Function:
-(void) starButtonsound:(id)sender
{
[[SimpleAudioEngine sharedEngine] setEffectsVolume:1.0f]; //Do this in init method
[[SimpleAudioEngine sharedEngine] playEffect:#"fire_truck_1.wav"];
}
A) Set a breakpoint - essential knowledge for any programmer.
B) The CCMenuItemImage selector does not take an argument. Remove the colon from #selector(startButtonSound) and change the method to this:
-(void)starButtonsound
{
[[SimpleAudioEngine sharedEngine] playEffect:#"fire_truck_1.wav"];
}
Some reported that this is a solution: turning sound off and on again (no joke)
[SimpleAudioEngine sharedEngine].muted = YES;
[SimpleAudioEngine sharedEngine].muted = NO;
I had added a UILongPressGestureRecognizer to a tableview in my ViewDidLoad method. I added this to detect long press on table view in my code. But it never works. In ViewDidLoad I added this code :
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.resultTableView addGestureRecognizer:lpgr];
[lpgr release];
I also added this method :
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:self.resultTableView];
NSIndexPath *indexPath = [self.resultTableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(#"long press on table view but not on a row");
}
else {
NSLog(#"long press on table view at row %d", indexPath.row);
}
}
Please help me to resolve this?
Your code is working. I think you have to add UIGestureRecognizerDelegate delegate in .h file or how to declare resultTableView i mean you define programmatically or using .xib file.Check it once.
I have tried like this.
resultTableView = [[UITableView alloc] init];
resultTableView =[[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 420) style:UITableViewStylePlain];
resultTableView.rowHeight = 100.0;
resultTableView.delegate=self;
resultTableView.dataSource=self;
[self.view addSubview:resultTableView];
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[resultTableView addGestureRecognizer:lpgr];
[lpgr release];
It looks like you want to add the gesture to the individual cells, but you are adding the gesture to the table. Try adding the gesture to your UITableViewCell instead.
If the gesture recognizer is being blocked by the UITableView panGestureRecognizer, implement the delegate to ensure both can work
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Currently I'm facing a problem, I would like to perform action when the UIImageView on my UITableViewCell had been tapped.
Question: How could I do it? Could any one show me the code, or any tutorial?
Thanks in advance!
This is actually easier than you would think. You just need to make sure that you enable user interaction on the imageView, and you can add a tap gesture to it. This should be done when the cell is instantiated to avoid having multiple tap gestures added to the same image view. For example:
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myTapMethod:)];
[self.imageView addGestureRecognizer:tap];
[self.imageView setUserInteractionEnabled:YES];
}
return self;
}
- (void)myTapMethod:(UITapGestureRecognizer *)tapGesture
{
UIImageView *imageView = (UIImageView *)tapGesture.view;
NSLog(#"%#", imageView);
}
Try this
//within cellForRowAtIndexPath (where customer table cell with imageview is created and reused)
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
tap.cancelsTouchesInView = YES;
tap.numberOfTapsRequired = 1;
[imageView addGestureRecognizer:tap];
// handle method
- (void) handleImageTap:(UIGestureRecognizer *)gestureRecognizer
{
RKLogDebug(#"imaged tab");
}
make sure u have....
imageView.userInteractionEnabled = YES;
you can use a customButton instead UIImageView
A tap gesture recogniser can be very memory hungry and can cause other things on the page to break. I would personally reconmend you create a custom table cell, insert a button into the custom cell frame and in the tableview code set the self.customtablecell.background.image to the image you want. This way you can assign the button an IBaction to make it push to whatever view you want.
Use ALActionBlocks to action in block
__weak ALViewController *wSelf = self;
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithBlock:^(UITapGestureRecognizer *weakGR) {
NSLog(#"pan %#", NSStringFromCGPoint([weakGR locationInView:wSelf.view]));
}];
[self.imageView addGestureRecognizer:gr];
I need help with some programming logic... I need to loop this method to display the math problem in my labels then sleep(5) and then loop again. Anything I've tried ends of freezing the program. PLEASE help! I've been tearing my hair out trying everything I know!
EDIT: I edited the code to this, After 3 seconds it fades away the label displaying the problem but then it crashed and the debugger displays 2010-08-06 10:43:27.776 Reactor [13444:207] modifying layer that is being finalized - 0x5c13500
//quickfire problems
-(void)simpleMath{ //"Tap when the answer is X"
isTimeToTap = NO;
int problemSelector = arc4random() % 4;
NSArray *mathProblems = [[NSArray alloc] initWithObjects:#"6 - 1",#"2 + 3",#"3 x 2",#"3 x 1",#"2 x 4",nil]; //correct index 2
NSArray *mathAnswers = [[NSArray alloc] initWithObjects:#"5",#"5",#"6",#"3",#"8",nil]; //correct index 2
if ([mathAnswers objectAtIndex:problemSelector] == #"6") {
isTimeToTap = YES;
}
if (ranBefore == NO) { //create labels
//tell when to tap
tapTellerTop.text = #"Tap when the answer is 6!";
tapTellerBottom.text = #"Tap when the answer is 6!";
//make bottom label
mathDisplayBottom = [[UILabel alloc] initWithFrame:CGRectMake(15, 250, 242, 92)];
mathDisplayBottom.font = [UIFont fontWithName:#"Helvetica" size: 96.0];
mathDisplayBottom.textColor = [UIColor whiteColor];
mathDisplayBottom.backgroundColor = [UIColor clearColor];
[self.view addSubview: mathDisplayBottom];
//make top label
mathDisplayTop = [[UILabel alloc] initWithFrame:CGRectMake(55, 120, 242, 92)];
mathDisplayTop.font = [UIFont fontWithName:#"Helvetica" size: 96.0];
mathDisplayTop.textColor = [UIColor whiteColor];
mathDisplayTop.backgroundColor = [UIColor clearColor];
[self.view addSubview: mathDisplayTop];
//rotate top label
mathDisplayTop.transform = CGAffineTransformMakeRotation(180.0 /180.0 * M_PI);
}
//if ran before just update the text
mathDisplayBottom.text = [mathProblems objectAtIndex:problemSelector];
mathDisplayTop.text = [mathProblems objectAtIndex:problemSelector];
ranBefore = YES; //if its here. its been ran.
//run timer wait for (3) then loop again until userTaps = YES
[self performSelector:#selector(simpleMath) withObject:nil afterDelay:3.0f];
[mathProblems release];
[mathAnswers release];
[mathDisplayBottom release];
[mathDisplayTop release];
}
Sleep will stop your application from running or responding at all. Here is a quick partial example of a view controller you could use. This assumes you wire up the tap button and only uses one of the labels, etc. but you can play around with it. Also, this won't deal with memory issues or anything, so you'd add support for that.
But, once this view controller is created and the view installed, the math problem will update every 5 seconds. If the user presses the button and the answer is valid, we log a success message, otherwise we log fail message.
#interface myMathController : UIViewController {
NSArray* mathProblems;
NSIndexSet* validIndexes;
NSUInteger currentIndex;
NSTimer* timer;
}
#property(nonatomic,assign) IBOutlet UILabel* mathDisplayLabel;
- (void)updateProblem:(NSTimer*)timer;
- (IBAction)userTap;
#end
#implementation myMathController
- (void)viewDidLoad
{
[super viewDidLoad];
mathProblems = [[NSArray alloc] initWithObjects:#"6 - 1",#"2 + 3",#"3 x 2",#"3 x 1",#"2 x 4",nil];
// Add all valid answers
NSMutableIndexSet* tempIndexes = [[NSMutableIndexSet alloc] init];
[tempIndexes addIndex:2];
validIndexs = [tempIndexes copy];
[tempIndexes release];
timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:5.0 target:self selector:#selector(updateProblem:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
- (void)updateProblem:(NSTimer*)timer
{
currentIndex = arc4random() % [mathProblems count];
[mathDisplayLabel setText:[mathProblems objectAtIndex:currentIndex]];
}
- (void)userTap
{
if( [validIndexes containsIndex:currentIndex] ) {
NSLog(#"This user is SMART!");
} else {
NSLog(#"This user needs more work!");
}
}
- (void)dealloc
{
[timer invalidate];
[timer release];
[mathProblems release];
[validIndexes release];
[super dealloc];
}
#end
You shouldn't sleep(), ever. To invoke a function repeatedly, call:
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(doStuff:)
userInfo:nil repeats:YES];
then define the function:
-(void)doStuff:(NSTimer*)timer
{
// stuff
if ( iAmDone ) [timer invalidate];
}
OR if you want to fire another call, after 5 seconds, you could call
if ( !iAmDone ) [self performSelector:#selector(simpleMath) afterDelay:5];
at the end of simpleMath.