public class

WearableNavigationDrawerView

extends WearableDrawerView

 java.lang.Object

↳FrameLayout

androidx.wear.widget.drawer.WearableDrawerView

↳androidx.wear.widget.drawer.WearableNavigationDrawerView

Gradle dependencies

compile group: 'androidx.wear', name: 'wear', version: '1.4.0-alpha01'

  • groupId: androidx.wear
  • artifactId: wear
  • version: 1.4.0-alpha01

Artifact androidx.wear:wear:1.4.0-alpha01 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.wear:wear com.android.support:wear

Androidx class mapping:

androidx.wear.widget.drawer.WearableNavigationDrawerView android.support.wear.widget.drawer.WearableNavigationDrawerView

Overview

Ease of use class for creating a Wearable navigation drawer. This can be used with WearableDrawerLayout to create a drawer for users to easily navigate a wearable app.

There are two ways this information may be presented: as a single page and as multiple pages. The single page navigation drawer will display 1-7 items to the user representing different navigation verticals. If more than 7 items are provided to a single page navigation drawer, the navigation drawer will be displayed as empty. The multiple page navigation drawer will display 1 or more pages to the user, each representing different navigation verticals.

The developer may specify which style to use with the app:navigationStyle custom attribute. If not specified, singlePage will be used as the default.

Summary

Fields
public static final intMULTI_PAGE

Multi-page navigation drawer style.

public static final intSINGLE_PAGE

Single page navigation drawer style.

from WearableDrawerViewSTATE_DRAGGING, STATE_IDLE, STATE_SETTLING
Constructors
publicWearableNavigationDrawerView(Context context)

publicWearableNavigationDrawerView(Context context, AttributeSet attrs)

publicWearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr)

publicWearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)

Methods
public voidaddOnItemSelectedListener(WearableNavigationDrawerView.OnItemSelectedListener listener)

Add an WearableNavigationDrawerView.OnItemSelectedListener that will be notified when the user selects an item.

public booleancanScrollHorizontally(int direction)

public intgetNavigationStyle()

Returns the style this drawer is using, either WearableNavigationDrawerView.SINGLE_PAGE or WearableNavigationDrawerView.MULTI_PAGE.

public voidonDrawerClosed()

Called when the drawer has settled in a completely closed state.

public voidonDrawerOpened()

Called when the drawer has settled in a completely open state.

public booleanonInterceptTouchEvent(MotionEvent ev)

public voidremoveOnItemSelectedListener(WearableNavigationDrawerView.OnItemSelectedListener listener)

Remove an WearableNavigationDrawerView.OnItemSelectedListener.

public voidsetAdapter(WearableNavigationDrawerView.WearableNavigationDrawerAdapter adapter)

Set a WearableNavigationDrawerView.WearableNavigationDrawerAdapter that will supply data for this drawer.

public voidsetCurrentItem(int index, boolean smoothScrollTo)

Changes which index is selected.

from WearableDrawerViewaddView, getController, getDrawerContent, getDrawerState, isAutoPeekEnabled, isClosed, isLocked, isLockedWhenClosed, isOpened, isOpenOnlyAtTopEnabled, isPeeking, isPeekOnScrollDownEnabled, onAttachedToWindow, onDrawerStateChanged, onFinishInflate, onPeekContainerClicked, setDrawerContent, setIsAutoPeekEnabled, setIsLocked, setLockedWhenClosed, setOpenOnlyAtTopEnabled, setPeekContent, setPeekOnScrollDownEnabled
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

public static final int SINGLE_PAGE

Single page navigation drawer style. This is the default drawer style. It is ideal for 1-5 items, but works with up to 7 items. If more than 7 items exist, then the drawer will be displayed as empty.

public static final int MULTI_PAGE

Multi-page navigation drawer style. Each item is on its own page. Useful when more than 7 items exist.

Constructors

public WearableNavigationDrawerView(Context context)

public WearableNavigationDrawerView(Context context, AttributeSet attrs)

public WearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr)

public WearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)

Methods

Set a WearableNavigationDrawerView.WearableNavigationDrawerAdapter that will supply data for this drawer.

public void addOnItemSelectedListener(WearableNavigationDrawerView.OnItemSelectedListener listener)

Add an WearableNavigationDrawerView.OnItemSelectedListener that will be notified when the user selects an item.

public void removeOnItemSelectedListener(WearableNavigationDrawerView.OnItemSelectedListener listener)

Remove an WearableNavigationDrawerView.OnItemSelectedListener.

public void setCurrentItem(int index, boolean smoothScrollTo)

Changes which index is selected. WearableNavigationDrawerView.OnItemSelectedListener.onItemSelected(int) will be called when the specified index is reached, but it won't be called for items between the current index and the destination index.

public int getNavigationStyle()

Returns the style this drawer is using, either WearableNavigationDrawerView.SINGLE_PAGE or WearableNavigationDrawerView.MULTI_PAGE.

public boolean onInterceptTouchEvent(MotionEvent ev)

public boolean canScrollHorizontally(int direction)

public void onDrawerOpened()

Called when the drawer has settled in a completely open state. The drawer is interactive at this point. This is analogous to WearableDrawerLayout.DrawerStateCallback.onDrawerOpened(WearableDrawerLayout, WearableDrawerView).

public void onDrawerClosed()

Called when the drawer has settled in a completely closed state. This is analogous to WearableDrawerLayout.DrawerStateCallback.onDrawerClosed(WearableDrawerLayout, WearableDrawerView).

Source

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.wear.widget.drawer;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityManager;

import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.core.view.ViewCompat;
import androidx.wear.R;
import androidx.wear.internal.widget.drawer.MultiPagePresenter;
import androidx.wear.internal.widget.drawer.MultiPageUi;
import androidx.wear.internal.widget.drawer.SinglePagePresenter;
import androidx.wear.internal.widget.drawer.SinglePageUi;
import androidx.wear.internal.widget.drawer.WearableNavigationDrawerPresenter;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.TimeUnit;

/**
 * Ease of use class for creating a Wearable navigation drawer. This can be used with {@link
 * WearableDrawerLayout} to create a drawer for users to easily navigate a wearable app.
 *
 * <p>There are two ways this information may be presented: as a single page and as multiple pages.
 * The single page navigation drawer will display 1-7 items to the user representing different
 * navigation verticals. If more than 7 items are provided to a single page navigation drawer, the
 * navigation drawer will be displayed as empty. The multiple page navigation drawer will display 1
 * or more pages to the user, each representing different navigation verticals.
 *
 * <p>The developer may specify which style to use with the {@code app:navigationStyle} custom
 * attribute. If not specified, {@link #SINGLE_PAGE singlePage} will be used as the default.
 */
public class WearableNavigationDrawerView extends WearableDrawerView {

    private static final String TAG = "WearableNavDrawer";

    /**
     * Listener which is notified when the user selects an item.
     */
    public interface OnItemSelectedListener {

        /**
         * Notified when the user has selected an item at position {@code pos}.
         */
        void onItemSelected(int pos);
    }

    /**
     * Enumeration of possible drawer styles.
     */
    @Retention(RetentionPolicy.SOURCE)
    @RestrictTo(Scope.LIBRARY)
    @IntDef({SINGLE_PAGE, MULTI_PAGE})
    public @interface NavigationStyle {}

    /**
     * Single page navigation drawer style. This is the default drawer style. It is ideal for 1-5
     * items, but works with up to 7 items. If more than 7 items exist, then the drawer will be
     * displayed as empty.
     */
    public static final int SINGLE_PAGE = 0;

    /**
     * Multi-page navigation drawer style. Each item is on its own page. Useful when more than 7
     * items exist.
     */
    public static final int MULTI_PAGE = 1;

    @NavigationStyle private static final int DEFAULT_STYLE = SINGLE_PAGE;
    private static final long AUTO_CLOSE_DRAWER_DELAY_MS = TimeUnit.SECONDS.toMillis(5);
    private final boolean mIsAccessibilityEnabled;
    private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
    private final Runnable mCloseDrawerRunnable =
            new Runnable() {
                @Override
                public void run() {
                    getController().closeDrawer();
                }
            };
    /**
     * Listens for single taps on the drawer.
     */
    @Nullable private final GestureDetector mGestureDetector;
    @NavigationStyle private final int mNavigationStyle;
    final WearableNavigationDrawerPresenter mPresenter;
    private final SimpleOnGestureListener mOnGestureListener =
            new SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return mPresenter.onDrawerTapped();
                }
            };
    public WearableNavigationDrawerView(Context context) {
        this(context, (AttributeSet) null);
    }
    public WearableNavigationDrawerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public WearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        mGestureDetector = new GestureDetector(getContext(), mOnGestureListener);

        @NavigationStyle int navStyle = DEFAULT_STYLE;
        if (attrs != null) {
            TypedArray typedArray = context.obtainStyledAttributes(
                    attrs,
                    R.styleable.WearableNavigationDrawerView,
                    defStyleAttr,
                    0 /* defStyleRes */);

            ViewCompat.saveAttributeDataForStyleable(
                    this, context, R.styleable.WearableNavigationDrawerView, attrs, typedArray,
                    defStyleAttr, 0);

            //noinspection WrongConstant
            navStyle = typedArray.getInt(
                    R.styleable.WearableNavigationDrawerView_navigationStyle, DEFAULT_STYLE);
            typedArray.recycle();
        }

        mNavigationStyle = navStyle;
        AccessibilityManager accessibilityManager =
                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        mIsAccessibilityEnabled = accessibilityManager.isEnabled();

        mPresenter =
                mNavigationStyle == SINGLE_PAGE
                        ? new SinglePagePresenter(new SinglePageUi(this), mIsAccessibilityEnabled)
                        : new MultiPagePresenter(this, new MultiPageUi(), mIsAccessibilityEnabled);

        getPeekContainer()
                .setContentDescription(
                        context.getString(R.string.ws_navigation_drawer_content_description));

        setOpenOnlyAtTopEnabled(true);
    }

    /**
     * Set a {@link WearableNavigationDrawerAdapter} that will supply data for this drawer.
     */
    public void setAdapter(final WearableNavigationDrawerAdapter adapter) {
        mPresenter.onNewAdapter(adapter);
    }

    /**
     * Add an {@link OnItemSelectedListener} that will be notified when the user selects an item.
     */
    public void addOnItemSelectedListener(OnItemSelectedListener listener) {
        mPresenter.onItemSelectedListenerAdded(listener);
    }

    /**
     * Remove an {@link OnItemSelectedListener}.
     */
    public void removeOnItemSelectedListener(OnItemSelectedListener listener) {
        mPresenter.onItemSelectedListenerRemoved(listener);
    }

    /**
     * Changes which index is selected. {@link OnItemSelectedListener#onItemSelected} will
     * be called when the specified {@code index} is reached, but it won't be called for items
     * between the current index and the destination index.
     */
    public void setCurrentItem(int index, boolean smoothScrollTo) {
        mPresenter.onSetCurrentItemRequested(index, smoothScrollTo);
    }

    /**
     * Returns the style this drawer is using, either {@link #SINGLE_PAGE} or {@link #MULTI_PAGE}.
     */
    @NavigationStyle
    public int getNavigationStyle() {
        return mNavigationStyle;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        autoCloseDrawerAfterDelay();
        return mGestureDetector != null && mGestureDetector.onTouchEvent(ev);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        // Prevent the window from being swiped closed while it is open by saying that it can scroll
        // horizontally.
        return isOpened();
    }

    @Override
    public void onDrawerOpened() {
        autoCloseDrawerAfterDelay();
    }

    @Override
    public void onDrawerClosed() {
        mMainThreadHandler.removeCallbacks(mCloseDrawerRunnable);
    }

    private void autoCloseDrawerAfterDelay() {
        if (!mIsAccessibilityEnabled) {
            mMainThreadHandler.removeCallbacks(mCloseDrawerRunnable);
            mMainThreadHandler.postDelayed(mCloseDrawerRunnable, AUTO_CLOSE_DRAWER_DELAY_MS);
        }
    }

    @Override
  /* package */ int preferGravity() {
        return Gravity.TOP;
    }

    /**
     * Adapter for specifying the contents of WearableNavigationDrawer.
     */
    public abstract static class WearableNavigationDrawerAdapter {

        @Nullable
        private WearableNavigationDrawerPresenter mPresenter;

        /**
         * Get the text associated with the item at {@code pos}.
         */
        public abstract CharSequence getItemText(int pos);

        /**
         * Get the drawable associated with the item at {@code pos}.
         */
        public abstract Drawable getItemDrawable(int pos);

        /**
         * Returns the number of items in this adapter.
         */
        public abstract int getCount();

        /**
         * This method should be called by the application if the data backing this adapter has
         * changed and associated views should update.
         */
        public void notifyDataSetChanged() {
            // If this method is called before drawer.setAdapter, then we will not yet have a
            // presenter.
            if (mPresenter != null) {
                mPresenter.onDataSetChanged();
            } else {
                Log.w(TAG,
                        "adapter.notifyDataSetChanged called before drawer.setAdapter; ignoring.");
            }
        }

        /**
         */
        @RestrictTo(Scope.LIBRARY)
        public void setPresenter(WearableNavigationDrawerPresenter presenter) {
            mPresenter = presenter;
        }
    }

}