码迷,mamicode.com
首页 > Windows程序 > 详细

[Stanford 2011] hapiness

时间:2014-12-02 22:04:01      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   ar   color   os   使用   

From:view6-view7(00:17)

1.Introduction:

   Implement two gestures:pinch and pan.

   We first implement the pinch. We add delegate to faceView(the view) that allowed faceView to get the data,which is the degree(-1 to 1) of the smile face. Then the Controller can set self as the  delegate, and provide the smile degree(-1 to 1)  for view using the model.

   Another thing is adding the pan updown gesture to control the happiness.

2. Visual Effects:

     Pan:fig(1),fig(2),fig(3)

     Pinch:fig(4)

bubuko.com,布布扣bubuko.com,布布扣bubuko.com,布布扣bubuko.com,布布扣

3. The codes:

创建faceView的类型必须是CocoaTouch下的Obj-C class类型,创建为UIView子类

//faceView.h
#import <UIKit/UIKit.h>
@class faceView;//只是告诉编译器,faceView类是存在的,对于protocol也可以有比如@protocol FaceViewDataSource;
@protocol FaceViewDataSource<NSObject>//把faceView的笑脸程度委托给任何想要设置它的人
-(float)smileForfaceView:(faceView*)sender;//在委托的方法里,当我们获取数据和把某个东西委托给另一个东西的时候,我们几乎都会把自己(sender)传过去,因为这样就不需要再回到faceView去问。因此任何时候做一个委托或者数据源,你都会把你自己作为发送者传递过去,这和target action相类似。
//因为此句使用了faceView,而faceView在这之前还没定义,所以必须用@class faceView;声明类(即,前向引用)。
@end

@interface faceView : UIView
@property(nonatomic) CGFloat scale;  //scale表示缩放的程度,是为了实现缩放的手势,缩放和笑没有关系,所以手势的处理就放在view里,这样其他的controller也可以使用我的view的缩放功能了。
-(void)pinch:(UIPinchGestureRecognizer *)gesture; //手势处理方法是public的,因为要让所有使用faceView的人知道它有缩放功能
@property(nonatomic,weak)IBOutlet id<FaceViewDataSource> dataSource;//如果有人想控制笑脸程度,就得把自己设为FaceView的数据源
@end

//faceView.m
#import "faceView.h"
@implementation faceView
@synthesize dataSource=_dataSource;
@synthesize scale=_scale;
#define DEFAULT_SCALE 0.90  //笑脸的大小是view短边大小的90%
-(CGFloat)scale    //getter
{  
     if (!_scale)  
    {return DEFAULT_SCALE ;}
     else     {return _scale;}
}
-(void)setScale:(CGFloat)scale  //setter
{    
      if(scale !=_scale)   //if条件表示scale改变了。为了更高效,只有在scale改变的时候才自动重绘    
       {   
              _scale=scale;        
             [self setNeedsDisplay];
        }
}
-(void)pinch:(UIPinchGestureRecognizer *)gesture  //手势处理(这之前需要把缩放手势添加到view上,添加需要在controller里进行,处理在view里做,添加在faceView的outlet的setter里),缩放处理方法,在模拟器上用option键测试
{    
      if ((gesture.state == UIGestureRecognizerStateChanged)||(gesture.state == UIGestureRecognizerStateEnded))    
       {
            self.scale *= gesture.scale;
             gesture.scale = 1;  //重设scale为1,这样每次比较的就是上次的变化
        }
 }
