如何在 Google VR 视图中导航?

2023-12-10

我正在编写一个 Android 应用程序,使用Vr全景视图我知道在 VR 应用程序中有两种导航方式

  • 使用纸板上的单个按钮作为点击
  • 将长时间注视某物视为一次点击

我如何使用其中一个来实现导航,以便如果用户单击按钮 panoview 将跳到下一张图片?

以下是示例 Vr PanoramaView 代码

**
 * A basic PanoWidget Activity to load panorama images from disk. It will load a test image by
 * default. It can also load an arbitrary image from disk using:
 *   adb shell am start -a "android.intent.action.VIEW" \
 *     -n "com.google.vr.sdk.samples.simplepanowidget/.SimpleVrPanoramaActivity" \
 *     -d "/sdcard/FILENAME.JPG"
 *
 * To load stereo images, "--ei inputType 2" can be used to pass in an integer extra which will set
 * VrPanoramaView.Options.inputType.
 */
public class SimpleVrPanoramaActivity extends Activity {
  InputStream istr = null;

  private static final String TAG = SimpleVrPanoramaActivity.class.getSimpleName();
  /** Actual panorama widget. **/
  private VrPanoramaView panoWidgetView;
  /**
   * Arbitrary variable to track load status. In this example, this variable should only be accessed
   * on the UI thread. In a real app, this variable would be code that performs some UI actions when
   * the panorama is fully loaded.
   */
  public boolean loadImageSuccessful;
  /** Tracks the file to be loaded across the lifetime of this app. **/
  private Uri fileUri;
  /** Configuration information for the panorama. **/
  private Options panoOptions = new Options();
  private ImageLoaderTask backgroundImageLoaderTask;

