带有Xcode的VFL用于自动布局

时间:2015-10-28 14:41:19

标签: ios objective-c xcode autolayout visual-format-language

我有一个现有的应用程序,它具有用代码编写的所有元素的定位,而不是自动布局。我正在尝试使用现有代码为这些元素添加自动布局。

我正在尝试将两个按钮xButtoncheckButton显示在屏幕底部,彼此相邻,这将适用于所有iPhone屏幕。目前的行为是按钮偏向屏幕底部。

下面是我的VFL所在的代码 - 但是它放在UIView而不是ViewController中。

我试图自己解决这个问题,但没有运气,如果有人能帮我解决这个问题以及这个问题,我会很高兴。 谢谢

@implementation DraggableViewBackground{
    NSInteger cardsLoadedIndex; //%%% the index of the card you have loaded into the loadedCards array last
    NSMutableArray *loadedCards; //%%% the array of card loaded (change max_buffer_size to increase or decrease the number of cards this holds)

    UIButton* checkButton;
    UIButton* xButton;
}
//this makes it so only two cards are loaded at a time to
//avoid performance and memory costs
static const int MAX_BUFFER_SIZE = 2; //%%% max number of cards loaded at any given time, must be greater than 1
static const float CARD_HEIGHT = 386; //%%% height of the draggable card
static const float CARD_WIDTH = 290; //%%% width of the draggable card

@synthesize exampleCardLabels; //%%% all the labels I'm using as example data at the moment
@synthesize allCards;//%%% all the cards

- (void)loadView {
  [self setupView];
  exampleCardLabels = [[NSArray alloc]initWithObjects:@"Are you in the Technology Industry?",@"Do you have more then 3 years of work experiance?",@"Do you have more then 3 years of work experiance?",@"Are you willing to relocate?",@"Did you enjoy this app?", nil]; //%%% placeholder for card-specific information
  loadedCards = [[NSMutableArray alloc] init];
  allCards = [[NSMutableArray alloc] init];
  cardsLoadedIndex = 0;
  [self loadCards];

}

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
    [super layoutSubviews];
    [self setupView];
    exampleCardLabels = [[NSArray alloc]initWithObjects:@"Are you in the Technology Industry?",@"Do you have more then 3 years of work experiance?",@"Do you have more then 3 years of work experiance?",@"Are you willing to relocate?",@"Did you enjoy this app?", nil]; //%%% placeholder for card-specific information
    loadedCards = [[NSMutableArray alloc] init];
    allCards = [[NSMutableArray alloc] init];
    cardsLoadedIndex = 0;
    [self loadCards];
}
    return self;
}

//%%% sets up the extra buttons on the screen
// VFL Visual Formal Language -

