Programmatically determine screen shape in Android Wear

I am looking for a technique to determine in Java if the screen of an Android Wear device is round or rectangular. Please note that this is not only about layouts; my code really needs to know what form it works with, because they are handled differently.

As far as I can see from the code examples on the Internet, two different approaches should be possible - but I could not get them to work. I will include them here to eliminate them from work, or for possible troubleshooting (if someone can see a problem with them). Please do not refer me to another SO post which simply repeats solutions that do not work for me here.

Please note that all the code here works on the clock. In addition, I still use Eclipse, FWIW.

The simplest method I've seen involves adding an onApplyWindowInsets() listener to the 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 this code:

 view.setOnApplyWindowInsetsListener(this); 

in my onCreate () method. It looks good as possible, but the listener was never called. I also found a tip saying that I need to call it manually, as such:

 view.requestApplyInsets(); 

but that doesn't seem to make any difference. I experimented with placing it on different representations, in different methods of the life cycle, etc., but I have never seen that it was really called in my application. This works on my LG G Watch, BTW.

The second approach is a bit of a hack and is based on a helper class published by WatchViewStub . I jumped over hoops to get a downloadable support library imported into an Eclipse project, and 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" /> 

and created rect.xml as such:

 <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" /> 

and round.xml as follows:

 <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" /> 

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(); } }); 

It's a long way around a block, but it should work, right? Not much ... displayShape always set to "rectangular" , indicating that it is always rect.xml used, even when working on a circular emulator. [I do not have round-screen equipment to try it for now.]

So does anyone see where I made a mistake with either of these two approaches? Or can you suggest a third way that really works?

+5
source share
3 answers

After several days chasing false conclusions, I finally found the answer. It turns out that this android:theme application in the manifest makes a difference.

In order for WatchViewStub use the correct rectangle / round layouts, it seems your application should use @android:style/Theme.DeviceDefault as its theme. Here is an example:

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

I expect this to work as well if you used a theme inherited from DeviceDefault , although I haven't tested it. But it seems that if you use any other custom theme, WatchViewStub will not work correctly.

@WaynePiekarski, it would be nice if that were documented.

In addition, here are a few other tips that I learned along the way:

  • The rectangular layout always swells before the round layout; IOW, on the round device you get two onLayoutInflated() . It’s kind of a pain if you use layout inflation to get the screen shape into your Java code, and this proves necessary because ...

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

Finally, the question of the bonus: is there a good reason why Android Wear not only reports its screen shape as a resource qualifier? You know, like -land , -large , etc. Why do we need to bother with WatchViewStub at WatchViewStub ?

+12
source

In CanvasWatchFaceService.Engine their overide method is available setOnApplyWindowInsets you can check if the inserts are round or square

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

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

and 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 }); 

The difference between your code and its is that you return zero, and it returns the inserts.

+1
source

Source: https://habr.com/ru/post/1201678/


All Articles