【问题标题】:Dynamic UIButton positioning?动态UIButton定位?
【发布时间】:2012-11-19 06:48:33
【问题描述】:

我有用户可以在我的游戏中获得的奖励。现在他们只显示他们是否解锁。他们可以获得4种不同的奖励。现在他们可能解锁了 1 个奖励或 2 个或 3 个或 4 个奖励。但是我希望动态定位图像,使其看起来像下面的图像。在下图中,每一行都应与解锁奖励数量相同。

现在,我将如何继续这样做? (注意:图像在Y轴上没有变化,它们只是在X轴上动态定位,所以不要被图像迷惑了)

谢谢!

【问题讨论】:

  • 好吧,你已经把我彻底搞糊涂了……你能举一个解锁1、2、3和4奖励的例子吗?当你说“图像在 Y 轴上没有变化,它们只会在 X 轴上动态定位,所以不要被图像所迷惑”或“每一行应该看起来像解锁的奖励数量是这样的。”....
  • 嗯...也许您的意思是每行可以有一到四个框?而金字塔在这种情况下只是巧合?
  • 只有 1 行,一个或所有按钮的位置在 Y 轴上将是相同的值。现在如果是 1 奖励,它应该看起来像图像的第一行,如果是 2,它应该看起来像图像的第二行,等等......这个问题中图像的中心将代表中间设备。
  • 几乎我只想根据奖励图像的数量在 X 轴上平均分配奖励图像,在我的情况下,奖励图像的范围可以从 1 到 4。

标签: ios dynamic uibutton positioning


【解决方案1】:

我会创建一个自定义的UIView 子类来执行此操作,以便您可以在任何可以使用视图的地方使用它。

用法

MyFlexibleSpacedButtons *myButtons = [[MyFlexibleSpacedButtons alloc] initWithFrame:CGRectMake(50, 50, 250, 60)];
[myButtons setButtonAtIndex:2 hidden:NO];
[myButtons setButtonAtIndex:0 hidden:NO];
[self.view addSubview:myButtons];

这是示例类:

MyFlexibleSpacedButtons.h

#import <UIKit/UIKit.h>

@interface MyFlexibleSpacedButtons : UIView

@property (nonatomic, readonly) NSArray *allButtons;

- (void)setButtonAtIndex:(NSUInteger)index hidden:(BOOL)hidden;

@end

MyFlexibleSpacedButtons.m

#import "MyFlexibleSpacedButtons.h"

const NSUInteger    maxButtons          = 9;
const NSUInteger    buttonsPerRow       = 3; // This can not be 0.
const CGFloat       buttonHeight        = 50;
const CGFloat       buttonWidth         = 50;
const CGFloat       spaceBetweenButtons = 10.0;

@interface MyFlexibleSpacedButtons ()
@property (nonatomic, readwrite) NSArray        *allButtons;
@end

@implementation MyFlexibleSpacedButtons

@synthesize allButtons;

- (id)initWithFrame:(CGRect)frame
{
    NSUInteger numberOfRows = ceil((double)maxButtons / (double)buttonsPerRow);
    CGFloat    minHeight    = buttonHeight * numberOfRows + spaceBetweenButtons * (numberOfRows - 1);
    if (frame.size.height < minHeight)
    {
        frame.size.height = minHeight;
    }

    CGFloat minWidth = buttonWidth * maxButtons + spaceBetweenButtons * (maxButtons-1);
    if (frame.size.width < minWidth)
    {
        frame.size.width = minWidth;
    }

    self = [super initWithFrame:frame];
    if (self) {
        // Defaults
        // Uncomment the following line if needed for debugging:
        // self.backgroundColor = [UIColor grayColor];

        // Create the buttons and add them to the array.  Default to hidden buttons
        self.allButtons = [NSArray new];
        for (int i = 0; i < maxButtons; i++)
        {
            UIButton *button   = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            button.hidden      = YES;
            [button setTitle:[NSString stringWithFormat:@"%d", i] forState:UIControlStateNormal];
            [self addSubview:button];
            self.allButtons = [self.allButtons arrayByAddingObject:button];
        }

        [self setButtonFrames];
    }
    return self;
}

- (void)dealloc
{
    allButtons = nil;
}

