【问题标题】:How to detect round screen on Android Wear - onApplyWindowInsets not called on device如何在 Android Wear 上检测圆形屏幕 - 设备上未调用 onApplyWindowInsets
【发布时间】:2014-08-25 21:58:32
【问题描述】:

我在 Android Wear 项目中实现了 onApplyWindowInsets 回调。在该方法中,它调用 isRound() 来确定代码是在圆形还是矩形 Wear 智能手表上运行。这个回调是从圆形磨损模拟器中调用的。 (虽然 isRound() 返回 false,这是错误的。)但问题是我的 Samsung Gear Live 从未调用过 onApplyWindowInsets 回调。因此,如果从 onApplyWindowInsets 膨胀视图,则视图不会膨胀。有没有人让 onApplyWindowInsets 在真实设备上触发?似乎不能保证。如果是这样,那么如何根据屏幕类型来扩展不同的视图?

【问题讨论】:

    标签: android rounding screens


    【解决方案1】:

    在您的布局中,您可以为圆形/矩形屏幕设置特定的“子”布局:

     <FrameLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
    
          <android.support.wearable.view.WatchViewStub
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:id="@+id/stub"
              app:rectLayout="@layout/rect_layout"
              app:roundLayout="@layout/round_layout"/>
     </FrameLayout>
    

    如果你对rect_layout和round_layout使用不同的id,你可以在onCreate上查看,像这样:

    @Override
    public void onCreate(Bundle b) {
        super.onCreate(b);
        setContentView(R.layout.main_activity);
        WatchViewStub stub = (WatchViewStub) findViewById(R.id.stub);
        stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
            @Override
            public void onLayoutInflated(WatchViewStub stub) {
                mRectBackground = (RelativeLayout) findViewById(R.id.rect_layout);
                mRoundBackground = (RelativeLayout) findViewById(R.id.round_layout);
            }
        });
    }
    

    mRectBackground 或 mRoundBackground 中的任何一个都将为非 null,而不是两者。文档在这里:https://developer.android.com/training/wearables/apps/layouts.html#UiLibrary

    其他人尝试使用使用 setOnApplyWindowInsetsListener 的策略,如下所示:https://github.com/xamarin/monodroid-samples/blob/master/wear/GridViewPager/GridViewPager/MainActivity.cs。它对我不起作用。

    【讨论】:

    • 谢谢!你聪明的技术似乎已经解决了这个问题。 (我说“似乎”,因为在将 mRoundBackground 设置为非空值的真实圆形设备上测试代码之前,我无法确定。)
    【解决方案2】:

    onApplyWindowInsets实际上需要开发者在监听器中调用WatchViewStubonApplyWindowInsets方法。例如:

    WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    stub.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
    
        @Override
        public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
            //////////////////////////////////////////////////
            // IMPORTANT - the following line is required
            stub.onApplyWindowInsets(windowInsets);
    
            // Set the instance variable to say whether this is round...
            mIsRound = windowInsets.isRound();
    
            return windowInsets;
        }
    });
    

    虽然乍一看可能不直观,但这允许开发人员选择覆盖默认的onApplyWindowInsets 实现。

    View.OnApplyWindowInsetsListener 的文档指出:“侦听器可以可选地调用参数 View 的 onApplyWindowInsets 方法来应用 View 的正常行为作为其自身的一部分。”

    【讨论】:

    • 不幸的是,我无法扩展 InsetActivity,因为我的主类已经扩展了 FragmentActivity。我尝试将 Hoi 的方法作为内部类,但也没有运气。到目前为止,我已经尝试了至少十几种方法,但在真实设备上检测圆形或方形屏幕都没有运气。 (onLayoutInflated 方法总是返回方形,即使在 Moto 360 圆形屏幕上也是如此。onApplyWindowInsets 回调永远不会触发。...等等)任何人都知道一种在真实设备上实际工作的方法,用于检测形状和填充正确的布局,而不仅仅是在模拟器?我已经在这几个星期了,仍然没有答案。
    • 在真正的 Moto 360 上测试过,但这不起作用 :(.isRound() 无论设备如何,总是返回 false。
    • 12 月 11 日编辑的上述答案现在可以使用。 10 月 25 日 WillT 和 11 月 15 日 HyLian 的评论对于使用 InsetActivity (因为已弃用)的先前答案(10 月 9 日发布)有效。感谢您的反馈。
    【解决方案3】:

    谢谢艾德!你聪明的技术似乎已经解决了这个问题。 (我说“似乎”,因为在将 mRoundBackground 设置为非空值的真实圆形设备上测试代码之前,我无法确定。)

    现在 Android Wear 有 3 种形状(矩形/方形、带下巴的圆形和圆形),我添加了两个全局值来查找屏幕形状,然后修改回调如下:

       stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
            @Override
            public void onLayoutInflated(WatchViewStub stub) {
                //mRectBackground = (RelativeLayout) findViewById(R.id.LinearLayout1);
                mRoundBackground = (RelativeLayout) findViewById(R.id.LinearLayout2);
                if (mRoundBackground != null) round = true;
                else round = false;
    
                WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
                Display display = window.getDefaultDisplay();
                //Added android.graphics.Point to imports for this next section
                Point point = new Point (0,0);
                display.getSize(point);
                scrnHeight = point.y;
                scrnWidth  = point.x;
                if (round && scrnWidth == scrnHeight) chin = false;
                else chin = true;
                //round = true; //For testing on the emulator!!!!!!
           }
        });
    

    有人知道在 Moto360 上检测下巴的更好方法吗?

    更新:刚刚在 Moto 360 上运行此代码,但此技术未检测到圆形屏幕。所以现在我只是检测高度是否等于宽度。但当更多的 Android Wear 设备出现时,这对未来来说是一个糟糕的技术。那么问题依然存在,如何在真正的 Android Wear 设备上确定圆形屏幕?

    【讨论】:

    • 嘿。那么moto360会报告它的屏幕高度为320吗?
    • 不要使用“高度等于宽度”之类的测试,因为至少 G Watch(方形屏幕)就是这种情况。
    【解决方案4】:

    非官方方式(不使用 WatchViewStub)——但对我来说这要容易得多。 https://github.com/tajchert/ShapeWear

    只需复制ShapeWear.java类,并订阅屏幕形状检测事件setOnShapeChangeListener()或调用方法ShapeWear.isRound()(可能会抛出错误是形状尚未确定)或ShapeWear. getShape() - 这可能会导致ShapeWear.SHAPE_UNSURE in同样的情况。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多