  /**
   * Called when the app is launched via the app icon or an intent using the adb command above. This
   * initializes the app and loads the image to render.
   */
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);

    // Make the source link clickable.
    TextView sourceText = (TextView) findViewById(R.id.source);
    sourceText.setText(Html.fromHtml(getString(R.string.source)));
    sourceText.setMovementMethod(LinkMovementMethod.getInstance());

    panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);
    panoWidgetView.setEventListener(new ActivityEventListener());

    // Initial launch of the app or an Activity recreation due to rotation.
    handleIntent(getIntent());
  }

  /**
   * Called when the Activity is already running and it's given a new intent.
   */
  @Override
  protected void onNewIntent(Intent intent) {
    Log.i(TAG, this.hashCode() + ".onNewIntent()");
    // Save the intent. This allows the getIntent() call in onCreate() to use this new Intent during
    // future invocations.
    setIntent(intent);
    // Load the new image.
    handleIntent(intent);
  }

  /**
   * Load custom images based on the Intent or load the default image. See the Javadoc for this
   * class for information on generating a custom intent via adb.
   */
  private void handleIntent(Intent intent) {
    // Determine if the Intent contains a file to load.
    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
      Log.i(TAG, "ACTION_VIEW Intent recieved");

      fileUri = intent.getData();
      if (fileUri == null) {
        Log.w(TAG, "No data uri specified. Use \"-d /path/filename\".");
      } else {
        Log.i(TAG, "Using file " + fileUri.toString());
      }

      panoOptions.inputType = intent.getIntExtra("inputType", Options.TYPE_MONO);
      Log.i(TAG, "Options.inputType = " + panoOptions.inputType);
    } else {
      Log.i(TAG, "Intent is not ACTION_VIEW. Using default pano image.");
      fileUri = null;
      panoOptions.inputType = Options.TYPE_MONO;
    }

    // Load the bitmap in a background thread to avoid blocking the UI thread. This operation can
    // take 100s of milliseconds.
    if (backgroundImageLoaderTask != null) {
      // Cancel any task from a previous intent sent to this activity.
      backgroundImageLoaderTask.cancel(true);
    }
    backgroundImageLoaderTask = new ImageLoaderTask();
    backgroundImageLoaderTask.execute(Pair.create(fileUri, panoOptions));
  }

  @Override
  protected void onPause() {
    panoWidgetView.pauseRendering();
    super.onPause();
  }

  @Override
  protected void onResume() {
    super.onResume();
    panoWidgetView.resumeRendering();
  }

  @Override
  protected void onDestroy() {
    // Destroy the widget and free memory.
    panoWidgetView.shutdown();

    // The background task has a 5 second timeout so it can potentially stay alive for 5 seconds
    // after the activity is destroyed unless it is explicitly cancelled.
    if (backgroundImageLoaderTask != null) {
      backgroundImageLoaderTask.cancel(true);
    }
    super.onDestroy();
  }

  /**
   * Helper class to manage threading.
   */
  class ImageLoaderTask extends AsyncTask<Pair<Uri, Options>, Void, Boolean> {

    /**
     * Reads the bitmap from disk in the background and waits until it's loaded by pano widget.
     */
    @Override
    protected Boolean doInBackground(Pair<Uri, Options>... fileInformation) {
      Options panoOptions = null;  // It's safe to use null VrPanoramaView.Options.
      InputStream istr = null;
      if (fileInformation == null || fileInformation.length < 1
          || fileInformation[0] == null || fileInformation[0].first == null) {
        AssetManager assetManager = getAssets();
        try {
          istr=new URL("https://s18.postimg.org/rnoymr5o9/andes.jpg").openStream();
          //istr = assetManager.open("andes.jpg");
          panoOptions = new Options();
          panoOptions.inputType = Options.TYPE_STEREO_OVER_UNDER;
        } catch (IOException e) {
          Log.e(TAG, "Could not decode default bitmap: " + e);
          return false;
        }
      } else {
        try {
          istr = new FileInputStream(new File(fileInformation[0].first.getPath()));
          panoOptions = fileInformation[0].second;
        } catch (IOException e) {
          Log.e(TAG, "Could not load file: " + e);
          return false;
        }
      }

      try {
        istr.close();
      } catch (IOException e) {
        Log.e(TAG, "Could not close input stream: " + e);
      }

      return true;
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
      super.onPostExecute(aBoolean);

      panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);

    }
  }

  /**
   * Listen to the important events from widget.
   */
  private class ActivityEventListener extends VrPanoramaEventListener {
    /**
     * Called by pano widget on the UI thread when it's done loading the image.
     */
    @Override
    public void onLoadSuccess() {
      loadImageSuccessful = true;
    }

    /**
     * Called by pano widget on the UI thread on any asynchronous error.
     */
    @Override
    public void onLoadError(String errorMessage) {
      loadImageSuccessful = false;
      Toast.makeText(
          SimpleVrPanoramaActivity.this, "Error loading pano: " + errorMessage, Toast.LENGTH_LONG)
          .show();
      Log.e(TAG, "Error loading pano: " + errorMessage);
    }
  }
}

  1. 您需要声明传感器

    private SensorManager mSensorManager;
    private OrientationSensor mOrientationSensor;
    mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
    mOrientationSensor = new OrientationSensor(this, mSensorManager, OrientationSensor.MODE_LOOK_THROUGH);
    
  2. 使您的 Activity 或 Fragment 实现SensorEventListener

  3. 创建向量以检索旋转值

     private float[] mHeadRotation = new float[2];
    
  4. 在 onSensorChanged 中

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        mUiPanoWidgetView.getHeadRotation(mHeadRotation);
        updateReticule();
    }
    
  5. 根据您在图片中的位置做您想做的事情。例子:

    private void updateReticule() {
        if(mHeadRotation[1] > -20 && mHeadRotation[1] < 20 && mHeadRotation[0] > -15 && mHeadRotation[0] < 15){
            showButton();
        } else {
            showReticule();
        }
    }
    
  6. showButton() 可以显示或隐藏屏幕中央的箭头(ImageButton)。然后在箭头上设置一个 OnClickListener。如果用户点击,则可以转到下一张图片。

