如何移除特定状态下UIButton的图像?

10

我正在制作一款卡牌游戏。我希望卡背显示一张图片,卡面显示卡牌内容。我已经成功让图片出现在卡背,但我无法解决当选中时如何清除该图片的问题。(所有选中时运行的代码都在运行,所以我知道这不是实际上没有改变状态的问题。)以下是我的代码:

-(void)updateUI {
for (UIButton *cardButton in self.cardButtons) {
    Card *card = [self.game cardAtIndex:[self.cardButtons indexOfObject:cardButton]];
    [cardButton setTitle:card.contents forState:UIControlStateSelected];
    [cardButton setTitle:card.contents forState:UIControlStateSelected | UIControlStateDisabled];
    [cardButton setImage:[UIImage imageNamed:@"cardback.png"] forState:UIControlStateNormal];

//I've tried various permutations of the following three lines, but the image never disappears.

    [cardButton setImage:nil forState:UIControlStateSelected];
    [cardButton setImage:nil forState:UIControlStateSelected | UIControlStateHighlighted];
    [cardButton setImage:nil forState:UIControlStateNormal];

    cardButton.selected = card.faceUp;
    cardButton.alpha=(card.unplayable ? 0.3:1.0);
    [self.scoreLabel setText:[NSString stringWithFormat:@"Score: %d",self.game.score]];
}
}

有没有关于我做错了什么的想法?


2
保罗·赫加蒂真是太棒了 :D - Dima Deplov
7个回答

6
我猜你的问题是这样的(来自苹果文档中的setImage:forState:):
通常情况下,如果一个状态没有设置属性,则默认使用UIControlStateNormal值。如果UIControlStateNormal值未设置,则该属性默认为系统值。因此,至少应为正常状态设置值。
因此,您不能仅为某些状态取消图像,因为将使用默认图像。
我看到了几个解决方案:
1. 对于您想要透过显示的状态,请使用透明图像而不是nil 2. 给您的卡片添加一个UIImageView子视图,将其设置为卡背面图像。如果卡片朝下,请使用setHidden:显示子视图。如果卡片朝上,请使用setHidden:隐藏子视图。我可能会在您的自定义按钮类中使用– addTarget:action:forControlEvents:方法注册一个自定义方法来显示或隐藏卡背面子视图。
请注意,您可以通过在子视图中显示卡片正面,然后轻松地在这两个子视图之间进行翻转转换,从而更进一步地采用第二种方法,以便在按下时卡片“翻转”。

6

快速创建一个透明图片用于其它状态的方法是分配并赋值一个空图片,因为 nil 将默认为 UIControlStateNormal 的值:

UIImage *cardBackImage = [UIImage imageNamed:@"cardback.png"];
UIImage *cardFrontImage = [[UIImage alloc] init];
[cardButton setImage:cardBackImage forState:UIControlStateNormal];
[cardButton setImage:cardFrontImage forState:UIControlStateSelected];
[cardButton setImage:cardFrontImage forState:UIControlStateSelected|UIControlStateDisabled];

我从未见过 UIImage *cardFrontImage = [UIImage alloc];,为什么我们不进行初始化呢?这不是一个错误吗?作为初学者,您能解释一下吗?谢谢。另外,为什么我们不能这样写:UIImage *cardFrontImage = nil; - Dima Deplov
另外,它帮助了我。我认为 UIImage *cardFrontImage = [[UIImage alloc] init]; 是正确的方式。顺便说一下,Paul Hegarty多次表示,alloc从不单独使用。 - Dima Deplov
1
UIImage *cardFrontImage = nil; 不能使用,因为它与 [cardButton setImage:nil forState:UIControlStateSelected]; 相同,而 nil 值默认为 UIControlStateNormal 使用的值。通过给它一个实例化的 UIImage,即使它正在绘制没有图像数据的图像,它也将“绘制”此图像。 - Kokaubeam

1

如果你像我一样对Objective C不太熟悉,这是Sharon和MultiColourPixel用Swift实现的解决方案。

func removeImageIfSelected(myButton: UIButton) {
    if myButton.isSelected {
        //set nil for .normal so there isn't a default value for Swift to use
        self.setImage(nil, for: .normal) 
    } else {
        self.setImage(UIImage(systemName: "checkmark.circle.fill"), for: .normal)
    }
}

1
我来晚了,不能为MultiColour Pixel的回答投票或评论,可能是因为我在这里还很新,没有声望。但那确实是最好和最简单的方法;不需要透明图像或额外的视图。
我现在正在学习与OP相同的课程,也遇到了同样的问题。解决方案是,当按钮被选中时,仍然将未选择状态的图像设置为零(nil):
UIImage *image = [UIImage imageNamed:@"cardback.png"];
// ...
[cardButton setImage:(card.isFaceUp ? nil : image) forState:UIControlStateNormal];

而且你永远不会为任何其他状态设置图像。

1
我找到的最简单的解决方案是检查按钮是否被标记为选中状态。如果没有,应用背景图像,否则应用空UIImage。

1
如果您使用setBackgroundImage,那就没问题了。这是我的代码。
- (void)updateUI
{
    for (int i=0; i < self.cardButtons.count; i++) {
        Card *card = [self.game cardAtIndex:i];
        UIButton *cardButton = self.cardButtons[i];
        [cardButton setTitle:card.contents forState:UIControlStateSelected];
        [cardButton setTitle:card.contents forState:UIControlStateSelected|UIControlStateDisabled];
        cardButton.selected = card.isFaceup;
        cardButton.enabled = !card.isUnplayable;
        cardButton.alpha = card.isUnplayable ? 0.3 : 1.0;
        //handle flipcard backgroundimage changes;
        UIImage *backgroundImage = (!cardButton.selected) ? [CardGameViewController cardBackgroundImage] : nil;
        [cardButton setBackgroundImage:backgroundImage forState:UIControlStateNormal];
        [self updateScoreLabel:self.game.score];
        NSArray *matchCards = [self.game.matchCards lastObject];
        if (matchCards) {
            UIColor *color = [self getOneMatchColor];
            for (NSNumber *matchCardIndex in matchCards) {
                NSUInteger index = [matchCardIndex integerValue];
                UIButton *matchCardButton = self.cardButtons[index];
                if (color) matchCardButton.backgroundColor = color;
            }
            [self.game.matchCards removeLastObject];
        }
    }
}

0

您可以使用标签:

例如:

- (IBAction)btnClicked:(id)sender {

if([sender tag]==1){

//do something

}
if([sender tag]==2){

//do something else
}

确保您通过转到属性检查器为按钮设置不同的标签,并将默认值从0更改为其他值...
希望这对您有所帮助...

谢谢,但问题不在于图像被删除或未被删除的错误按钮 - 问题在于无论按钮状态如何,图像都不会被删除。 :( - Joel Derfner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接