簡體   English   中英

如何制作像KAYAK應用程序中的進度視圖

[英]how to make a progress view like the one in KAYAK app

我想知道如何制作一個看起來像KAYAK應用程序中的進度視圖(它是一個搜索航班和酒店的旅行應用程序),截圖:

在此輸入圖像描述

我在越獄的iPhone上挖掘了KAYAK應用程序的資源,發現以下3個圖像構建了這個進度視圖:

progressbar-background@2x.png

在此輸入圖像描述

progressbar-gradient@2x.png

在此輸入圖像描述

progressbar-overlay@2x.png

在此輸入圖像描述

假設進度視圖具有與梯度圖像一起重復移動的移動疊加圖像。

任何想法或示例代碼將受到高度贊賞。

我制作了完整的工作包,模仿你發布的這個進度視圖。 但是,為了使其更具可定制性,我沒有使用任何圖像,而是使用CoreGraphics來繪制它。 該軟件包可以在lightdesign / LDProgressView中找到。 如果你知道那是什么,我也可能把它變成一個CocoaPod

如何繪制類似KAYAK的進度視圖

可以在此文件中找到進度視圖的所有內部工作方式以及如何模擬KAYAK進度視圖。 為了便於理解,我在代碼塊中添加了一些注釋。 這是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屬性,我會繪制純色,或者我繪制一個計算的漸變(方法lighterColordarkerColor屬於UIColor類別)。 第三,我繪制條紋,最后繪制百分比標簽。 讓我們快速介紹這兩種方法。 這是drawStripes:inRect:方法:

- (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_WIDTH0之間,由計時器遞增。 然后,我創建一個簡單的循環,以便我只創建足夠的條帶來完全填充視圖的進度部分。 我還留下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.01.0之間)轉換為百分比(從0%100% )。 然后我根據所選進度顏色的暗度將顏色設置為暗或亮,並在CGContext繪制標簽。

可定制

有三個屬性可以直接在LDProgressView的實例上設置,也可以在UIAppearance方法中預先UIAppearance

  • 顏色

顏色顯然會設置拾取器的整體外觀。 漸變,條紋和/或輪廓顏色由此決定。 UIAppearance方法將是這樣的:

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

這將確定進度視圖的背景是漸變還是只是color屬性。 這個UIAppearance方法看起來像這樣:

[[LDProgressView appearance] setFlat:@NO];
  • 活躍

最后,這將確定條紋是否會被動畫化。 這個UIAppearance方法也可以通用地設置LDProgressView所有實例,如下所示:

[[LDProgressView appearance] setAnimate:@YES];

結論

呼! 這是一個很長的答案。 我希望我沒有給你們太多的鼓勵。 如果你剛剛跳到這里,這里是用於繪制代碼而不是圖像的要點。 我認為CoreGraphics是一種優秀的iOS繪圖方式,如果你有時間/經驗,因為它允許更多的自定義,我相信往往會更快。

這是最終的工作產品圖片:

LDProgressView

您可以使用NSTimer更新開始渲染疊加層的“偏移量”。 你可以在這里找到一個例子。 它是OS X控件,它使用自定義繪圖,而不是圖像,但原理是相同的。

調整顏色和厚度,你很高興! https://www.cocoacontrols.com/controls/ylprogressbar

這個似乎也很好......但我還沒有使用它。 https://github.com/JonasGessner/JGProgressView

祝好運!

下面是一些示例,您可以根據需要修改一些代碼並獲取進度視圖:檢查Example1Example2

您的案例中最近的相關進度條是ADVProgressBar

在這里,您需要做一些修改。 比如,你必須改變背景圖像,你可以添加那些圓角。 完成這些更改后,進度條將與您在問題中提到的完全一致。


截圖:

在此輸入圖像描述

您可以使用此自定義cocoa控件

ADV控制

嘗試使用Cocoa控件進行ProgressView .......對於重疊圖像,您需要使用與進度視圖絕對同步的NSTimer中繼

當您設置UIProgressViewself.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的圖像名稱和數字。 這將給你以下內容: 帶圖像的進度條

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM