Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WearSquare: Introduction to Android Wear Design & Development

WearSquare: Introduction to Android Wear Design & Development

David Vávra

January 06, 2015
Tweet

More Decks by David Vávra

Other Decks in Technology

Transcript

  1. WearSquare
    Introduction to
    Android Wear Design & Development
    David Vávra

    View full-size slide

  2. Design principles
    and how to implement them in native code

    View full-size slide

  3. Focus on not stopping the user and all
    else will follow
    1/5
    Wearable UI Library
    DelayedConfirmationView

    View full-size slide

  4. DelayedConfirmationView
    android:id="@+id/confirmation"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@drawable/ic_cancel"
    app:circle_color="@color/action_button"
    app:circle_radius="40dp"
    app:circle_radius_pressed="35dp"
    app:circle_padding="5dp"
    app:circle_border_width="5dp"
    app:circle_border_color="@color/primary_light"/>
    /wear/src/main/res/layout/fragment_check_in.xml
    vConfirmation.setTotalTimeMs(3000);
    vConfirmation.start();
    mTimerInvalid = false;
    vConfirmation.setListener(new DelayedConfirmationView.
    DelayedConfirmationListener() {
    @Override
    public void onTimerFinished(View view) {
    if (!mTimerInvalid) {
    ((CheckInActivity)getActivity()).sendCheckInMessage();
    }
    }
    @Override
    public void onTimerSelected(View view) {
    mTimerInvalid = true;
    getActivity().finish();
    }
    });
    /wear/src/main/java/cz/destil/wearsquare/fragment/CheckInFragment.java

    View full-size slide

  5. Design for big gestures
    2/5
    3 items on screen
    WearableListView

    View full-size slide

  6. WearableListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
    /wear/src/main/res/layout/activity_fragment_list.xml
    public class CheckInListAdapter extends WearableListView.Adapter {
    public CheckInListAdapter(Context context, List items){}
    @Override
    public WearableListView.ViewHolder onCreateViewHolder(ViewGroup
    viewGroup, int i) {}
    @Override
    public void onBindViewHolder(WearableListView.ViewHolder
    viewHolder, int position) {}
    @Override
    public int getItemCount() {}
    class ListItem extends FrameLayout implements WearableListView.
    OnCenterProximityListener {
    @Override
    public void onCenterPosition(boolean b) {}
    @Override
    public void onNonCenterPosition(boolean b) {}
    }
    } /wear/src/main/java/cz/destil/wearsquare/adapter/CheckInListAdapter.java

    View full-size slide

  7. Think about stream cards first
    3/5
    It would be best to show
    card automatically
    But Don’t be a constant
    shoulder tapper
    GridViewPager
    FragmentGridPagerAdapter
    CardFragment

    View full-size slide

  8. FragmentGridPagerAdapter
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    android:keepScreenOn="true"/>
    android:id="@+id/page_indicator"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal|bottom"/>

    /wear/src/main/res/layout/activity_gridpager.xml
    public class ExploreAdapter extends FragmentGridPagerAdapter
    {
    public ExploreAdapter(ExploreActivity activity,
    List items) {}
    @Override
    public Fragment getFragment(int row, int col) {
    final Venue venue = mItems.get(row);
    CardFragment fragment = CardFragment.create(venue.
    name, venue.tip);
    }
    @Override
    public Drawable getBackgroundForRow(int row) {}
    @Override
    public int getRowCount() {return mItems.size();}
    @Override
    public int getColumnCount(int rowNum) {}
    }
    /wear/src/main/java/cz/destil/wearsquare/adapter/ExploreAdapter.java

    View full-size slide

  9. Do one thing, really fast
    4/5
    Display most
    important data +
    action buttons
    CircledImageView
    ActionFragment

    View full-size slide

  10. ActionFragment

    android:layout_width="match_parent"
    android:layout_height="match_parent">
    android:id="@+id/icon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    app:circle_color="@color/action_button"
    app:circle_radius="45dp"
    app:circle_border_width="0dp"/>
    .../>

    /wear/src/main/res/layout/fragment_action.xml
    public class ActionFragment extends BaseFragment implements
    View.OnClickListener {
    public static ActionFragment create(int iconResId, int
    labelResId, Listener listener) {}
    @Override
    public void onViewCreated(View view, Bundle
    savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    vIcon.setImageResource(getArguments().getInt("ICON"));
    vLabel.setText(getArguments().getInt("LABEL"));
    view.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
    mListener.onActionPerformed();}
    public interface Listener {
    public void onActionPerformed();
    }
    } /wear/src/main/java/cz/destil/wearsquare/fragment/ActionFragment.java

    View full-size slide

  11. Design for the corner of the eye
    5/5
    ConfirmationActivity:
    ○ success
    ○ failure
    ○ open on phone

    View full-size slide

  12. ConfirmationActivity
    Intent i = new Intent(this, ConfirmationActivity.class);
    i.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, ConfirmationActivity.SUCCESS_ANIMATION);
    i.putExtra(ConfirmationActivity.EXTRA_MESSAGE, getString(R.string.checked_in));
    startActivityForResult(i, CheckInActivity.CONFIRM_ACTIVITY);
    /wear/src/main/java/cz/destil/wearsquare/activity/CheckInActivity.java

    View full-size slide

  13. Q&A
    Code: https://github.com/destil/wearsquare
    App: https://play.google.com/store/apps/details?id=cz.destil.wearsquare

    View full-size slide

  14. Development tips

    View full-size slide

  15. Use Teleport library
    1/3
    Removes boilerplate code from Data Layer API
    https://github.com/Mariuxtheone/Teleport by GDE Mario Viviani
    mTeleportClient.syncString("hello", "Hello, World!");
    /mobile/...
    mTeleportClient.setOnSyncDataItemTask(new ShowToastHelloWorldTask());
    public class ShowToastHelloWorldTask extends TeleportClient.OnSyncDataItemTask {
    @Override
    protected void onPostExecute(DataMap dataMap) {
    String hello = dataMap.getString("hello");
    Toast.makeText(context, hello, Toast.LENGTH_SHORT).show();
    }
    } /wear/...

    View full-size slide

  16. Sync images later
    2/3
    private void downloadImages(Set imageUrls) {
    int i = 0;
    mTargets = new SparseArray<>();
    for (final String imageUrl : imageUrls) {
    mTargets.put(i, new Target() {
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
    Asset asset = ImageUtils.createAssetFromBitmap(bitmap);
    final PutDataMapRequest data = PutDataMapRequest.createWithAutoAppendedId("/image");
    data.getDataMap().putString("image_url", imageUrl);
    data.getDataMap().putAsset("asset", asset);
    syncDataItem(data);
    }
    @Override
    public void onBitmapFailed(Drawable errorDrawable) {}
    });
    Picasso.with(App.get()).load(imageUrl).into(mTargets.get(i));
    i++;
    }
    } /mobile/src/main/java/cz/destil/wearsquare/service/FoursquareService.java

    View full-size slide

  17. Send unhandled Exceptions to phone
    3/3
    public class App extends Application {
    @Override
    public void onCreate() {
    super.onCreate();
    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()));
    }
    } /wear/src/main/java/cz/destil/wearsquare/core/App.java
    public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
    public ExceptionHandler(Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler) { }
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
    App.bus().post(new ExceptionEvent(ex));
    mDefaultUncaughtExceptionHandler.uncaughtException(thread, ex);
    }
    public static void sendExceptionToPhone(Throwable exception, TeleportClient mTeleportClient) {
    mTeleportClient.sendMessage(buildMessageText(exception), null);
    }
    } /wear/src/main/java/cz/destil/wearsquare/util/ExceptionHandler.java

    View full-size slide