iOS,创建自定义popover样式UIView

时间:2015-01-23 11:00:08

标签: ios objective-c uiview

我知道有很多关于这个主题的文档,而且从我所读过的内容中我已经学到了很多东西。我的问题是我开始在viewcontroller&中创建一个自定义的UIView。现在当我试图让它成为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;
    }];
}

我了解到,当我通过代码进行/调用时,我需要覆盖initinitWithFrame:。我是否通过initWithFrame:包含视图控制器边界,可以计算自定义视图,以及如何处理动画?

我设法设置了委托协议,该协议将在按下保存按钮时通知。我理解的这部分,其他部分我还不清楚。

2 个答案:

答案 0 :(得分:2)

首先是一些背景。

通常对于弹出框控制器,您有一个透明的根视图,其中包含弹出视图本身。此根视图是包含窗口的大小,通常在z顺序上高于所有其他视图。这有两个原因:

1)popover需要在所有其他视图之上绘制。如果根视图不在所有其他视图的顶部,则可以剪切弹出框,而不是绘制其所有内容。

2)用户通常需要一些地方来点击并关闭弹出窗口(实际上是取消操作)。

UIPopoverController就像第三方的popovers一样。有些甚至甚至使用自己的UIWindows。

回答您的具体问题:

1)initWithFrame:/ setFrame:应该传递一个CGRect,它位于将包含视图的视图的坐标空间中。换句话说,超级视图。如果您决定使用透明根视图,则弹出窗口(在屏幕上绘制的部分)将在透明根视图的坐标空间中传递CGRect。

2)通常情况下,popover是动画的:

// 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;
                 }
];

答案 1 :(得分:0)

我实际上得到了它的工作! (虽然我不能保证这是最干净或最有资源的方式 - 我们将继续努力)。

这就是我所做的:

makeBox功能拆分为3个功能,initWithWidth:andHeight:forViewopenBox& updateBoxWithWidth:andHeight。 我使用saveButton委托方法通知父母已按下保存按钮。

的.h

    @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

    @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!");
}