【问题标题】:Toggling fullscreen & orientation like YouTube像 YouTube 一样切换全屏和方向
【发布时间】:2014-04-03 20:23:27
【问题描述】:

我试图模仿 YouTube Android 应用在视频播放器中单击“全屏”按钮时的行为:

  • 如果设备当前处于纵向,则立即旋转到横向(即使用户仍以纵向方式握住设备)并保持横向,直到用户将设备旋转到横向,然后再旋转回纵向
    • 如果设备当前处于横向状态,请立即旋转为纵向(即使用户仍以纵向方式握住设备)并保持纵向,直到用户将设备旋转为纵向,然后再旋转回横向。
    • 允许用户随时将设备手动旋转到所需方向。

似乎如果我强制旋转为横向或纵向使用:

getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

...我立即失去了检测传感器方向变化的能力(即,一旦用户处于横向状态,并且他们想要手动将设备旋转回纵向)。

如果我将请求的方向更改为未指定或 onConfigurationChanged 中的传感器,则方向会短暂翻转为横向/纵向(无论我从上面请求什么),然后快速恢复到与设备握持方式相匹配的方向。

对如何实现上述目标有任何想法吗?

【问题讨论】:

    标签: android


    【解决方案1】:

    我遇到了完全相同的问题。我最终得到的是使用 OrientationListener 来检测用户何时实际将手机倾斜到横向,然后将方向设置为 SCREEN_ORIENTATION_SENSOR。

    OrientationEventListener orientationEventListener = 
    new OrientationEventListener(getActivity()) {
        @Override
        public void onOrientationChanged(int orientation) {
            int epsilon = 10;
            int leftLandscape = 90;
            int rightLandscape = 270;
            if(epsilonCheck(orientation, leftLandscape, epsilon) ||
               epsilonCheck(orientation, rightLandscape, epsilon)){
                    getMainActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                }
            }
    
            private boolean epsilonCheck(int a, int b, int epsilon) {
                return a > b - epsilon && a < b + epsilon;
            }
        };
        orientationEventListener.enable();
    

    这是 OrientationEventListener 的文档:Documentation

    您还需要为 Portrait 添加检查,因为您在原始帖子中描述了需要它。

    【讨论】:

    • 这应该是选择的答案。也可以做 Math.abs(a - b)
    • 老而金。你拯救了我的一天。谢谢!
    • 这是金子,我在上面卡了 5 个小时。这是我处理它的 kotlin 代码。
    • 2020年,答案还是有帮助的。谢谢兄弟
    【解决方案2】:

    大 tnx 到 havch

    这是金子,我在上面卡了 5 个小时。这是我处理它的 kotlin 代码。

    orientationEventListener = object: OrientationEventListener(this) {
                override fun onOrientationChanged(orientation: Int) {
                    val isPortrait = orientation > 300 || orientation < 60 || orientation in 120..240
    
                    if ((requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT && isPortrait) ||
                        (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && !isPortrait)){
                        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
                    }
                }
            }
            orientationEventListener.enable()

    【讨论】:

      【解决方案3】:

      Alexander 代码的这种修改对我来说效果更好

         object : OrientationEventListener(requireContext()) {
              override fun onOrientationChanged(orientation: Int) {
                  val isPortrait = orientation > 345 || orientation < 15 || orientation in 165..195
                  val isLandscape = orientation in 255..285 || orientation in 75..105
                  if (
                      (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT && isPortrait) ||
                      (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && isLandscape)
                  ) {
                      lifecycleScope.launch {
                          // adding a delay to avoid orientation change glitch
                          delay(200)
                          activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
                      }
                  }
              }
          }
      

      【讨论】:

      • 你说的那个故障还在发生。相反,我们需要像这样编程,只有当方向保持纵向或横向 200 毫秒或 300 毫秒时才更改为 Orientation_sensor。以编程方式,与调用 delay() 函数时相比,我们必须检查手机是否仍处于该特定方向
      【解决方案4】:
      /**
           * -1 -> Unknown
           * 1 -> Portrait
           * 0 -> Landscape
           */
          var previousOrientation = -1
      
          val orientationEventListener: OrientationEventListener =
              object : OrientationEventListener(this) {
                  override fun onOrientationChanged(orientation: Int) {
      
                      val isPortrait = (orientation > 340 || orientation < 20 || orientation in 160..200) &&
                              requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
                      val isLandscape = (orientation in 250..290 || orientation in 70..110) &&
                              requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
      
                      if (isPortrait || isLandscape) {
                          lifecycleScope.launch {
                              if (previousOrientation == -1) {
                                  previousOrientation = if (isPortrait) 1 else 0
                              }
                              delay(700)
                              val currentOrientation = if (isPortrait) 1 else 0
                              if (previousOrientation == currentOrientation) {
                                  previousOrientation = -1
                                  requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
                              }
                          }
                      }
                  }
              }
          orientationEventListener.enable()
      

      这个可以更正确地处理方向故障。 此代码是 @Buntupana 发布的改进版本

      【讨论】:

        【解决方案5】:

        尝试将RequestedOrientation 设置为SCREEN_ORIENTATION_SENSOR 当从全屏退出时! 设置 OrientationEventListener 可能会导致一些意外的资源使用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-10
          • 1970-01-01
          相关资源
          最近更新 更多