1 /* 2 * Copyright (C) 2014 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 17 package com.android.tv.settings.widget; 18 19 import android.view.View; 20 21 import com.android.tv.settings.widget.ScrollAdapterView; 22 import com.android.tv.settings.widget.ScrollAdapterView.OnScrollListener; 23 24 /** 25 * ScrollAdapterView OnScrollListener that supports edit mode. 26 */ 27 public class ScrollAdapterEditScrollListener implements OnScrollListener { 28 29 /** 30 * Callback listener which listens to when scrolling started. 31 */ 32 public interface OnScrollStartListener { 33 public void onScrollStart(int direction); 34 } 35 36 /** 37 * Flag indicating whether currently is in edit mode or not. 38 */ 39 private boolean mEnableEditMode; 40 41 /** 42 * Index of current selected view in edit mode. 43 */ 44 private int mCurrentIndex; 45 46 /** 47 * Index of first selected view when entering edit mode. 48 */ 49 private int mEditStartIndex; 50 51 private float mLastPosition = 0; 52 53 /** 54 * The scrolling distance in edit mode. 55 */ 56 private float mEditScrollDis; 57 58 private ScrollAdapterView mScrollAdapterView; 59 60 private int mOrientation; 61 62 private int mDirection; 63 64 private boolean mStartScrolling; 65 66 private OnScrollStartListener mOnScrollStartListener; 67 68 public ScrollAdapterEditScrollListener(ScrollAdapterView scrollAdapterView) { 69 mScrollAdapterView = scrollAdapterView; 70 } 71 72 public void setOnScrollStartListener(OnScrollStartListener onScrollStartListener) { 73 mOnScrollStartListener = onScrollStartListener; 74 } 75 76 public void startEditMode(int index) { 77 mEnableEditMode = true; 78 mOrientation = mScrollAdapterView.getOrientation(); 79 80 mCurrentIndex = index; 81 mEditStartIndex = index; 82 83 View selectedView = mScrollAdapterView.getItemView(index); 84 if (selectedView != null) { 85 float space = mScrollAdapterView.getSpace(); 86 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 87 mEditScrollDis = selectedView.getMeasuredWidth() + space; 88 } else if (mOrientation == ScrollAdapterView.VERTICAL) { 89 mEditScrollDis = selectedView.getMeasuredHeight() + space; 90 } 91 } 92 } 93 94 public void exitEditMode() { 95 mEnableEditMode = false; 96 } 97 98 public int getCurrentIndex() { 99 return mCurrentIndex; 100 } 101 102 public int getEditStartIndex() { 103 return mEditStartIndex; 104 } 105 106 public boolean isEditMode() { 107 return mEnableEditMode; 108 } 109 110 @Override 111 public void onScrolled(View view, int position, float mainPosition, float secondPosition) { 112 mCurrentIndex = position; 113 114 float currentPosition = position + mainPosition; 115 116 if (mEnableEditMode) { 117 View startView = mScrollAdapterView.getItemView(mEditStartIndex); 118 if (startView != null && startView.getAlpha() != 0f) { 119 startView.setAlpha(0f); 120 } 121 122 int size = mScrollAdapterView.getAdapter().getCount(); 123 124 if (mCurrentIndex >= mEditStartIndex) { 125 // If current index is greater than starting index, translate current view 126 // to the left/down while scrolling position changing. 127 View curView = mScrollAdapterView.getItemView(mCurrentIndex + 1); 128 float scrollDis = mainPosition * mEditScrollDis; 129 if (curView != null) { 130 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 131 curView.setTranslationX(-scrollDis); 132 } else { 133 curView.setTranslationY(-scrollDis); 134 } 135 } 136 137 for (int index = mEditStartIndex; index < mCurrentIndex + 1; ++index) { 138 curView = mScrollAdapterView.getItemView(index); 139 if (curView != null) { 140 // Set the translation of all views between start index and 141 // current index to -mEditScrollDis. 142 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 143 curView.setTranslationX(-mEditScrollDis); 144 } else { 145 curView.setTranslationY(-mEditScrollDis); 146 } 147 } 148 } 149 150 // Reset all other views translation to 0. 151 if (mCurrentIndex + 2 < size) { 152 for (int index = mCurrentIndex + 2; index < size; ++index) { 153 curView = mScrollAdapterView.getItemView(index); 154 if (curView != null) { 155 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 156 curView.setTranslationX(0); 157 } else { 158 curView.setTranslationY(0); 159 } 160 } 161 } 162 } 163 164 for (int index = 0; index < mEditStartIndex; ++index) { 165 curView = mScrollAdapterView.getItemView(index); 166 if (curView != null) { 167 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 168 curView.setTranslationX(0); 169 } else { 170 curView.setTranslationY(0); 171 } 172 } 173 } 174 } else if (mCurrentIndex < mEditStartIndex) { 175 // If current index is less than starting index, translate current view 176 // to the right/down while scrolling position changing. 177 View curView = mScrollAdapterView.getItemView(mCurrentIndex); 178 float scrollDis = (1 - mainPosition) * mEditScrollDis; 179 if (curView != null) { 180 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 181 curView.setTranslationX(scrollDis); 182 } else { 183 curView.setTranslationY(scrollDis); 184 } 185 } 186 187 if (mCurrentIndex + 1 <= size) { 188 for (int index = mCurrentIndex + 1; index < mEditStartIndex; ++index) { 189 curView = mScrollAdapterView.getItemView(index); 190 if (curView != null) { 191 // Set the translation of all views between start index and 192 // current index to mEditScrollDis. 193 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 194 curView.setTranslationX(mEditScrollDis); 195 } else { 196 curView.setTranslationY(mEditScrollDis); 197 } 198 } 199 } 200 } 201 202 // Reset all other views translation to 0. 203 for (int index = 0; index < mCurrentIndex; ++index) { 204 curView = mScrollAdapterView.getItemView(index); 205 if (curView != null) { 206 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 207 curView.setTranslationX(0); 208 } else { 209 curView.setTranslationY(0); 210 } 211 } 212 } 213 214 for (int index = mEditStartIndex; index < size; ++index) { 215 curView = mScrollAdapterView.getItemView(index); 216 if (curView != null) { 217 if (mOrientation == ScrollAdapterView.HORIZONTAL) { 218 curView.setTranslationX(0); 219 } else { 220 curView.setTranslationY(0); 221 } 222 } 223 } 224 } 225 226 if (mScrollAdapterView.isInScrollingOrDragging() && !mStartScrolling) { 227 // Start scrolling 228 mStartScrolling = true; 229 230 if (currentPosition > mLastPosition) { 231 mDirection = mOrientation == ScrollAdapterView.HORIZONTAL ? View.FOCUS_RIGHT 232 : View.FOCUS_DOWN; 233 234 if (mOnScrollStartListener != null) { 235 mOnScrollStartListener.onScrollStart(mDirection); 236 } 237 } else { 238 mDirection = mOrientation == ScrollAdapterView.HORIZONTAL ? View.FOCUS_LEFT 239 : View.FOCUS_UP; 240 241 if (mOnScrollStartListener != null) { 242 mOnScrollStartListener.onScrollStart(mDirection); 243 } 244 } 245 } else if (mStartScrolling && !mScrollAdapterView.isInScrollingOrDragging()) { 246 // End of scrolling. 247 mStartScrolling = false; 248 } else if (mStartScrolling && currentPosition > mLastPosition) { 249 if ((mOrientation == ScrollAdapterView.HORIZONTAL) 250 && (mDirection == View.FOCUS_LEFT)) { 251 // Revert scrolling direction to right before finishing previous left scroll. 252 mDirection = View.FOCUS_RIGHT; 253 254 if (mOnScrollStartListener != null) { 255 mOnScrollStartListener.onScrollStart(mDirection); 256 } 257 } else if ((mOrientation == ScrollAdapterView.VERTICAL) 258 && (mDirection == View.FOCUS_UP)) { 259 // Revert scrolling direction to down before finishing previous up scroll. 260 mDirection = View.FOCUS_DOWN; 261 262 if (mOnScrollStartListener != null) { 263 mOnScrollStartListener.onScrollStart(mDirection); 264 } 265 } 266 } else if (mStartScrolling && currentPosition < mLastPosition) { 267 if ((mOrientation == ScrollAdapterView.HORIZONTAL) 268 && (mDirection == View.FOCUS_RIGHT)) { 269 // Revert scrolling direction to left before finishing previous right scroll. 270 mDirection = View.FOCUS_LEFT; 271 272 if (mOnScrollStartListener != null) { 273 mOnScrollStartListener.onScrollStart(mDirection); 274 } 275 } else if ((mOrientation == ScrollAdapterView.VERTICAL) 276 && (mDirection == View.FOCUS_DOWN)) { 277 // Revert scrolling direction to up before finishing previous down scroll. 278 mDirection = View.FOCUS_UP; 279 280 if (mOnScrollStartListener != null) { 281 mOnScrollStartListener.onScrollStart(mDirection); 282 } 283 } 284 } 285 } 286 287 mLastPosition = currentPosition; 288 } 289 } 290