斯坦福IOS開發第五課(第二部分)

來源:互聯網
上載者:User

標籤:ios開發   手勢識別   struts   xcode   斯坦福   

轉載請註明出處

http://blog.csdn.net/pony_maggie/article/details/27845257


作者:小馬


 

五 程式碼範例

上面講到的知識點在這個樣本都有涉及。另外我這裡也只是分析部分重要的代碼,更多的知識瞭解請自行下載代碼(文章最下面有地址)並結合公開課一起看。

 

建立一個single view的工程,然後新增一個視圖類,叫FaceView,如所示:


 

然後我們在storyboard裡拖進來一個通用的視圖控制項,作為上面那個視圖類對應的視圖,如所示:

     

 

接著要做視圖控制器類裡增加這個FaceView的oulet以便我們可以操作視圖,如下:


 

開始關注代碼了。


我們打算在FaceView畫一個笑臉,來反映幸福的程式,一個笑臉由下面幾部分組成:

臉的輪廓(一個大圓)

眼睛(兩個小圓)

嘴巴(貝茲路徑)

 

好,代碼如下:

- (void)drawCircleAtPoint:(CGPoint)p withRadius:(CGFloat)radius inContext:(CGContextRef)context{    //設定成當前的context    //使用UIKit來進行任意繪圖,你會希望儲存當前的UIKit上下文,包括所有已經繪製的內容,    //接著切換到一個全新的繪圖上下文中    UIGraphicsPushContext(context);    CGContextBeginPath(context);    CGContextAddArc(context, p.x, p.y, radius, 0, 2*M_PI, YES);    CGContextStrokePath(context);    UIGraphicsPopContext();}//This method is called when a view is first displayed or when an event occurs that invalidates a visible part of the view// Only override drawRect: if you perform custom drawing.// An empty implementation adversely affects performance during animation.- (void)drawRect:(CGRect)rect{    CGContextRef context = UIGraphicsGetCurrentContext();        //draw face (circle)    //draw eyes (2 circles)    //no nose    //mouth (Bézier curve)    CGPoint midPoint;    //注意這裡,因為畫圓本身是基於faceView自己,所以計算座標也是相對於faceView,所以要用bounds下的座標    //當我們把faceView在storyboard裡拉下一些,然後用frame對比看效果就很明顯了    midPoint.x = self.bounds.origin.x + self.bounds.size.width/2;    midPoint.y = self.bounds.origin.y + self.bounds.size.height/2;    CGFloat size = self.bounds.size.width/2; //大圓半徑    if (self.bounds.size.height < self.bounds.size.width) {        size = self.bounds.size.height/2;    }    size *= self.scale;        //設定線條寬度和顏色等    CGContextSetLineWidth(context,5.0);    [[UIColor blueColor] setStroke];    [self drawCircleAtPoint:midPoint withRadius:size inContext:context];    #define EYE_H 0.35#define EYE_V 0.35#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];      #define MOUTH_H 0.45#define MOUTH_V 0.45#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;    mouthCP1.x += size * MOUTH_H * 2/3;    CGPoint mouthCP2 = mouthEnd;    mouthCP1.x -= size * MOUTH_H * 2/3;        float smile = [self.dataSource smileForFaceView:self];    if (smile < -1)    {        smile = -1;    }    else 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);            }

先上個圖看一下效果:


 

 

這裡有一點要注意,我們需要考慮橫屏的情況,因為我是在xcode5環境下寫的代碼,就不用老師進的Struts and springs了,直接加約束,讓storyboard幫我自動計算,如下所示:

  

 

然後再來看一下效果,


這個似乎也不是我們想要的,它自動展開了,我們還需要加一些代碼調整,橫屏時要重繪笑臉。

 

- (void)setup{    //UIViewContentModeRedraw可以使旋轉螢幕時調用drawRect    self.contentMode = UIViewContentModeRedraw;}- (void)awakeFromNib{    [self setup];}


這樣再來看看效果:


 

現在我們來添加手勢識別,讓這個笑臉支援縮放功能。

 

需要在facView和根控制器裡加入相應的代碼,facView裡:

//手勢識別,縮放功能- (void)pinch:(UIPinchGestureRecognizer *)gesture{    if ((gesture.state == UIGestureRecognizerStateChanged) ||        (gesture.state == UIGestureRecognizerStateEnded))    {        /*         下面兩行代碼其實和這一行效果是一樣的,所以注意理解第二行置1的作用.可以查一下gesture.scale是怎麼取值的         self.scale = gesture.scale;         */        self.scale *= gesture.scale;        NSLog(@"scale:%f", gesture.scale);        gesture.scale = 1;    }}

然後在根控制器裡:

[self.faceView addGestureRecognizer:[[UIPinchGestureRecognizer alloc] initWithTarget:self.faceView action:@selector(pinch:)]];

看看效果:

     

 

 


接下來繼續添加功能,我們用代理和上下滑動的手勢識別來實現通過上下滑動來控制笑臉的微笑程度。

 

手勢識別好理解,為什麼要用代理呢?可以這樣理解,FaceView裡的這個笑臉,是通過一個幸福指數(controller裡的happiness)來控制,這個幸福指數是一個資料來源,那FaceView是一個視圖,視圖本身是不能擁有資料來源的,所以要把controller作為代理管理資料來源。

 

 

下面是代碼。

 

添加手勢識別

添加一個上下滑動的手勢,注意target不是faceView而是controller,所以處理函數也在controller裡實現, UIPanGestureRecognizer主要用於拖動,就是捕捉手指的位移

 

[self.faceView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleHappinessGesture:)]];self.faceView.dataSource = self; //把控制器設為代理

注意下面inView後面都是指定self.faceView作為參數,這個參數的意義是你打算讓這個手勢轉換在哪個座標系工作,當然是我們的FaceView了

- (void)handleHappinessGesture:(UIPanGestureRecognizer *)gesture{    if ((gesture.state == UIGestureRecognizerStateChanged) ||        (gesture.state == UIGestureRecognizerStateEnded))    {        CGPoint translation = [gesture translationInView:self.faceView];//轉換成座標系中的點位移變化        self.happiness -= translation.y / 2; //除2的作用時,減少變化的幅度        [gesture setTranslation:CGPointZero inView:self.faceView];//置0可以讓變化幅度不累加    }}


接下來實現協議中定義的函數,

- (float)smileForFaceView:(FaceView *)sender{    return (self.happiness - 50)/50.0;//happiness是0~100, 微笑程度是-1~1,需要轉換}

 

使用代理的位置

 

float smile = [self.dataSource smileForFaceView:self];    if (smile < -1)    {        smile = -1;    }    else if (smile > 1)    {        smile = 1;    }

模擬器下運行,會發現隨著滑鼠的上下拖動,笑臉的微笑程度會變化。


代碼:

https://github.com/pony-maggie/Happiness

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.