RecentsHorizontalScrollView.java revision 3b1fc47d004f6b29af8f40d181baa3460b1e3b15
19f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller/* 29f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * Copyright (C) 2011 The Android Open Source Project 39f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * 49f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 59f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * you may not use this file except in compliance with the License. 69f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * You may obtain a copy of the License at 79f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * 89f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * http://www.apache.org/licenses/LICENSE-2.0 99f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * 109f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * Unless required by applicable law or agreed to in writing, software 119f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * distributed under the License is distributed on an "AS IS" BASIS, 129f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * See the License for the specific language governing permissions and 149f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller * limitations under the License. 159f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller */ 169f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 179f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerpackage com.android.systemui.recent; 189f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 193b1fc47d004f6b29af8f40d181baa3460b1e3b15Michael Jurkaimport com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; 209f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 219f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.animation.Animator; 229f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.animation.Animator.AnimatorListener; 239f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.animation.LayoutTransition; 249f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.animation.ObjectAnimator; 259f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.animation.ValueAnimator; 269f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.animation.ValueAnimator.AnimatorUpdateListener; 279f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.content.Context; 289f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.database.DataSetObserver; 299f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.graphics.RectF; 309f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.util.AttributeSet; 319f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.util.Log; 329f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.LayoutInflater; 339f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.MotionEvent; 349f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.VelocityTracker; 359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.View; 369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.animation.DecelerateInterpolator; 379f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.animation.LinearInterpolator; 389f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.widget.HorizontalScrollView; 399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.widget.LinearLayout; 409f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 419f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport com.android.systemui.R; 429f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 439f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerpublic class RecentsHorizontalScrollView extends HorizontalScrollView 449f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller implements View.OnClickListener, View.OnTouchListener { 459f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private static final float FADE_CONSTANT = 0.5f; 469f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private static final int SNAP_BACK_DURATION = 250; 479f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it 489f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private static final String TAG = RecentsPanelView.TAG; 499f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private static final float THRESHHOLD = 50; 509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private static final boolean DEBUG_INVALIDATE = false; 519f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private LinearLayout mLinearLayout; 523b1fc47d004f6b29af8f40d181baa3460b1e3b15Michael Jurka private ActivityDescriptionAdapter mAdapter; 539f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private RecentsCallback mCallback; 549f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected int mLastScrollPosition; 559f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private View mCurrentView; 569f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private float mLastY; 579f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private boolean mDragging; 589f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private VelocityTracker mVelocityTracker; 599f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 609f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public RecentsHorizontalScrollView(Context context) { 619f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller this(context, null); 629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 639f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 649f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public RecentsHorizontalScrollView(Context context, AttributeSet attrs) { 659f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super(context, attrs, 0); 669f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 679f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 689f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private int scrollPositionOfMostRecent() { 699f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return mLinearLayout.getWidth() - getWidth(); 709f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 729f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void update() { 739f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.removeAllViews(); 749f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller for (int i = 0; i < mAdapter.getCount(); i++) { 759f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller View view = mAdapter.getView(i, null, mLinearLayout); 769f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.setClickable(true); 779f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.setOnClickListener(this); 789f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.setOnTouchListener(this); 799f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.addView(view); 809f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 819f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // Scroll to end after layout. 829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller post(new Runnable() { 839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void run() { 849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastScrollPosition = scrollPositionOfMostRecent(); 859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller scrollTo(mLastScrollPosition, 0); 869f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 879f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 889f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 909f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 919f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onInterceptTouchEvent(MotionEvent ev) { 929f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (mVelocityTracker == null) { 939f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker = VelocityTracker.obtain(); 949f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 959f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker.addMovement(ev); 969f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller switch (ev.getAction()) { 979f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_DOWN: 989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mDragging = false; 999f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastY = ev.getY(); 1009f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1019f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1029f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_MOVE: 1039f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller float delta = ev.getY() - mLastY; 1049f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (Math.abs(delta) > THRESHHOLD) { 1059f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mDragging = true; 1069f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1079f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1089f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1099f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_UP: 1109f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mDragging = false; 1119f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1129f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1139f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return mDragging ? true : super.onInterceptTouchEvent(ev); 1149f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1159f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1169f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private float getAlphaForOffset(View view, float thumbHeight) { 1179f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float fadeHeight = FADE_CONSTANT * thumbHeight; 1189f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller float result = 1.0f; 1199f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (view.getY() >= thumbHeight) { 1209f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller result = 1.0f - (view.getY() - thumbHeight) / fadeHeight; 1219f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } else if (view.getY() < 0.0f) { 1229f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller result = 1.0f + (thumbHeight + view.getY()) / fadeHeight; 1239f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1249f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return result; 1259f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1269f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1279f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 1289f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onTouchEvent(MotionEvent ev) { 1299f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (!mDragging) { 1309f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return super.onTouchEvent(ev); 1319f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1329f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1339f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker.addMovement(ev); 1349f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final View animView = mCurrentView; 1369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // TODO: Cache thumbnail 1379f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final View thumb = animView.findViewById(R.id.app_thumbnail); 1389f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller switch (ev.getAction()) { 1399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_MOVE: 1409f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (animView != null) { 1419f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float delta = ev.getY() - mLastY; 1429f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller animView.setY(animView.getY() + delta); 1439f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); 1449f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller invalidateGlobalRegion(animView); 1459f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1469f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastY = ev.getY(); 1479f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1489f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1499f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_UP: 1509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final ObjectAnimator anim; 1519f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (animView != null) { 1529f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final VelocityTracker velocityTracker = mVelocityTracker; 1539f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller velocityTracker.computeCurrentVelocity(1000, 10000); 1549f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float velocityX = velocityTracker.getXVelocity(); 1559f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float velocityY = velocityTracker.getYVelocity(); 1569f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float curY = animView.getY(); 1579f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight(); 1589f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1599f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (Math.abs(velocityY) > Math.abs(velocityX) 1609f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller && Math.abs(velocityY) > ESCAPE_VELOCITY 1619f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller && (velocityY >= 0.0f) == (animView.getY() >= 0)) { 1629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final long duration = 1639f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)); 1649f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim = ObjectAnimator.ofFloat(animView, "y", curY, newY); 1659f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setInterpolator(new LinearInterpolator()); 1669f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final int swipeDirection = animView.getY() >= 0.0f ? 1679f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; 1689f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.addListener(new AnimatorListener() { 1699f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationStart(Animator animation) { 1709f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationRepeat(Animator animation) { 1729f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1739f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationEnd(Animator animation) { 1749f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.removeView(mCurrentView); 1759f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback.handleSwipe(animView, swipeDirection); 1769f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1779f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationCancel(Animator animation) { 1789f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.removeView(mCurrentView); 1799f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback.handleSwipe(animView, swipeDirection); 1809f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1819f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 1829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setDuration(duration); 1839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } else { // Animate back to position 1849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final long duration = Math.abs(velocityY) > 0.0f ? 1859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)) 1869f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller : SNAP_BACK_DURATION; 1879f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f); 1889f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setInterpolator(new DecelerateInterpolator(2.0f)); 1899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setDuration(duration); 1909f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1919f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1929f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.addUpdateListener(new AnimatorUpdateListener() { 1939f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationUpdate(ValueAnimator animation) { 1949f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); 1959f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller invalidateGlobalRegion(animView); 1969f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1979f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 1989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.start(); 1999f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2009f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2019f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker.recycle(); 2029f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker = null; 2039f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 2049f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2059f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return true; 2069f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2079f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2089f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller void invalidateGlobalRegion(View view) { 2099f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller RectF childBounds 2109f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); 2119f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller childBounds.offset(view.getX(), view.getY()); 2129f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (DEBUG_INVALIDATE) Log.v(TAG, "-------------"); 2139f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller while (view.getParent() != null && view.getParent() instanceof View) { 2149f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view = (View) view.getParent(); 2159f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.getMatrix().mapRect(childBounds); 2169f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.invalidate((int) Math.floor(childBounds.left), 2179f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (int) Math.floor(childBounds.top), 2189f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (int) Math.ceil(childBounds.right), 2199f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (int) Math.ceil(childBounds.bottom)); 2209f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (DEBUG_INVALIDATE) { 2219f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) 2229f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller + "," + (int) Math.floor(childBounds.top) 2239f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller + "," + (int) Math.ceil(childBounds.right) 2249f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller + "," + (int) Math.ceil(childBounds.bottom)); 2259f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2269f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2279f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2289f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2299f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2309f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onFinishInflate() { 2319f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onFinishInflate(); 2329f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller LayoutInflater inflater = (LayoutInflater) 2339f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 2349f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller setScrollbarFadingEnabled(true); 2369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2379f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout); 2389f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final int leftPadding = mContext.getResources() 2409f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); 2419f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller setOverScrollEffectPadding(leftPadding, 0); 2429f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2439f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2449f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private void setOverScrollEffectPadding(int leftPadding, int i) { 2459f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // TODO Add to RecentsHorizontalScrollView 2469f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2479f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2489f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2499f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onSizeChanged(int w, int h, int oldw, int oldh) { 2509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onSizeChanged(w, h, oldw, oldh); 2519f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // Keep track of the last visible item in the list so we can restore it 2529f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // to the bottom when the orientation changes. 2539f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastScrollPosition = scrollPositionOfMostRecent(); 2549f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2559f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // This has to happen post-layout, so run it "in the future" 2569f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller post(new Runnable() { 2579f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void run() { 2589f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller scrollTo(0, mLastScrollPosition); 2599f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2609f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 2619f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2639f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2649f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onVisibilityChanged(View changedView, int visibility) { 2659f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onVisibilityChanged(changedView, visibility); 2669f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // scroll to bottom after reloading 2679f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (visibility == View.VISIBLE && changedView == this) { 2689f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller post(new Runnable() { 2699f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void run() { 2709f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 2719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2729f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 2739f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2749f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2759f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2763b1fc47d004f6b29af8f40d181baa3460b1e3b15Michael Jurka public void setAdapter(ActivityDescriptionAdapter adapter) { 2779f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mAdapter = adapter; 2789f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mAdapter.registerDataSetObserver(new DataSetObserver() { 2799f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onChanged() { 2809f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 2819f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onInvalidated() { 2849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 2859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2869f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 2879f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2889f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2909f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void setLayoutTransition(LayoutTransition transition) { 2919f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // The layout transition applies to our embedded LinearLayout 2929f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.setLayoutTransition(transition); 2939f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2949f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2959f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onClick(View view) { 2969f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback.handleOnClick(view); 2979f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2999f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void setCallback(RecentsCallback callback) { 3009f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback = callback; 3019f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3029f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3039f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onTouch(View v, MotionEvent event) { 3049f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCurrentView = v; 3059f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return false; 3069f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3079f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller} 308