- (void)setupView {

#warning customize all of this.  These are just place holders to make it look pretty
self.backgroundColor = [UIColor colorWithRed:.92 green:.93 blue:.95 alpha:1]; //the gray background colors

xButton = [[UIButton alloc]initWithFrame:CGRectMake(60, CGRectGetHeight(self.frame)- 100, 59, 59)];
[xButton setImage:[UIImage imageNamed:@"xButton"] forState:UIControlStateNormal];
[xButton addTarget:self action:@selector(swipeLeft) forControlEvents:UIControlEventTouchUpInside];
[xButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[xButton setBackgroundColor:[UIColor redColor]];

checkButton = [[UIButton alloc]initWithFrame:CGRectMake(200, CGRectGetHeight(self.frame)- 100, 59, 59)];
[checkButton setImage:[UIImage imageNamed:@"checkButton"] forState:UIControlStateNormal];
[checkButton addTarget:self action:@selector(swipeRight) forControlEvents:UIControlEventTouchUpInside];
[checkButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[checkButton setBackgroundColor:[UIColor blueColor]];

   [self addSubview:xButton];
   [self addSubview:checkButton];
}

#warning include own card customization here!
//%%% creates a card and returns it.  This should be customized to fit your needs.
// use "index" to indicate where the information should be pulled.  If this doesn't apply to you, feel free
// to get rid of it (eg: if you are building cards from data from the internet)

-(DraggableView *)createDraggableViewWithDataAtIndex:(NSInteger)index
{
DraggableView *draggableView = [[DraggableView alloc]initWithFrame:CGRectMake((self.frame.size.width - CARD_WIDTH)/2,(self.frame.size.height - CARD_HEIGHT)/2, CARD_WIDTH, CARD_HEIGHT)];
draggableView.information.text = [exampleCardLabels objectAtIndex:index];//%%% placeholder for card-specific information
draggableView.delegate = self;
return draggableView;
}

//%%% loads all the cards and puts the first x in the "loaded cards" array
-(void)loadCards
{
if([exampleCardLabels count] > 0) {
    NSInteger numLoadedCardsCap =(([exampleCardLabels count] > MAX_BUFFER_SIZE)?MAX_BUFFER_SIZE:[exampleCardLabels count]);
    //%%% if the buffer size is greater than the data size, there will be an array error, so this makes sure that doesn't happen

    //%%% loops through the exampleCardsLabels array to create a card for each label.  This should be customized by removing "exampleCardLabels" with your own array of data
    for (int i = 0; i<[exampleCardLabels count]; i++) {
        DraggableView* newCard = [self createDraggableViewWithDataAtIndex:i];
        [allCards addObject:newCard];

        if (i<numLoadedCardsCap) {
            //%%% adds a small number of cards to be loaded
            [loadedCards addObject:newCard];
        }
    }

    //%%% displays the small number of loaded cards dictated by MAX_BUFFER_SIZE so that not all the cards
    // are showing at once and clogging a ton of data
    for (int i = 0; i<[loadedCards count]; i++) {
        if (i>0) {
            [self insertSubview:[loadedCards objectAtIndex:i] belowSubview:[loadedCards objectAtIndex:i-1]];
        } else {
            [self addSubview:[loadedCards objectAtIndex:i]];
        }
        cardsLoadedIndex++; //%%% we loaded a card into loaded cards, so we have to increment
    }
}
}

#warning include own action here!
//%%% action called when the card goes to the left.
// This should be customized with your own action
-(void)cardSwipedLeft:(UIView *)card;
{
//do whatever you want with the card that was swiped
//    DraggableView *c = (DraggableView *)card;

[loadedCards removeObjectAtIndex:0]; //%%% card was swiped, so it's no longer a "loaded card"

if (cardsLoadedIndex < [allCards count]) { //%%% if we haven't reached the end of all cards, put another into the loaded cards
    [loadedCards addObject:[allCards objectAtIndex:cardsLoadedIndex]];
    cardsLoadedIndex++;//%%% loaded a card, so have to increment count
    [self insertSubview:[loadedCards objectAtIndex:(MAX_BUFFER_SIZE-1)] belowSubview:[loadedCards objectAtIndex:(MAX_BUFFER_SIZE-2)]];
}
}

#warning include own action here!
//%%% action called when the card goes to the right.
// This should be customized with your own action
-(void)cardSwipedRight:(UIView *)card
{
//do whatever you want with the card that was swiped
//    DraggableView *c = (DraggableView *)card;

[loadedCards removeObjectAtIndex:0]; //%%% card was swiped, so it's no longer a "loaded card"

if (cardsLoadedIndex < [allCards count]) { //%%% if we haven't reached the end of all cards, put another into the loaded cards
    [loadedCards addObject:[allCards objectAtIndex:cardsLoadedIndex]];
    cardsLoadedIndex++;//%%% loaded a card, so have to increment count
    [self insertSubview:[loadedCards objectAtIndex:(MAX_BUFFER_SIZE-1)] belowSubview:[loadedCards objectAtIndex:(MAX_BUFFER_SIZE-2)]];
}

}

//%%% when you hit the right button, this is called and substitutes the swipe
-(void)swipeRight
{
DraggableView *dragView = [loadedCards firstObject];
dragView.overlayView.mode = GGOverlayViewModeRight;
[UIView animateWithDuration:0.2 animations:^{
    dragView.overlayView.alpha = 1;
}];
[dragView rightClickAction];
}

//%%% when you hit the left button, this is called and substitutes the swipe
-(void)swipeLeft
{
DraggableView *dragView = [loadedCards firstObject];
dragView.overlayView.mode = GGOverlayViewModeLeft;
[UIView animateWithDuration:0.2 animations:^{
    dragView.overlayView.alpha = 1;
}];
[dragView leftClickAction];
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/

@end

1 个答案:

答案 0 :(得分:1)

要实现您想要使用的按钮,您可以像这样使用VFL:

self.view.translatesAutoresizingMaskIntoConstraints = NO;
button1.translatesAutoresizingMaskIntoConstraints = NO;
button2.translatesAutoresizingMaskIntoConstraints = NO;

NSDictionary *viewsDict = @{@"button1": button1, @"button2": button2};
NSArray *horizontalContraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button1(150)][button2(150)]-|"
                                                                            options:NSLayoutFormatAlignAllBottom
                                                                            metrics:nil
                                                                              views:viewsDict];
NSArray *verticalConstraintsButton1 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[button1]-20-|"
                                                                                  options:NSLayoutFormatAlignAllCenterX
                                                                                  metrics:nil
                                                                                    views:viewsDict];
NSArray *verticalConstraintsButton2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[button2]-20-|"
                                                                                  options:NSLayoutFormatAlignAllCenterX
                                                                                  metrics:nil
                                                                                    views:viewsDict];
[self.view addConstraints:horizontalContraints];
[self.view addConstraints:verticalConstraintsButton1];
[self.view addConstraints:verticalConstraintsButton2];

这样每个按钮的宽度为150 pt,并从视图的左侧,右侧和底部放置20 pt。