2013-09-19 3 views
3

Интересно, как сделать вид прогресса, который выглядит, как в KAYAK приложение (это приложение путешествий для поиска рейсов и отелей), скриншот:как сделать вид прогресса, как в KAYAK приложение

enter image description here

я копаться в ресурсах KAYAK приложение на взломанных iPhone и обнаружил следующие 3 изображения, которые конструируют этот вид прогресса:

[email protected]

enter image description here

[email protected]

enter image description here

[email protected]

enter image description here

дает, что вид прогресса имеет движущихся наложения изображений, которая движется вдоль несколько раз с градиентным изображением.

любые идеи или образец кода будут высоко оценены.

+0

Посмотрите на - (UIImage *) resizableImageWithCapInsets: (UIEdgeInsets) capInsets. Это с любым из предложений github должно быть работоспособным. – EricLeaf

ответ

7

Я сделал весь рабочий пакет, который будет имитировать этот прогресс, который вы опубликовали. Однако, чтобы сделать его более настраиваемым, я не использовал никаких изображений, но использовал CoreGraphics для его рисования. Пакет можно найти по адресу: lightdesign/LDProgressView. Я также, вероятно, сделаю это в CocoaPod, если вы знаете, что это такое.

Как рисовать байдарку типа Прогресс Просмотр

Все внутренние работы зрения прогресса и, следовательно, как имитировать вид прогресса каяк можно найти в this file. Я добавил несколько комментариев здесь, в блоках кода, для более легкого понимания. Вот drawRect метод:

- (void)drawRect:(CGRect)rect { 
    [self setAnimateIfNotSet]; 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    [self drawProgressBackground:context inRect:rect]; 
    if (self.progress > 0) { 
     [self drawProgress:context withFrame:rect]; 
    } 
} 

Это довольно очевидно. Я установил свойство animate, если оно уже не установлено, и я рисую фон. Тогда, если прогресс будет больше 0, я нарисую прогресс в общем фрейме. Давайте перейдем к методу drawProgressBackground:inRect::

- (void)drawProgressBackground:(CGContextRef)context inRect:(CGRect)rect { 
    CGContextSaveGState(context); 

    // Draw the background with a gray color within a rounded rectangle 
    UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:10]; 
    CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.51f green:0.51f blue:0.51f alpha:1.00f].CGColor); 
    [roundedRect fill]; 

    // Create the inner shadow path 
    UIBezierPath *roundedRectangleNegativePath = [UIBezierPath bezierPathWithRect:CGRectMake(-10, -10, rect.size.width+10, rect.size.height+10)]; 
    [roundedRectangleNegativePath appendPath:roundedRect]; 
    roundedRectangleNegativePath.usesEvenOddFillRule = YES; 
    CGSize shadowOffset = CGSizeMake(0.5, 1); 
    CGContextSaveGState(context); 
    CGFloat xOffset = shadowOffset.width + round(rect.size.width); 
    CGFloat yOffset = shadowOffset.height; 
    CGContextSetShadowWithColor(context, 
      CGSizeMake(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset)), 5, [[UIColor blackColor] colorWithAlphaComponent:0.7].CGColor); 

    // Draw the inner shadow 
    [roundedRect addClip]; 
    CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(rect.size.width), 0); 
    [roundedRectangleNegativePath applyTransform:transform]; 
    [[UIColor grayColor] setFill]; 
    [roundedRectangleNegativePath fill]; 

    CGContextRestoreGState(context); 
} 

Здесь я создаю прямоугольник с закругленными углами в пределах вида с радиусом 10 (который я впоследствии может позволить быть настраиваемым) и заполнить его. Затем остальная часть кода рисует внутреннюю тень, о которой мне не нужно подробно останавливаться. Теперь, вот код для рисования прогресса в методе drawProgress:withFrame::

