Posted on

UIView及繪圖練習範例APP

作業目標:Youtube操作影片
練習原始碼:homework0803

這個作業主要是在練習對view以及簡單的繪圖的操作,還有timer的使用
因此我截錄一些我覺得是練習關鍵的程式碼

下面的是viewController的相關程式碼

一個個出現的程式碼,按下show按鈕時觸發

- (IBAction)showButtonClick {
    [self clearButtonClick];
    [self.circleNumber resignFirstResponder];
    total = [self.circleNumber.text integerValue];
    index = 0;
    //設定間隔一個個產生circle
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(addItems:) userInfo:NULL repeats:YES];
}

取得圓圈排列坐標的程式碼,傳入值為圓半徑及角度

//取得坐標
- (CGPoint)getPoint:(int) radius withAngel:(CGFloat) degrees{

    int y = sin(degrees * M_PI / 180)*radius;
    int x = cos(degrees * M_PI / 180)*radius;
    CGPoint btCorner = CGPointMake(x, y) ;
    return btCorner;
}

下面的程式碼則是在被新增的UIView物件裡面

顯示動畫,這邊要注意的是因為定位點的關係,由於我們希望元件的縮放是以view的中心來做縮放
所以改變的值是self.bounds,一般我們在做元件內部繪圖事件,都會使用self.bounds
而self.frame則是在外部設定物件資訊時使用。

-(void) playAnimation{
    [UIView animateWithDuration:0.5f
                     animations:^{
                         self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, 50, 50);
                     }completion:^(BOOL finished) {
                         [UIView animateWithDuration:0.5f
                                          animations:^{
                                               self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, 30, 30);
                                          }completion:^(BOOL finished) {
                                          }];

                     }];
}

另外,因為- (id)initWithFrame:(CGRect)frame被呼叫的時間是在circle被新建的時後,而不是在被加到畫面時,
為了落實動畫的被執行時間,所以我又實作了layoutSubviews這個方法,
並加上BOOL init當今天是第一次被呼叫時,才會執行playAnimation

-(void)layoutSubviews{
    if(init){
        [self playAnimation];
        init = NO;
    }
}

然後實作按下後縮小離開時恢復大小的功能

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [UIView animateWithDuration:0.2f
                     animations:^{
                         self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, 0, 0);
                     }
                     completion:^(BOOL finished) {
                     }];
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

    [UIView animateWithDuration:0.2f
                     animations:^{
                         self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, 30, 30);
                     }
                     completion:^(BOOL finished) {
                     }];

}

原始碼下載:homework0803

Posted on

上課筆記(五) – UIView操作及繪圖介紹

view介紹

  1. UIWindow是會在一開始便被xcode建立起來,裡面有很多view。
  2. View的操作:
    1. 於上層操作subview: 在supervview裡是用MutableArray的index去管理subView,這index就是tag,tag=0是代表subview自己。
      [self addSubView: view];//新增view
      [self insertSubView: view atIndex:0];//新增view在layer0
      [self insertSubView:view belowSubview:upView];//新增view在upView之下
      [self insertSubView:view aboveSubview:upView];//新增view在upView之上
      [self exchangeSubviewAtIndex:0 withSubviewAtIndex:1];//將第0層的物件和第1層的調換
      UIView view = [self viewWithTag:1];//取出在storyboard中tag為1的物件
    2. 移除自己: [view removeFromSuperview];
    3. 設為隱藏:[view setHidden:YES];
  3. 繪圖資訊相關的包括CGRect和CGSize及CGPoint,可以用NSValue包起來
        //將NSRect放入NSArray中
        NSMutableArray *array = [[NSMutableArray alloc] init];
        NSValue *value;
        CGRect rect = CGRectMake(0, 0, 320, 480);
        value = [NSValue valueWithBytes:&rect objCType:@encode(CGRect)];
        [array addObject:value];
        NSLog(@"array:%@",array);
    
        //從Array中提取
        value = [array objectAtIndex:0];
        [value getValue:&rect];
        NSLog(@"value:%@",value);
  4. view有兩個用來描述其資訊的rect:framebounds
    這個網頁有說明這兩者的不同:http://n11studio.blogspot.tw/2012/06/frame-bounds.html
    值得一題的是這兩者的定位點不同,bounds是在畫面的中心,frame則是在左上角。

    1. Frame:Frame指定了View相對於其父View座標系的位置和大小,用在想要加入一個新產生的view時。
    2. Bounds:Bounds則是view相對於自身坐標系的位置和大小,bounds的起點通常都是(0,0)。處理事件或要畫內部的元件時使用。
    3. Center:顧名思義就是view的Frame的中心。
  5. 要注意,在viewDidLoad裡取得的frame和viewWillAppear裡的並不一樣,在viewWillAppear裡時的x及y坐標位置才會被移到正確位置。
  6. 元件自動縮放:imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
  7. UIView的各個函數呼叫時間(請見此),以下說明幾個我曾用過的:
    1. setNeedsDisplay:讓uiview重新執行drawRect
    2. setNeedsLayout:重新計算view layout的大小
    3. layoutSubviews:需要調整subview的大小時呼叫(詳細解說
    4. 其他view相關處理事件
      – didAddSubview:
      – willRemoveSubview:
      – willMoveToSuperview:
      – didMoveToSuperview
      – willMoveToWindow:
      – didMoveToWindow
    5. view的動畫處理相關
      + animateWithDuration:delay:options:animations:completion:
      + animateWithDuration:animations:completion:
      + animateWithDuration:animations:
      + transitionWithView:duration:options:animations:completion:
      + transitionFromView:toView:duration:options:completion:

Drawing介紹

    1. 每次繪圖都需要取出繪圖物件:CGContextRef ctx = UIGraphicsGetCurrentContext();
    2. 畫三角型範例:
      - (void)drawRect:(CGRect)rect
          CGContextRef context = UIGraphicsGetCurrentContext();
          [[UIColor whiteColor] set];
          UIRectFill([self bounds]);
          CGContextBeginPath(context);
          CGContextMoveToPoint(context, 50, 50);
          CGContextAddLineToPoint(context, 50, 150);
          CGContextAddLineToPoint(context, 150, 50);
          CGContextClosePath(context);
      
          [[UIColor blueColor] setFill];
          [[UIColor blackColor] setStroke];
          CGContextDrawPath(context, kCGPathEOFillStroke);
      }
    3. 畫圓型範例:
      - (void)drawRect:(CGRect)rect
      {
          CGContextRef ctx = UIGraphicsGetCurrentContext();
          CGContextAddEllipseInRect(ctx, rect);
          CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
          CGContextFillPath(ctx);
      
      }

 

Posted on

切換View會用到的函數

切換UIViewController的兩種方式

1. 有NavigationController時

方法一:右側進入

SecondViewController* svc=[[SecondViewController alloc]init];
[self.navigationController pushViewController:svc animated:YES];

返回到上一頁

[self.navigationController popViewControllerAnimated:YES];

方法二:下面切入

SecondViewController* svc=[[SecondViewController alloc]init];
[self.navigationController presentModalViewController:svc animated:YES];

返回到上一個UIViewController

[self.navigationController dismissModalViewControllerAnimated:YES];

2、没有NavigationController的切換方法

SecondViewController* svc=[[SecondViewController alloc]init];
[self presentModalViewController:svc animated:YES];

返回到上一個UIViewController

[self dismissModalViewControllerAnimated:YES];

取得子viewController或父ViewController的方式

假設View A是來源的ViewController,而View B是目標ViewController。
1.取得子viewController

((B *)self.presentedViewController).屬性名

2.取得父viewController

((A *)self.presentingViewController).屬性名

其中括號和類名是一種強制轉類型的用法。