【iOS-Cocos2d游戏开发之十六】添加本地通知(UILocalNotification)以及添加系统组件滚动视图(UIScrollView)!【2011年11月15日更新】

 李华明Himi 原创,转载务必在明显处注明:
转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/iphone-cocos2d/492.html


-------------【11月28日更新解决添加组件Cocos2d动画停止播放的BUG】--------
【iOS-Cocos2d游戏开发之七】在cocos2d中添加/删除系统组件,并解决View设置透明会影响View中的其他组件的问题【11月28日更新解决添加组件Cocos2d动画停止播放的BUG】!

 


          首先申明下:希望大家转载的时候不要忘记给原文连接,看到不少论坛转载完全变成他们论坛自己原创了~ 请大家配合哈~谢谢~娃哈哈;

         本篇Himi为童鞋们介绍两个常用的知识点:一个是在Cocos2d中添加UILocalNotification本地化通知,另外一个就是添加UIScrollViewiOS系统组件实现滚动字幕效果;
          对于UILocalNotification这个本地化通知功能实现比较简单,用途很广,最大的用途就是阶段性的让用户回归我们的应用中;那么下面就直接上代码:
          因为是添加到cocos2d引擎中,另一方面一般我们需要用户进入我们应用后就开启通知功能的;所以我们将代码放在 AppDelegate.m 类中的applicationDidFinishLaunching中,代码如下:
             
[cpp] view plaincopyprint?- (void) applicationDidFinishLaunching:(UIApplication*)application 
{  
    ...  
    application.applicationIconBadgeNumber = 0;//应用程序右上角的数字=0(消失)   
    [[UIApplication sharedApplication] cancelAllLocalNotifications];//取消所有的通知   
    //------通知;   
    UILocalNotification *notification=[[UILocalNotification alloc] init];   
    if (notification!=nil) {//判断系统是否支持本地通知   
        notification.fireDate=[NSDate dateWithTimeIntervalSinceNow:kCFCalendarUnitDay];//本次开启立即执行的周期  
        notification.repeatInterval=kCFCalendarUnitDay;//循环通知的周期   
        notification.timeZone=[NSTimeZone defaultTimeZone];  
        notification.alertBody=@"哇,我的女神,你怎了?";//弹出的提示信息   
        notification.applicationIconBadgeNumber=1; //应用程序的右上角小数字   
        notification.soundName= UILocalNotificationDefaultSoundName;//本地化通知的声音   
        notification.alertAction = NSLocalizedString(@"营救女神!", nil);  //弹出的提示框按钮  
        [[UIApplication sharedApplication]   scheduleLocalNotification:notification]; 
    }   
 ...  
}  
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
    ...
    application.applicationIconBadgeNumber = 0;//应用程序右上角的数字=0(消失)
    [[UIApplication sharedApplication] cancelAllLocalNotifications];//取消所有的通知
    //------通知;
    UILocalNotification *notification=[[UILocalNotification alloc] init]; 
    if (notification!=nil) {//判断系统是否支持本地通知
        notification.fireDate=[NSDate dateWithTimeIntervalSinceNow:kCFCalendarUnitDay];//本次开启立即执行的周期
        notification.repeatInterval=kCFCalendarUnitDay;//循环通知的周期
        notification.timeZone=[NSTimeZone defaultTimeZone];
        notification.alertBody=@"哇,我的女神,你怎了?";//弹出的提示信息
        notification.applicationIconBadgeNumber=1; //应用程序的右上角小数字
        notification.soundName= UILocalNotificationDefaultSoundName;//本地化通知的声音
        notification.alertAction = NSLocalizedString(@"营救女神!", nil);  //弹出的提示框按钮
        [[UIApplication sharedApplication]   scheduleLocalNotification:notification];
    } 
 ...
} 
           这里Himi首先是将之前的所有通知都取消掉,防止开启多个循环本地化通知,并且让应用右上角的数字设置为0,这里设置为0就相当与取消数字的显示了;
           然后需要说明的是循环通知的周期,iOS提供如下一些周期:
  