- (void)setButtonFrames
{
    CGFloat viewHeight                  = self.bounds.size.height;
    CGFloat viewWidth                   = self.bounds.size.width;

    NSUInteger  buttonCount             = [self visibleButtonsCount];
    NSUInteger  numberOfRows            = ceil((double)maxButtons / (double)buttonsPerRow);
    CGFloat     buttonY                 = (viewHeight - buttonHeight * numberOfRows - spaceBetweenButtons * (numberOfRows - 1)) / 2;
    CGFloat     buttonGroupTotalWidth   = buttonCount * buttonWidth + (buttonCount - 1) * spaceBetweenButtons;
    CGFloat     buttonGroupStartingX    = (viewWidth - buttonGroupTotalWidth) / 2;

    // Set frames of buttons
    NSUInteger  visibleButtonIndex      = 0;
    for (int i = 0; i < maxButtons; i++)
    {
        UIButton *button    = [self.allButtons objectAtIndex:i];

        if (!button.hidden)
        {
            CGFloat buttonX     = buttonGroupStartingX + visibleButtonIndex % buttonsPerRow * (buttonWidth + spaceBetweenButtons);
            button.frame        = CGRectMake(buttonX, buttonY, buttonWidth, buttonHeight);
            visibleButtonIndex++;

            if (visibleButtonIndex % buttonsPerRow == 0)
            {
                buttonY = buttonY + buttonHeight + spaceBetweenButtons;
            }
        }
    }
}

- (void)setButtonAtIndex:(NSUInteger)index hidden:(BOOL)hidden
{
    if (index > maxButtons - 1)
    {
        return;
    }

    UIButton *button    = [self.allButtons objectAtIndex:index];
    button.hidden       = hidden;

    [self setButtonFrames];
}

- (NSUInteger)visibleButtonsCount
{
    NSUInteger buttonCount = 0;

    for (UIButton *button in self.allButtons)
    {
        if (!button.hidden)
        {
            buttonCount++;
        }
    }
    return buttonCount;
}

@end

【讨论】:

  • 这看起来很棒,正是我想要的,但是我对此有一个问题。您手动创建 4 个按钮,但我只想在 NSUserDefaults 中的 BOOL 为 YES 时创建它。每个按钮的键是“Button1”、“Button2”等......因此,与其手动创建它们,不如仅当 bool 为每个按钮的键返回 YES 时才创建按钮?
  • 我通过在开始时创建它们来简化了这一点,以便我可以安全地假设它们都在那里。然后我只是隐藏我不需要的那些。要更改可见按钮的数量,我只需将visibleButtons 属性更改为我要显示的数字!
  • 啊,我明白了,但是我如何根据用户默认值显示或隐藏特定按钮?这就是为什么我只想根据用户默认值 bool 显示按钮。
  • 我更改了类,以便它们可以单独打开和关闭。
  • 谢谢,我理解正确,可以说按钮 1 和按钮 4 是唯一显示的按钮。根据您的代码,它们不会有 40.0 的空间,而是应该有 10.0 的空间,对吗? (只是为了解释一下,如果按钮 2 显示不正确,按钮 4 会进入按钮 2 的典型位置?)
【解决方案2】:

我认为最简单和更灵活的方法是使用 UITableView 和带有方法的自定义单元格:- (void)NumberOfButtonsInCell:(NSUInteger)buttons;

所以在tableView数据源中调用时

您只需将按钮的数量相应地设置为

- (void)numberOfButtonsInCell:(NSUInteger)buttons {
  int i;
  for (i = 0; i<buttons;i++) {
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((cell.frame.size.widht/buttons)*i, 0, buttonWidth, buttonHeight)];

  button.tag = i;

  [self addSubview:button];

    [button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

  }
}

- (void)buttonPressed:(id)sender {
   UIButton *button = (UIButton*)sender;

   [self.delegate userDidSelectButtonAtIndex:(button.tag)];
   //so your table view resolves the row with [self.tableView indexPathForCell:cell];



}

这样你就可以为[cell configureButtonAtIndex:index];设置一个方法

只需几行代码,您就可以轻松更改所有行为、外观甚至设计。

【讨论】:

  • 我明白了,但是我特意问的是如何根据按钮的数量来实现按钮的设计(定位)。
  • 只需使用 [cell numberOfButtonsInCell:i];它使用 int i = i + 1;整数计数+=我; (至少在您使用的示例图像中)并将 i 设置为 indexPath.row 在该几何结构中,您将始终拥有空按钮,具体取决于按钮的数量,如果您必须使底行更大(添加更多按钮)您想避免有空按钮,因此如果 count >= totalOfButtonYouNeed (您将按钮添加到前一个单元格)(对不起,该单元格在数据源方法和逻辑中配置,可以在 viewDidLoad 之前完成,所以您不需要重新加载表格)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-09
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多