Flutter PIP 插件 ---- 为iOS 重构PipController, Demo界面,更好的体验

接上文 Flutter PIP 插件 ---- 新增PipActivity,Android 11以下支持自动进入PIP Mode
项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力

在之前的界面设计中,还原动画等体验一直不太好,遂优化一下,现在体验效果看起来更好了,

唯一一个还没搞定的是应用内还原的动画,应用内还原的时候,有一个从小到达逐渐拉伸的效果,猜测可能是和图片的渲染有关?有大佬能指点一二不?

不再获取PipViewController

前面也讲到这个比较危险,虽然多方求证似乎也没什么,但还是怕,所以改成查找PipWindow,并在pictureInPictureControllerDidStartPictureInPicture通知中把自渲染View添加到rootView中去

objc 复制代码
- (void)pictureInPictureControllerDidStartPictureInPicture:
    (AVPictureInPictureController *)pictureInPictureController {
  PIP_LOG(@"pictureInPictureControllerDidStartPictureInPicture");

#if USE_PIP_VIEW_CONTROLLER
  // if you use the pipViewController, you must call this every time to bring
  // the content view to the front, otherwise the content view will not be
  // visible and covered by the pip host view.
  if (_pipViewController) {
    [_pipViewController.view bringSubviewToFront:_contentView];
  }
#else
  // TODO @sylar: check if this is the best way to do this, what will happen if
  // we have multiple windows? what if the root view controller is not a
  // UIViewController?
  UIWindow *window = [[UIApplication sharedApplication] windows].firstObject;
  if (window) {
    UIViewController *rootViewController = window.rootViewController;
    UIView *superview = rootViewController.view.superview;
    [self insertContentViewIfNeeded:superview];
  } else {
    PIP_LOG(
        @"pictureInPictureControllerDidStartPictureInPicture: window is nil");
    [_pipStateDelegate pipStateChanged:PipStateFailed
                                 error:@"Can not find the pip window"];
    return;
  }
#endif

  _isPipActived = YES;
  [_pipStateDelegate pipStateChanged:PipStateStarted error:nil];
}

遗留项是,这个查找PipWindow的方法靠不靠谱?有其他方法但是看起来也不靠谱

不再每次都将自渲染UIView从PipWindow移除

观察到一个现象是,如果是依赖PipViewController在 pictureInPictureControllerWillStartPictureInPicture 中添加UIView,还必须得在 pictureInPictureControllerDidStartPictureInPicture 中调用一次 bringSubviewToFront ,否则的话你会比系统自动添加的View早添加,导致你的层级在下面;改用通过获取PipWindow方式后,就不用在bringSubviewToFront,因为不是一个parent了。

另外一些场景下可能会创建一个悬空的UIView用来做渲染,这样的话我们就没必要每次都把他从PipWindow上移除还原到父parent上,可以在PipWindow显示的一瞬间就立即看到渲染的内容

objc 复制代码
- (void)pictureInPictureControllerDidStopPictureInPicture:
    (AVPictureInPictureController *)pictureInPictureController {
  PIP_LOG(@"pictureInPictureControllerDidStopPictureInPicture");

  // restore the content view in
  // pictureInPictureControllerDidStopPictureInPicture will have the best user
  // experience.
  [self restoreContentViewIfNeeded];

  _isPipActived = NO;
  [_pipStateDelegate pipStateChanged:PipStateStopped error:nil];
}

- (void)restoreContentViewIfNeeded {
  if (_contentView == nil) {
    PIP_LOG(@"restoreContentViewIfNeeded: contentView is nil");
    return;
  }

  // do not restore the content view if the original parent view is nil or
  // the content view is already in the original parent view.
  // keep the content view in the pip view controller will make the user
  // experience better, the pip content view will be visible immediately.
  if (_contentViewOriginalParentView == nil ||
      [_contentViewOriginalParentView.subviews containsObject:_contentView]) {
    PIP_LOG(
        @"restoreContentViewIfNeeded: _contentViewOriginalParentView is nil or "
        @"contentView is already in the original parent view");
    return;
  }

  [_contentView removeFromSuperview];
  PIP_LOG(
      @"restoreContentViewIfNeeded: contentView is removed from the original "
      @"parent view");

  if (_contentViewOriginalParentView != nil) {
    // in case that the subviews of _contentViewOriginalParentView has been
    // changed, we need to get the real index of the content view.
    NSUInteger trueIndex = MIN(_contentViewOriginalParentView.subviews.count,
                               _contentViewOriginalIndex);
    [_contentViewOriginalParentView insertSubview:_contentView
                                          atIndex:trueIndex];

    PIP_LOG(@"restoreContentViewIfNeeded: contentView is added to the original "
            @"parent view "
            @"at index: %lu",
            trueIndex);

    // restore the original frame
    _contentView.frame = _contentViewOriginalFrame;

    // restore the original constraints
    [_contentView removeConstraints:_contentView.constraints.copy];
    [_contentView addConstraints:_contentViewOriginalConstraints];

    // restore the original translatesAutoresizingMaskIntoConstraints
    _contentView.translatesAutoresizingMaskIntoConstraints =
        _contentViewOriginalTranslatesAutoresizingMaskIntoConstraints;

    // restore the original parent view
    [_contentViewOriginalParentView
        removeConstraints:_contentViewOriginalParentView.constraints.copy];
    [_contentViewOriginalParentView
        addConstraints:_contentViewOriginalParentViewConstraints];
  }
}

支持动态设置PipWindow窗口大小

这个没什么好说的,修改创建contentSource的时候的sampleBufferDisplayer的大小就可以动态修改PipWindow窗口大小,判断各种对象都已经有了的话就只修改大小而不用重新创建controller就行了

objc 复制代码
if (options.preferredContentSize.width > 0 &&
    options.preferredContentSize.height > 0) {
  [_pipView
      updateFrameSize:CGSizeMake(options.preferredContentSize.width,
                                  options.preferredContentSize.height)];
}

重要的事情说三遍

项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力
项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力
项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力

相关推荐
恋猫de小郭18 小时前
Android 17 正式版发布,全新 AI 和各种破坏性更新
android·前端·flutter
911hzh19 小时前
Flutter MethodChannel 跨端通信框架 zh_native_channel:快速入门、优势分析与 Pigeon 对比
flutter
kingbal20 小时前
Flutter:Flutter SDK版本管理工具FVM
android·flutter·ios·android-studio·window
风华圆舞20 小时前
鸿蒙 Flutter 页面怎么感知防窥状态并调整 UI 可见性
flutter·ui·harmonyos
天天开发20 小时前
Flutter状态管理新宠:RiverPod全面解析与实战指南
android·flutter
「、皓子~1 天前
海狸IM 2.0 正式发布:六端齐发,开源 IM 迈入新阶段
flutter·electron·开源软件·ai编程·交友·im
JIngles1231 天前
flutter避免对widget图片作重复刷新(含实际图片发生变化或不发生变化)
flutter
雾沉川2 天前
Flutter 入门开发环境完整搭建教程
学习·flutter
MemoriKu2 天前
Flutter 本地 AI 相册工程收口:从屏幕常亮、标签体系到照片属性后台队列
大数据·人工智能·python·flutter·elasticsearch·搜索引擎·数据库架构
master3362 天前
python 安装pip
开发语言·python·pip