代码之家  ›  专栏  ›  技术社区  ›  cspam

使用UIViewAnimationTransitionFlipFromRight在按下时翻转UIButton并在“另一侧”显示新按钮

  •  0
  • cspam  · 技术社区  · 11 年前

    为MOXY编辑。

    我有一个顶部有图像的按钮阵列和一个视图为背景色的按钮阵列。当我点击一个按钮时,我想检索该按钮索引,并使用该索引来获得其他视图的适当背景色。。并使用该信息翻转按钮(与图像一起),然后“翻转”以显示背景颜色。

    我的屏幕组成是,ViewControllersView->平铺视图->(按钮阵列)。

     -(void)viewDidAppear:(BOOL)animated{
     _viewContents = [model getRequestedView];  //this retrieves an array of UIButtons(24 
      //of them) whose frames and background colors have already been initialized to fit
       //within the TileView.
     _viewFrontImageContents =[model getRequestedViewFrontCardImagesWithFrame:_viewContents];
    
    for(int screenViewIndex = 0; screenViewIndex < [_viewContents count]; screenViewIndex++){
        [TileView addSubview:[_viewFrontImageContents objectAtIndex:screenViewIndex]];
        [[_viewFrontImageContents objectAtIndex:screenViewIndex] addTarget:self action:@selector(frontOfCardPushed:) forControlEvents:UIControlEventTouchUpInside];
        //[TileView addSubview:[_viewContents objectAtIndex:screenViewIndex]];
        //[[_viewContents objectAtIndex:screenViewIndex] addTarget:self action:@selector(frontOfCardPushed:) forControlEvents:UIControlEventTouchUpInside];
    }
    
    }
    

    //getRequestedViewFrontCardImagesWithFrame方法

    -(NSMutableArray *)getRequestedViewFrontCardImagesWithFrame:(NSArray *)views{
            NSMutableArray *cards = [[NSMutableArray alloc] init];
            UIImage *frontOfCardImage = [UIImage imageNamed:@"Back_of_Tile"];
            UIButton *frontOfCardView;
    
            for(int viewIndex = 0; viewIndex < [views count]; viewIndex++){
                frontOfCardView = [[UIButton alloc] initWithFrame:[[views objectAtIndex:viewIndex] frame]];
                frontOfCardView.backgroundColor = [UIColor colorWithPatternImage:frontOfCardImage];
      //setting the tag of each frontCard to match the view index to keep them aligned.
                frontOfCardView.tag = viewIndex;
                [cards addObject:frontOfCardView];
    
                if(viewIndex == 0){
                  NSLog(@"first frontcard frame %@, first _viewContentsFrame %@", [cards objectAtIndex:0], [views objectAtIndex:0]);
        }
            }
            return cards;
        }
    

    上面我添加了UIButtons,上面有一个图像,代表“扑克牌的正面”。所述按钮的索引与_viewContents数组的索引完全匹配。我设置每个按钮以匹配已经初始化的按钮的框架(大小和位置)。

    -(IBAction)frontOfCardPushed:(id)sender{
    int containerViewIndex = -1;
    UIButton *pressedButton = (UIButton *)sender;
    NSLog(@"Button Index: %i", pressedButton.tag);
    containerViewIndex = pressedButton.tag;
    UIView *container = [TileView viewWithTag:containerViewIndex];
    UIView *viewToShow = [_viewContents objectAtIndex:containerViewIndex];
    NSLog(@"container: %@, viewToShow: %@", container, viewToShow);
    //viewToShow.frame = container.frame;
    //NSLog(@"container: %@, viewToShow: %@", container, viewToShow);
    
    [UIView transitionWithView:container duration:0.5 options:UIViewAnimationOptionTransitionFlipFromRight
                    animations:^{
                        [sender removeFromSuperview];
                        [container addSubview:viewToShow];
                    }
                    completion:nil];
    

    我想做的是使用一个转换,即“UIViewAnimationTransitionFlipFromRight”,在按下时“翻转卡片”,以显示关联的_viewContents数组的内容。我还希望用户能够将卡片向后翻转,以显示正面CardButton的图像。上面的这段代码只关注卡片的第一次翻转,以避免出现代码墙。

    我看到了合适的背景颜色,但动画本身不起作用。

    我做错了什么?我需要向这段代码添加/删除什么才能使其正常工作?

    • 编辑* 如下文对Moxy所述,请查看getRequestedViewFrontCardImagesWithFrame方法中whats的输出。在请求带有适当标记的视图后,查看第一张卡的输出,然后查看frontCardPushed:方法中容器视图的输出——它们不匹配。我正在打印按钮索引,这样你就可以看到我正在点击第一个TileView子视图。_viewContents视图的标记是一个表示颜色的标记集,与我在getRequestedViewFrontCardImagesWithFrame方法中分配的TileView标记无关。然而,令人困惑的是,当我打印第一个按钮时,在给它分配了一个标签之后,标签却没有列出。

    输出:

    //why doesnt the first frontcard frame list a tag? I had just assigned it one?
    

    第一个前卡框架UIButton:0x1c53f020;帧=(6 5;145 145); 不透明=否;layer=CL层:0x1c534ac0,第一个视图内容帧(_V) UI按钮:0x1d045220;帧=(6 5;145 145);不透明=否;标签=3; 层=C层:0x1d04535

    按钮索引:0
    容器:UI视图:0x1c53a400;框架=(51 83;922 614); clipseToBounds=是;自动复位=W+H;手势识别器= NSA阵列:0x1d05afe0>;layer=C图层:0x1c53a460,视图显示: UI按钮:0x1d045220;帧=(6 5;145 145);不透明=否;标签=3; 层=C层:0x1d045350

    2 回复  |  直到 11 年前
        1
  •  3
  •   avenged    11 年前

    一种更简单的方法是使用[UIWiew transitionWithView]:

    [UIView transitionWithView:self.flipButton
                      duration:0.8
                       options:displayingFirstButton ? UIViewAnimationOptionTransitionFlipFromLeft : UIViewAnimationOptionTransitionFlipFromRight
                    animations:^{
                      //change image for button
                    }
                    completion:^(BOOL finished) {
    
                    }];
    
        2
  •  2
  •   Moxy    11 年前

    您可以通过使用容器视图来按住按钮来使其工作。

    -(void)viewDidAppear:(BOOL)animated
    {
        _viewContents = [model getRequestedView];  //this retrieves an array of UIButtons(24 of them) whose frames and background colors have already been initialized to fit within the TileView.
    
        for(int i = 0; i < [_viewContents count]; i++){
            UIView *container = [[UIView alloc] initWithFrame:[[_viewContents objectAtIndex:screenViewIndex] frame]]; 
            container.tag = i;      
            UIButton *frontOfCardView = [[UIButton alloc] initWithFrame:container.bounds];
            frontOfCardView.backgroundColor = [UIColor colorWithPatternImage:_frontOfCardImage];
            frontOfCardView.tag = i;
            [container addSubview:frontOfCardView]; 
            [frontOfCardView addTarget:self action:@selector(frontOfCardPushed:) forControlEvents:UIControlEventTouchUpInside];
            [tileView addSubview:container];
        }
    }
    
    -(IBAction)frontOfCardPushed:(UIButton *)sender
    {
        UIView *container = [tileView viewWithTag:sender.tag];
        UIView *viewToShow = [_viewContents objectAtIndex:index];
        viewToShow.frame = sender.frame;
        [UIView transitionWithView:container
                          duration:0.5
                           options:UIViewAnimationOptionTransitionFlipFromRight
                        animations:^{
                          [sender removeFromSuperView];
                          [container addSubview:viewToShow];
                        }
                        completion:nil];
    }
    

    我还没有测试过,但应该可以。无论如何,这不是很干净/漂亮的代码。但是,我知道这只是为了学习。

    如果仍然不起作用,请告诉我。

    编辑:

    我做了一个简单的项目,以单个视图控制器为例。我认为你记录所有视图/按钮的方式是无用的。在这种情况下,模型只是一种背景色,您所想做的就是显示/隐藏它,所以一旦您将颜色分配给按钮,它所需要知道的就是切换状态,因此您甚至不需要标记。(在其他情况下,控制器需要识别接收到事件的按钮,以便询问模型需要什么内容)

    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic, strong) NSArray *colors;
    @property (nonatomic, strong) UIView *tileView;
    @end
    
    @implementation ViewController
    
    #pragma mark -
    #pragma Getters and setters
    
    // I'm assuming the tileView is just a simple view to wrap all the buttons
    // PS : propertys should always start with a lowercase letter
    -(UIView *)tileView
    {
        if (!_tileView) {
            _tileView = [[UIView alloc] initWithFrame:self.view.bounds];
            _tileView.backgroundColor = [UIColor greenColor];
        }
        return _tileView;
    }
    
    // The model: just an array of colors, you can generate it or use other complicated stuff
    -(NSArray *)colors
    {
        if (!_colors) {
            _colors = @[[UIColor blackColor], [UIColor redColor], [UIColor grayColor], [UIColor yellowColor],
                        [UIColor whiteColor], [UIColor blueColor], [UIColor orangeColor], [UIColor darkGrayColor],
                        [UIColor lightGrayColor], [UIColor cyanColor], [UIColor brownColor], [UIColor magentaColor],
                        [UIColor blackColor], [UIColor redColor], [UIColor grayColor], [UIColor yellowColor],
                        [UIColor whiteColor], [UIColor blueColor], [UIColor orangeColor], [UIColor darkGrayColor],
                        [UIColor lightGrayColor], [UIColor cyanColor], [UIColor brownColor], [UIColor magentaColor]];
        }
        return _colors;
    }
    
    #pragma mark -
    #pragma mark Helper methods
    
    #define ROWS 6
    #define COLUMNS 4
    #define CARD_HEIGHT 60.0f
    #define CARD_WIDTH 40.0f
    
    // Gets the width that each card can use based on the chose number of columns
    -(CGFloat)horizontalStep
    {
        return self.tileView.frame.size.width / COLUMNS;
    }
    
    // Gets the height that each card can use based on the chose number of columns
    -(CGFloat)verticalStep
    {
        return self.tileView.frame.size.height / ROWS;
    }
    
    // Calculates the center for the card frame (return (0,0) if the index is out of bounds)
    -(CGPoint)centerForCardAtIndex:(NSUInteger)index
    {
        CGFloat x = 0.0f, y = 0.0f;
        if (index < [self.colors count]) {
            x = [self horizontalStep] * 0.5f + (index % COLUMNS) * [self horizontalStep];
            y = [self verticalStep] * 0.5f + (index / COLUMNS) * [self verticalStep];
        }
        return CGPointMake(x, y);
    }
    
    // Gets the frame for the card at index
    -(CGRect)frameForCardAtIndex:(NSUInteger)index
    {
        CGPoint center = [self centerForCardAtIndex:index];
        CGPoint origin = CGPointMake(center.x - CARD_WIDTH * 0.5f, center.y - CARD_HEIGHT * 0.5f);
        return CGRectMake(origin.x, origin.y, CARD_WIDTH, CARD_HEIGHT);
    }
    
    -(void)layoutCards
    {
        // Add tileView to the controller's view
        [self.view addSubview:self.tileView];
        // Create the card buttons and add them to the tile view
        for (int i = 0; i < [self.colors count]; i++) {
            UIButton *card = [UIButton buttonWithType:UIButtonTypeCustom];
            card.frame = [self frameForCardAtIndex:i];
    
            // The only use of the model IN THIS CASE
            card.backgroundColor = self.colors[i];
            [card setImage:[UIImage imageNamed:@"back_of_tile.png"]
                  forState:UIControlStateNormal];
    
            [card addTarget:self
                     action:@selector(cardPressed:)
           forControlEvents:UIControlEventTouchUpInside];
    
            [self.tileView addSubview:card];
        }
    }
    
    -(void)cardPressed:(UIButton *)card
    {
        [UIView transitionWithView:card
                          duration:0.5
                           options:UIViewAnimationOptionTransitionFlipFromRight
                        animations:^{
                            card.selected = !card.selected;
                            if (!card.selected) {
                                [card setImage:[UIImage imageNamed:@"back_of_tile.png"]
                                      forState:UIControlStateNormal];
                            } else {
                                [card setImage:nil
                                      forState:UIControlStateNormal];
                            }
                        }
                        completion:nil];
    }
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        [self layoutCards];
    }