iOS流媒体开发:滑动手势控制音量、亮度和进度(转)


自定义一个UIButton
我们需要在视频上添加一个透明的button来捕捉和响应用户的点击滑动屏幕的事件,同时在.h文件中声明一个代理,向相应的页面传递自定义button的响应事件,代码如下:
.h文件

    #import <UIKit/UIKit.h>

    @protocol ZYLButtonDelegate <NSObject>

    /**
     * 开始触摸
     */
    - (void)touchesBeganWithPoint:(CGPoint)point;

    /**
     * 结束触摸
     */
    - (void)touchesEndWithPoint:(CGPoint)point;

    /**
     * 移动手指
     */
    - (void)touchesMoveWithPoint:(CGPoint)point;

    @end

    @interface ZYLButton : UIButton

    /**
     * 传递点击事件的代理
     */
    @property (weak, nonatomic) id <ZYLButtonDelegate> touchDelegate;

    @end
.m文件

    #import "ZYLButton.h"

    @implementation ZYLButton

    //触摸开始
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [super touchesBegan:touches withEvent:event];
        //获取触摸开始的坐标
        UITouch *touch = [touches anyObject];
        CGPoint currentP = [touch locationInView:self];
        [self.touchDelegate touchesBeganWithPoint:currentP];
    }

    //触摸结束
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [super touchesEnded:touches withEvent:event];
        UITouch *touch = [touches anyObject];
        CGPoint currentP = [touch locationInView:self];
        [self.touchDelegate touchesEndWithPoint:currentP];
    }

    //移动
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
        UITouch *touch = [touches anyObject];
        CGPoint currentP = [touch locationInView:self];
        [self.touchDelegate touchesMoveWithPoint:currentP];
    }

    @end
注意:之所以选择UIButton有2点原因:1、不用手动开启userInteractionEnabled用户交互2、同时可以很方便的为UIButton添加Target,不需要像UIView那样在再定义一个UITapGestureRecognizer,当然UIButton添加各种状态的背景颜色各背景图也要比UIView方便得多。

将自定义的Button添加到视频上

  //添加自定义的Button到视频画面上
      self.button = [[ZYLButton alloc] initWithFrame:playerLayer.frame];
      self.button.touchDelegate = self;
      [playerView addSubview:self.button];
在代理方法中改变定音量、亮度和进度
首先定义个一枚举表示上下左右,这里只需要判断手指是上下还是左右滑动

  typedef NS_ENUM(NSUInteger, Direction) {
      DirectionLeftOrRight,
      DirectionUpOrDown,
      DirectionNone
  };
同时声明一个表示方向的变量、一个记录用户触摸视频时的坐标变量、一个记录用户触摸视频时的亮度和音量大小的变量和一个记录用户触摸屏幕是视频进度的变量

  @property (assign, nonatomic) Direction direction;
  @property (assign, nonatomic) CGPoint startPoint;
  @property (assign, nonatomic) CGFloat startVB;
  @property (assign, nonatomic) CGFloat startVideoRate;
刚开始触摸视频的代理
当用户首次触摸视频时,记录首次触摸的坐标、当前音量或者亮度、当前视频的进度,为了获取当前音量要首先定义MPVolumeView、 UISlider

  @property (strong, nonatomic) MPVolumeView *volumeView;//控制音量的view

  @property (strong, nonatomic) UISlider* volumeViewSlider;//控制音量
    //设置self.volumeView的frame
    self.volumeView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width * 9.0 / 16.0);
在getter方法中初始化:

    - (MPVolumeView *)volumeView {
        if (_volumeView == nil) {
            _volumeView  = [[MPVolumeView alloc] init];
            [_volumeView sizeToFit];
            for (UIView *view in [_volumeView subviews]){
                if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
                    self.volumeViewSlider = (UISlider*)view;
                    break;
                }
            }
        }
        return _volumeView;
    }