希望它能帮助你:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Google VR 视图中导航? 的相关文章

  • Android 通知进度条冻结

    这是我正在使用的代码 http pastebin com 3bMCKURu http pastebin com 3bMCKURu 问题是 一段时间后 文件变得更重 通知栏下拉速度变慢 最后它就冻结了 你的通知太频繁了 这就是它冻结的原因 让
  • GCM 向主题发送消息:TOO_MANY_TOPICS 错误

    以前 GCM 每个应用程序有 100 万个主题订阅的限制 我发现他们现在已经取消了这一限制 基于发布 订阅模型 主题消息支持 每个应用程序无限订阅 https developers google com cloud messaging to
  • Android - 如何一次只允许播放一个 MediaPlayer 实例?

    我正在尝试创建一个简单的 Sound board Android 应用程序 使用 ListView 项目作为按钮 顺便说一句 我是一个新手程序员 我的想法是 我按下一个按钮 就会播放一个特定的声音文件 如果我在播放声音时按下任何按钮 它应该
  • Android 应用程序在后台运行时保存数据

    目前我正在开发 xmmp 客户端 当应用程序位于前台时 该客户端工作得很好 但由于事实上 当应用程序处于后台时 我在 Application 类中保存了大量数据 复杂的 ArrayList 字符串和布尔值作为公共静态 每个字段都被垃圾收集
  • 如何更新 Firebase 中的节点密钥?

    如何重命名14 04 2017 node 没有用于重命名节点的 API 您必须获取节点的值 使用新名称将其保存到数据库并删除旧节点
  • 为什么将函数参数声明为最终的?

    我目前正在阅读 Sams 出版的 24 小时自学 Android 应用程序开发 一书 我对 Java Android 或其他方面还比较陌生 我对 ActionScript 3 有非常扎实的背景 它与 Java 有足够的相似之处 因此该语言本
  • 如何从 SQLite 获取记录总数

    我正在尝试从 Sqlite DB 获取行的总数 以下是我想要做的代码片段 我不知道我在这里做错了什么 public static int getTotalCount Context context Cursor c null try c g
  • Phonegap - 如何将.txt文件保存在Android手机的根目录中

    我正在尝试使用phonegap 将 txt 文件保存在Android 手机的根目录中 我已经安装了这些插件 cordova plugin file 和 cordova plugin file transfer 在 config xml 文件
  • Android:“dp”到“px”转换?

    我正在读这篇文章 http developer android com guide practices screens support html http developer android com guide practices scre
  • 设置从 Facebook 登录获取用户电子邮件 ID 的权限

    我在用着Facebook 3 0 SDK对于安卓 我必须实施Facebook登录 我正在访问用户的基本信息 例如姓名 用户 ID 但我也想访问用户的电子邮件 我浏览了很多博客和论坛 但不知道该怎么做 我正在使用我自己的 android 按钮
  • Android 原理图内容提供程序库配置?

    Jake Wharton 在最近的一次演讲中提到了这个库 它看起来是避免大量样板文件的好方法 所以我尝试了一下 但没有任何成功 https github com SimonVT schematic https github com Simo
  • OnClick 事件中的 finish() 如何工作?

    我有一个Activity一键退出Activity 通过layout xml我必须设置OnClick事件至cmd exit调用 this finish 效果很好 public void cmd exit View editLayout thi
  • Firebase:如何在Android应用程序中设置默认通知渠道?

    如何设置default通知渠道通知消息当应用程序在后台运行时会出现什么情况 默认情况下 这些消息使用 杂项 通道 如你看到的在官方文档中 https firebase google com docs cloud messaging andr
  • 在 Jetpack Compose 中启动动画矢量 Drawable

    我有一个动画矢量可绘制R drawable my anim 我想在 Jetpack Compose 中展示并开始 可绘制对象显示 渲染正确 但动画未启动 这是撰写视图 Composable fun SplashView Surface mo
  • MediaCodec 创建输入表面

    我想使用 MediaCodec 将 Surface 编码为 H 264 使用 API 18 有一种方法可以通过调用 createInputSurface 然后在该表面上绘图来对表面中的内容进行编码 我在 createInputSurface
  • Android相机意图:如何获取全尺寸照片?

    我正在使用意图来启动相机 Intent cameraIntent new Intent android provider MediaStore ACTION IMAGE CAPTURE getParent startActivityForR
  • Android 设备上的静默安装

    我已经接受了一段时间了 在 Android 上静默安装应用程序是不可能的 也就是说 让程序安装捆绑为 APK 的应用程序 而不提供标准操作系统安装提示并完成应用程序安装程序活动 但现在我已经拿到了 Appbrain 快速网络安装程序的副本
  • 在 Android 上按下电源按钮时,如何防止先调用 onDestroy() 再调用 onCreate()

    我正在记录每个 onCreate 和 onDestroy 调用 我发现 一旦我单击 Android 上的电源按钮 以及模拟器上的电源按钮 我的活动中就会拨打电话 gt onDestroy gt onCreate 这会杀死我的游戏 然后立即从
  • 为什么Android的ImageReader类这么慢?

    我尝试了适用于 Android 3 4 1 的全新 OpenCVJavaCamera2View但它太慢了 仅显示相机视图约 15 fps 当我尝试较旧的JavaCameraView相反 它给了我很好的结果 30fps 这是我相机的极限 我想
  • 无法将 admob 与 firebase iOS/Android 项目链接

    我有两个帐户 A 和 B A 是在 Firebase 上托管 iOS Android unity 手机游戏的主帐户 B 用于将 admob 集成到 iOS Android 手机游戏中 我在尝试将 admob 分析链接到 Firebase 项

随机推荐