12

I am curious to know about the wear type, whether it's round or square, because on the basis of device type I want to make different views for round and square. From This Post I got to know that in SDK-20 android.view.View class has a new listener to detect device type, using this I am trying to get the device type but nothing is printing on logcat. Below is the code I tried.

public class WearSplash extends Activity implements OnApplyWindowInsetsListener {
private WatchViewStub _stub = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_wear_splash);

    _stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    _stub.setOnApplyWindowInsetsListener(this);
    _stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {

        @Override
        public void onLayoutInflated(WatchViewStub mStub) {
            // here on the basis of device type i want to inflate views.
        }
    });

}
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
    System.out.println(" in testing phase");
    if (insets.isRound())
        System.out.println("in round");
    else
        System.out.println("in square");
    return null;
  }
}

xml files.

<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.WatchViewStub xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="@layout/rect"
app:roundLayout="@layout/round"
tools:context="com.app.WearSplash"
tools:deviceIds="wear" >

</android.support.wearable.view.WatchViewStub>

Round:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.app.WearSplash"
tools:deviceIds="wear_round" >

<TextView
    android:id="@+id/text"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:contentDescription="@string/hello_world" />

</RelativeLayout>

Square:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.app.WearSplash"
tools:deviceIds="wear_square" >

<ImageView 
    android:id="@+id/image"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    android:contentDescription="@string/hello_world"
    android:background="@drawable/ic_launcher"/>

</LinearLayout>

I am new to wear development, let me know where I am going wrong. Helping hands will be highly appreciated.

Community
  • 1
  • 1
