1

私は を持ってUITabBarControllerStoryboardます。現在、それは 5UITabBarItemsです。他のにいるときは、曲やアルバムを購入するときにアプリがこの「ジャンプのような」アニメーションで行うのとUITabBarItem同じように、他の UITabBarItem (私の「ダウンロード」) のバッジを更新したいと考えています。iTunesこれは可能ですか?はいの場合、どのように?

ありがとうございました。

4

1 に答える 1

1

はい...

「ダウンロードに送信」タイプのアニメーションと呼びます。例を使用してこの質問に答えます。

MVC警告: この例は私が望む以上にパラダイムを壊していますが、それでも十分長いです。

このようなシンプルなストーリーボードを使用します (実際には、まさにこれです):

2 つのビュー コントローラーを持つ tabBarController を示すストーリーボード。 最初のビュー コントローラーとダウンロード ビュー コントローラー。

まず、「First View Controller - First」について説明します。

ビュー内のこれらの多くのボタンは、リストされている 1 つのIBActionメソッドに接続されています。これで、View Controller に必要なすべての説明が終わりました。これがその.mファイルです:(切り捨てられた)

//#import "First_View_Controller.h"
@interface First_View_Controller ()
@property (weak, nonatomic) DownloadViewController *downloadViewController;
@end

@implementation First_View_Controller
@synthesize downloadViewController = _downloadViewController;
-(DownloadViewController *)downloadViewController{
    if (!_downloadViewController){
        // Code to find instance of DownloadViewController in the tabBarController's view controllers.
        for (UIViewController *vc in self.tabBarController.viewControllers) {
            if ([vc isKindOfClass:[DownloadViewController class]]){
                _downloadViewController = (DownloadViewController *)vc;
                break;
            }
        }
    }
    return _downloadViewController;
}
-(IBAction)buttonPush:(UIButton *)button{
    [self.downloadViewController addADownload:nil withViewToAnimate:button];
}
// Other typical VC crap...
@end

これIBActionはかなり自明です。DownloadViewControllertabBarController のビュー コントローラを調べてのインスタンスへの参照を取得し、アニメーション化するビューをそのインスタンスに渡します。

今すぐDownloadViewController.m。それはたくさんのコードです。明確にするために、コメントしました:

#import "DownloadViewController.h"
#import <QuartzCore/QuartzCore.h>
// A Category on UITabBar to grab the view of a tab by index.
@implementation UITabBar (WhyIsntThisBuiltIn)
-(UIView *)nj_ViewOfTabNumber:(NSUInteger)number{
    if (number == NSNotFound) return nil;
    // Fairly standard method for getting tabs, getting the UIControl objects from the 'subviews' array.
    // I pulled the next few lines from an SO question.
    NSMutableArray *tabs = [[NSMutableArray alloc] init];
    [self.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
        if ([(NSObject *)obj isKindOfClass:UIControl.class]){
            [tabs addObject:obj];
        }
    }];
    // The code above gets the tabs' views, but they may not be in the correct order.
    // This sort is required if a view controller has been replaced,...
    // Since, in that case, the order in which the tabs' views appear in the 'subviews' array will not be the left-to-right order.
    [tabs sortUsingComparator:^NSComparisonResult(UIView *obj1, UIView *obj2){
        CGFloat v1 = obj1.center.x;
        CGFloat v2 = obj2.center.x;
        if (v1<v2) return NSOrderedAscending;
        if (v1>v2) return NSOrderedDescending;
        return NSOrderedSame;
    }];
    // This if is required for the case where the view controller is in the "more" tab.
    if (number >= tabs.count) number = tabs.count-1;
    return [tabs objectAtIndex:number];
}
@end
// A Category on UITabBarController to get the view of a tab that represents a certain view controller.
@implementation UITabBarController (WhyIsntThisBuiltIn)
-(UIView *)nj_viewOfTabForViewController:(UIViewController *)viewController{
    // Find index of the passed in viewController.
    NSUInteger indexOfViewController = [self.viewControllers indexOfObject:viewController];
    if (indexOfViewController == NSNotFound) return nil;
    // Return the view of the tab representing the passed in viewController.
    return [self.tabBar nj_ViewOfTabNumber:indexOfViewController];
}
@end

// Insert required warning about using #defines here.
#define MY_ANIMATION_DURATION 0.8
@implementation DownloadViewController{
    NSUInteger _numberOfDownloads;
}
-(void)updateBadgeValue{
    self.tabBarItem.badgeValue = [NSString stringWithFormat:@"%i",_numberOfDownloads];
}
// This method creates a "snapshot" of the animation view and animates it to the "downloads" tab.
// Removal of the original animationView must, if desired, be done manually by the caller.
-(void)addADownload:(id)someDownload withViewToAnimate:(UIView *)animationView{
    // update model...
    _numberOfDownloads++;

    // Animate if required
    if (animationView){

        // Create a `UIImageView` of the "animationView" name it `dummyImageView`
        UIGraphicsBeginImageContextWithOptions(animationView.frame.size, NO, [[UIScreen mainScreen] scale]);
        [animationView.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *dummyImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        UIImageView *dummyImageView = [[UIImageView alloc] initWithImage:dummyImage];
        dummyImageView.frame = animationView.frame;

        // Determine UIView of tab using non-private API.
        UITabBarController *tabBarController = self.tabBarController;
        UIView *downloadsTab = [tabBarController nj_viewOfTabForViewController:self];

        // Determine animation points in tabBarController's view's coordinates.
        CGPoint animationStartPoint = [tabBarController.view convertPoint:dummyImageView.center fromView:dummyImageView.superview];
        CGPoint animationEndPoint = [tabBarController.view convertPoint:downloadsTab.center fromView:downloadsTab.superview];
        CGFloat totalXTravel = animationEndPoint.x - animationStartPoint.x;
        // This is an arbitrary equation to create a control point, this is by no means canonical.
        CGPoint controlPoint = CGPointMake(animationEndPoint.x, animationStartPoint.y - fabs(totalXTravel/1.2));

        // Create the animation path.
        UIBezierPath *path = [[UIBezierPath alloc] init];
        [path moveToPoint:animationStartPoint];
        [path addQuadCurveToPoint:animationEndPoint controlPoint:controlPoint];

        // Create the CAAnimation.
        CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        moveAnimation.duration = MY_ANIMATION_DURATION;
        moveAnimation.path = path.CGPath;
        moveAnimation.removedOnCompletion = NO;
        moveAnimation.fillMode = kCAFillModeBoth;

        [tabBarController.view addSubview:dummyImageView];
        dummyImageView.center = animationStartPoint;

        // Animate the move.
        [dummyImageView.layer addAnimation:moveAnimation forKey:@""];

        // Use the block based API to add size reduction and handle completion.
        [UIView animateWithDuration:MY_ANIMATION_DURATION
                         animations:^{
                             dummyImageView.transform = CGAffineTransformMakeScale(0.3, 0.3);
                         }
                         completion:^(BOOL b){
                             // Animate BIG FINISH! nah, just...
                             [dummyImageView removeFromSuperview];
                             [self updateBadgeValue];
                         }];
    }
}
// Other typical VC crap...
@end

そしてそれはそれについてです。このコードを実行すると、左上のボタンからかなり強力なジャンプが生成されますが、右側のボタン、特に右下のボタンは投げ捨てられます。アニメーションが終了すると、ダウンロード タブのバッジがカウントアップします。iTunes でコンテンツを購入するときに Apple が使用する効果のかなりまともな模造品。

Quartz Framework をアプリに追加することを忘れないでください。

于 2013-01-01T03:04:17.240 に答える