2015-01-23 3 views
1

나는이 주제에 대한 많은 문서를 알고 있으며 내가 읽은 것에서 많이 배웠다. 내 문제는 내가 여기에 viewcontroller & 내 UIView 자신의 클래스를 만들려고 할 때 사용자 정의 UIView를 만들기 시작, & 작업 응용 프로그램 내에서 사용되는 전화로 꽤 혼란 무엇입니까 나는 그것을 달성하기 위해해야합니다.iOS, 사용자 정의 popover 스타일 만들기 UIView

클래스의 전반적인 목표는 사용자 정의보기를 인스턴스화 한 다음 표시하는보기 컨트롤러 하나를 선택하는 것입니다. 사용자를위한 시각적 효과는 단추를 클릭 한 다음 단추 경계에서 나타나는 창이 생기고 (아래 코드는 현재 왼쪽 위의 위치 지정을 사용하지만) 스위치 조합을 표시합니다 (레이블 &). 등받이가있는 & 저장 버튼.

당신은 내 코드에서 내가이 프로세스를 달성하기 위해 필요한 것을 볼 수있다. 나는 하나의 함수로 구현할 수 있었다. (다시 이것은 viewcontroller 내에서 생성했다.) 필자가 지금 겪고 있고, 이해할 수없는 것은 커스텀 뷰를 임포트하기위한 것이고, 메인 뷰 컨트롤러의 버튼의 동작에서 뷰를 self.view에 추가한다.

- (void)makeBox{ 
    //view bounds 
    CGFloat viewWidth = CGRectGetWidth(self.view.frame); 
    CGFloat viewHeight = CGRectGetHeight(self.view.frame); 

    //red box x, y & size 
    CGFloat startx = (viewWidth/100) * 10; 
    CGFloat starty = (viewHeight /100) * 20; 
    CGFloat width = (viewWidth/100) * 80; 
    CGFloat height = (viewHeight /100) * 70; 
    CGRect view1Frame = CGRectMake(startx, starty, width, height); 

    //label & switch frame 
    CGRect labelMR = CGRectMake(10, ((height/100) * 12), ((width/100) * 80) - 7.5, 25); 
    CGRect switchMR = CGRectMake(((width/100) * 80) + 7.5, ((height/100) * 11), ((width/100) * 10), 15); 

    //this is repeated for 6 other labels & switches 

    CGRect backButtonR = CGRectMake(5, 5, 50, 35); 
    CGRect saveButtonR = CGRectMake((width - 50), 5, 50, 35); 

    if (!self.view1) { 
     self.switchM = [[UISwitch alloc] initWithFrame:switchMR]; 
     self.switchM.tag = 10; 
     if(self.monday){ //self.monday refers to a BOOL property of the viewcontroller that this was originally made in 
      self.switchM.on = true; 
     } else{ 
      self.switchM.on = false; 
     } 
     [self.switchM addTarget:self action:@selector(switched:) forControlEvents:UIControlEventTouchUpInside]; 

     // this switch instantiation process is repeated 6 other times 

     self.backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
     [self.backButton addTarget:self 
          action:@selector(hideBox) 
        forControlEvents:UIControlEventTouchUpInside]; 
     [self.backButton setTitle:@"Back" forState:UIControlStateNormal]; 
     self.backButton.frame = backButtonR; 


     self.saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
     [self.saveButton addTarget:self 
          action:@selector(daysChanged) 
        forControlEvents:UIControlEventTouchUpInside]; 
     [self.saveButton setTitle:@"Save" forState:UIControlStateNormal]; 
     self.saveButton.frame = saveButtonR; 


     self.labelM = [[UILabel alloc] initWithFrame:labelMR]; 
     self.labelM.layer.masksToBounds = YES; 
     self.labelM.layer.cornerRadius = 5; 
     self.labelM.layer.borderColor = [UIColor blackColor].CGColor; 
     self.labelM.layer.borderWidth = .5; 
     self.labelM.text = @" Monday"; 
     self.labelM.backgroundColor = [UIColor whiteColor]; 

     //again - repeated 6 times 

     //use this starting frame to make the 'popover' appear small at first 
     CGRect startFrame = CGRectMake(10, 10, 10, 10); 

     self.view1 = [[UIView alloc] initWithFrame:startFrame]; 

     [self.view addSubview:self.view1]; 
     [UIView animateWithDuration:0.5 animations:^(void){ 

      self.view1.layer.cornerRadius = 10; 
      self.view1.layer.borderColor = [UIColor blackColor].CGColor; 
      self.view1.layer.borderWidth = .5; 
      [self.view1 setBackgroundColor:[UIColor lightGrayColor]]; 


      self.view1.frame = view1Frame; 

     } completion:^(BOOL finished){ 

      [self.view1 addSubview:self.labelM]; 
      [self.view1 addSubview:self.switchM]; 
      //repeat 6 times for other labels & switches 
     }]; 

    } 
    else { 
     [UIView animateWithDuration:0.3 animations:^() { 
      self.view1.frame = view1Frame; 

     } completion:^(BOOL finished) { 
      self.labelM.frame = labelMR; 
      self.switchM.frame = switchMR; 

      //repeated for the other 6 

      self.backButton.frame = backButtonR; 
      self.saveButton.frame = saveButtonR; 
     }]; 
    } 
} 

