Простой способ использования кнопок неправильной формы - PullRequest
6 голосов
/ 21 сентября 2010

Я наконец-то получил релиз своего основного приложения (коснитесь Play MMO - проверьте его ;-)), и сейчас я работаю над его расширением.

Для этого мне нужно иметь круг с четырьмя отдельными кнопками, эти кнопки будут по существу четвертями. Я пришел к выводу, что кольцевое изображение нужно будет построить из четырех изображений, по одному на каждую четверть, но из-за необходимости прямоугольных форм изображения я получу некоторое перекрытие, хотя наложение будет прозрачный.

Какой лучший способ заставить это работать? Мне нужно что-то действительно простое действительно, я посмотрел на это http://iphonedevelopment.blogspot.com/2010/03/irregularly-shaped-uibuttons.html

Раньше, но пока не удалось заставить его работать. Кто-нибудь может дать совет?

В случае, если будет какая-то разница, я буду развертывать на платформе iOS 3.X (будет 4,2, когда выйдет 4.2 для iPad)

Ответы [ 3 ]

7 голосов
/ 21 сентября 2010

Пропускайте кнопки и просто реагируйте на прикосновения в вашем представлении, которые содержат круг.

Создайте CGPath для каждой области, которую вы хотите захватывать касаниями. Когда ваш UIview получает касание, проверьте наличие членства в путях.

[Отредактированный ответ, чтобы показать детали реализации скелета - TomH]

Вот как я мог бы подойти к этой проблеме: (Я не проверял этот код, и синтаксис может быть не совсем правильным, но это общая идея)

1) Используя PS или ваше любимое приложение для создания изображений, создайте один png четверти кругов. Добавьте его в свой проект XCode.

2) Добавить UIView в интерфейс. Установите содержимое слоя UIView в png.

self.myView = [[UIView alloc] initWithRect:CGRectMake(10.0, 10.0, 100.0, 100,0)];
[myView.layer setContents:(id)[UIImage loadImageNamed:@"my.png"]];

3) Создайте CGPath, которые описывают интересующий вас регион в UIView.

self.quadrantOnePath = CGPathCreateMutable();
CGPathMoveToPoint(self.quadrantOnePath, NULL, 50.0, 50.0);
CGPathAddLineToPoint(self.quadrantOnePath, NULL, 100.0, 50.0);
CGPathAddArc(self.quadrantOnePath, NULL, 50.0, 50.0, 50.0, 0.0, M_PI2, 1);
CGPathCloseSubpath(self.quadrantOnePath);

// create paths for the other 3 circle quadrants too!

4) Добавить UIGestureRecognizer и слушать / наблюдать за касаниями в представлении

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
[tapRecognizer setNumberOfTapsRequired:2]; // default is 1

5) Когда tapRecognizer вызывает свой селектор цели

- (void)handleGesture:(UIGestureRecognizer *) recognizer {

  CGPoint touchPoint = [recognizer locationOfTouch:0 inView:self.myView];
  bool processTouch = CGPathContainsPoint(self.quadrantOnePath, NULL, touchPoint, true);

  if(processTouch) {
     // call your method to process the touch
  }
}

Не забудьте освободить все при необходимости - используйте CGPathRelease для освобождения путей.

Еще одна мысль: если изображение, которое вы используете для представления своих круговых квадрантов, является просто закрашенным цветом (то есть без причудливой графики, эффектов слоя и т. Д.), Вы также можете использовать пути, созданные в методе drawRect из UIView, чтобы рисовать квадранты тоже. Это устранит один из недостатков подхода, приведенного выше: нет тесной интеграции между графикой и путями, используемыми для проверки касаний. То есть, если вы поменяете графику на что-то другое, измените размер графики и т. Д., Ваши пути, используемые для проверки касаний, будут не синхронизированы. Потенциально кусок кода с высоким уровнем обслуживания.

5 голосов
/ 21 сентября 2010

Не понимаю, зачем нужно перекрытие.
Просто создайте 4 кнопки и дайте каждому кусочек своего изображения.

редактировать после комментария

см. отличный проект . Одним из примеров является именно то, что вы хотите сделать.

Он работает путем включения альфа-значения пикселя в перезаписанный

pointInside:withEvent: и категория на UIImage, которая добавляет этот метод

- (UIColor *)colorAtPixel:(CGPoint)point {
    // Cancel if point is outside image coordinates
    if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point)) {
        return nil;
    }


    // Create a 1x1 pixel byte array and bitmap context to draw the pixel into.
    // Reference: /1221660/poluchenie-alfa-znacheniya-pikselya-dlya-uiimage
    NSInteger pointX = trunc(point.x);
    NSInteger pointY = trunc(point.y);
    CGImageRef cgImage = self.CGImage;
    NSUInteger width = self.size.width;
    NSUInteger height = self.size.height;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * 1;
    NSUInteger bitsPerComponent = 8;
    unsigned char pixelData[4] = { 0, 0, 0, 0 };
    CGContextRef context = CGBitmapContextCreate(pixelData, 
                                                 1,
                                                 1,
                                                 bitsPerComponent, 
                                                 bytesPerRow, 
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(context, kCGBlendModeCopy);

    // Draw the pixel we are interested in onto the bitmap context
    CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
    CGContextRelease(context);

    // Convert color values [0..255] to floats [0.0..1.0]
    CGFloat red   = (CGFloat)pixelData[0] / 255.0f;
    CGFloat green = (CGFloat)pixelData[1] / 255.0f;
    CGFloat blue  = (CGFloat)pixelData[2] / 255.0f;
    CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}
4 голосов
/ 05 января 2012

Вот замечательный проект, который так легко решает проблему кнопок неправильной формы: http://christinemorris.com/2011/06/ios-irregular-shaped-buttons/

...