然后在开始触摸的代理里记录

    #pragma mark - 开始触摸

    - (void)touchesBeganWithPoint:(CGPoint)point {
        //记录首次触摸坐标
        self.startPoint = point;
        //检测用户是触摸屏幕的左边还是右边,以此判断用户是要调节音量还是亮度,左边是亮度,右边是音量
        if (self.startPoint.x <= self.button.frame.size.width / 2.0) {
            //亮度
            self.startVB = [UIScreen mainScreen].brightness;
        } else {
            //音量
            self.startVB = self.volumeViewSlider.value;
        }
    }
    CMTime ctime = self.avPlayer.currentTime;
    self.startVideoRate = ctime.value / ctime.timescale / self.total;
接着在拖动的代理方法里改变音量、亮度和进度

  #pragma mark - 拖动 
  - (void)touchesMoveWithPoint:(CGPoint)point {
      //得出手指在Button上移动的距离
      CGPoint panPoint = CGPointMake(point.x - self.startPoint.x, point.y - self.startPoint.y);
      //分析出用户滑动的方向
       if (self.direction == DirectionNone) {
          if (panPoint.x >= 30 || panPoint.x <= -30) {
              //进度
              self.direction = DirectionLeftOrRight;
          } else if (panPoint.y >= 30 || panPoint.y <= -30) {
              //音量和亮度
              self.direction = DirectionUpOrDown;
          }
      }

      if (self.direction == DirectionNone) {
          return;
      } else if (self.direction == DirectionUpOrDown) {
          //音量和亮度
          if (self.startPoint.x <= self.button.frame.size.width / 2.0) {
      //调节亮度
              if (panPoint.y < 0) {
                  //增加亮度
                  [[UIScreen mainScreen] setBrightness:self.startVB + (-panPoint.y / 30.0 / 10)];
              } else {
                  //减少亮度
                  [[UIScreen mainScreen] setBrightness:self.startVB - (panPoint.y / 30.0 / 10)];
              }

          } else {
              //音量
              if (panPoint.y < 0) {
                   //增大音量
                  [self.volumeViewSlider setValue:self.startVB + (-panPoint.y / 30.0 / 10) animated:YES];
                  if (self.startVB + (-panPoint.y / 30 / 10) - self.volumeViewSlider.value >= 0.1) {
                      [self.volumeViewSlider setValue:0.1 animated:NO];
                      [self.volumeViewSlider setValue:self.startVB + (-panPoint.y / 30.0 / 10) animated:YES];
                  }

              } else {
                  //减少音量
                  [self.volumeViewSlider setValue:self.startVB - (panPoint.y / 30.0 / 10) animated:YES];
              }
          }
      } else if (self.direction == DirectionLeftOrRight ) {
          //进度
          CGFloat rate = self.startVideoRate + (panPoint.x / 30.0 / 20.0);
          if (rate > 1) {
              rate = 1;
          } else if (rate < 0) {
              rate = 0;
          }
      }
}
注意:1、前面提到一个增大音量的bug,我这里的解决办法是如果检测到用户设置的音量比系统当前的音量大于0.1,表示此时设置的音量已经无效了,然后把音量设置为0.1后再设置为我们设置无效的那个音量就可以了,具体做法参考代码;2、在修改视频播放进度的时候,最好不在移动的方法中实时修改视频播放进度,一方面会造成卡顿的现象,一方面没有必要这么做,所以这里只是记录了用户想要调整的进度,然后在触摸结束的方法中设置进度;3、这改变音量会调用系统自己的UI显示音量大小,但是在设置亮度的时候是系统没有提供相应的UI,需要我们自己设置,这个小伙伴们按照项目的需求自行添加一个UI效果就好了。

触摸结束的代理
#pragma mark - 结束触摸
  - (void)touchesEndWithPoint:(CGPoint)point {
      if (self.direction == DirectionLeftOrRight) {
          [self.avPlayer seekToTime:CMTimeMakeWithSeconds(self.total * self.currentRate, 1) completionHandler:^(BOOL finished) {
              //在这里处理进度设置成功后的事情
          }];
      }
  }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容