[cpp] view plaincopyprint?enum {  
    kCFCalendarUnitEra = (1UL << 1),  
    kCFCalendarUnitYear = (1UL << 2),  
    kCFCalendarUnitMonth = (1UL << 3),  
    kCFCalendarUnitDay = (1UL << 4),  
    kCFCalendarUnitHour = (1UL << 5),  
    kCFCalendarUnitMinute = (1UL << 6),  
    kCFCalendarUnitSecond = (1UL << 7),  
    kCFCalendarUnitWeek = (1UL << 8) /* CF_DEPRECATED(10_4, 10_7, 2_0, 5_0) */,  
    kCFCalendarUnitWeekday = (1UL << 9),  
    kCFCalendarUnitWeekdayOrdinal = (1UL << 10),  
#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED  
    kCFCalendarUnitQuarter = (1UL << 11),  
#endif   
#if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_5_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED  
    kCFCalendarUnitWeekOfMonth = (1UL << 12),  
    kCFCalendarUnitWeekOfYear = (1UL << 13),  
    kCFCalendarUnitYearForWeekOfYear = (1UL << 14),  
#endif   
};  
enum {
 kCFCalendarUnitEra = (1UL << 1),
 kCFCalendarUnitYear = (1UL << 2),
 kCFCalendarUnitMonth = (1UL << 3),
 kCFCalendarUnitDay = (1UL << 4),
 kCFCalendarUnitHour = (1UL << 5),
 kCFCalendarUnitMinute = (1UL << 6),
 kCFCalendarUnitSecond = (1UL << 7),
 kCFCalendarUnitWeek = (1UL << 8) /* CF_DEPRECATED(10_4, 10_7, 2_0, 5_0) */,
 kCFCalendarUnitWeekday = (1UL << 9),
 kCFCalendarUnitWeekdayOrdinal = (1UL << 10),
#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
 kCFCalendarUnitQuarter = (1UL << 11),
#endif
#if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_5_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
 kCFCalendarUnitWeekOfMonth = (1UL << 12),
 kCFCalendarUnitWeekOfYear = (1UL << 13),
 kCFCalendarUnitYearForWeekOfYear = (1UL << 14),
#endif
};         下面是真机截图:
                    


       

 

          以上是在我真机iOS5系统上的测试效果,主界面中的展示效果以及通知栏内的通知效果,在iOS5之前都会出现类似弹出一个框,框中有你设置的按钮名称和提示文字~
         OK,这个知识点就不多说了,比较easy;下面介绍如何在cocos2d中添加UIScrollView;
        对于UIScrollView视图,比较常用,Android也有此视图,那么它用途比较广,最常用也是最容易想到的就是利用此功能实现游戏中公司介绍、字幕滚动效果,那么Himi就简单的实现在cocos2d中利用UIScrollView添加一个无线循环滚动的小例子加以讲解;
        注意:对于还不知道如何在cocos2d中添加系统组建的童鞋请移步到《【Cocos2d游戏开发之七】在cocos2d中添加/删除系统组件,并解决View设置透明会影响View中的其他组件的问题!》此贴学习先,下面开始添加:
         首先我们新建一个cocos2d项目,然后添加显示一个自定义的MyView(UIViewController)的视图,并且在MyView.xib中添加了一些label和ScrollView组件中;
          如下图:
            


           然后修改MyView.h,和MyView.m类,在MyView.h中如下代码:
          
[cpp] view plaincopyprint?@interface MyView : UIViewController{ 
    IBOutlet UIScrollView *scrollView;  
}  
@property(nonatomic,retain)IBOutlet UIScrollView *scrollView;  
@end  
@interface MyView : UIViewController{
    IBOutlet UIScrollView *scrollView;
}
@property(nonatomic,retain)IBOutlet UIScrollView *scrollView;
@end

  .h类中添加了一个UIScrollView并使用UIScrollViewDelegate协议,并IBOutlet出去,接着让xib文件中的UIScrollView组件连接此scrollView;


          之后在MyView.m中添加如下代码:
         1.添加一行如下代码:
[cpp] view plaincopyprint?@synthesize scrollView; 
@synthesize scrollView;         2.在- (void)viewDidLoad{}中添加如下代码:
[cpp] view plaincopyprint?- (void)viewDidLoad  
{  
    [super viewDidLoad];  
    //滚动view    
    scrollView.delegate = self;  
    scrollView.scrollEnabled = YES;   
    scrollView.contentSize = CGSizeMake(100, 249);//设置滚动的可视区域   
    // Do any additional setup after loading the view from its nib.   
}  
- (void)viewDidLoad
{
    [super viewDidLoad];
    //滚动view 
    scrollView.delegate = self;
    scrollView.scrollEnabled = YES; 
    scrollView.contentSize = CGSizeMake(100, 249);//设置滚动的可视区域
    // Do any additional setup after loading the view from its nib.
}
    整个MyView.m代码如下:
[cpp] view plaincopyprint?//   
//  MyView.m   
//  ScrollViewByHimi   
//   
//  Created by 华明 李 on 11-10-22.   
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.   
//   
  
#import "MyView.h"   
  
@implementation MyView  
@synthesize scrollView;  
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{  
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
    if (self) {  
        // Custom initialization   
    }  
    return self;  
}  
  