- (void)drawProgress:(CGContextRef)context withFrame:(CGRect)frame { 
    CGRect rectToDrawIn = CGRectMake(0, 0, frame.size.width * self.progress, frame.size.height); 
    CGRect insetRect = CGRectInset(rectToDrawIn, 0.5, 0.5); 

    UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:insetRect cornerRadius:10]; 
    if ([self.flat boolValue]) { 
     CGContextSetFillColorWithColor(context, self.color.CGColor); 
     [roundedRect fill]; 
    } else { 
     CGContextSaveGState(context); 
     [roundedRect addClip]; 
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
     CGFloat locations[] = {0.0, 1.0}; 
     NSArray *colors = @[(__bridge id)[self.color lighterColor].CGColor, (__bridge id)[self.color darkerColor].CGColor]; 
     CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations); 

     CGContextDrawLinearGradient(context, gradient, CGPointMake(insetRect.size.width/2, 0), CGPointMake(insetRect.size.width/2, insetRect.size.height), 0); 
     CGContextRestoreGState(context); 

     CGGradientRelease(gradient); 
     CGColorSpaceRelease(colorSpace); 
    } 

    CGContextSetStrokeColorWithColor(context, [[self.color darkerColor] darkerColor].CGColor); 
    [self drawStripes:context inRect:insetRect]; 
    [roundedRect stroke]; 

    [self drawRightAlignedLabelInRect:insetRect]; 
} 

Есть 4 первичные частей к этому методу. Во-первых, я вычисляю фрейм, что прогресс будет зависеть от свойства self.progress. Во-вторых, я рисую сплошной цвет, если установлено свойство flat, или я рисую градиент (методы lighterColor и darkerColor относятся к категории UIColor). В-третьих, я рисую полосы и, наконец, рисую процентную метку. Давайте рассмотрим эти 2 метода быстро. Вот метод:

- (void)drawStripes:(CGContextRef)context inRect:(CGRect)rect { 
    CGContextSaveGState(context); 
    [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:10] addClip]; 
    CGContextSetFillColorWithColor(context, [[UIColor whiteColor] colorWithAlphaComponent:0.2].CGColor); 
    CGFloat xStart = self.offset, height = rect.size.height, width = STRIPE_WIDTH; 
    while (xStart < rect.size.width) { 
     CGContextSaveGState(context); 
     CGContextMoveToPoint(context, xStart, height); 
     CGContextAddLineToPoint(context, xStart + width * 0.25, 0); 
     CGContextAddLineToPoint(context, xStart + width * 0.75, 0); 
     CGContextAddLineToPoint(context, xStart + width * 0.50, height); 
     CGContextClosePath(context); 
     CGContextFillPath(context); 
     CGContextRestoreGState(context); 
     xStart += width; 
    } 
    CGContextRestoreGState(context); 
} 

Это где анимация «магия» происходит. По существу, я рисую эти полосы на основе self.offset, который находится где-то между -STRIPE_WIDTH и 0 с увеличением по таймеру. Затем я создаю простой цикл, так что я создаю достаточно полосок, чтобы полностью заполнить часть прогресса представления. Я также оставляю 25% пустого STRIPE_WIDTH, так что полосы не скреплены друг с другом.Вот последний метод рисования drawRightAlignedLabelInRect::

- (void)drawRightAlignedLabelInRect:(CGRect)rect { 
    UILabel *label = [[UILabel alloc] initWithFrame:rect]; 
    label.backgroundColor = [UIColor clearColor]; 
    label.textAlignment = NSTextAlignmentRight; 
    label.text = [NSString stringWithFormat:@"%.0f%%", self.progress*100]; 
    label.font = [UIFont boldSystemFontOfSize:17]; 
    UIColor *baseLabelColor = [self.color isLighterColor] ? [UIColor blackColor] : [UIColor whiteColor]; 
    label.textColor = [baseLabelColor colorWithAlphaComponent:0.6]; 
    [label drawTextInRect:CGRectOffset(rect, -6, 0)]; 
} 

В этом методе я создаю ярлык с текстом, который преобразует с плавающей точкой (между 0.0 и 1.0) в процентах (от 0% до 100%). Затем я либо устанавливаю, чтобы цвет был темным или светлым, в зависимости от темноты выбранного цвета хода и рисовал ярлык в CGContext.

