2

My WearableRecyclerView the lines go like a triangle and not really curved like the homescreen of the watch. I can't find any mistakes in my code.

ShareActivity:

private void initListView() {
    WearableRecyclerView recyclerView = findViewById(R.id.lVDevices);
    recyclerView.setEdgeItemsCenteringEnabled(true);
    final ScrollingLayoutCallback scrollingLayoutCallback =
            new ScrollingLayoutCallback();
    adapter = new ShareAdapter(new ShareAdapter.Callback() {
        @Override
        public void onDeviceClicked(int position, String deviceName) {
            onListItemClick(position, deviceName);
        }
    });
    recyclerView.setLayoutManager(
            new WearableLinearLayoutManager(this, scrollingLayoutCallback));
    recyclerView.setAdapter(adapter);
}

ScrollingLayoutCallback:

public class ScrollingLayoutCallback extends WearableLinearLayoutManager.LayoutCallback  {
private static final float MAX_ICON_PROGRESS = 0.65f;

@Override
public void onLayoutFinished(View child, RecyclerView parent) {

    // Figure out % progress from top to bottom
    float centerOffset = ((float) child.getHeight() / 2.0f) / (float) parent.getHeight();
    float yRelativeToCenterOffset = (child.getY() / parent.getHeight()) + centerOffset;

    // Normalize for center
    float mProgressToCenter = Math.abs(0.5f - yRelativeToCenterOffset);
    // Adjust to the maximum scale
    mProgressToCenter = Math.min(mProgressToCenter, MAX_ICON_PROGRESS);

    child.setScaleX(1 - mProgressToCenter);
    child.setScaleY(1 - mProgressToCenter);
}
}

ListView-XML

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/refreshlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent">

    <android.support.wear.widget.WearableRecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/lVDevices"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:scrollbars="vertical"/>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>

XML of the row

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/lVDevices_row"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@android:color/transparent"
      android:drawableStart="@drawable/point_img"
      android:layout_centerHorizontal="true"
      android:textSize="18sp">
</TextView>

Is the problem in the Callback method? I mean is there a mistake in the calculation because it is from the developer website.

Edit 1: New Math in ScrollingCallback class

float centerOffset = ((float) child.getHeight() / 2.0f) / (float) parent.getHeight();
float yRelativeToCenterOffset = (child.getY() / parent.getHeight()) + centerOffset;

float progresstoCenter = (float) Math.sin(yRelativeToCenterOffset * Math.PI);

child.setScaleX(progresstoCenter);
child.setScaleY(progresstoCenter);
user7174483
  • 73
  • 1
  • 9
  • I think you need to see this [SO post](https://stackoverflow.com/questions/25633446/programmatically-determine-screen-shape-in-android-wear). According to the [answer](https://stackoverflow.com/a/26393184) in the post, your application must use `@android:style/Theme.DeviceDefault` as it's theme so that `WatchViewStub` will use the correct rectangle/round layouts. Example was given in the post. For further reference, you can also refer to the [documentation](https://developer.android.com/reference/android/support/wearable/view/WatchViewStub.html). – MαπμQμαπkγVπ.0 Nov 14 '17 at 11:57
  • Sry, but this doesn't work. I have found a small solution, which I posted under Edit 1. That makes it a little bit smoother but not very beautifull. The problem is that the objects are very close in the middle and make a big distance very fast. The solution will be to flatten the sinus, but I don't know how to do this. – user7174483 Nov 17 '17 at 14:19
  • 1
    Did you ever figure out a real solution? I have no clue why Google posted that `WearableLinearLayoutManager.LayoutCallback` code because it looks nothing like the animation for the app list on the watch. Really frustrating. – Kris B Feb 15 '19 at 21:44
  • @KrisB what about you? did you find solution? – pushandpop Apr 07 '19 at 20:59
  • 1
    Nope, I gave up and just went with a flat scroll. Modifying the values does nothing but make it look worse. Really wish Google would open source WearOS. – Kris B Apr 08 '19 at 20:31

1 Answers1

0

I've created a solution.

Like the OP, I never liked the solution given in the official Android documentation, which causes the list elements to move along a triangular path (straight line from the top center to the middle left, and then straight line from there to the bottom center).

The solution is simple, using trig to change the path to semi-circular. Replace the CustomScrollingLayoutCallback with this:

class CustomScrollingLayoutCallback extends WearableLinearLayoutManager.LayoutCallback {
    @Override
    public void onLayoutFinished(View child, RecyclerView parent) {
        final float MAX_ICON_PROGRESS = 0.65f;

        try {
            float centerOffset              = ((float) child.getHeight() / 2.0f) / (float) parent.getHeight();
            float yRelativeToCenterOffset   = (child.getY() / parent.getHeight()) + centerOffset;

         // Normalize for center, adjusting to the maximum scale
            float progressToCenter          = Math.min(Math.abs(0.5f - yRelativeToCenterOffset), MAX_ICON_PROGRESS);

         // Follow a curved path, rather than triangular!
            progressToCenter                = (float)(Math.cos(progressToCenter * Math.PI * 0.70f));

            child.setScaleX (progressToCenter);
            child.setScaleY (progressToCenter);
        } catch (Exception ignored) {}
    }
}

The "... * 0.70f" on that 4th-to-last line was determined by trial-and-error, and alters the curve to best match the official Android Wear curve.

Nick Esposito
  • 23
  • 1
  • 4