summaryrefslogtreecommitdiffstats
path: root/src/com/android/browser/NavTabScroller.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/browser/NavTabScroller.java')
-rw-r--r--src/com/android/browser/NavTabScroller.java1068
1 files changed, 534 insertions, 534 deletions
diff --git a/src/com/android/browser/NavTabScroller.java b/src/com/android/browser/NavTabScroller.java
index c940bf553..f1f8e3582 100644
--- a/src/com/android/browser/NavTabScroller.java
+++ b/src/com/android/browser/NavTabScroller.java
@@ -1,18 +1,18 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License. You may obtain a copy of
+* the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations under
+* the License.
+*/
package com.android.browser;
@@ -35,535 +35,535 @@ import android.widget.LinearLayout;
import com.android.browser.view.ScrollerView;
/**
- * custom view for displaying tabs in the nav screen
- */
+* custom view for displaying tabs in the nav screen
+*/
public class NavTabScroller extends ScrollerView {
- static final int INVALID_POSITION = -1;
- static final float[] PULL_FACTOR = { 2.5f, 0.9f };
-
- interface OnRemoveListener {
- public void onRemovePosition(int position);
- }
-
- interface OnLayoutListener {
- public void onLayout(int l, int t, int r, int b);
- }
-
- private ContentLayout mContentView;
- private BaseAdapter mAdapter;
- private OnRemoveListener mRemoveListener;
- private OnLayoutListener mLayoutListener;
- private int mGap;
- private int mGapPosition;
- private ObjectAnimator mGapAnimator;
-
- // after drag animation velocity in pixels/sec
- private static final float MIN_VELOCITY = 1500;
- private AnimatorSet mAnimator;
-
- private float mFlingVelocity;
- private boolean mNeedsScroll;
- private int mScrollPosition;
-
- DecelerateInterpolator mCubic;
- int mPullValue;
-
- public NavTabScroller(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init(context);
- }
-
- public NavTabScroller(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context);
- }
-
- public NavTabScroller(Context context) {
- super(context);
- init(context);
- }
-
- private void init(Context ctx) {
- mCubic = new DecelerateInterpolator(1.5f);
- mGapPosition = INVALID_POSITION;
- setHorizontalScrollBarEnabled(false);
- setVerticalScrollBarEnabled(false);
- mContentView = new ContentLayout(ctx, this);
- mContentView.setOrientation(LinearLayout.HORIZONTAL);
- addView(mContentView);
- mContentView.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
- // ProGuard !
- setGap(getGap());
- mFlingVelocity = getContext().getResources().getDisplayMetrics().density
- * MIN_VELOCITY;
- }
-
- protected int getScrollValue() {
- return mHorizontal ? mScrollX : mScrollY;
- }
-
- protected void setScrollValue(int value) {
- scrollTo(mHorizontal ? value : 0, mHorizontal ? 0 : value);
- }
-
- protected NavTabView getTabView(int pos) {
- return (NavTabView) mContentView.getChildAt(pos);
- }
-
- protected boolean isHorizontal() {
- return mHorizontal;
- }
-
- public void setOrientation(int orientation) {
- mContentView.setOrientation(orientation);
- if (orientation == LinearLayout.HORIZONTAL) {
- mContentView.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
- } else {
- mContentView.setLayoutParams(
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+ static final int INVALID_POSITION = -1;
+ static final float[] PULL_FACTOR = { 2.5f, 0.9f };
+
+ interface OnRemoveListener {
+ public void onRemovePosition(int position);
+ }
+
+ interface OnLayoutListener {
+ public void onLayout(int l, int t, int r, int b);
+ }
+
+ private ContentLayout mContentView;
+ private BaseAdapter mAdapter;
+ private OnRemoveListener mRemoveListener;
+ private OnLayoutListener mLayoutListener;
+ private int mGap;
+ private int mGapPosition;
+ private ObjectAnimator mGapAnimator;
+
+ // after drag animation velocity in pixels/sec
+ private static final float MIN_VELOCITY = 1500;
+ private AnimatorSet mAnimator;
+
+ private float mFlingVelocity;
+ private boolean mNeedsScroll;
+ private int mScrollPosition;
+
+ DecelerateInterpolator mCubic;
+ int mPullValue;
+
+ public NavTabScroller(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ public NavTabScroller(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public NavTabScroller(Context context) {
+ super(context);
+ init(context);
+ }
+
+ private void init(Context ctx) {
+ mCubic = new DecelerateInterpolator(1.5f);
+ mGapPosition = INVALID_POSITION;
+ setHorizontalScrollBarEnabled(false);
+ setVerticalScrollBarEnabled(false);
+ mContentView = new ContentLayout(ctx, this);
+ mContentView.setOrientation(LinearLayout.HORIZONTAL);
+ addView(mContentView);
+ mContentView.setLayoutParams(
+ new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
+ // ProGuard !
+ setGap(getGap());
+ mFlingVelocity = getContext().getResources().getDisplayMetrics().density
+ * MIN_VELOCITY;
+ }
+
+ protected int getScrollValue() {
+ return mHorizontal ? mScrollX : mScrollY;
+ }
+
+ protected void setScrollValue(int value) {
+ scrollTo(mHorizontal ? value : 0, mHorizontal ? 0 : value);
+ }
+
+ protected NavTabView getTabView(int pos) {
+ return (NavTabView) mContentView.getChildAt(pos);
+ }
+
+ protected boolean isHorizontal() {
+ return mHorizontal;
+ }
+
+ public void setOrientation(int orientation) {
+ mContentView.setOrientation(orientation);
+ if (orientation == LinearLayout.HORIZONTAL) {
+ mContentView.setLayoutParams(
+ new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
+ } else {
+ mContentView.setLayoutParams(
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+ }
+ super.setOrientation(orientation);
+ }
+
+ @Override
+ protected void onMeasure(int wspec, int hspec) {
+ super.onMeasure(wspec, hspec);
+ calcPadding();
+ }
+
+ private void calcPadding() {
+ if (mAdapter.getCount() > 0) {
+ View v = mContentView.getChildAt(0);
+ if (mHorizontal) {
+ int pad = (getMeasuredWidth() - v.getMeasuredWidth()) / 2 + 2;
+ mContentView.setPadding(pad, 0, pad, 0);
+ } else {
+ int pad = (getMeasuredHeight() - v.getMeasuredHeight()) / 2 + 2;
+ mContentView.setPadding(0, pad, 0, pad);
+ }
+ }
+ }
+
+ public void setAdapter(BaseAdapter adapter) {
+ setAdapter(adapter, 0);
+ }
+
+
+ public void setOnRemoveListener(OnRemoveListener l) {
+ mRemoveListener = l;
+ }
+
+ public void setOnLayoutListener(OnLayoutListener l) {
+ mLayoutListener = l;
+ }
+
+ protected void setAdapter(BaseAdapter adapter, int selection) {
+ mAdapter = adapter;
+ mAdapter.registerDataSetObserver(new DataSetObserver() {
+
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ handleDataChanged();
+ }
+
+ @Override
+ public void onInvalidated() {
+ super.onInvalidated();
+ }
+ });
+ handleDataChanged(selection);
+ }
+
+ protected ViewGroup getContentView() {
+ return mContentView;
+ }
+
+ protected int getRelativeChildTop(int ix) {
+ return mContentView.getChildAt(ix).getTop() - mScrollY;
+ }
+
+ protected void handleDataChanged() {
+ handleDataChanged(INVALID_POSITION);
+ }
+
+ void handleDataChanged(int newscroll) {
+ int scroll = getScrollValue();
+ if (mGapAnimator != null) {
+ mGapAnimator.cancel();
+ }
+ mContentView.removeAllViews();
+ for (int i = 0; i < mAdapter.getCount(); i++) {
+ View v = mAdapter.getView(i, null, mContentView);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ lp.gravity = (mHorizontal ? Gravity.CENTER_VERTICAL : Gravity.CENTER_HORIZONTAL);
+ mContentView.addView(v, lp);
+ if (mGapPosition > INVALID_POSITION){
+ adjustViewGap(v, i);
+ }
+ }
+ if (newscroll > INVALID_POSITION) {
+ newscroll = Math.min(mAdapter.getCount() - 1, newscroll);
+ mNeedsScroll = true;
+ mScrollPosition = newscroll;
+ requestLayout();
+ } else {
+ setScrollValue(scroll);
+ }
+ }
+
+ protected void finishScroller() {
+ mScroller.forceFinished(true);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (mNeedsScroll) {
+ mScroller.forceFinished(true);
+ snapToSelected(mScrollPosition, false);
+ mNeedsScroll = false;
+ }
+ if (mLayoutListener != null) {
+ mLayoutListener.onLayout(l, t, r, b);
+ mLayoutListener = null;
+ }
+ }
+
+ void clearTabs() {
+ mContentView.removeAllViews();
+ }
+
+ void snapToSelected(int pos, boolean smooth) {
+ if (pos < 0) return;
+ View v = mContentView.getChildAt(pos);
+ if (v == null) return;
+ int sx = 0;
+ int sy = 0;
+ if (mHorizontal) {
+ sx = (v.getLeft() + v.getRight() - getWidth()) / 2;
+ } else {
+ sy = (v.getTop() + v.getBottom() - getHeight()) / 2;
+ }
+ if ((sx != mScrollX) || (sy != mScrollY)) {
+ if (smooth) {
+ smoothScrollTo(sx,sy);
+ } else {
+ scrollTo(sx, sy);
+ }
+ }
+ }
+
+ protected void animateOut(View v) {
+ if (v == null) return;
+ animateOut(v, -mFlingVelocity);
+ }
+
+ private void animateOut(final View v, float velocity) {
+ float start = mHorizontal ? v.getTranslationY() : v.getTranslationX();
+ animateOut(v, velocity, start);
+ }
+
+ private void animateOut(final View v, float velocity, float start) {
+ if ((v == null) || (mAnimator != null)) return;
+ final int position = mContentView.indexOfChild(v);
+ int target = 0;
+ if (velocity < 0) {
+ target = mHorizontal ? -getHeight() : -getWidth();
+ } else {
+ target = mHorizontal ? getHeight() : getWidth();
+ }
+ int distance = target - (mHorizontal ? v.getTop() : v.getLeft());
+ long duration = (long) (Math.abs(distance) * 1000 / Math.abs(velocity));
+ int scroll = 0;
+ int translate = 0;
+ int gap = mHorizontal ? v.getWidth() : v.getHeight();
+ int centerView = getViewCenter(v);
+ int centerScreen = getScreenCenter();
+ int newpos = INVALID_POSITION;
+ if (centerView < centerScreen - gap / 2) {
+ // top view
+ scroll = - (centerScreen - centerView - gap);
+ translate = (position > 0) ? gap : 0;
+ newpos = position;
+ } else if (centerView > centerScreen + gap / 2) {
+ // bottom view
+ scroll = - (centerScreen + gap - centerView);
+ if (position < mAdapter.getCount() - 1) {
+ translate = -gap;
+ }
+ } else {
+ // center view
+ scroll = - (centerScreen - centerView);
+ if (position < mAdapter.getCount() - 1) {
+ translate = -gap;
+ } else {
+ scroll -= gap;
+ }
+ }
+ mGapPosition = position;
+ final int pos = newpos;
+ ObjectAnimator trans = ObjectAnimator.ofFloat(v,
+ (mHorizontal ? TRANSLATION_Y : TRANSLATION_X), start, target);
+ ObjectAnimator alpha = ObjectAnimator.ofFloat(v, ALPHA, getAlpha(v,start),
+ getAlpha(v,target));
+ AnimatorSet set1 = new AnimatorSet();
+ set1.playTogether(trans, alpha);
+ set1.setDuration(duration);
+ mAnimator = new AnimatorSet();
+ ObjectAnimator trans2 = null;
+ ObjectAnimator scroll1 = null;
+ if (scroll != 0) {
+ if (mHorizontal) {
+ scroll1 = ObjectAnimator.ofInt(this, "scrollX", getScrollX(), getScrollX() + scroll);
+ } else {
+ scroll1 = ObjectAnimator.ofInt(this, "scrollY", getScrollY(), getScrollY() + scroll);
+ }
+ }
+ if (translate != 0) {
+ trans2 = ObjectAnimator.ofInt(this, "gap", 0, translate);
+ }
+ final int duration2 = 200;
+ if (scroll1 != null) {
+ if (trans2 != null) {
+ AnimatorSet set2 = new AnimatorSet();
+ set2.playTogether(scroll1, trans2);
+ set2.setDuration(duration2);
+ mAnimator.playSequentially(set1, set2);
+ } else {
+ scroll1.setDuration(duration2);
+ mAnimator.playSequentially(set1, scroll1);
+ }
+ } else {
+ if (trans2 != null) {
+ trans2.setDuration(duration2);
+ mAnimator.playSequentially(set1, trans2);
+ }
+ }
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator a) {
+ if (mRemoveListener != null) {
+ mRemoveListener.onRemovePosition(position);
+ mAnimator = null;
+ mGapPosition = INVALID_POSITION;
+ mGap = 0;
+ handleDataChanged(pos);
}
- super.setOrientation(orientation);
- }
-
- @Override
- protected void onMeasure(int wspec, int hspec) {
- super.onMeasure(wspec, hspec);
- calcPadding();
- }
-
- private void calcPadding() {
- if (mAdapter.getCount() > 0) {
- View v = mContentView.getChildAt(0);
- if (mHorizontal) {
- int pad = (getMeasuredWidth() - v.getMeasuredWidth()) / 2 + 2;
- mContentView.setPadding(pad, 0, pad, 0);
- } else {
- int pad = (getMeasuredHeight() - v.getMeasuredHeight()) / 2 + 2;
- mContentView.setPadding(0, pad, 0, pad);
- }
+ }
+ });
+ mAnimator.start();
+ }
+
+ public void setGap(int gap) {
+ if (mGapPosition != INVALID_POSITION) {
+ mGap = gap;
+ postInvalidate();
+ }
+ }
+
+ public int getGap() {
+ return mGap;
+ }
+
+ void adjustGap() {
+ for (int i = 0; i < mContentView.getChildCount(); i++) {
+ final View child = mContentView.getChildAt(i);
+ adjustViewGap(child, i);
+ }
+ }
+
+ private void adjustViewGap(View view, int pos) {
+ if ((mGap < 0 && pos > mGapPosition)
+ || (mGap > 0 && pos < mGapPosition)) {
+ if (mHorizontal) {
+ view.setTranslationX(mGap);
+ } else {
+ view.setTranslationY(mGap);
+ }
+ }
+ }
+
+ private int getViewCenter(View v) {
+ if (mHorizontal) {
+ return v.getLeft() + v.getWidth() / 2;
+ } else {
+ return v.getTop() + v.getHeight() / 2;
+ }
+ }
+
+ private int getScreenCenter() {
+ if (mHorizontal) {
+ return getScrollX() + getWidth() / 2;
+ } else {
+ return getScrollY() + getHeight() / 2;
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mGapPosition > INVALID_POSITION) {
+ adjustGap();
+ }
+ super.draw(canvas);
+ }
+
+ @Override
+ protected View findViewAt(int x, int y) {
+ x += mScrollX;
+ y += mScrollY;
+ final int count = mContentView.getChildCount();
+ for (int i = count - 1; i >= 0; i--) {
+ View child = mContentView.getChildAt(i);
+ if (child.getVisibility() == View.VISIBLE) {
+ if ((x >= child.getLeft()) && (x < child.getRight())
+ && (y >= child.getTop()) && (y < child.getBottom())) {
+ return child;
}
- }
-
- public void setAdapter(BaseAdapter adapter) {
- setAdapter(adapter, 0);
- }
-
-
- public void setOnRemoveListener(OnRemoveListener l) {
- mRemoveListener = l;
- }
-
- public void setOnLayoutListener(OnLayoutListener l) {
- mLayoutListener = l;
- }
-
- protected void setAdapter(BaseAdapter adapter, int selection) {
- mAdapter = adapter;
- mAdapter.registerDataSetObserver(new DataSetObserver() {
-
- @Override
- public void onChanged() {
- super.onChanged();
- handleDataChanged();
- }
-
- @Override
- public void onInvalidated() {
- super.onInvalidated();
- }
- });
- handleDataChanged(selection);
- }
-
- protected ViewGroup getContentView() {
- return mContentView;
- }
-
- protected int getRelativeChildTop(int ix) {
- return mContentView.getChildAt(ix).getTop() - mScrollY;
- }
-
- protected void handleDataChanged() {
- handleDataChanged(INVALID_POSITION);
- }
-
- void handleDataChanged(int newscroll) {
- int scroll = getScrollValue();
- if (mGapAnimator != null) {
- mGapAnimator.cancel();
- }
- mContentView.removeAllViews();
- for (int i = 0; i < mAdapter.getCount(); i++) {
- View v = mAdapter.getView(i, null, mContentView);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- lp.gravity = (mHorizontal ? Gravity.CENTER_VERTICAL : Gravity.CENTER_HORIZONTAL);
- mContentView.addView(v, lp);
- if (mGapPosition > INVALID_POSITION){
- adjustViewGap(v, i);
- }
- }
- if (newscroll > INVALID_POSITION) {
- newscroll = Math.min(mAdapter.getCount() - 1, newscroll);
- mNeedsScroll = true;
- mScrollPosition = newscroll;
- requestLayout();
- } else {
- setScrollValue(scroll);
- }
- }
-
- protected void finishScroller() {
- mScroller.forceFinished(true);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void onOrthoDrag(View v, float distance) {
+ if ((v != null) && (mAnimator == null)) {
+ offsetView(v, distance);
+ }
+ }
+
+ @Override
+ protected void onOrthoDragFinished(View downView) {
+ if (mAnimator != null) return;
+ if (mIsOrthoDragged && downView != null) {
+ // offset
+ float diff = mHorizontal ? downView.getTranslationY() : downView.getTranslationX();
+ if (Math.abs(diff) > (mHorizontal ? downView.getHeight() : downView.getWidth()) / 2) {
+ // remove it
+ animateOut(downView, Math.signum(diff) * mFlingVelocity, diff);
+ } else {
+ // snap back
+ offsetView(downView, 0);
+ }
+ }
+ }
+
+ @Override
+ protected void onOrthoFling(View v, float velocity) {
+ if (v == null) return;
+ if (mAnimator == null && Math.abs(velocity) > mFlingVelocity / 2) {
+ animateOut(v, velocity);
+ } else {
+ offsetView(v, 0);
+ }
+ }
+
+ private void offsetView(View v, float distance) {
+ v.setAlpha(getAlpha(v, distance));
+ if (mHorizontal) {
+ v.setTranslationY(distance);
+ } else {
+ v.setTranslationX(distance);
+ }
+ }
+
+ private float getAlpha(View v, float distance) {
+ return 1 - (float) Math.abs(distance) / (mHorizontal ? v.getHeight() : v.getWidth());
+ }
+
+ private float ease(DecelerateInterpolator inter, float value, float start,
+ float dist, float duration) {
+ return start + dist * inter.getInterpolation(value / duration);
+ }
+
+ @Override
+ protected void onPull(int delta) {
+ boolean layer = false;
+ int count = 2;
+ if (delta == 0 && mPullValue == 0) return;
+ if (delta == 0 && mPullValue != 0) {
+ // reset
+ for (int i = 0; i < count; i++) {
+ View child = mContentView.getChildAt((mPullValue < 0)
+ ? i
+ : mContentView.getChildCount() - 1 - i);
+ if (child == null) break;
+ ObjectAnimator trans = ObjectAnimator.ofFloat(child,
+ mHorizontal ? "translationX" : "translationY",
+ mHorizontal ? getTranslationX() : getTranslationY(),
+ 0);
+ ObjectAnimator rot = ObjectAnimator.ofFloat(child,
+ mHorizontal ? "rotationY" : "rotationX",
+ mHorizontal ? getRotationY() : getRotationX(),
+ 0);
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(trans, rot);
+ set.setDuration(100);
+ set.start();
+ }
+ mPullValue = 0;
+ } else {
+ if (mPullValue == 0) {
+ layer = true;
+ }
+ mPullValue += delta;
+ }
+ final int height = mHorizontal ? getWidth() : getHeight();
+ int oscroll = Math.abs(mPullValue);
+ int factor = (mPullValue <= 0) ? 1 : -1;
+ for (int i = 0; i < count; i++) {
+ View child = mContentView.getChildAt((mPullValue < 0)
+ ? i
+ : mContentView.getChildCount() - 1 - i);
+ if (child == null) break;
+ if (layer) {
+ }
+ float k = PULL_FACTOR[i];
+ float rot = -factor * ease(mCubic, oscroll, 0, k * 2, height);
+ int y = factor * (int) ease(mCubic, oscroll, 0, k*20, height);
+ if (mHorizontal) {
+ child.setTranslationX(y);
+ } else {
+ child.setTranslationY(y);
+ }
+ if (mHorizontal) {
+ child.setRotationY(-rot);
+ } else {
+ child.setRotationX(rot);
+ }
+ }
+ }
+
+ static class ContentLayout extends LinearLayout {
+
+ NavTabScroller mScroller;
+
+ public ContentLayout(Context context, NavTabScroller scroller) {
+ super(context);
+ mScroller = scroller;
}
@Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- if (mNeedsScroll) {
- mScroller.forceFinished(true);
- snapToSelected(mScrollPosition, false);
- mNeedsScroll = false;
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (mScroller.getGap() != 0) {
+ View v = getChildAt(0);
+ if (v != null) {
+ if (mScroller.isHorizontal()) {
+ int total = v.getMeasuredWidth() + getMeasuredWidth();
+ setMeasuredDimension(total, getMeasuredHeight());
+ } else {
+ int total = v.getMeasuredHeight() + getMeasuredHeight();
+ setMeasuredDimension(getMeasuredWidth(), total);
+ }
}
- if (mLayoutListener != null) {
- mLayoutListener.onLayout(l, t, r, b);
- mLayoutListener = null;
- }
- }
- void clearTabs() {
- mContentView.removeAllViews();
+ }
}
- void snapToSelected(int pos, boolean smooth) {
- if (pos < 0) return;
- View v = mContentView.getChildAt(pos);
- if (v == null) return;
- int sx = 0;
- int sy = 0;
- if (mHorizontal) {
- sx = (v.getLeft() + v.getRight() - getWidth()) / 2;
- } else {
- sy = (v.getTop() + v.getBottom() - getHeight()) / 2;
- }
- if ((sx != mScrollX) || (sy != mScrollY)) {
- if (smooth) {
- smoothScrollTo(sx,sy);
- } else {
- scrollTo(sx, sy);
- }
- }
- }
-
- protected void animateOut(View v) {
- if (v == null) return;
- animateOut(v, -mFlingVelocity);
- }
-
- private void animateOut(final View v, float velocity) {
- float start = mHorizontal ? v.getTranslationY() : v.getTranslationX();
- animateOut(v, velocity, start);
- }
-
- private void animateOut(final View v, float velocity, float start) {
- if ((v == null) || (mAnimator != null)) return;
- final int position = mContentView.indexOfChild(v);
- int target = 0;
- if (velocity < 0) {
- target = mHorizontal ? -getHeight() : -getWidth();
- } else {
- target = mHorizontal ? getHeight() : getWidth();
- }
- int distance = target - (mHorizontal ? v.getTop() : v.getLeft());
- long duration = (long) (Math.abs(distance) * 1000 / Math.abs(velocity));
- int scroll = 0;
- int translate = 0;
- int gap = mHorizontal ? v.getWidth() : v.getHeight();
- int centerView = getViewCenter(v);
- int centerScreen = getScreenCenter();
- int newpos = INVALID_POSITION;
- if (centerView < centerScreen - gap / 2) {
- // top view
- scroll = - (centerScreen - centerView - gap);
- translate = (position > 0) ? gap : 0;
- newpos = position;
- } else if (centerView > centerScreen + gap / 2) {
- // bottom view
- scroll = - (centerScreen + gap - centerView);
- if (position < mAdapter.getCount() - 1) {
- translate = -gap;
- }
- } else {
- // center view
- scroll = - (centerScreen - centerView);
- if (position < mAdapter.getCount() - 1) {
- translate = -gap;
- } else {
- scroll -= gap;
- }
- }
- mGapPosition = position;
- final int pos = newpos;
- ObjectAnimator trans = ObjectAnimator.ofFloat(v,
- (mHorizontal ? TRANSLATION_Y : TRANSLATION_X), start, target);
- ObjectAnimator alpha = ObjectAnimator.ofFloat(v, ALPHA, getAlpha(v,start),
- getAlpha(v,target));
- AnimatorSet set1 = new AnimatorSet();
- set1.playTogether(trans, alpha);
- set1.setDuration(duration);
- mAnimator = new AnimatorSet();
- ObjectAnimator trans2 = null;
- ObjectAnimator scroll1 = null;
- if (scroll != 0) {
- if (mHorizontal) {
- scroll1 = ObjectAnimator.ofInt(this, "scrollX", getScrollX(), getScrollX() + scroll);
- } else {
- scroll1 = ObjectAnimator.ofInt(this, "scrollY", getScrollY(), getScrollY() + scroll);
- }
- }
- if (translate != 0) {
- trans2 = ObjectAnimator.ofInt(this, "gap", 0, translate);
- }
- final int duration2 = 200;
- if (scroll1 != null) {
- if (trans2 != null) {
- AnimatorSet set2 = new AnimatorSet();
- set2.playTogether(scroll1, trans2);
- set2.setDuration(duration2);
- mAnimator.playSequentially(set1, set2);
- } else {
- scroll1.setDuration(duration2);
- mAnimator.playSequentially(set1, scroll1);
- }
- } else {
- if (trans2 != null) {
- trans2.setDuration(duration2);
- mAnimator.playSequentially(set1, trans2);
- }
- }
- mAnimator.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator a) {
- if (mRemoveListener != null) {
- mRemoveListener.onRemovePosition(position);
- mAnimator = null;
- mGapPosition = INVALID_POSITION;
- mGap = 0;
- handleDataChanged(pos);
- }
- }
- });
- mAnimator.start();
- }
-
- public void setGap(int gap) {
- if (mGapPosition != INVALID_POSITION) {
- mGap = gap;
- postInvalidate();
- }
- }
-
- public int getGap() {
- return mGap;
- }
-
- void adjustGap() {
- for (int i = 0; i < mContentView.getChildCount(); i++) {
- final View child = mContentView.getChildAt(i);
- adjustViewGap(child, i);
- }
- }
-
- private void adjustViewGap(View view, int pos) {
- if ((mGap < 0 && pos > mGapPosition)
- || (mGap > 0 && pos < mGapPosition)) {
- if (mHorizontal) {
- view.setTranslationX(mGap);
- } else {
- view.setTranslationY(mGap);
- }
- }
- }
-
- private int getViewCenter(View v) {
- if (mHorizontal) {
- return v.getLeft() + v.getWidth() / 2;
- } else {
- return v.getTop() + v.getHeight() / 2;
- }
- }
-
- private int getScreenCenter() {
- if (mHorizontal) {
- return getScrollX() + getWidth() / 2;
- } else {
- return getScrollY() + getHeight() / 2;
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- if (mGapPosition > INVALID_POSITION) {
- adjustGap();
- }
- super.draw(canvas);
- }
-
- @Override
- protected View findViewAt(int x, int y) {
- x += mScrollX;
- y += mScrollY;
- final int count = mContentView.getChildCount();
- for (int i = count - 1; i >= 0; i--) {
- View child = mContentView.getChildAt(i);
- if (child.getVisibility() == View.VISIBLE) {
- if ((x >= child.getLeft()) && (x < child.getRight())
- && (y >= child.getTop()) && (y < child.getBottom())) {
- return child;
- }
- }
- }
- return null;
- }
-
- @Override
- protected void onOrthoDrag(View v, float distance) {
- if ((v != null) && (mAnimator == null)) {
- offsetView(v, distance);
- }
- }
-
- @Override
- protected void onOrthoDragFinished(View downView) {
- if (mAnimator != null) return;
- if (mIsOrthoDragged && downView != null) {
- // offset
- float diff = mHorizontal ? downView.getTranslationY() : downView.getTranslationX();
- if (Math.abs(diff) > (mHorizontal ? downView.getHeight() : downView.getWidth()) / 2) {
- // remove it
- animateOut(downView, Math.signum(diff) * mFlingVelocity, diff);
- } else {
- // snap back
- offsetView(downView, 0);
- }
- }
- }
-
- @Override
- protected void onOrthoFling(View v, float velocity) {
- if (v == null) return;
- if (mAnimator == null && Math.abs(velocity) > mFlingVelocity / 2) {
- animateOut(v, velocity);
- } else {
- offsetView(v, 0);
- }
- }
-
- private void offsetView(View v, float distance) {
- v.setAlpha(getAlpha(v, distance));
- if (mHorizontal) {
- v.setTranslationY(distance);
- } else {
- v.setTranslationX(distance);
- }
- }
-
- private float getAlpha(View v, float distance) {
- return 1 - (float) Math.abs(distance) / (mHorizontal ? v.getHeight() : v.getWidth());
- }
-
- private float ease(DecelerateInterpolator inter, float value, float start,
- float dist, float duration) {
- return start + dist * inter.getInterpolation(value / duration);
- }
-
- @Override
- protected void onPull(int delta) {
- boolean layer = false;
- int count = 2;
- if (delta == 0 && mPullValue == 0) return;
- if (delta == 0 && mPullValue != 0) {
- // reset
- for (int i = 0; i < count; i++) {
- View child = mContentView.getChildAt((mPullValue < 0)
- ? i
- : mContentView.getChildCount() - 1 - i);
- if (child == null) break;
- ObjectAnimator trans = ObjectAnimator.ofFloat(child,
- mHorizontal ? "translationX" : "translationY",
- mHorizontal ? getTranslationX() : getTranslationY(),
- 0);
- ObjectAnimator rot = ObjectAnimator.ofFloat(child,
- mHorizontal ? "rotationY" : "rotationX",
- mHorizontal ? getRotationY() : getRotationX(),
- 0);
- AnimatorSet set = new AnimatorSet();
- set.playTogether(trans, rot);
- set.setDuration(100);
- set.start();
- }
- mPullValue = 0;
- } else {
- if (mPullValue == 0) {
- layer = true;
- }
- mPullValue += delta;
- }
- final int height = mHorizontal ? getWidth() : getHeight();
- int oscroll = Math.abs(mPullValue);
- int factor = (mPullValue <= 0) ? 1 : -1;
- for (int i = 0; i < count; i++) {
- View child = mContentView.getChildAt((mPullValue < 0)
- ? i
- : mContentView.getChildCount() - 1 - i);
- if (child == null) break;
- if (layer) {
- }
- float k = PULL_FACTOR[i];
- float rot = -factor * ease(mCubic, oscroll, 0, k * 2, height);
- int y = factor * (int) ease(mCubic, oscroll, 0, k*20, height);
- if (mHorizontal) {
- child.setTranslationX(y);
- } else {
- child.setTranslationY(y);
- }
- if (mHorizontal) {
- child.setRotationY(-rot);
- } else {
- child.setRotationX(rot);
- }
- }
- }
-
- static class ContentLayout extends LinearLayout {
-
- NavTabScroller mScroller;
-
- public ContentLayout(Context context, NavTabScroller scroller) {
- super(context);
- mScroller = scroller;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mScroller.getGap() != 0) {
- View v = getChildAt(0);
- if (v != null) {
- if (mScroller.isHorizontal()) {
- int total = v.getMeasuredWidth() + getMeasuredWidth();
- setMeasuredDimension(total, getMeasuredHeight());
- } else {
- int total = v.getMeasuredHeight() + getMeasuredHeight();
- setMeasuredDimension(getMeasuredWidth(), total);
- }
- }
-
- }
- }
-
- }
+ }
-} \ No newline at end of file
+}