Sin sombra / relieve en UIBarButtonItem

Tengo un problema con un UIBarButtonItem personalizado. Cuando creo un UIBarButtonItem personalizado vía

[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"FilterIcon.png"] style:UIBarButtonItemStyleBordenetworking target:self action:@selector(filterTouched:)]; 

el button resultante no tiene el aspecto "grabado", que los elementos del sistema logran al colocar una sombra negra semitransparente detrás de sus íconos.

Izquierda: elemento del sistema, a la derecha: elemento personalizado

A la izquierda, verá el elemento del button de la barra del sistema "Organizar", a la derecha, el resultado del código de arriba.

Crear la sombra en el recurso es inútil, porque iOS / Cocoa solo usó la máscara de la image y descarta cualquier información de color.

Curiosamente, si creo el elemento del button de barra en el Interface-Builder, se ve bien. Sin embargo, en el context de mi problema, necesito crear el elemento del button en el código.

Hay una versión de Objective-C del guión de James Furey.

 - (UIImage *)applyToolbarButtonStyling:(UIImage *)oldImage { float shadowOffset = 1; float shadowOpacity = .54; CGRect imageRect = CGRectMake(0, 0, oldImage.size.width, oldImage.size.height); CGRect shadowRect = CGRectMake(0, shadowOffset, oldImage.size.width, oldImage.size.height); CGRect newRect = CGRectUnion(imageRect, shadowRect); UIGraphicsBeginImageContextWithOptions(newRect.size, NO, oldImage.scale); CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextScaleCTM(ctx, 1, -1); CGContextTranslateCTM(ctx, 0, -(newRect.size.height)); CGContextSaveGState(ctx); CGContextClipToMask(ctx, shadowRect, oldImage.CGImage); CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0 alpha:shadowOpacity].CGColor); CGContextFillRect(ctx, shadowRect); CGContextRestoreGState(ctx); CGContextClipToMask(ctx, imageRect, oldImage.CGImage); CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:1 alpha:1].CGColor); CGContextFillRect(ctx, imageRect); UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Creo que la razón por la que esto ocurre está cubierta por estas respuestas a otra pregunta:

https://stackoverflow.com/a/3476424/1210490

https://stackoverflow.com/a/6528603/1210490

UIBarButtonItems se comportan de manera diferente dependiendo de dónde los conecte mediante progtwigción. Si los adjuntas a una barra de herramientas, se convertirán en icons blancos "en relieve". Si los agrega a una barra de navigation, no lo harán.

Pasé las últimas horas escribiendo una function para aplicar el estilo UIBarButtonItem de la barra de herramientas a UIImages. Está escrito en C # para MonoTouch , pero estoy seguro de que podrás modificarlo a Obj-C sin problemo …

 UIImage ApplyToolbarButtonStyling(UIImage oldImage) { float shadowOffset = 1f; float shadowOpacity = .54f; RectangleF imageRect = new RectangleF(PointF.Empty, oldImage.Size); RectangleF shadowRect = new RectangleF(new PointF(0, shadowOffset), oldImage.Size); RectangleF newRect = RectangleF.Union(imageRect, shadowRect); UIGraphics.BeginImageContextWithOptions(newRect.Size, false, oldImage.CurrentScale); CGContext ctxt = UIGraphics.GetCurrentContext(); ctxt.ScaleCTM(1f, -1f); ctxt.TranslateCTM(0, -newRect.Size.Height); ctxt.SaveState(); ctxt.ClipToMask(shadowRect, oldImage.CGImage); ctxt.SetFillColor(UIColor.FromWhiteAlpha(0f, shadowOpacity).CGColor); ctxt.FillRect(shadowRect); ctxt.RestoreState(); ctxt.ClipToMask(imageRect, oldImage.CGImage); ctxt.SetFillColor(UIColor.FromWhiteAlpha(1f, 1f).CGColor); ctxt.FillRect(imageRect); UIImage newImage = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); return newImage; } 

Entonces, un UIBarButtonItem que solía verse así:

antes de

Creado en su lugar con la function anterior, así:

 UIBarButtonItem barButtonItem = new UIBarButtonItem(ApplyToolbarButtonStyling(UIImage.FromFile("MusicIcon.png")), UIBarButtonItemStyle.Plain, delegate {}); 

Ahora se vería así:

Después

Espero que esto ayude a alguien en el futuro.

Tome nota de la compensación de la sombra en el guión de James Furey. He hecho la siguiente experiencia:

 float shadowOffset = 1.0f // for a UIBarButtonItem in UINavigationItem float shadowOffset = 0.0f // for a UIBarButtonItem in UIToolBar 

Esto se observó con iOS 6.1 SDK.

(Ahora obsoleto bajo iOS 7)