-(void) hideBox{ 
    //back button was selected 
    [UIView animateWithDuration:0.5 animations:^(void){ 
     [self.view1 removeFromSuperview]; 
     self.view1 = nil; 
    }]; 
} 

나는 내가 뭘로/코드를 통해이 호출, 내가 init 또는 initWithFrame: 중 하나를 오버라이드 (override) 할 필요가 있음을 이해합니다. initWithFrame:을 포함하는보기 컨트롤러 경계에 전달할 수 있으며 그 중 사용자 정의보기를 계산할 수 있으며 애니메이션을 어떻게 처리합니까?

저장 버튼을 눌렀을 때 알릴 위임 프로토콜을 설정하는 데 성공했습니다. 그 부분은 제가 이해합니다. 그 부분은 제가 분명하지 않습니다.

답변

0

나는 실제로 일을있어! (비록 내가 이것이 가장 깨끗하거나 가장 수완있는 방법이라고 약속 할 수는 없지만, 우리는 그것에 대해 연구 할 것이다).

는 여기에 내가했던 일이야 :

분할 3 기능, initWithWidth:andHeight:forView, openBox & updateBoxWithWidth:andHeightmakeBox 기능. 저장 단추가 눌려 졌음을 부모에게 알리는 saveButton 대리자 메서드를 사용했습니다.

@synthesize delegate; 
    -(id) initWithWidth:(CGFloat)inWidth andHeight:(CGFloat)inHeight withView: (UIView*) theView{ 
    self = [super init]; 

    self.mainView = theView; 
    //super view bounds 
    self.viewWidth = inWidth; 
    self.viewHeight = inHeight; 

    //red box x, y & size 
    CGFloat startx = (self.viewWidth/100) * 10; 
    CGFloat starty = (self.viewHeight /100) * 20; 
    self.width = (self.viewWidth/100) * 80; 
    self.height = (self.viewHeight /100) * 70; 
    self.view1Frame = CGRectMake(startx, starty, self.width, self.height); 

    //label & switch frame 
    self.labelMR = CGRectMake(10, ((self.height/100) * 12), ((self.width/100) * 80) - 7.5, 25); 
    self.switchMR = CGRectMake(((self.width/100) * 80) + 7.5, ((self.height/100) * 11), ((self.width/100) * 10), 15); 

    //repeated for the other 6 
    self.backButtonR = CGRectMake(5, 5, 50, 35); 
    self.saveButtonR = CGRectMake((self.width - 50), 5, 50, 35); 


    self.switchM = [[UISwitch alloc] initWithFrame:self.switchMR]; 
    self.switchM.tag = 10; 
    if(self.monday){ 
     self.switchM.on = true; 
    } else{ 
     self.switchM.on = false; 
    } 
    [self.switchM addTarget:self action:@selector(switched:) forControlEvents:UIControlEventTouchUpInside]; 

    self.labelM = [[UILabel alloc] initWithFrame:self.labelMR]; 
    self.labelM.layer.masksToBounds = YES; 
    self.labelM.layer.cornerRadius = 5; 
    self.labelM.layer.borderColor = [UIColor blackColor].CGColor; 
    self.labelM.layer.borderWidth = .5; 
    self.labelM.text = @" Monday"; 
    self.labelM.backgroundColor = [UIColor whiteColor]; 

    //repeated for the other 6 
    self.saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    [self.saveButton addTarget:delegate 
         action:@selector(daysChanged) 
       forControlEvents:UIControlEventTouchUpInside]; 
    [self.saveButton setTitle:@"Save" forState:UIControlStateNormal]; 
    self.saveButton.frame = self.saveButtonR; 
    return self; 
} 


-(void) openBox{ 
    CGRect startFrame = CGRectMake(10, 10, 10, 10); 

    self.view1 = [[UIView alloc] initWithFrame:startFrame]; 

    [self.mainView addSubview:self.view1]; 
    [UIView animateWithDuration:0.5 animations:^(void){ 

     self.view1.layer.cornerRadius = 10; 
     self.view1.layer.borderColor = [UIColor blackColor].CGColor; 
     self.view1.layer.borderWidth = .5; 
     [self.view1 setBackgroundColor:[UIColor lightGrayColor]]; 

     // repeated for the other 6 

     self.view1.frame = self.view1Frame; 

    } completion:^(BOOL finished){ 
     [self.view1 addSubview:self.labelM]; 
     [self.view1 addSubview:self.switchM]; 

     [self.view1 addSubview:self.backButton]; 
     [self.view1 addSubview:self.saveButton]; 


    }]; 
} 