Pankaj Arora
  • 10,224
  • 2
  • 37
  • 59
  • Not sure it this is the issue, I have not tried with wear either, but when I tried to implement the `OnApplyWindowInsetsListener` in android studio, it got autocompleted as `View.OnApplyWindowInsetsListener`. So can you please try `public class WearSplash extends Activity implements View.OnApplyWindowInsetsListener` instead of `class WearSplash extends Activity implements OnApplyWindowInsetsListener`. – Harikrishnan Jul 23 '14 at 10:17
  • Already tried ,not working – Pankaj Arora Jul 23 '14 at 10:21
  • Actually I am getting an error when I try to implement `OnApplyWindowInsetsListener` without the `View.` part. – Harikrishnan Jul 23 '14 at 10:23
  • Did you try debugging? Is `public WindowInsets onApplyWindowInsets(View v, WindowInsets insets)` getting triggered? – Harikrishnan Jul 23 '14 at 10:25
  • 1
    yes i debug, public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) is never called. – Pankaj Arora Jul 23 '14 at 10:26
  • I don't have a device and the emulator is not working well for me, so I can't test it. Can you try `findViewById(android.R.id.content).setOnApplyWindowInsetsListener(this);` right after the `setContentView` and then comment off `_stub.setOnApplyWindowInsetsListener(this);` and then try running? If it works please do inform. :) – Harikrishnan Jul 23 '14 at 11:10
  • 07-23 11:11:30.590: E/AndroidRuntime(1189): java.lang.NullPointerException 07-23 11:11:30.590: E/AndroidRuntime(1189): at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:5436) 07-23 11:11:30.590: E/AndroidRuntime(1189): at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:5439) 07-23 11:11:30.590: E/AndroidRuntime(1189): at android.view.ViewRootImpl.dispatchApplyInsets(ViewRootImpl.java:1170) – Pankaj Arora Jul 23 '14 at 11:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57826/discussion-between-harikrishnan-t-and-pankaj-arora). – Harikrishnan Jul 23 '14 at 11:15
  • sorry..chat is not allowed in my office. – Pankaj Arora Jul 23 '14 at 11:16
  • I went through the documentation and found that you can force the view to apply Window Insets by using `dispatchApplyWindowInsets(some_Window_insets_Object)` hence triggering the method. Why not give it a try? – Harikrishnan Jul 23 '14 at 11:42
  • can you write the code? – Pankaj Arora Jul 23 '14 at 11:54
  • Can you post your xml layout file? – Maciej Ciemięga Jul 23 '14 at 17:08
  • @MaciejCiemięga check xml files. – Pankaj Arora Jul 24 '14 at 04:11
  • @MaciejCiemięga i want to inflate different view account to round and square,like if app is running of round UI will be Diffrent from when app is running on square wear. i hope i am able to clear my requirement. – Pankaj Arora Jul 24 '14 at 04:34
  • @PankajArora: please go with the solutions described in the answers below. From me I will also add that you CANNOT `return null` in `onApplyWindowInsets` method. You NEED to either return `insets` object (unmodified or modified). `return null;` will result in `NullPointerException`. – Maciej Ciemięga Jul 24 '14 at 18:17
  • Possible duplicate of [Is there any way to detect if the clock is round?](http://stackoverflow.com/questions/22525582/is-there-any-way-to-detect-if-the-clock-is-round) – rekire Mar 14 '16 at 19:12

4 Answers4

9

API 23 introduced:

isScreenRound()

rmgoncalo
  • 567
  • 6
  • 16
  • Would be good if this answer provided more context. The link to the reference is nice but for beginners (like myself), it's quite difficult to see how this can be used in code. – bartaxyz Apr 17 '21 at 08:15
7

Unofficial way (without using WatchViewStub) - but for me it was way way easier. https://github.com/tajchert/ShapeWear

Just copy ShapeWear.java class, and subscribe to screen shape detection event setOnShapeChangeListener() or call method ShapeWear.isRound() (can throw error is shape is not yet determined) or ShapeWear. getShape() - which can result in ShapeWear.SHAPE_UNSURE in same situation.

Michał Tajchert
  • 10,333
  • 4
  • 30
  • 47
1

Use WatchViewStub to inflate the view.Later in the layout file you may specify the layout for each watch type as below.It will automatically pick the correct layout as required by the device.

<android.support.wearable.view.WatchViewStub
    .
    .
    .
    app:rectLayout="@layout/rect_activity_my_wear"
    app:roundLayout="@layout/round_activity_my_wear"
    .
    .
    .
>
1

If you need to get this information programmatically, you are correct in adding add a listener for setOnApplyWindowInsetsListener(). However, in order to trigger that, you must also call requestApplyInsets().

In any case, if you only want to know this to switch between two alternative layouts, you can use the WatchViewStub class which does this automatically (docs here).

matiash
  • 54,791
  • 16
  • 125
  • 154
  • can you tell how to implement this in my code to get the wear type? – Pankaj Arora Jul 24 '14 at 04:18
  • I don't think there is a need to invoke `requestApplyInsets()` manually. I've successfully had this listener called without it. – Maciej Ciemięga Jul 24 '14 at 05:15
  • @MaciejCiemięga On a `WatchViewStub`, or with other View subclasses? – matiash Jul 24 '14 at 15:08
  • @matiash: On any view - like `FrameLayout`, `TextView` etc. – Maciej Ciemięga Jul 24 '14 at 18:13
  • @MaciejCiemięga I didn't test it on other views, but `WatchViewStub` does call `requestApplyInsets()` manually. My theory is that it's fired once when laid out, so that if you add the listener later, it's not called again unless you request it again. – matiash Jul 24 '14 at 18:47
  • @PankajArora Try adding `_stub.requestApplyInsets();` after `stub.setOnApplyWindowInsetsListener(this);` – matiash Jul 24 '14 at 22:06
  • @MaciejCiemięga Possibly you added the listener to a new view _before_ the view was added to the view hierarchy -- which is not the case here. – matiash Jul 24 '14 at 22:34
  • @matiash I'm talking about the same case as in OP, but with other view instead of `WatchViewStub`. In shorter form it will be like: `setContentView(R.layout.main_activity); findViewById(R.id.frameLayout).setOnApplyWindowInsetsListener(this);` and everything works just fine. The `onApplyWindowInsets` callback is fired. The `frameLayout` is added to view hierarchy (not laid out yet of course), but this is the case from question. – Maciej Ciemięga Jul 24 '14 at 23:12
  • guys i don't understand,what finally i have to apply. – Pankaj Arora Jul 25 '14 at 04:23
  • @matiash i already tried what you suggested ude,but nothing happens with this also. – Pankaj Arora Jul 25 '14 at 04:24