136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley/*
236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Copyright (C) 2017 The Android Open Source Project
336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley *
436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Licensed under the Apache License, Version 2.0 (the "License");
536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * you may not use this file except in compliance with the License.
636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * You may obtain a copy of the License at
736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley *
836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley *      http://www.apache.org/licenses/LICENSE-2.0
936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley *
1036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Unless required by applicable law or agreed to in writing, software
1136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * distributed under the License is distributed on an "AS IS" BASIS,
1236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * See the License for the specific language governing permissions and
1436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * limitations under the License.
1536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley */
1636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
1736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleypackage android.support.wear.widget.drawer;
1836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
1936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.annotation.TargetApi;
2036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.content.Context;
2136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.content.res.TypedArray;
2236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.graphics.drawable.Drawable;
2336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.os.Build;
2436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.os.Handler;
2536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.os.Looper;
2636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.annotation.IntDef;
2736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.annotation.Nullable;
2836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.annotation.RestrictTo;
2936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.annotation.RestrictTo.Scope;
3036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.R;
3136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.internal.widget.drawer.MultiPagePresenter;
3236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.internal.widget.drawer.MultiPageUi;
3336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.internal.widget.drawer.SinglePagePresenter;
3436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.internal.widget.drawer.SinglePageUi;
3536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.internal.widget.drawer.WearableNavigationDrawerPresenter;
3636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.util.AttributeSet;
3736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.util.Log;
3836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.GestureDetector;
3936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.GestureDetector.SimpleOnGestureListener;
4036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.Gravity;
4136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.MotionEvent;
4236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.accessibility.AccessibilityManager;
4336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
4436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport java.lang.annotation.Retention;
4536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport java.lang.annotation.RetentionPolicy;
4636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport java.util.concurrent.TimeUnit;
4736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
4836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley/**
4936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Ease of use class for creating a Wearable navigation drawer. This can be used with {@link
5036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * WearableDrawerLayout} to create a drawer for users to easily navigate a wearable app.
5136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley *
5236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * <p>There are two ways this information may be presented: as a single page and as multiple pages.
5336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * The single page navigation drawer will display 1-7 items to the user representing different
5436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * navigation verticals. If more than 7 items are provided to a single page navigation drawer, the
5536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * navigation drawer will be displayed as empty. The multiple page navigation drawer will display 1
5636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * or more pages to the user, each representing different navigation verticals.
5736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley *
586e7866f3a3fb65848d9ab46c1ffd7ed9b712244eSean Kelley * <p>The developer may specify which style to use with the {@code app:navigationStyle} custom
596e7866f3a3fb65848d9ab46c1ffd7ed9b712244eSean Kelley * attribute. If not specified, {@link #SINGLE_PAGE singlePage} will be used as the default.
6036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley */
6136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley@TargetApi(Build.VERSION_CODES.M)
6236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleypublic class WearableNavigationDrawerView extends WearableDrawerView {
6336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
6436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private static final String TAG = "WearableNavDrawer";
6536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
6636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
6736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Listener which is notified when the user selects an item.
6836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
6936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public interface OnItemSelectedListener {
7036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
7136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        /**
7236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         * Notified when the user has selected an item at position {@code pos}.
7336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         */
7436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        void onItemSelected(int pos);
7536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
7636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
7736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
7836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Enumeration of possible drawer styles.
7936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * @hide
8036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
8136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @Retention(RetentionPolicy.SOURCE)
8236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @RestrictTo(Scope.LIBRARY_GROUP)
8336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @IntDef({SINGLE_PAGE, MULTI_PAGE})
8436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public @interface NavigationStyle {}
8536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
8636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
8736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Single page navigation drawer style. This is the default drawer style. It is ideal for 1-5
8836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * items, but works with up to 7 items. If more than 7 items exist, then the drawer will be
8936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * displayed as empty.
9036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
9136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public static final int SINGLE_PAGE = 0;
9236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
9336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
9436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Multi-page navigation drawer style. Each item is on its own page. Useful when more than 7
9536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * items exist.
9636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
9736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public static final int MULTI_PAGE = 1;
9836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
9936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @NavigationStyle private static final int DEFAULT_STYLE = SINGLE_PAGE;
10036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private static final long AUTO_CLOSE_DRAWER_DELAY_MS = TimeUnit.SECONDS.toMillis(5);
10136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private final boolean mIsAccessibilityEnabled;
10236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
10336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private final Runnable mCloseDrawerRunnable =
10436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            new Runnable() {
10536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                @Override
10636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                public void run() {
10736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                    getController().closeDrawer();
10836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                }
10936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            };
11036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
11136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Listens for single taps on the drawer.
11236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
11336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @Nullable private final GestureDetector mGestureDetector;
11436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @NavigationStyle private final int mNavigationStyle;
11536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private final WearableNavigationDrawerPresenter mPresenter;
11636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private final SimpleOnGestureListener mOnGestureListener =
11736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            new SimpleOnGestureListener() {
11836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                @Override
11936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                public boolean onSingleTapUp(MotionEvent e) {
12036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                    return mPresenter.onDrawerTapped();
12136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                }
12236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            };
12336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public WearableNavigationDrawerView(Context context) {
12436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        this(context, (AttributeSet) null);
12536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
12636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public WearableNavigationDrawerView(Context context, AttributeSet attrs) {
12736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        this(context, attrs, 0);
12836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
12936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
13036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public WearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr) {
13136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        this(context, attrs, defStyleAttr, 0);
13236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
13336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
13436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public WearableNavigationDrawerView(Context context, AttributeSet attrs, int defStyleAttr,
13536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            int defStyleRes) {
13636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        super(context, attrs, defStyleAttr, defStyleRes);
13736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
13836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mGestureDetector = new GestureDetector(getContext(), mOnGestureListener);
13936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
14036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        @NavigationStyle int navStyle = DEFAULT_STYLE;
14136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        if (attrs != null) {
14236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            TypedArray typedArray = context.obtainStyledAttributes(
14336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                    attrs,
14436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                    R.styleable.WearableNavigationDrawerView,
14536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                    defStyleAttr,
14636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                    0 /* defStyleRes */);
14736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
14836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            //noinspection WrongConstant
14936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            navStyle = typedArray.getInt(
15036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                    R.styleable.WearableNavigationDrawerView_navigationStyle, DEFAULT_STYLE);
15136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            typedArray.recycle();
15236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        }
15336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
15436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mNavigationStyle = navStyle;
15536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        AccessibilityManager accessibilityManager =
15636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
15736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mIsAccessibilityEnabled = accessibilityManager.isEnabled();
15836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
15936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mPresenter =
16036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                mNavigationStyle == SINGLE_PAGE
16136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                        ? new SinglePagePresenter(new SinglePageUi(this), mIsAccessibilityEnabled)
16236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                        : new MultiPagePresenter(this, new MultiPageUi(), mIsAccessibilityEnabled);
16336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
16436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        getPeekContainer()
16536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                .setContentDescription(
16697f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska                        context.getString(R.string.ws_navigation_drawer_content_description));
16736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
16836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        setOpenOnlyAtTopEnabled(true);
16936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
17036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
17136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
17236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Set a {@link WearableNavigationDrawerAdapter} that will supply data for this drawer.
17336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
17436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public void setAdapter(final WearableNavigationDrawerAdapter adapter) {
17536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mPresenter.onNewAdapter(adapter);
17636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
17736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
17836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
17936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Add an {@link OnItemSelectedListener} that will be notified when the user selects an item.
18036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
18136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public void addOnItemSelectedListener(OnItemSelectedListener listener) {
18236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mPresenter.onItemSelectedListenerAdded(listener);
18336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
18436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
18536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
18636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Remove an {@link OnItemSelectedListener}.
18736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
18836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public void removeOnItemSelectedListener(OnItemSelectedListener listener) {
18936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mPresenter.onItemSelectedListenerRemoved(listener);
19036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
19136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
19236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
19336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Changes which index is selected. {@link OnItemSelectedListener#onItemSelected} will
19436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * be called when the specified {@code index} is reached, but it won't be called for items
19536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * between the current index and the destination index.
19636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
19736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public void setCurrentItem(int index, boolean smoothScrollTo) {
19836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mPresenter.onSetCurrentItemRequested(index, smoothScrollTo);
19936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
20036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
20136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
20236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Returns the style this drawer is using, either {@link #SINGLE_PAGE} or {@link #MULTI_PAGE}.
20336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
20436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @NavigationStyle
20536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public int getNavigationStyle() {
20636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        return mNavigationStyle;
20736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
20836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
20936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @Override
21036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public boolean onInterceptTouchEvent(MotionEvent ev) {
21136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        autoCloseDrawerAfterDelay();
21236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        return mGestureDetector != null && mGestureDetector.onTouchEvent(ev);
21336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
21436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
21536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @Override
21636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public boolean canScrollHorizontally(int direction) {
21736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        // Prevent the window from being swiped closed while it is open by saying that it can scroll
21836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        // horizontally.
21936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        return isOpened();
22036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
22136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
22236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @Override
22336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public void onDrawerOpened() {
22436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        autoCloseDrawerAfterDelay();
22536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
22636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
22736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @Override
22836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public void onDrawerClosed() {
22936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        mMainThreadHandler.removeCallbacks(mCloseDrawerRunnable);
23036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
23136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
23236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    private void autoCloseDrawerAfterDelay() {
23336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        if (!mIsAccessibilityEnabled) {
23436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            mMainThreadHandler.removeCallbacks(mCloseDrawerRunnable);
23536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            mMainThreadHandler.postDelayed(mCloseDrawerRunnable, AUTO_CLOSE_DRAWER_DELAY_MS);
23636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        }
23736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
23836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
23936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    @Override
24036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley  /* package */ int preferGravity() {
24136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        return Gravity.TOP;
24236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
24336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
24436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    /**
24536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     * Adapter for specifying the contents of WearableNavigationDrawer.
24636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley     */
24736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    public abstract static class WearableNavigationDrawerAdapter {
24836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
24936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        @Nullable
25036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        private WearableNavigationDrawerPresenter mPresenter;
25136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
25236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        /**
25336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         * Get the text associated with the item at {@code pos}.
25436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         */
25536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        public abstract CharSequence getItemText(int pos);
25636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
25736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        /**
25836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         * Get the drawable associated with the item at {@code pos}.
25936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         */
26036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        public abstract Drawable getItemDrawable(int pos);
26136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
26236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        /**
26336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         * Returns the number of items in this adapter.
26436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         */
26536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        public abstract int getCount();
26636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
26736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        /**
26836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         * This method should be called by the application if the data backing this adapter has
26936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         * changed and associated views should update.
27036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         */
27136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        public void notifyDataSetChanged() {
27236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            // If this method is called before drawer.setAdapter, then we will not yet have a
27336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            // presenter.
27436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            if (mPresenter != null) {
27536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                mPresenter.onDataSetChanged();
27636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            } else {
27736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                Log.w(TAG,
27836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley                        "adapter.notifyDataSetChanged called before drawer.setAdapter; ignoring.");
27936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            }
28036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        }
28136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
28236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        /**
28336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         * @hide
28436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley         */
28536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        @RestrictTo(Scope.LIBRARY_GROUP)
28636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        public void setPresenter(WearableNavigationDrawerPresenter presenter) {
28736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley            mPresenter = presenter;
28836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley        }
28936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley    }
29036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley
29136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley}
292