-(void) updateViewWithWidth: (CGFloat) width andHeight:(CGFloat) height{ 

    //re-calculate 
    self.viewWidth = width; 
    self.viewHeight = height; 

    CGFloat startx = (self.viewWidth/100) * 10; 
    CGFloat starty = (self.viewHeight /100) * 20; 
    self.width = (self.viewWidth/100) * 80; 
    self.height = (self.viewHeight /100) * 70; 
    self.view1Frame = CGRectMake(startx, starty, self.width, self.height); 

    //label & switch frame 
    self.labelMR = CGRectMake(10, ((self.height/100) * 12), ((self.width/100) * 80) - 7.5, 25); 
    self.switchMR = CGRectMake(((self.width/100) * 80) + 7.5, ((self.height/100) * 11), ((self.width/100) * 10), 15); 

    self.backButtonR = CGRectMake(5, 5, 50, 35); 
    self.saveButtonR = CGRectMake((self.width - 50), 5, 50, 35); 

    [UIView animateWithDuration:0.3 animations:^() { 
     self.view1.frame = self.view1Frame; 

    } completion:^(BOOL finished) { 
     self.labelM.frame = self.labelMR; 
     self.switchM.frame = self.switchMR; 
     self.backButton.frame = self.backButtonR; 
     self.saveButton.frame = self.saveButtonR; 
    }]; 

} 

그리고 우리의 부모에 내가 아이폰 응용 프로그램 및 내가 일하고 있어요

@property aBox *theBox; 
... 
- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.theBox = [[aBox alloc] initWithWidth:self.view.frame.size.width andHeight:self.view.frame.size.height withView:self.view]; 
    [self.theBox openBox]; 

} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{ 
    [self.theBox updateViewWithWidth:self.view.frame.size.width andHeight:self.view.frame.size.height]; 
} 
- (void) daysChanged{ 
    NSLog(@"Days Changed!"); 
} 
2

처음 몇 가지 배경.

일반적으로 팝 오버 컨트롤러의 경우 팝 오버보기 자체가 포함 된 단일 투명 루트보기가 있습니다. 이 루트보기는 포함하는 창의 크기이며 일반적으로 다른 모든보기보다 z 순서가 더 높습니다. 다음과 같은 두 가지 이유가 있습니다.

1) Popover는 다른 모든보기 위에 그려야합니다. 루트보기가 다른 모든보기 위에 있지 않은 경우, 팝 오버가 잘리고 모든 내용을 그릴 수 없습니다.

2) 사용자는 일반적으로 팝 오버 (실제로는 취소 작업)를 탭하고 닫을 장소가 필요합니다.

UIPopoverController는 일부 타사 팝 오버와 마찬가지로 이것을 수행합니다. 일부는 심지어 자신의 UIWindows를 사용하기까지합니다.

1) initWithFrame :/setFrame을 :

는 특정 질문에 답하려면 뷰를 포함 할 뷰의 좌표 공간에있는 CGRect을 통과해야한다. 다른 말로하면, 슈퍼 뷰. 투명한 루트보기를 사용하기로 결정하면 popover (화면에 그려주는 부분)는 투명 루트보기의 좌표 공간에 CGRect를 전달합니다.

2) 일반적으로 팝 오버는과 같이 애니메이션 :

// set initial frame 
popover.frame = CGRectMake(x, y, width, 0); 
popover.alpha = 0.0; 
[rootView addSubview:popover]; 

[UIView animateWithDuration:0.5 
       animations:^{ 
        CGRect frame = popover.frame; 
        frame.size.height = some-height; 
        popover.frame = frame; 
        popover.alpha = 1; 
       } 
]; 
+0

의 ViewController

@protocol BoxDelegate -(void) daysChanged; @end __weak id <BoxDelegate> delegate; @interface aBox : UIView @property (nonatomic) BOOL monday; @property (nonatomic, weak) id <BoxDelegate> delegate; //property values for the custom view -(id) initWithWidth: (CGFloat) width andHeight: (CGFloat) height withView: (UIView*) theView; -(void) updateViewWithWidth: (CGFloat) width andHeight: (CGFloat) height; -(void) openBox; @end 

하는 .m 믿고 .H

UIPopoverControl ler는 아이폰에서 사용할 수 없습니다. 루트보기 내에서 팝업을 유지하는 것에 대한 요점을 보았습니다. 그러나이를 사용하는보기마다 코드를 다시 작성하는 데 제한을받지는 않습니까? 나는 질문을 게시 한 이후에 약간의 진전을 보였다. (나는 이것을 곧 반영 할 질문을 업데이트 할 것이다.) init, openbox 및 업데이트 상자의 기능을 분할. –

+0

예, UIPopoverViewController는 iPhone에서 사용할 수 없지만 cocoapod를 통해 쉽게 통합 할 수있는 타사 팝 오버 컨트롤러가 있습니다. 즉, popover에 대해 작성한 코드가 무엇이든 UIPopoverController와 매우 유사한 API/인터페이스가 있어야합니다. 즉, 콘텐츠를주고 위임하고 특정 위치에 표시합니다. –

+0

글쎄, 실제로 뭔가 효과가있어! 나는 그 완벽한 것은 아니지만 개념은 거기에 :) 당신의 도움에 감사드립니다! –

관련 문제