本文介绍了以编程方式确定 Android Wear 中的屏幕形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm looking for a technique to determine in Java if the Android Wear device screen is round or rectangular. Note that this isn't just about layouts; my code actually needs to know which shape it's working with, because they're handled differently.

就我从在线代码示例中看到的而言,应该可以使用两种不同的方法 - 但我一直无法让它们中的任何一种工作.我将它们包含在此处以将它们从运行中消除,或用于可能的故障排除(如果有人能看到它们的问题).请不要将我转介到另一篇 SO 帖子,该帖子只是重申了在这里对我不起作用的解决方案.

As far as I can see from code samples online, two different approaches should be possible - but I've been unable to get either of them to work. I'll include them here to eliminate them from the running, or for possible troubleshooting (if anyone can see the problem with them). Please don't refer me to another SO post that just reiterates the solutions that aren't working for me here.

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

Note that all code here is running on the watch. Also, I'm still using Eclipse, FWIW.

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

The most straightforward method I've seen involves adding an onApplyWindowInsets() listener to a view in my layout. So I created a listener that looks like this:

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

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

and added it to the root view of my layout with code like this:

view.setOnApplyWindowInsetsListener(this);

在我的 onCreate() 方法中.就目前而言看起来不错 - 但侦听器永远不会被调用.我还发现建议说我需要手动调用它,例如:

in my onCreate() method. Looks OK as far as it goes - but the listener never gets called. I also found advice saying that I needed to invoke it manually, as such:

view.requestApplyInsets();

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

but that didn't seem to make any difference. I've experimented with putting it on different views, in different lifecycle methods, and so forth, but never once saw it actually get called in my app. This is running on my LG G Watch, BTW.

第二种方法有点像hack,它基于已发布的WatchViewStub 帮助器类.我跳过了箍,将可穿戴支持库导入到 Eclipse 项目中,然后将以下内容添加到我的根布局中:

The second approach is something of a hack, and is based on the published WatchViewStub helper class. I jumped through the hoops to get the wearable support library imported into an Eclipse project, then added the following to my root layout:

<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 代码:

Finally, in my onCreate() I added the following Java code:

    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,即使在运行时在圆形模拟器上.[我还没有圆屏硬件可以试用.]

It's a long way around the block, but it should work, right? Not so much... displayShape is always set to "rectangular", indicating that it's always rect.xml that gets used, even when running on a round emulator. [I don't have round-screened hardware to try it on just yet.]

那么有没有人看到我在这两种方法中的任何一种中出了什么问题?或者你能提出第三种实际有效的方法吗?

So does anyone see where I've gone wrong with either of these two approaches? Or can you suggest a third way which actually works?

推荐答案

在花了几天时间寻找错误线索之后,我终于找到了答案.事实证明,区别在于清单中应用程序的 android:theme.

After several days spent chasing false leads, I've finally found the answer. It turns out that it's the android:theme of the application in the manifest that makes the difference.

为了让 WatchViewStub 使用正确的矩形/圆形布局,您的应用程序必须使用 @android:style/Theme.DeviceDefault代码> 作为它的主题.举个例子:

In order for WatchViewStub to use the correct rect/round layouts, it appears that your application must use @android:style/Theme.DeviceDefault as its theme. Here's an example:

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

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

I expect it would also work if you used a theme that inherited from DeviceDefault, though I haven't tested that. But it appears that if you use any other custom theme, WatchViewStub will not function correctly.

@WaynePiekarski,如果能在此处记录下来就好了.

@WaynePiekarski, it'd be nice if this was documented somehere.

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

Also, here are a couple of other tips that I learned along the way:

  1. 矩形布局总是在圆形布局之前膨胀;IOW,在圆形设备上,您将获得两个 onLayoutInflated() 回调.如果您使用布局膨胀来将屏幕形状添加到 Java 代码中,这将是一种痛苦,而事实证明这是必要的,因为...

  1. The rectangular layout always inflates before the round layout; IOW, on a round device, you'll get two onLayoutInflated() callbacks. This is kind of a pain if you're using the layout inflation to get the screen shape into your Java code, and that turns out to be necessary, because...

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

Calling setOnApplyWindowInsetsListener() on WatchViewStub prevents the round layout from loading at all (at least in my testing). So if you try to use this callback to determine the screen shape, round devices will still get the square layout.

最后,一个额外的问题:Android Wear 不只是将其屏幕形状报告为资源限定符有什么好的理由吗?你知道,比如 -land-large 等.我们到底为什么要搞乱 WatchViewStub 呢?

Finally, a bonus question: Is there any good reason why Android Wear doesn't just report its screen shape as a resource qualifier? You know, like -land, -large, and so on. Why on earth do we need to mess around with WatchViewStub at all?

这篇关于以编程方式确定 Android Wear 中的屏幕形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 14:23