zoukankan      html  css  js  c++  java
  • ios -- 为导航栏添加播放动画

    FLAudioVisualizerView.h

    #import <UIKit/UIKit.h>
    
    @interface FLAudioVisualizerView : UIView
    
    #pragma mark -
    
    // 默认UIEdgeInsetsZero
    @property (nonatomic, assign) UIEdgeInsets contentInsets;
    // 默认为4
    @property (nonatomic, assign) NSInteger barCount;
    @property (nonatomic, copy) NSArray<NSNumber *> *barHeightRateList;
    // 默认白色
    @property (nonatomic, copy) UIColor *barColor;
    // 默认2
    @property (nonatomic, assign) CGFloat cornerRadius;
    // 默认5
    @property (nonatomic, assign) CGFloat barSpace;
    // NSValue包装CGPoint
    @property (nonatomic, strong) NSArray<NSValue *> *aniamteOffsetList;
    @property (nonatomic, readonly) BOOL isAniamting;
    
    - (void)restart;
    - (void)start;
    - (void)stop;
    
    @end

    FLAudioVisualizerView.m

    #import "FLAudioVisualizerView.h"
    
    @interface FLAudioVisualizerView ()
    
    @property (nonatomic, strong) NSArray<UIView *> *barList;
    @property (nonatomic, assign) BOOL isAniamting;
    
    @end
    
    @implementation FLAudioVisualizerView
    
    #pragma mark -
    
    - (id)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self setBarCount:4];
            _barSpace = 5;
            _barColor = [UIColor whiteColor];
            self.cornerRadius = 2;
            self.barHeightRateList = @[@(0.4), @(0.75), @(0.55), @(0.95)];
            self.transform = CGAffineTransformMakeRotation(M_PI);
            self.aniamteOffsetList = @[[NSValue valueWithCGPoint:CGPointMake(0.1, 0.4)],
                                       [NSValue valueWithCGPoint:CGPointMake(0.75, 0.3)],
                                       [NSValue valueWithCGPoint:CGPointMake(0.2, 0.55)],
                                       [NSValue valueWithCGPoint:CGPointMake(0.94, 0.4)],
                                       ];
            self.contentInsets = UIEdgeInsetsZero;
        }
        return self;
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        CGRect rect = self.bounds;
        if (fabs(rect.size.width) < 1e-3 || fabs(rect.size.height) < 1e-3 || rect.size.width < 0 || rect.size.height < 0 ) {
            return;
        }
        rect = CGRectWithEdgeInserts(rect, self.contentInsets);
        __block CGRect barRect = rect;
        barRect.size.width = (rect.size.width - (self.barCount - 1) * self.barSpace) / self.barCount;
        NSArray<NSNumber *> *barHeightRateList = self.barHeightRateList.reverseObjectEnumerator.allObjects;
        [self.barList enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            obj.layer.anchorPoint = CGPointZero;
            CGFloat rate = 1.0;
            if (idx < barHeightRateList.count) rate = barHeightRateList[idx].floatValue;
            barRect.size.height = rect.size.height * rate;
            obj.frame = barRect;
            barRect.origin.x += barRect.size.width + self.barSpace;
        }];
    }
    
    #pragma mark -
    
    static CGRect CGRectWithEdgeInserts(CGRect rect, UIEdgeInsets inserts)
    {
        rect.origin.x += inserts.left;
        rect.origin.y += inserts.top;
        rect.size.width -= inserts.left + inserts.right;
        rect.size.height -= inserts.top + inserts.bottom;
        return rect;
    }
    
    #pragma mark -
    
    - (void)setBarCount:(NSInteger)barCount
    {
        _barCount = barCount;
        NSInteger diff = self.barList.count - barCount;
        if (diff > 0) {
            NSArray<UIView *> *removeBarViewList = [self.barList subarrayWithRange:NSMakeRange(barCount, diff)];
            [removeBarViewList makeObjectsPerformSelector:@selector(removeFromSuperview)];
            self.barList = [self.barList subarrayWithRange:NSMakeRange(0, barCount)];
        } else if (diff < 0) {
            diff = -diff;
            NSMutableArray *addBarViewList = [NSMutableArray arrayWithCapacity:diff];
            for (NSInteger index = 0; index < diff; index ++) {
                UIView *imageView = [[UIView alloc] init];
                imageView.clipsToBounds = YES;
                imageView.layer.cornerRadius = self.cornerRadius;
                [addBarViewList addObject:imageView];
                imageView.backgroundColor = [UIColor whiteColor];
            }
            if (self.barList) {
                self.barList = [self.barList arrayByAddingObjectsFromArray:addBarViewList];
            } else {
                self.barList = addBarViewList;
            }
        }
        [self.barList enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [self addSubview:obj];
        }];
    }
    
    - (void)setCornerRadius:(CGFloat)cornerRadius
    {
        _cornerRadius = cornerRadius;
        [self.barList enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            obj.layer.cornerRadius = cornerRadius;
        }];
    }
    
    - (void)setBarColor:(UIColor *)barColor
    {
        [self.barList enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            obj.backgroundColor = barColor;
        }];
    }
    
    - (void)aniamteWithBar:(UIView *)bar startHeight:(CGFloat)startHeight endHeight:(CGFloat)endHeight
    {
        CABasicAnimation * animation;
        animation = [CABasicAnimation animationWithKeyPath:@"bounds.size.height"];
        animation.fromValue = [NSNumber numberWithFloat:startHeight];
        animation.toValue = [NSNumber numberWithFloat:endHeight];
        animation.duration = 0.25;
        animation.repeatCount = MAXFLOAT;
        animation.autoreverses = YES;
        [bar.layer addAnimation:animation forKey:@"bounds.size.height"];
    }
    
    - (void)restart
    {
        [self stop];
        [self start];
    }
    
    - (void)start
    {
        if (self.isAniamting) return;
        self.isAniamting = YES;
        NSArray<NSValue *> *aniamteOffsetList = self.aniamteOffsetList.reverseObjectEnumerator.allObjects;
        [self.barList enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if (idx < aniamteOffsetList.count) {
                CGRect rect = CGRectWithEdgeInserts(self.bounds, self.contentInsets);
                CGPoint offset = aniamteOffsetList[idx].CGPointValue;
                [self aniamteWithBar:obj startHeight:rect.size.height * offset.x endHeight:rect.size.height * offset.y];
            }
        }];
    }
    
    - (void)stop
    {
        self.isAniamting = NO;
        [self.barList enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [obj.layer removeAllAnimations];
        }];
    }
    
    @end

     

    ViewController.m

    #import "ViewController.h"
    #import "FLAudioVisualizerView.h"
    
    #define kScreen_width [UIScreen mainScreen].bounds.size.width
    #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
    
    @interface ViewController ()
    
    @property (nonatomic, strong) FLAudioVisualizerView *visualizerView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor whiteColor];
        
        self.title = @"首页";
        //修改导航栏标题字体大小和颜色,背景颜色
        [self.navigationController.navigationBar setBarTintColor:[UIColor whiteColor]];
        [self.navigationController.navigationBar setTitleTextAttributes:@{
                                                                          NSFontAttributeName:[UIFont systemFontOfSize:17],NSForegroundColorAttributeName:[UIColor blackColor]
                                                                          }];
        UIButton *playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        playBtn.frame = CGRectMake(10, 100, 100, 20);
        [self.view addSubview:playBtn];
        [playBtn setTitle:@"开始播放" forState:UIControlStateNormal];
        [playBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [playBtn addTarget:self action:@selector(playClick) forControlEvents:UIControlEventTouchUpInside];
        
        UIButton *stopPlayBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        stopPlayBtn.frame = CGRectMake(10, 150, 100, 20);
        [self.view addSubview:stopPlayBtn];
        [stopPlayBtn setTitle:@"停止播放" forState:UIControlStateNormal];
        [stopPlayBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [stopPlayBtn addTarget:self action:@selector(stopPlayBtnClick) forControlEvents:UIControlEventTouchUpInside];
        [self setupVisualizerView];
    }
    
    - (void)setupVisualizerView
    {
        CGSize size = CGSizeMake(23, 22);
        UIEdgeInsets insets = UIEdgeInsetsMake(10, 0, 10, 20);
        size.width += insets.left + insets.right;
        size.height += insets.top + insets.bottom;
        // 直接直接使用visualizerView的时候,在侧滑返回的时候,会出现很奇怪的现象,visualizerView的frame会发生变化,导致显示异常
        UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
        FLAudioVisualizerView *visualizerView = [[FLAudioVisualizerView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
        self.visualizerView = visualizerView;
        [containerView addSubview:visualizerView];
        visualizerView.barColor = [UIColor colorWithRed:63/255 green:63/255 blue:64/255 alpha:1];
        visualizerView.contentInsets = insets;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gotoCurrentPlayPage)];
        [containerView addGestureRecognizer:tap];
        UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:containerView];
        self.navigationItem.rightBarButtonItem = barItem;
        
        
        
        
    }
    
    - (void)gotoCurrentPlayPage
    {
        NSLog(@"点击了播放按钮");
    }
    
    - (void)playClick
    {
        NSLog(@"1");
        [self.visualizerView restart];
    }
    
    - (void)stopPlayBtnClick
    {
        NSLog(@"2");
        [self.visualizerView stop];
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    @end
  • 相关阅读:
    【Android Studio安装部署系列】三十六、从Android Studio3.1.4升级到Android studio3.2【以及创建android p模拟器(未成功)】
    Android Studio升级到3.1.4后打开旧项目警告:The `android.dexOptions.incremental` property is deprecated and it has no effect on the build process.
    Activity、Fragment、Dialog基类简单整理
    Android项目目录结构模板以及简单说明【简单版】
    【Android Studio安装部署系列】四十、Android Studio安装Statistic插件(统计项目总行数)
    java对象池化技术
    Java中的常量池(字符串常量池、class常量池和运行时常量池)
    Java进阶——Java中的字符串常量池
    字符串常量池深入解析
    资源对象的池化, java极简实现,close资源时,自动回收
  • 原文地址:https://www.cnblogs.com/qiyiyifan/p/7649299.html
Copyright © 2011-2022 走看看