blob: 312e2b8719042cb48097d6c132f10a10989daca8 [file] [log] [blame]
Michael Kolb2814a362011-05-19 15:49:41 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.android.browser;
18
Michael Kolb2814a362011-05-19 15:49:41 -070019import android.content.Context;
Michael Kolb4bd767d2011-05-27 11:33:55 -070020import android.content.res.Configuration;
Michael Kolb2814a362011-05-19 15:49:41 -070021import android.database.DataSetObserver;
22import android.util.AttributeSet;
23import android.view.MotionEvent;
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.BaseAdapter;
Michael Kolb4bd767d2011-05-27 11:33:55 -070027import android.widget.FrameLayout;
Michael Kolb2814a362011-05-19 15:49:41 -070028import android.widget.LinearLayout;
29
Michael Kolb4bd767d2011-05-27 11:33:55 -070030import com.android.browser.view.HorizontalScrollView;
31import com.android.browser.view.ScrollView;
32
Michael Kolb2814a362011-05-19 15:49:41 -070033/**
34 * custom view for displaying tabs in the nav screen
35 */
Michael Kolb4bd767d2011-05-27 11:33:55 -070036public class NavTabScroller extends FrameLayout {
Michael Kolb2814a362011-05-19 15:49:41 -070037
38 private LinearLayout mContentView;
Michael Kolb2814a362011-05-19 15:49:41 -070039 private BaseAdapter mAdapter;
Michael Kolb4bd767d2011-05-27 11:33:55 -070040 private SelectableSroller mScroller;
41 private int mOrientation;
Michael Kolb2814a362011-05-19 15:49:41 -070042
43 public NavTabScroller(Context context, AttributeSet attrs, int defStyle) {
44 super(context, attrs, defStyle);
45 init(context);
46 }
47
48 public NavTabScroller(Context context, AttributeSet attrs) {
49 super(context, attrs);
50 init(context);
51 }
52
53 public NavTabScroller(Context context) {
54 super(context);
55 init(context);
56 }
57
58 private void init(Context ctx) {
Michael Kolb4bd767d2011-05-27 11:33:55 -070059 mOrientation = ctx.getResources().getConfiguration().orientation;
60 mScroller = (mOrientation == Configuration.ORIENTATION_LANDSCAPE) ?
61 new HorizontalScroller(ctx) : new VerticalScroller(ctx);
62 mContentView = mScroller.getContentView();
63 View sview = (View) mScroller;
64 sview.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
65 LayoutParams.MATCH_PARENT));
66 addView(sview);
Michael Kolb2814a362011-05-19 15:49:41 -070067 }
68
Michael Kolbdb343c52011-05-29 12:18:52 -070069 @Override
70 protected void onMeasure(int wspec, int hspec) {
71 super.onMeasure(wspec, hspec);
72 calcPadding();
73 }
74
75 private void calcPadding() {
76 if (mAdapter.getCount() > 0) {
77 View v = mContentView.getChildAt(0);
78 if (mOrientation == Configuration.ORIENTATION_PORTRAIT) {
79 int pad = (getMeasuredHeight() - v.getMeasuredHeight()) / 2;
80 mContentView.setPadding(0, pad, 0, pad);
81 } else {
82 int pad = (getMeasuredWidth() - v.getMeasuredWidth()) / 2;
83 mContentView.setPadding(pad, 0, pad, 0);
84 }
85 }
86 }
87
Michael Kolb2814a362011-05-19 15:49:41 -070088 protected void setAdapter(BaseAdapter adapter) {
89 mAdapter = adapter;
90 mAdapter.registerDataSetObserver(new DataSetObserver() {
91
92 @Override
93 public void onChanged() {
94 super.onChanged();
95 populateList();
96 }
97
98 @Override
99 public void onInvalidated() {
100 super.onInvalidated();
101 }
102 });
103 populateList();
104 }
105
106 protected void setSelection(int ix) {
Michael Kolb4bd767d2011-05-27 11:33:55 -0700107 mScroller.setSelection(ix);
Michael Kolb2814a362011-05-19 15:49:41 -0700108 }
109
110 protected int getSelectionIndex() {
Michael Kolb4bd767d2011-05-27 11:33:55 -0700111 return mScroller.getSelection();
Michael Kolb2814a362011-05-19 15:49:41 -0700112 }
113
114 protected Tab getSelectedItem() {
Michael Kolb4bd767d2011-05-27 11:33:55 -0700115 return (Tab) mAdapter.getItem(mScroller.getSelection());
Michael Kolb2814a362011-05-19 15:49:41 -0700116 }
117
118 protected ViewGroup getContentView() {
119 return mContentView;
120 }
121
122 private void populateList() {
Michael Kolb4bd767d2011-05-27 11:33:55 -0700123 mContentView.removeAllViewsInLayout();
Michael Kolb2814a362011-05-19 15:49:41 -0700124 for (int i = 0; i < mAdapter.getCount(); i++) {
Michael Kolb4bd767d2011-05-27 11:33:55 -0700125 NavTabView v = (NavTabView) mAdapter.getView(i, null, mContentView);
Michael Kolb2814a362011-05-19 15:49:41 -0700126 mContentView.addView(v);
Michael Kolb2814a362011-05-19 15:49:41 -0700127 }
128 }
129
130 View getSelectedTab() {
Michael Kolb4bd767d2011-05-27 11:33:55 -0700131 int selected = mScroller.getSelection();
132 if ((selected >= 0) && (selected < mContentView.getChildCount())) {
133 return mContentView.getChildAt(selected);
Michael Kolb2814a362011-05-19 15:49:41 -0700134 } else {
135 return null;
136 }
137 }
138
Michael Kolb4bd767d2011-05-27 11:33:55 -0700139 static interface SelectableSroller {
140 void setSelection(int index);
141 int getSelection();
142 LinearLayout getContentView();
143
Michael Kolb2814a362011-05-19 15:49:41 -0700144 }
145
Michael Kolb4bd767d2011-05-27 11:33:55 -0700146 static class VerticalScroller extends ScrollView implements SelectableSroller {
147
148 private LinearLayout mContentView;
149 private int mSelected;
150 private boolean mSnapScroll;
151
152 public VerticalScroller(Context context, AttributeSet attrs, int defStyle) {
153 super(context, attrs, defStyle);
154 init(context);
155 }
156
157 public VerticalScroller(Context context, AttributeSet attrs) {
158 super(context, attrs);
159 init(context);
160 }
161
162 public VerticalScroller(Context context) {
163 super(context);
164 init(context);
165 }
166
167 private void init(Context ctx) {
168 setHorizontalScrollBarEnabled(false);
169 mContentView = new LinearLayout(ctx);
170 mContentView.setOrientation(LinearLayout.VERTICAL);
171 setVerticalScrollBarEnabled(false);
172 setSmoothScrollingEnabled(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700173 mContentView.setLayoutParams(
174 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
175 addView(mContentView);
176
177 }
178
179 public LinearLayout getContentView() {
180 return mContentView;
181 }
182
183 public void setSelection(int ix) {
184 mSelected = ix;
185 }
186
187 public int getSelection() {
188 return mSelected;
189 }
190
191 protected void onScrollChanged(int sl, int st, int ol, int ot) {
192 int midy = getScrollY() + getHeight() / 2;
193 int sel = -1;
194 for (int i = 0; i < mContentView.getChildCount(); i++) {
Michael Kolb0f91e032011-06-01 09:54:20 -0700195 NavTabView child = (NavTabView) mContentView.getChildAt(i);
196 int top = child.getTop();
197 int bottom = child.getBottom();
198 if (top <= midy && bottom >= midy) {
Michael Kolb4bd767d2011-05-27 11:33:55 -0700199 sel = i;
Michael Kolbdbf39812011-06-10 14:06:40 -0700200 break;
Michael Kolb4bd767d2011-05-27 11:33:55 -0700201 }
202 }
203 if (sel != -1) {
204 if (sel != mSelected) {
205 setSelection(sel);
206 }
Michael Kolb2814a362011-05-19 15:49:41 -0700207 }
208 }
Michael Kolb2814a362011-05-19 15:49:41 -0700209
Michael Kolb4bd767d2011-05-27 11:33:55 -0700210 @Override
211 public boolean onTouchEvent(MotionEvent evt) {
212 // save drag state before super call
213 boolean dragged = mIsBeingDragged;
214 boolean result = super.onTouchEvent(evt);
215 if (MotionEvent.ACTION_UP == evt.getActionMasked()) {
216 if (mScroller.isFinished() && dragged) {
217 snapToSelected();
218 }
Michael Kolbdb343c52011-05-29 12:18:52 -0700219 } else if (MotionEvent.ACTION_MOVE == evt.getActionMasked()) {
220 NavTabView ntv = (NavTabView) getSelectedView();
221 if (mIsBeingDragged && ntv.isHighlighted()) {
222 ntv.setHighlighted(false);
223 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700224 }
225 return result;
226 }
227
228 @Override
229 public void computeScroll() {
230 super.computeScroll();
231 if (mScroller.isFinished() && !mIsBeingDragged) {
232 if (!mSnapScroll) {
233 snapToSelected();
234 } else {
235 // reset snap scrolling flag
236 mSnapScroll = false;
237 NavTabView ntv = (NavTabView) getSelectedView();
Michael Kolbdb343c52011-05-29 12:18:52 -0700238 ntv.setHighlighted(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700239 }
Michael Kolb2814a362011-05-19 15:49:41 -0700240 }
241 }
Michael Kolb2814a362011-05-19 15:49:41 -0700242
Michael Kolb4bd767d2011-05-27 11:33:55 -0700243 private void snapToSelected() {
244 View v = mContentView.getChildAt(mSelected);
245 int top = (v.getTop() + v.getBottom()) / 2;
246 top -= getHeight() / 2;
247 if (top != getScrollY()) {
248 // snap to selected
249 mSnapScroll = true;
250 smoothScrollTo(0, top);
Michael Kolbdb343c52011-05-29 12:18:52 -0700251 } else {
252 NavTabView ntv = (NavTabView) getSelectedView();
253 ntv.setHighlighted(true);
Michael Kolb2814a362011-05-19 15:49:41 -0700254 }
255 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700256
257 protected View getSelectedView() {
258 return mContentView.getChildAt(mSelected);
259 }
260
Michael Kolb2814a362011-05-19 15:49:41 -0700261 }
262
Michael Kolb4bd767d2011-05-27 11:33:55 -0700263 static class HorizontalScroller extends HorizontalScrollView implements SelectableSroller {
264
265 private LinearLayout mContentView;
266 private int mSelected;
267 private boolean mSnapScroll;
268
269 public HorizontalScroller(Context context, AttributeSet attrs, int defStyle) {
270 super(context, attrs, defStyle);
271 init(context);
272 }
273
274 public HorizontalScroller(Context context, AttributeSet attrs) {
275 super(context, attrs);
276 init(context);
277 }
278
279 public HorizontalScroller(Context context) {
280 super(context);
281 init(context);
282 }
283
284 private void init(Context ctx) {
285 setHorizontalScrollBarEnabled(false);
286 mContentView = new LinearLayout(ctx);
287 mContentView.setOrientation(LinearLayout.HORIZONTAL);
288 setVerticalScrollBarEnabled(false);
289 setSmoothScrollingEnabled(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700290 mContentView.setLayoutParams(
291 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
292 addView(mContentView);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700293 }
294
295 public LinearLayout getContentView() {
296 return mContentView;
297 }
298
299 public void setSelection(int ix) {
300 mSelected = ix;
301 }
302
303 public int getSelection() {
304 return mSelected;
305 }
306
307 protected void onScrollChanged(int sl, int st, int ol, int ot) {
308 int midx = getScrollX() + getWidth() / 2;
309 int sel = -1;
310 for (int i = 0; i < mContentView.getChildCount(); i++) {
311 View child = mContentView.getChildAt(i);
312 if (child.getLeft() <= midx && child.getRight() >= midx) {
313 sel = i;
314 break;
315 }
316 }
317 if (sel != -1) {
318 if (sel != mSelected) {
319 setSelection(sel);
320 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700321 }
322 }
323
324 @Override
325 public boolean onTouchEvent(MotionEvent evt) {
326 // save drag state before super call
327 boolean dragged = mIsBeingDragged;
328 boolean result = super.onTouchEvent(evt);
329 if (MotionEvent.ACTION_UP == evt.getActionMasked()) {
330 if (mScroller.isFinished() && dragged) {
331 snapToSelected();
332 }
Michael Kolbdb343c52011-05-29 12:18:52 -0700333 } else if (MotionEvent.ACTION_MOVE == evt.getActionMasked()) {
334 NavTabView ntv = (NavTabView) getSelectedView();
335 if (mIsBeingDragged && ntv.isHighlighted()) {
336 ntv.setHighlighted(false);
337 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700338 }
339 return result;
340 }
341
342 @Override
343 public void computeScroll() {
344 super.computeScroll();
345 if (mScroller.isFinished() && !mIsBeingDragged) {
346 if (!mSnapScroll) {
347 snapToSelected();
348 } else {
349 // reset snap scrolling flag
350 mSnapScroll = false;
351 NavTabView ntv = (NavTabView) getSelectedView();
Michael Kolbdb343c52011-05-29 12:18:52 -0700352 ntv.setHighlighted(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700353 }
354 }
355 }
356
Michael Kolb4bd767d2011-05-27 11:33:55 -0700357 private void snapToSelected() {
358 View v = mContentView.getChildAt(mSelected);
359 int left = (v.getLeft() + v.getRight()) / 2;
360 left -= getWidth() / 2;
361 if (left != getScrollX()) {
362 // snap to selected
363 mSnapScroll = true;
364 smoothScrollTo(left, 0);
Michael Kolbdb343c52011-05-29 12:18:52 -0700365 } else {
366 NavTabView ntv = (NavTabView) getSelectedView();
367 ntv.setHighlighted(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700368 }
369 }
370
371 protected View getSelectedView() {
372 return mContentView.getChildAt(mSelected);
373 }
374
Michael Kolb2814a362011-05-19 15:49:41 -0700375 }
376
377}