web-dev-qa-db-fra.com

UIBarButtonItems personnalisés à partir de Boutons avec images personnalisées - est-il possible d'agrandir les éléments tactiles?

Je fais UIBarButtons comme suit:

// Create "back" UIBarButtonItem
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame = CGRectMake(0, 0, 28, 17);
[backButton addTarget:self action:@selector(backButtonTapped) forControlEvents:UIControlEventTouchUpInside];
backButton.showsTouchWhenHighlighted = YES;

UIImage *backButtonImage = [UIImage imageNamed:@"back-button.png"];
[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

[toolBarItems addObject:backBarButtonItem];

Cependant, les éléments tactiles sont minuscules. Plus précisément, ils sont la taille des images personnalisées. (Lesquels encore sont minuscules.) Existe-t-il un moyen d'augmenter la taille de leur cible tactile?

(Remarque: la modification de la propriété frame des boutons UIB étend uniquement l'image.)

14
Doug Smith

De petits changements à votre code feront l'affaire

Changements nécessaires:

  • Je suppose que la taille de backButtonImage est {28,17} et que le cadre du bouton est défini comme CGRectMake(0, 0, 48, 37) `
  • supprimer la backGroundImage et utiliser setImage:
  • définissez la propriété imageEdgeInsets sur UIEdgeInsetsMake(10, 10, 10, 10)

Votre code deviendra comme ceci:

UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame = CGRectMake(0, 0, 48, 37);
[backButton addTarget:self action:@selector(backButtonTapped) forControlEvents:UIControlEventTouchUpInside];
backButton.showsTouchWhenHighlighted = YES;

UIImage *backButtonImage = [UIImage imageNamed:@"back-button.png"];
[backButton setImage:backButtonImage forState:UIControlStateNormal];

backButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

[toolBarItems addObject:backBarButtonItem];

Vous pouvez modifier la valeur de frame et de imageEdgeInsets selon vos besoins.
Ce code a fonctionné pour moi.

26
Prasad Devadiga

Vous pouvez modifier la propriété UIBarButtonItem's width

backBarButtonItem.width = x;

Malheureusement, vous ne pouvez pas changer la hauteur, car il n'y a pas de propriété height.

Ce que vous pouvez faire, cependant, est de passer UIBarButtonItem une UIButton avec un cadre défini en utilisant initWithCustomView

par exemple:

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

    UIImage *backButtonImage = [UIImage imageNamed:@"back-button.png"];

   [button setBackgroundImage:backButtonImage forState:UIControlStateNormal];

    button.frame = CGRectMake(0, 0, width, height);

    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];

Si votre image semble étirée, assurez-vous de conserver le même rapport d'aspect! Ou assurez-vous que l'image est exactement la même taille.

5
VGruenhagen

1) Ajoutez une catégorie à votre UIButton
2) Ajouter de nouvelles propriétés à la catégorie
3) Ajoutez votre méthode pour initialiser le bouton retour
4) Remplacer -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
5) Sous-classe toolBarItems

@implementation UIButton (yourButtonCategory)
@dynamic shouldHitTest; // boolean
@dynamic hitTestRect; // enlarge rect of the button
@dynamic buttonPressedInterval; // interval of press, sometimes its being called twice

-(id)initBackBtnAtPoint:(CGPoint)_point{
// we only need the Origin of the button since the size and width are fixed so the image won't be stretched
    self = [self initWithFrame:CGRectMake(_point.x, _point.y, 28, 17)];   
    [self setBackgroundImage:[UIImage imageNamed:@"back-button.png"]forState:UIControlStateNormal];

    self.shouldHitTest = CGRectMake(self.frame.Origin.x - 25, self.frame.Origin.y-10, self.frame.size.width+25, self.frame.size.height+25); // this will be the enlarge frame of the button
    self.shouldHitTest = YES;
    return self;
}


-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
BOOL shouldReturn = [super pointInside:point withEvent:event];
NSSet *touches = [event allTouches];
BOOL shouldSendTouches = NO;

for (UITouch *touch in touches) {
    switch (touch.phase) {
        case UITouchPhaseBegan:
            shouldSendTouches = YES;
            break;
        default:
            shouldSendTouches = NO;
            break;
    }
}


if(self.shouldHitTest){

    double elapse = CFAbsoluteTimeGetCurrent();
    CGFloat totalElapse = elapse - self.buttonPressedInterval;
    if (totalElapse < .32) {
        return NO;
        // not the event we were interested in
    } else {
                    // use this call

        if(CGRectContainsPoint(self.hitTestRect, point)){
            if(shouldSendTouches){
                self.buttonPressedInterval = CFAbsoluteTimeGetCurrent();

                [self sendActionsForControlEvents:UIControlEventTouchUpInside];
            }

            return NO;
        }
    }

}

return shouldReturn;

}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject]; 
CGPoint touch_point = [touch locationInView:self];
[self pointInside:touch_point withEvent:event];
}

@end

Disons que l'événement tactile ne déclenche pas, nous avons besoin de la vue. Son en est appelé pour appeler le bouton. Ainsi, dans toolBarItems, nous faisons quelque chose comme:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    for(id subs in self.subviews){
        if([subs isKindOfClass:[UIButton class]]){
            [subs touchesBegan:touches withEvent:event];
        }
    }


}

alors c'est tout. nous agrandissons le cadre sans agrandir le bouton réel.

vous venez d’initier votre bouton comme suit: UIButton *btn = [[UIButton alloc]initBackBtnAtPoint:CGPointMake(0,0)];

J'espère que ça aide

3
Joshua

Lorsque vous appelez initWithCustomView, le UIBarButtonItem délègue la gestion des événements à la vue personnalisée, qui, dans votre cas, est le UIButton. À son tour, la variable UIButton tire ses limites de l'image et, en tant qu'image d'arrière-plan, elle devrait s'étendre pour remplir de nouvelles limites si nécessaire.

Au lieu de cela, définissez les propriétés image et imageInsets directement sur UIBarButtonItem. Ces propriétés sont déclarées dans la classe parente, UIBarItem. Vous pouvez également définir leurs variantes de paysage.

1
Steven McGrath

Changer le cadre du bouton en grand et changer votre ligne

[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

à:

[backButton setImage:backButtonImage forState:UIControlStateNormal];
1
Alexander Merchi

Vous devez changer trois lignes de code et espérer que cela fonctionnera.

1) Modifiez la largeur du bouton arrière selon vos besoins.

2) Définissez le Image de backButton au lieu du BackgroundImage de backButton

[backButton setImage:backButtonImage forState:UIControlStateNormal];

3) Définissez également le contentHorizontalAlignment de backButton.

backButton.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft;
1
korat prashant

mmm ... pour ce que vous devez réaliser - il n’ya pas d’étirement de l’image - il existe un moyen simple:

1) utilisez Gimp ou photoshop et créez un calque transparent sous votre image, de sorte qu’il corresponde à la taille souhaitée.

2) fusionnez et créez des images rétines et non rétines.

3) mettez à jour votre code afin qu'il reflète la nouvelle taille de l'image.

4) assigner les images et ensuite exécuter votre code.

De cette façon, votre image d'origine ne sera pas étirée, car ses limites prendront en compte la partie transparente de celle-ci.

En dehors de cela, vous pouvez probablement tout faire par programme, mais je doute que ce soit une bonne idée, sauf si vous aviez prévu de plonger dans UIGraphics pour d'autres raisons.

1
Alex

Juste utiliser

[button setImage:backButtonImage forState:UIControlStateNormal];

au lieu de

[backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

et réglez le cadre comme bon vous semble. L'image sera alors centrée et le bouton recevra le toucher dans le cadre donné.

Quelque chose comme ça:

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(50, 50, 50, 50);
[button setImage:backButtonImage forState:UIControlStateNormal];
1
Lukas Kukacka

Augmentez le nombre de cadres UIButton (jusqu'à la taille de prise souhaitée)

      button.frame = CGRectMake(0, 0, 56, 20);

Si vous voulez voir l'image pour le bouton complet s'il vous plaît écrivez la méthode suivante

      [backButton setBackgroundImage:backButtonImage forState:UIControlStateNormal];

Si vous souhaitez voir la taille réelle de l'image (la taille de votre bouton ne concerne que la taille du toucher

      [backButton setImage:backButtonImage forState:UIControlStateNormal];

Et enfin

      UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

J'espère que ça vous aide!

0
Ganee....

vous devriez pouvoir définir les incrustations Edge sur le bouton.

définissez donc le cadre du bouton sur une taille supérieure à celle de l'image, puis définissez les incrustations Edge sur le bouton.

donc pour élargir votre largeur de 10 pixels de chaque côté quelque chose comme ça devrait fonctionner

backButton.frame = CGRectMake(0,0,28,37);
backButton.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 10);
0
andrew lattis