blob: 9434ff09e8d31c7775c438e2fa7a5bde53b80627 [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++) {
195 View child = mContentView.getChildAt(i);
196 if (child.getTop() <= midy && child.getBottom() >= midy) {
197 sel = i;
198 break;
199 }
200 }
201 if (sel != -1) {
202 if (sel != mSelected) {
203 setSelection(sel);
204 }
Michael Kolb2814a362011-05-19 15:49:41 -0700205 }
206 }
Michael Kolb2814a362011-05-19 15:49:41 -0700207
Michael Kolb4bd767d2011-05-27 11:33:55 -0700208 @Override
209 public boolean onTouchEvent(MotionEvent evt) {
210 // save drag state before super call
211 boolean dragged = mIsBeingDragged;
212 boolean result = super.onTouchEvent(evt);
213 if (MotionEvent.ACTION_UP == evt.getActionMasked()) {
214 if (mScroller.isFinished() && dragged) {
215 snapToSelected();
216 }
Michael Kolbdb343c52011-05-29 12:18:52 -0700217 } else if (MotionEvent.ACTION_MOVE == evt.getActionMasked()) {
218 NavTabView ntv = (NavTabView) getSelectedView();
219 if (mIsBeingDragged && ntv.isHighlighted()) {
220 ntv.setHighlighted(false);
221 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700222 }
223 return result;
224 }
225
226 @Override
227 public void computeScroll() {
228 super.computeScroll();
229 if (mScroller.isFinished() && !mIsBeingDragged) {
230 if (!mSnapScroll) {
231 snapToSelected();
232 } else {
233 // reset snap scrolling flag
234 mSnapScroll = false;
235 NavTabView ntv = (NavTabView) getSelectedView();
Michael Kolbdb343c52011-05-29 12:18:52 -0700236 ntv.setHighlighted(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700237 }
Michael Kolb2814a362011-05-19 15:49:41 -0700238 }
239 }
Michael Kolb2814a362011-05-19 15:49:41 -0700240
Michael Kolb4bd767d2011-05-27 11:33:55 -0700241 private void snapToSelected() {
242 View v = mContentView.getChildAt(mSelected);
243 int top = (v.getTop() + v.getBottom()) / 2;
244 top -= getHeight() / 2;
245 if (top != getScrollY()) {
246 // snap to selected
247 mSnapScroll = true;
248 smoothScrollTo(0, top);
Michael Kolbdb343c52011-05-29 12:18:52 -0700249 } else {
250 NavTabView ntv = (NavTabView) getSelectedView();
251 ntv.setHighlighted(true);
Michael Kolb2814a362011-05-19 15:49:41 -0700252 }
253 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700254
255 protected View getSelectedView() {
256 return mContentView.getChildAt(mSelected);
257 }
258
Michael Kolb2814a362011-05-19 15:49:41 -0700259 }
260
Michael Kolb4bd767d2011-05-27 11:33:55 -0700261 static class HorizontalScroller extends HorizontalScrollView implements SelectableSroller {
262
263 private LinearLayout mContentView;
264 private int mSelected;
265 private boolean mSnapScroll;
266
267 public HorizontalScroller(Context context, AttributeSet attrs, int defStyle) {
268 super(context, attrs, defStyle);
269 init(context);
270 }
271
272 public HorizontalScroller(Context context, AttributeSet attrs) {
273 super(context, attrs);
274 init(context);
275 }
276
277 public HorizontalScroller(Context context) {
278 super(context);
279 init(context);
280 }
281
282 private void init(Context ctx) {
283 setHorizontalScrollBarEnabled(false);
284 mContentView = new LinearLayout(ctx);
285 mContentView.setOrientation(LinearLayout.HORIZONTAL);
286 setVerticalScrollBarEnabled(false);
287 setSmoothScrollingEnabled(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700288 mContentView.setLayoutParams(
289 new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
290 addView(mContentView);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700291 }
292
293 public LinearLayout getContentView() {
294 return mContentView;
295 }
296
297 public void setSelection(int ix) {
298 mSelected = ix;
299 }
300
301 public int getSelection() {
302 return mSelected;
303 }
304
305 protected void onScrollChanged(int sl, int st, int ol, int ot) {
306 int midx = getScrollX() + getWidth() / 2;
307 int sel = -1;
308 for (int i = 0; i < mContentView.getChildCount(); i++) {
309 View child = mContentView.getChildAt(i);
310 if (child.getLeft() <= midx && child.getRight() >= midx) {
311 sel = i;
312 break;
313 }
314 }
315 if (sel != -1) {
316 if (sel != mSelected) {
317 setSelection(sel);
318 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700319 }
320 }
321
322 @Override
323 public boolean onTouchEvent(MotionEvent evt) {
324 // save drag state before super call
325 boolean dragged = mIsBeingDragged;
326 boolean result = super.onTouchEvent(evt);
327 if (MotionEvent.ACTION_UP == evt.getActionMasked()) {
328 if (mScroller.isFinished() && dragged) {
329 snapToSelected();
330 }
Michael Kolbdb343c52011-05-29 12:18:52 -0700331 } else if (MotionEvent.ACTION_MOVE == evt.getActionMasked()) {
332 NavTabView ntv = (NavTabView) getSelectedView();
333 if (mIsBeingDragged && ntv.isHighlighted()) {
334 ntv.setHighlighted(false);
335 }
Michael Kolb4bd767d2011-05-27 11:33:55 -0700336 }
337 return result;
338 }
339
340 @Override
341 public void computeScroll() {
342 super.computeScroll();
343 if (mScroller.isFinished() && !mIsBeingDragged) {
344 if (!mSnapScroll) {
345 snapToSelected();
346 } else {
347 // reset snap scrolling flag
348 mSnapScroll = false;
349 NavTabView ntv = (NavTabView) getSelectedView();
Michael Kolbdb343c52011-05-29 12:18:52 -0700350 ntv.setHighlighted(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700351 }
352 }
353 }
354
Michael Kolb4bd767d2011-05-27 11:33:55 -0700355 private void snapToSelected() {
356 View v = mContentView.getChildAt(mSelected);
357 int left = (v.getLeft() + v.getRight()) / 2;
358 left -= getWidth() / 2;
359 if (left != getScrollX()) {
360 // snap to selected
361 mSnapScroll = true;
362 smoothScrollTo(left, 0);
Michael Kolbdb343c52011-05-29 12:18:52 -0700363 } else {
364 NavTabView ntv = (NavTabView) getSelectedView();
365 ntv.setHighlighted(true);
Michael Kolb4bd767d2011-05-27 11:33:55 -0700366 }
367 }
368
369 protected View getSelectedView() {
370 return mContentView.getChildAt(mSelected);
371 }
372
Michael Kolb2814a362011-05-19 15:49:41 -0700373 }
374
375}