以编程方式确定Android Wear中的屏幕形状

时间:2014-09-02 22:33:14

标签: wear-os

我正在寻找一种在Java中确定Android Wear设备屏幕是圆形还是矩形的技术。请注意,这不仅仅是布局;我的代码实际上需要知道它正在使用哪种形状,因为它们的处理方式不同。

据我在网上的代码示例中可以看到,应该有两种不同的方法 - 但是我无法让它们中的任何一种工作。我将它们包括在这里以消除它们的运行,或者可能的故障排除(如果有人可以看到它们的问题)。请不要将我推荐给另一个SO帖子,这个帖子只是重申了我在这里不起作用的解决方案。

请注意,此处的所有代码都在手表上运行。另外,我还在使用Eclipse,FWIW。

我见过的最直接的方法是在我的布局中为视图添加onApplyWindowInsets()侦听器。所以我创建了一个如下所示的监听器:

@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
    if (insets.isRound()) {
     displayShape = "round";
    } else {
     displayShape = "rectangular";
    }
    return null;
}

并将其添加到我的布局的根视图中,代码如下:

view.setOnApplyWindowInsetsListener(this);

在我的onCreate()方法中。尽管看起来很好 - 但是听众永远不会被调用。我还发现建议说我需要手动调用它,如下:

view.requestApplyInsets();

但这似乎没有任何区别。我已经尝试将它放在不同的视图,不同的生命周期方法等等,但从来没有看到它实际上在我的应用程序中被调用。这是在我的LG G Watch,BTW上运行。

第二种方法是黑客攻击,它基于已发布的WatchViewStub帮助程序类。我跳过了箍,将可穿戴支持库导入到Eclipse项目中,然后将以下内容添加到我的根布局中:

<android.support.wearable.view.WatchViewStub 
    android:id="@+id/watch_view_stub"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:rectLayout="@layout/rect"
    app:roundLayout="@layout/round"
    />

并创建了rect.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:id="@+id/layout_type"
    android:text="rectangular"
    />

round.xml是这样的:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:id="@+id/layout_type"
    android:text="round"
    />

最后,在我的onCreate()中,我添加了以下Java代码:

    final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
        @Override
        public void onLayoutInflated(WatchViewStub stub) {
            TextView layoutType = (TextView) findViewById(R.id.layout_type);
            displayShape = layoutType.getText().toString();
        }
    });

这是一个很长的路要走,但它应该工作,对吗?与此同样...... displayShape始终设置为"rectangular",表示即使在圆形模拟器上运行,它也始终被rect.xml使用。 [我还没有经过圆形筛选的硬件来试试它。]

所以有人看到我在这两种方法中出错了吗?或者你能提出第三种实际有用的方法吗?

4 个答案:

答案 0 :(得分:13)

在追逐虚假线索的几天后,我终于找到了答案。事实证明,它是清单中应用程序的android:theme产生差异。

为了让WatchViewStub使用正确的矩形/圆形布局,您的应用必须使用@android:style/Theme.DeviceDefault作为主题。这是一个例子:

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.DeviceDefault">

我希望如果您使用从DeviceDefault继承的主题,它也会有用,但我还没有测试过。但似乎如果您使用任何其他自定义主题,WatchViewStub将无法正常运行。

@WaynePiekarski,如果在某处记录下来会很好。

此外,这里还有一些我在学习过程中学到的其他技巧:

  1. 矩形布局在圆形布局之前总是膨胀; IOW,在圆形设备上,您将获得两个onLayoutInflated()回调。如果你使用布局膨胀来将屏幕形状变成你的Java代码,那就太麻烦了,结果证明是必要的,因为......

  2. setOnApplyWindowInsetsListener()上调用WatchViewStub会阻止圆形布局加载(至少在我的测试中)。因此,如果您尝试使用此回调来确定屏幕形状,则圆形设备仍将获得方形布局。

  3. 最后,一个额外的问题: Android Wear是否有任何理由不仅仅将其屏幕形状报告为资源限定符?您知道,如-land,{{1 }}, 等等。为什么我们需要根据-large搞砸?

答案 1 :(得分:2)

在CanvasWatchFaceService.Engine中有一个覆盖方法可用,设置OnApplyWindowInsets,你可以检查插图是圆形还是方形

@Override
    public void onApplyWindowInsets(WindowInsets insets) {
        super.onApplyWindowInsets(insets);
        if(insets.isRound()){
          //round
        } 
        else{
          //square 
        }

    }

答案 2 :(得分:1)

https://plus.google.com/+NicolasPomepuy/posts/ZJ3KZK6uu2e#+NicolasPomepuy/posts/ZJ3KZK6uu2e

https://github.com/PomepuyN/WatchviewStubIssue/blob/bcad0de7fa473c757dc27f9dfe65e31561c6097f/wear/src/main/java/com/example/watchviewstubissue/ViewService.java

        mainView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { 
51             @Override 
52             public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { 
53                 if (insets.isRound()) { 
54                     Log.d("ViewService", "Round"); 
55                 } else { 
56                     Log.d("ViewService", "Square"); 
57                 } 
58                 return insets; 
59             } 
60         }); 

你的代码和他之间的差别在于你返回null并且他正在返回insets。

答案 3 :(得分:0)

我不确定为什么在您的情况下需要使用回调,但是屏幕形状的一般问题的答案是:Is there any way to detect if the clock is round?

也就是说,获取当前上下文并进行测试

context.getResources().getConfiguration().isScreenRound()