- (void)didReceiveMemoryWarning  
{  
    // Releases the view if it doesn't have a superview.   
    [super didReceiveMemoryWarning];  
      
    // Release any cached data, images, etc that aren't in use.   
}  
  
#pragma mark - View lifecycle   
  
- (void)viewDidLoad  
{  
    [super viewDidLoad];  
    //滚动view    
    scrollView.delegate = self;  
    scrollView.scrollEnabled = YES;   
    scrollView.contentSize = CGSizeMake(100, 249);//设置滚动的可视区域   
    // Do any additional setup after loading the view from its nib.   
}  
  
- (void)viewDidUnload  
{  
    [super viewDidUnload];  
    // Release any retained subviews of the main view.   
    // e.g. self.myOutlet = nil;   
}  
  
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{  
    // Return YES for supported orientations   
    return (interfaceOrientation == UIInterfaceOrientationPortrait);  
}  
  
@end  
//
//  MyView.m
//  ScrollViewByHimi
//
//  Created by 华明 李 on 11-10-22.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import "MyView.h"

@implementation MyView
@synthesize scrollView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    //滚动view 
    scrollView.delegate = self;
    scrollView.scrollEnabled = YES; 
    scrollView.contentSize = CGSizeMake(100, 249);//设置滚动的可视区域
    // Do any additional setup after loading the view from its nib.
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

       OK,运行代码即可,运行效果如下:
               

       可以拖动ScrollView中的数据了,ScrollView默认显示滚动条的,可以代码设置隐藏也可以xib中对ScrollView属性调整都可以;


             下面介绍如何让ScrollView中的数据无限循环运动:
       首先在HelloWorldLayer.m种的init添加我们自定义view的下面设置一个选择器:
[cpp] view plaincopyprint?[self schedule:@selector(viewAddPointY) interval:0.03];//每0.03秒执行一次viewAddPointY方法 
[self schedule:@selector(viewAddPointY) interval:0.03];//每0.03秒执行一次viewAddPointY方法       然后viewAddPointY方法是Himi自定义的函数,代码如下:
[cpp] view plaincopyprint?-(void)viewAddPointY{  
    view.scrollView.contentOffset=ccpAdd(view.scrollView.contentOffset, ccp(0,0.5));//让UIScrollView显示内容每次慢慢向上移动0.5像素  
    //view.scrollView.contentSize.height :得到UIScrollView的高度   
    if(view.scrollView.contentOffset.y>=view.scrollView.contentSize.height){  
        view.scrollView.contentOffset=ccp(0,-view.scrollView.frame.size.height); 
    }  
}  
-(void)viewAddPointY{
    view.scrollView.contentOffset=ccpAdd(view.scrollView.contentOffset, ccp(0,0.5));//让UIScrollView显示内容每次慢慢向上移动0.5像素
    //view.scrollView.contentSize.height :得到UIScrollView的高度
    if(view.scrollView.contentOffset.y>=view.scrollView.contentSize.height){
        view.scrollView.contentOffset=ccp(0,-view.scrollView.frame.size.height);
    }
}
    运行效果如下:


                  


      备注:我的Xcode是4.2用的模拟器是iOS5的模拟器,可能童鞋们按照我的这个教程运行后发现虽然UIScrollView中的数据滚动了但是没有循环播放,这个是因为模拟器的问题,Himi真机测试无问题的~
 
      好了,最后我把 HelloWorldLayer.h 和HelloWorldLayer.m也完整放上来,省得有的童鞋不知道添加代码的地方也方便童鞋们拷贝代码;


   HelloWorldLayer.h

[cpp] view plaincopyprint?//   
//  HelloWorldLayer.h   
//  ScrollViewByHimi   
//   
//  Created by 华明 李 on 11-10-22.   
//  Copyright __MyCompanyName__ 2011年. All rights reserved.   
//   
  
  
// When you import this file, you import all the cocos2d classes   
#import "cocos2d.h"   
#import "MyView.h"   
// HelloWorldLayer   
@interface HelloWorldLayer : CCLayer  
{  
    MyView *view;  
}  
  
// returns a CCScene that contains the HelloWorldLayer as the only child   
+(CCScene *) scene;  
  
@end  
//
//  HelloWorldLayer.h
//  ScrollViewByHimi
//
//  Created by 华明 李 on 11-10-22.
//  Copyright __MyCompanyName__ 2011年. All rights reserved.
//


// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
#import "MyView.h"
// HelloWorldLayer
@interface HelloWorldLayer : CCLayer
{
    MyView *view;
}

// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;

@end

 

   HelloWorldLayer.m

 

