1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.wear.internal.widget.drawer; 18 19import android.graphics.drawable.Drawable; 20import android.os.Handler; 21import android.os.Looper; 22import android.support.annotation.IdRes; 23import android.support.annotation.LayoutRes; 24import android.support.annotation.Nullable; 25import android.support.annotation.RestrictTo; 26import android.support.annotation.RestrictTo.Scope; 27import android.support.wear.R; 28import android.support.wear.widget.CircledImageView; 29import android.support.wear.widget.drawer.WearableNavigationDrawerView; 30import android.view.Gravity; 31import android.view.LayoutInflater; 32import android.view.View; 33import android.widget.TextView; 34import android.widget.Toast; 35 36/** 37 * Handles view logic for the single page style {@link WearableNavigationDrawerView}. 38 * 39 * @hide 40 */ 41@RestrictTo(Scope.LIBRARY_GROUP) 42public class SinglePageUi implements SinglePagePresenter.Ui { 43 44 @IdRes 45 private static final int[] SINGLE_PAGE_BUTTON_IDS = 46 new int[]{ 47 R.id.wearable_support_nav_drawer_icon_0, 48 R.id.wearable_support_nav_drawer_icon_1, 49 R.id.wearable_support_nav_drawer_icon_2, 50 R.id.wearable_support_nav_drawer_icon_3, 51 R.id.wearable_support_nav_drawer_icon_4, 52 R.id.wearable_support_nav_drawer_icon_5, 53 R.id.wearable_support_nav_drawer_icon_6, 54 }; 55 56 @LayoutRes 57 private static final int[] SINGLE_PAGE_LAYOUT_RES = 58 new int[]{ 59 0, 60 R.layout.single_page_nav_drawer_1_item, 61 R.layout.single_page_nav_drawer_2_item, 62 R.layout.single_page_nav_drawer_3_item, 63 R.layout.single_page_nav_drawer_4_item, 64 R.layout.single_page_nav_drawer_5_item, 65 R.layout.single_page_nav_drawer_6_item, 66 R.layout.single_page_nav_drawer_7_item, 67 }; 68 69 private final WearableNavigationDrawerView mDrawer; 70 private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); 71 private final Runnable mCloseDrawerRunnable = 72 new Runnable() { 73 @Override 74 public void run() { 75 mDrawer.getController().closeDrawer(); 76 } 77 }; 78 private WearableNavigationDrawerPresenter mPresenter; 79 private CircledImageView[] mSinglePageImageViews; 80 /** 81 * Indicates currently selected item. {@code null} when the layout lacks space to display it. 82 */ 83 @Nullable 84 private TextView mTextView; 85 86 public SinglePageUi(WearableNavigationDrawerView navigationDrawer) { 87 if (navigationDrawer == null) { 88 throw new IllegalArgumentException("Received null navigationDrawer."); 89 } 90 mDrawer = navigationDrawer; 91 } 92 93 @Override 94 public void setPresenter(WearableNavigationDrawerPresenter presenter) { 95 mPresenter = presenter; 96 } 97 98 @Override 99 public void initialize(int count) { 100 if (count < 0 || count >= SINGLE_PAGE_LAYOUT_RES.length 101 || SINGLE_PAGE_LAYOUT_RES[count] == 0) { 102 mDrawer.setDrawerContent(null); 103 return; 104 } 105 106 @LayoutRes int layoutRes = SINGLE_PAGE_LAYOUT_RES[count]; 107 LayoutInflater inflater = LayoutInflater.from(mDrawer.getContext()); 108 View content = inflater.inflate(layoutRes, mDrawer, false /* attachToRoot */); 109 final View peek = 110 inflater.inflate( 111 R.layout.single_page_nav_drawer_peek_view, mDrawer, 112 false /* attachToRoot */); 113 114 mTextView = (TextView) content.findViewById(R.id.wearable_support_nav_drawer_text); 115 mSinglePageImageViews = new CircledImageView[count]; 116 for (int i = 0; i < count; i++) { 117 mSinglePageImageViews[i] = (CircledImageView) content 118 .findViewById(SINGLE_PAGE_BUTTON_IDS[i]); 119 mSinglePageImageViews[i].setOnClickListener(new OnSelectedClickHandler(i, mPresenter)); 120 mSinglePageImageViews[i].setCircleHidden(true); 121 } 122 123 mDrawer.setDrawerContent(content); 124 mDrawer.setPeekContent(peek); 125 } 126 127 @Override 128 public void setIcon(int index, Drawable drawable, CharSequence contentDescription) { 129 mSinglePageImageViews[index].setImageDrawable(drawable); 130 mSinglePageImageViews[index].setContentDescription(contentDescription); 131 } 132 133 @Override 134 public void setText(CharSequence itemText, boolean showToastIfNoTextView) { 135 if (mTextView != null) { 136 mTextView.setText(itemText); 137 } else if (showToastIfNoTextView) { 138 Toast toast = Toast.makeText(mDrawer.getContext(), itemText, Toast.LENGTH_SHORT); 139 toast.setGravity(Gravity.CENTER, 0 /* xOffset */, 0 /* yOffset */); 140 toast.show(); 141 } 142 } 143 144 @Override 145 public void selectItem(int index) { 146 mSinglePageImageViews[index].setCircleHidden(false); 147 } 148 149 @Override 150 public void deselectItem(int index) { 151 mSinglePageImageViews[index].setCircleHidden(true); 152 } 153 154 @Override 155 public void closeDrawerDelayed(long delayMs) { 156 mMainThreadHandler.removeCallbacks(mCloseDrawerRunnable); 157 mMainThreadHandler.postDelayed(mCloseDrawerRunnable, delayMs); 158 } 159 160 @Override 161 public void peekDrawer() { 162 mDrawer.getController().peekDrawer(); 163 } 164 165 /** 166 * Notifies the {@code presenter} that the item at the given {@code index} has been selected. 167 */ 168 private static class OnSelectedClickHandler implements View.OnClickListener { 169 170 private final int mIndex; 171 private final WearableNavigationDrawerPresenter mPresenter; 172 173 private OnSelectedClickHandler(int index, WearableNavigationDrawerPresenter presenter) { 174 mIndex = index; 175 mPresenter = presenter; 176 } 177 178 @Override 179 public void onClick(View v) { 180 mPresenter.onSelected(mIndex); 181 } 182 } 183} 184