-(void)setup
{
      self.contentMode=UIViewContentModeRedraw;//在initWithFrame和awakeFromNib里必须有此句,则在controller里自动旋转YES后,则旋转后才能重绘。
}//其实有简单的不用写代码的方法,就是在storyboard里选中view,然后在右边Attributes Inspector里Mode里选Redraw就可以了。
-(void)awakeFromNib { [self setup]; } - (id)initWithFrame:(CGRect)frame //model自动从initWithFrame开始,确保你在这里面写的东西也放到了awakeFromNib里 {//用代码创建UIView对象,用initWithFrame做初始化;用xib创建UIView对象用awakeFromNib做其他的初始化工作. awakeFromNib是在UIVIEW中用,viewDIdLoad是在UIVIEWCONTROLLER里面用 self = [super initWithFrame:frame]; if (self) { // self.contentMode = UIViewContentModeRedraw; // 不会起作用,因为view离开storyboard之后,initWithFrame不会被调用,所以用setup方法,在awakeFromNib里调用。这样当view改变的时候就会重绘了,不管是调用init还是在view之外 [self setup]; } return self; } -(void) drawCircleAtPoint:(CGPoint)p withRadius:(CGFloat)radius inContext:(CGContextRef)context { UIGraphicsPushContext(context); //子程序在修改context之前要pushContext,在最后要pop回来。可以在中间做任何事,比如改变线条颜色,这样做就不会破坏外面的context。 CGContextBeginPath(context); CGContextAddArc(context, p.x, p.y, radius, 0, 2*M_PI, YES); //开始角度0,结束角度2pai, YES表示顺时针 CGContextStrokePath(context); //这里没有设置线条填充颜色或线宽,需要在调用的地方设置,即drawRect UIGraphicsPopContext(); } -(void)drawRect:(CGRect)rect { CGContextRef context =UIGraphicsGetCurrentContext(); //需要contex来调用其他的绘图方法。 // draw face [circle] CGPoint midPoint; midPoint.x=self.bounds.origin.x+self.bounds.size.width/2; // midPoint是整个view的中心点 midPoint.y=self.bounds.origin.y+self.bounds.size.height/2; CGFloat size=self.bounds.size.width/2; //找出view的短边 if (self.bounds.size.height<self.bounds.size.width) size=self.bounds.size.height/2; size *= self.scale; //笑脸的大小开始是整个view中短边的90%大小,后面随着scale大小来变大变小 CGContextSetLineWidth(context, 5.0); //设置线宽 [[UIColor blueColor]setStroke]; //设置线条颜色 [self drawCircleAtPoint:midPoint withRadius:size inContext:context]; //画大圆,表示脸的轮廓 // draw eyes [2 circle] #define EYE_H 0.30 #define EYE_V 0.30 #define EYE_RADIUS 0.10 CGPoint eyePoint; //左眼睛的中心点 eyePoint.x=midPoint.x-size*EYE_H; eyePoint.y=midPoint.y-size*EYE_V; [self drawCircleAtPoint:eyePoint withRadius:size*EYE_RADIUS inContext:context]; eyePoint.x +=size * EYE_H * 2; //右眼
[self drawCircleAtPoint:eyePoint withRadius:size*EYE_RADIUS inContext:context]; // no nose // draw mouth ,用贝塞尔曲线画mouth,就是在两点之间画条线,然后通过一个控制点调整这条线 #define MOUTH_H 0.45 #define MOUTH_V 0.40 #define MOUTH_SMILE 0.25 CGPoint mouthStart; //嘴的左边点 mouthStart.x = midPoint.x - size * MOUTH_H; mouthStart.y = midPoint.y + size * MOUTH_V; CGPoint mouthEnd = mouthStart; //嘴的右边点 mouthEnd.x += size * MOUTH_H * 2; CGPoint mouthCP1=mouthStart; //控制点1 mouthCP1.x += size * MOUTH_H * 2/3; CGPoint mouthCP2=mouthEnd; //控制点2 mouthCP2.x -= size * MOUTH_H * 2/3; //float smile=1.0; //smile表示移动控制点,0表示在中间,1表示控制点下移,因为下面是进行加法操作。所以1.0表示笑脸,-1.0表示哭脸 float smile = [self.dataSource smileForfaceView:self];//使用委托 if(smile<-1)smile = -1; if(smile>1)smile = 1; CGFloat smileOffset=MOUTH_SMILE * size * smile; mouthCP1.y += smileOffset; mouthCP2.y += smileOffset; CGContextBeginPath(context); CGContextMoveToPoint(context, mouthStart.x, mouthStart.y);//移动到左边起始点 CGContextAddCurveToPoint(context, mouthCP1.x, mouthCP1.y, mouthCP2.x, mouthCP2.y, mouthEnd.x, mouthEnd.y); CGContextStrokePath(context); //描边 } @end
//HappinessViewController.h
#import <UIKit/UIKit.h>
@interface HappinessViewController : UIViewController
@property (nonatomic) int happiness; // 0 is sad,100 is very happy.model里的幸福度和view里的表达方式不一样,可以演示controller如何把model翻译给view听
@end

 //HappinessViewController.m
#import "HappinessViewController.h" #import "faceView.h"
@interface HappinessViewController()<FaceViewDataSource>//私有实现此协议
@property (nonatomic,weak) IBOutlet faceView *faceView;//有了faceView(model),在controller创建一个它的outlet,然后就可以在storyboard里拖出来了。 (在storyboard里拖出通用view填充整个storyboard,在identity inspector里把它的类改成faceView,然后stroryboard里的view就是faceView了)(注意拖的时候stroryboard的view上有个黄色图标代表controller)
@end

@implementation HappinessViewController
@synthesize happiness=_happiness;
@synthesize faceView=_faceView;
-(void) setHappiness:(int)happiness//model改变,重绘view,要实现的方法

{
      _happiness=happiness;

     [self.faceView setNeedsDisplay]; //happiness一旦被设置,faceView就会被重绘。因为我们的view就是反映了幸福度。
}

-(void)setFaceView:(faceView *)faceView //在setter里添加手势识别!当系统把faceView和Controller连起来的时候,这是最佳的放置手势识别的时机。

{    
     _faceView=faceView;    

     [self.faceView addGestureRecognizer:[[UIPinchGestureRecognizer alloc] initWithTarget:self.faceView  action:@selector(pinch:)]]; //这里的target就是这个手势的处理者,也就是self.faceView

     [self.faceView addGestureRecognizer:[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handleHappinessGesture:)]];

     self.faceView.dataSource =self;//控制器把自己设置为委托

}          //添加手势识别到faceView,faceView会通过pinch来处理手势。



-(void)handleHappinessGesture:(UIPanGestureRecognizer*)gesture 

{    
      if ((gesture.state==UIGestureRecognizerStateChanged)||(gesture.state==UIGestureRecognizerStateEnded))

     {        
          CGPoint translation=[gesture translationInView:self.faceView];         

           self.happiness -= translation.y/2;        

          [gesture setTranslation:CGPointZero inView:self.faceView];    
     }
}


-(float)smileForfaceView:(faceView *)sender //The controller,part of its job is to interpret the data in the model ,for the views.
{
return (self.happiness-50)/50.0; //笑脸程度-1到1,The model‘s happiness is 0-100,此句为转化 } -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation //实现自动旋转,但运行发现没有调用drawRect重绘,需要在faceView.m里设置initWithFrame方法 { return YES; } @end

 

[Stanford 2011] hapiness

标签:des   style   blog   http   io   ar   color   os   使用   

原文地址:http://www.cnblogs.com/Xylophone/p/4138402.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!