[cpp] view plaincopyprint?//   
//  HelloWorldLayer.m   
//  ScrollViewByHimi   
//   
//  Created by 华明 李 on 11-10-22.   
//  Copyright __MyCompanyName__ 2011年. All rights reserved.   
//   
  
  
// Import the interfaces   
#import "HelloWorldLayer.h"   
#import "MyView.h"   
// HelloWorldLayer implementation   
@implementation HelloWorldLayer  
  
+(CCScene *) scene  
{   
    CCScene *scene = [CCScene node];   
    HelloWorldLayer *layer = [HelloWorldLayer node];   
    [scene addChild: layer];   
    return scene;  
}  
   
-(id) init  
{   
    if( (self=[super init])) {  
          
        view= [[MyView alloc] initWithNibName:@"MyView" bundle:nil];    
        [[[CCDirector sharedDirector] openGLView] addSubview:view.view];    
        [self schedule:@selector(viewAddPointY) interval:0.03];//每0.03秒执行一次viewAddPointY方法  
    }  
    return self;  
}  
-(void)viewAddPointY{  
    view.scrollView.contentOffset=ccpAdd(view.scrollView.contentOffset, ccp(0,0.5));//让UIScrollView显示内容每次慢慢向上移动0.5像素  
    //view.scrollView.contentSize.height :得到UIScrollView的高度   
    if(view.scrollView.contentOffset.y>=view.scrollView.contentSize.height){  
        view.scrollView.contentOffset=ccp(0,-view.scrollView.frame.size.height); 
    }  
}  
   
- (void) dealloc  
{    
    [super dealloc];  
}  
@end  
//
//  HelloWorldLayer.m
//  ScrollViewByHimi
//
//  Created by 华明 李 on 11-10-22.
//  Copyright __MyCompanyName__ 2011年. All rights reserved.
//


// Import the interfaces
#import "HelloWorldLayer.h"
#import "MyView.h"
// HelloWorldLayer implementation
@implementation HelloWorldLayer

+(CCScene *) scene
{ 
 CCScene *scene = [CCScene node]; 
 HelloWorldLayer *layer = [HelloWorldLayer node]; 
 [scene addChild: layer]; 
 return scene;
}
 
-(id) init
{ 
 if( (self=[super init])) {
  
        view= [[MyView alloc] initWithNibName:@"MyView" bundle:nil];  
        [[[CCDirector sharedDirector] openGLView] addSubview:view.view];  
        [self schedule:@selector(viewAddPointY) interval:0.03];//每0.03秒执行一次viewAddPointY方法
 }
 return self;
}
-(void)viewAddPointY{
    view.scrollView.contentOffset=ccpAdd(view.scrollView.contentOffset, ccp(0,0.5));//让UIScrollView显示内容每次慢慢向上移动0.5像素
    //view.scrollView.contentSize.height :得到UIScrollView的高度
    if(view.scrollView.contentOffset.y>=view.scrollView.contentSize.height){
        view.scrollView.contentOffset=ccp(0,-view.scrollView.frame.size.height);
    }
}
 
- (void) dealloc
{  
 [super dealloc];
}
@end


        OK,本篇结束;再次提醒下,希望大家转载的时候不要忘记给原文连接,看到不少论坛转载完全变成他们论坛自己原创了~ 请大家配合下哈~谢谢~


【2011年11月15日更新:】
 注意:有的童鞋使用系统的UIScrollView的时候出现如下问题:
       《因为尝试了些coco2d写的scrollview感觉效果都不太理想,所以打算用UIScrollView来实现一些功能的,可是遇到这样一个棘手的问题,感觉整个cocos2d都停止了一样,连显示的FPS也停了,只要scrollview一停止滑动,所有的动画效果都立刻恢复了。。。请问有高人知道怎么解决这个问题么?感激不禁~》

解决方法如下:
[html] view plaincopyprint?0.99.5版本的..  
  
首先:在CCDirectorIOS.m 文件中 第640行 找到以下注释.  
  
//  
// If you want to attach the opengl view into UIScrollView  
// uncomment this line to prevent 'freezing'. It doesn't work on  
// with the Fast Director  
//  
// [[NSRunLoop currentRunLoop] addTimer:animationTimerforMode:NSRunLoopCommonModes];   <-去掉这行代码注释. 
  
第二.  
在 AppDelegate.m 文件中找到.  
if( ! [CCDirector setDirectorType:kCCDirectorTypeDisplayLink] )  <-注释这一行  强制设置 CCDirector 为kCCDirectorTypeNSTimer类型. 
    [CCDirector setDirectorType:kCCDirectorTypeNSTimer];<- 如果类型不是kCCDirectorTypeNSTimer,则设置类型为 kCCDirectorTypeNSTimer 
  
搞定..  


 

你可能感兴趣的:(cocos2d)