Customizability

Есть три свойства, которые могут быть установлены либо непосредственно на экземпляре LDProgressView или заранее в методе UIAppearance.

  • Цвет

цвет будет, очевидно, установить общий вид сборщика. Из этого определяются градиенты, полосы и/или контурные цвета. Метод UIAppearance будет что-то вроде этого:

[[LDProgressView appearance] setColor:[UIColor colorWithRed:0.87f green:0.55f blue:0.09f alpha:1.00f]]; 
  • Flat

Это позволит определить, является ли фон с точки зрения прогресса будет градиент или просто color свойство. Этот UIAppearance метод будет выглядеть примерно так:

[[LDProgressView appearance] setFlat:@NO]; 
  • Animate

Наконец, это будет определять, будут ли анимированные полосы. Этот UIAppearance метод также может быть установлен в общем для всех экземпляров LDProgressView и выглядит следующим образом:

[[LDProgressView appearance] setAnimate:@YES]; 

Заключение

Уф! Это был длинный ответ. Надеюсь, я не слишком утомлял вас, ребята. Если вы просто пропустили сюда, вот суть для рисования кода, а не с помощью изображений. Я думаю, что CoreGraphics - превосходный способ рисования на iOS, если у вас есть время/опыт, поскольку он позволяет настраивать больше, и я считаю, что он быстрее.

Вот картина окончательного, рабочий продукт:

LDProgressView

+0

Я загрузил ваш проект из Github, но анимация вообще не работает, я попытался подключить представление прогресса с помощью IBOutlet, а затем запустить анимацию с помощью setAnimate, но безрезультатно ... там что-то не хватает, чтобы код работал правильно? – JAHelia

+0

Я обновил его ... Я специально тестирую IBOutlet, чтобы узнать, есть ли у меня проблема. ** Обновление: ** Я протестировал последнюю версию с помощью IBOutlet, и он отлично работает. Попробуйте и посмотрите, не по-прежнему ли это работает. –

+0

Большое вам спасибо, что я работал сейчас, но в консоли повторяется ошибка: : clip: Пустой путь, как я могу удалить эту досадную ошибку? – JAHelia

0

Вы можете использовать этот пользовательский элемент управления какао

ADV control

+0

Это полезно для вас ?? – user1673099

+0

он не удовлетворяет требованию в вопросе – JAHelia

+0

Почему это не соответствует требованиям? – user1673099

1

Вы можете использовать NSTimer обновить «смещение», в которой вы начинаете рендеринг наложения. Вы можете найти пример here. Это OS X control и использует пользовательский чертеж, а не изображения, но принцип тот же.

+0

у вас есть версия совместимого с iOS этого проекта? – JAHelia

+0

К сожалению, нет, но посмотрите на [Cocoa Controls] (https://www.cocoacontrols.com). Я уверен, что вы можете найти что-то подобное. – Tom

+0

Только что нашел это, если вы все еще ищете: https: // github.com/lightdesign/LDProgressView – Tom

0

Try какао управления для ProgressView ....... как и для накладываемых изображений, необходимо использовать NSTimer, что реле в абсолютной синхронизации с progressview

1

Вот некоторые из примера, который вы можете просто изменить некоторые из кода и получать представление о ходе, как вы хотите: проверка Example1 и Example2

1

Ближайший родственный Бар Прогресс в вашем случае ADVProgressBar.

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


Скриншот:

enter image description here

0

При настройке вашего UIProgressView (self.progress) нам следующие настройки, чтобы получить тот же вид:

 UIImage *mynd =[[UIImage imageNamed:@"KgcoJ.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(11, 13, 11, 13)]; 
     UIImage *bakMynd =[[UIImage imageNamed:@"UoS0A.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(11, 13, 11, 13)]; 
     [self.progress setProgressImage:mynd]; 
     [self.progress setTrackImage:bakMynd]; 

ПримечаниеМожет должны изменить имена изображений и номера в UIEdgeInsetsMake dependin g на размеры вашего изображения. Это даст вам следующее: Progress bar with Images