iOS如何为导航栏添加播放动画

本文实例为大家分享了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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 解决ios端点击按钮闪烁问题(小tips)

    在ios端,safari浏览器上触发click事件有300ms的延迟相应,为touch添加的样式会和click冲突而出现闪烁问题 在safari中触摸事件的相应顺序如下: touchstart --> touchmove --> touchend --> click(300ms) 此时可试用以下样式取消click事件的默认样式来消除页面闪烁问题 *{ -webkit-tap-highlight-color:rgba(0,0,0,0); } (值得一提的是,300ms的延迟主要是用于判断用

  • vue中axios处理http发送请求的示例(Post和get)

    本文介绍了vue中axios处理http发送请求的示例(Post和get),分享给大家,具体如下: axios中文文档 https://github.com/mzabriskie/axios#using-applicationx-www-form-urlencoded-format   axios文档 在处理http请求方面,已经不推荐使用vue-resource了,而是使用最新的axios,下面做一个简单的介绍. 安装 使用node npm install axios 使用cdn <scrip

  • IOS中UITextView或UITextField字数限制的实现

    IOS中UITextView或UITextField字数限制的实现 UITextView或UITextField字数限制,输入时的限制,复制粘贴时的限制 字数限制有三种方法 在代理方法 "- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string" 或 "- (BOOL)textView:

  • IOS开发仿微信右侧弹出视图实现

    IOS开发仿微信右侧弹出视图实现 微信首页的+号,点击之后会弹出一个更多的视图,这个视图如何实现呢? 实现该效果可能需要以下技术要点: 1.图片拉伸,通过拉伸图片的中间的较小区域来保持图片的边上的形状 2.仿射变换,用到仿射变换的缩放,平移和合并,视图动画 3.navigationBar的样式设置 实现效果,如下: 本Demo图片来源微信安装包解压得到的图片 实现代码: // // ViewController.m // appXX-微信更多工具栏 // // Created by MRBean

  • 解决iOS11刷新tableview会出现漂移的现象

    首先要注意这只是在iOS11下会出现的bug,如果iOS10以及以下也有问题的情况不属于此列 问题的动图如下所示,如果要做每隔一段短时间就刷新一个section甚至整个tableview的操作的时候会出现闹鬼式的不断移动. 它真的是自己回去的~(限制动图2M真的有点烦) 解决方案 在初始化tableview的时候加上这几行 _tableview.estimatedRowHeight = 0; _tableview.estimatedSectionHeaderHeight = 0; _tablev

  • IOS 中NSTimer定时器的使用

    IOS 中NSTimer定时器的使用 NSTimery 定时器,主要用于进行定时执行指定方法,常用场景如:获取验证码的按钮倒计时:图片轮播定时. 1 使用注意事项: 1.1 倒计时时间间隔(时间单位是秒) 1.2 指定的执行方法 1.3 实现指定执行方法的对象 1.4 是否重复执行 2 对象的内存管理及销毁 2.1 使用方法" invalidate "进行停止 2.2 将对象设置为" nil " 2.3 特别是在返回到其他视图控制器的时候,要在方法" -

  • iOS如何为导航栏添加播放动画

    本文实例为大家分享了iOS为导航栏添加播放动画的具体代码,供大家参考,具体内容如下 FLAudioVisualizerView.h #import <UIKit/UIKit.h> @interface FLAudioVisualizerView : UIView #pragma mark - // 默认UIEdgeInsetsZero @property (nonatomic, assign) UIEdgeInsets contentInsets; // 默认为4 @property (non

  • Jquery给当前页或者跳转后页面的导航栏添加选中后样式的实例

    解决方法有两种:一种是直接给当前页面添加特殊样式,当网页刷新或者跳转到下一页后,样式消失:另一种情况是即使刷新页面后样式仍然有效. 直接上代码: 第一种情况: <script type="text/javascript" src="templets/js/jquery.js"></script> <script type="text/javascript"> $(document).ready(function

  • iOS仿微博导航栏动画(CoreGraphics)的实现方法

    前言 昨天刚做完项目的新版本.除了尝试一些新的架构之外.功能方面并没什么特别的地方. 但是顺手搞了一些还算好玩的东西.其一就是这个导航栏的动画. 感觉还算简单易懂.分享一下(其实更多是最近攒了好多封面.不贴出来憋得人难受). 导航栏动画.gif 思路 先介绍CA的两个方法: 基于原始状态的位移 CG_EXTERN CGAffineTransform CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty) CG_AVAILABLE_STAR

  • iOS中的导航栏UINavigationBar与工具栏UIToolBar要点解析

    一.导航栏UINavigationBar 1.导航栏的使用 在iOS开发中,我们通常会使用导航控制器,导航控制器中封装了一个UINavigationBar,实际上,我们也可以在不使用导航控制器的前提下,单独使用导航栏,在UINavigationBar中,也有许多我们可以定制的属性,用起来十分方便. 2.UINavigationBar的创建和风格类型 导航栏继承于UIView,所以我们可以像创建普通视图那样创建导航栏,比如我们创建一个高度为80的导航栏,将其放在ViewController的头部,

  • iOS状态栏、导航栏的一些笔记分享

    前言 IOS的界面分为状态栏和导航栏,如下图所示: 状态栏与导航栏的位置如上图,我们可以通过[UIApplication sharedApplication].statusBarFrame.size获取状态栏的size(一般没有刘海时的高度为20,有刘海时的高度为44). 通过self.navigationController.navigationBar.frame.size获取导航栏的size(一般高度为44,大标题时高度为xyz,当然也可以通过自定义来改变导航栏样式). ***ps:***在

  • iOS定制UISearchBar导航栏同步iOS11的方法

    系统原生的UISearchBar在iOS 11经历了一次变革,高度由原来的44变成了56 (使用默认高度的估计都被坑了),样式也发生了些微的变化,比如在未输入状态下圆角变化,放大镜图标和文本的文字不再居中而是靠左了.具体看图 一些主流App也常见在导航栏嵌入searchBar,以网易云音乐和知乎为例,左边是主页,右边是搜索页面 (注意光标). 实现思路与案例 核心思想是设置导航栏的titleView和左右的barButtonItem.主要有3种方式 首页导航栏的titleView使用button

  • iOS轻松实现导航栏透明渐变

    首先我们来看下效果 一开始当我们什么只设置了一张图片作为它的头部视图的时候,它是这样的 1.首当其冲的,我们先得把导航栏弄透明 那么我们首先得知道,设置navigationBar的BackgroundColor为Clear是没用的,你可以试着设置它的clear,但是没用,原因一会儿我们就知道了. 而对于把导航栏设置为透明,网上大多数的方法是: [self.navigationController.navigationBar setBackgroundImage:[UIImage new] for

  • iOS开发之导航栏各种右滑返回失效的解决方法汇总

    前言 众所周知iOS 的几乎全部页面都是需要右滑返回的,否则用户体验会大打折扣,但是在开发过程中经常会碰到某些页面右滑返回失效的情况,下面记录一下各种情况下右滑返回失效的解决方法. 下面话不多说了,来随着小编一起学习学习吧 自定义返回按钮时失效 当你重写 self.navigationItem.leftBarButtonItem 之后,自带的返回按钮就会被覆盖,右滑返回就会失效,解决办法只要加入下面这句代码即可. - (void)viewDidLoad { [super viewDidLoad]

  • iOS如何去掉导航栏(UINavigationBar)下方的横线

    网上有很多关于隐藏的方法,设置后能够成功,但是跳转到其他界面的时候发现,其他界面横线也被隐藏了. 目前主流的方法是将shadowImage用一张空的图片图片替换掉 可是这种方法不能解决navigationController里面的某个界面隐藏,其他不变的问题. [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];

  • iOS实现顶部标签式导航栏及下拉分类菜单

    本文实例为大家分享了iOS实现顶部标签式导航栏及下拉分类菜单的全部过程,供大家参考,具体内容如下 当内容及分类较多时,往往采用顶部标签式导航栏,例如网易新闻客户端的顶部分类导航,最近刚好有这样的应用场景,参考网络上一些demo,实现了这种导航效果,记录一些要点. 效果图(由于视频转GIF掉帧,滑动和下拉动画显得比较生硬,刚发现quickTime可以直接录制手机视频,推荐一下,很方便) 1.顶部标签式导航栏 (1)实现思路 其实就是在上下两个UIScrollView上做文章,实现联动选择切换的效果

随机推荐