RecentsHorizontalScrollView.java revision 3c728fe61dcf49354ea761a3e4ef6032ec271630
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; 283c728fe61dcf49354ea761a3e4ef6032ec271630Jim Millerimport android.content.res.Configuration; 299f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.database.DataSetObserver; 309f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.graphics.RectF; 319f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.util.AttributeSet; 329f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.util.Log; 339f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.LayoutInflater; 349f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.MotionEvent; 359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.VelocityTracker; 369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.View; 373c728fe61dcf49354ea761a3e4ef6032ec271630Jim Millerimport android.view.ViewConfiguration; 389f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.animation.DecelerateInterpolator; 399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.animation.LinearInterpolator; 409f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.widget.HorizontalScrollView; 419f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.widget.LinearLayout; 429f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 439f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport com.android.systemui.R; 449f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 459f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerpublic class RecentsHorizontalScrollView extends HorizontalScrollView 469f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller implements View.OnClickListener, View.OnTouchListener { 479f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private static final boolean DEBUG_INVALIDATE = false; 483c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller private static final String TAG = RecentsPanelView.TAG; 493c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller private static final boolean DEBUG = RecentsPanelView.DEBUG; 509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private LinearLayout mLinearLayout; 513b1fc47d004f6b29af8f40d181baa3460b1e3b15Michael Jurka private ActivityDescriptionAdapter mAdapter; 529f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private RecentsCallback mCallback; 539f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected int mLastScrollPosition; 549f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private View mCurrentView; 559f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private float mLastY; 569f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private boolean mDragging; 579f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private VelocityTracker mVelocityTracker; 583c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller private float mDensityScale; 593c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller private float mPagingTouchSlop; 609f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 619f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public RecentsHorizontalScrollView(Context context) { 629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller this(context, null); 639f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 649f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 659f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public RecentsHorizontalScrollView(Context context, AttributeSet attrs) { 669f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super(context, attrs, 0); 673c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller mDensityScale = getResources().getDisplayMetrics().density; 683c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); 699f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 709f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private int scrollPositionOfMostRecent() { 729f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return mLinearLayout.getWidth() - getWidth(); 739f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 749f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 759f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void update() { 769f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.removeAllViews(); 779f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller for (int i = 0; i < mAdapter.getCount(); i++) { 789f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller View view = mAdapter.getView(i, null, mLinearLayout); 799f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.setClickable(true); 809f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.setOnClickListener(this); 819f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.setOnTouchListener(this); 829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.addView(view); 839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // Scroll to end after layout. 859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller post(new Runnable() { 869f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void run() { 879f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastScrollPosition = scrollPositionOfMostRecent(); 889f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller scrollTo(mLastScrollPosition, 0); 899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 909f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 919f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 929f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 939f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 949f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onInterceptTouchEvent(MotionEvent ev) { 959f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (mVelocityTracker == null) { 969f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker = VelocityTracker.obtain(); 979f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker.addMovement(ev); 999f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller switch (ev.getAction()) { 1009f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_DOWN: 1019f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mDragging = false; 1029f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastY = ev.getY(); 1039f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1049f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1059f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_MOVE: 1069f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller float delta = ev.getY() - mLastY; 1073c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta); 1083c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller if (Math.abs(delta) > mPagingTouchSlop) { 1099f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mDragging = true; 1109f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1119f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1129f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1139f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_UP: 1149f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mDragging = false; 1159f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1169f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1179f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return mDragging ? true : super.onInterceptTouchEvent(ev); 1189f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1199f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1209f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private float getAlphaForOffset(View view, float thumbHeight) { 1213c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller final float fadeHeight = Constants.FADE_CONSTANT * thumbHeight; 1229f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller float result = 1.0f; 1239f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (view.getY() >= thumbHeight) { 1249f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller result = 1.0f - (view.getY() - thumbHeight) / fadeHeight; 1259f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } else if (view.getY() < 0.0f) { 1269f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller result = 1.0f + (thumbHeight + view.getY()) / fadeHeight; 1279f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1283c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result); 1299f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return result; 1309f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1319f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1329f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 1339f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onTouchEvent(MotionEvent ev) { 1349f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (!mDragging) { 1359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return super.onTouchEvent(ev); 1369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1379f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1389f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker.addMovement(ev); 1399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1409f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final View animView = mCurrentView; 1419f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // TODO: Cache thumbnail 1429f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final View thumb = animView.findViewById(R.id.app_thumbnail); 1439f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller switch (ev.getAction()) { 1449f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_MOVE: 1459f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (animView != null) { 1469f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float delta = ev.getY() - mLastY; 1479f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller animView.setY(animView.getY() + delta); 1489f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); 1499f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller invalidateGlobalRegion(animView); 1509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1519f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastY = ev.getY(); 1529f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 1539f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1549f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller case MotionEvent.ACTION_UP: 1559f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final ObjectAnimator anim; 1569f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (animView != null) { 1579f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final VelocityTracker velocityTracker = mVelocityTracker; 1589f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller velocityTracker.computeCurrentVelocity(1000, 10000); 1599f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float velocityX = velocityTracker.getXVelocity(); 1609f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float velocityY = velocityTracker.getYVelocity(); 1619f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float curY = animView.getY(); 1629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight(); 1633c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale; 1649f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (Math.abs(velocityY) > Math.abs(velocityX) 1653c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller && Math.abs(velocityY) > maxVelocity 1669f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller && (velocityY >= 0.0f) == (animView.getY() >= 0)) { 1673c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller long duration = 1689f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)); 1693c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION); 1709f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim = ObjectAnimator.ofFloat(animView, "y", curY, newY); 1719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setInterpolator(new LinearInterpolator()); 1729f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final int swipeDirection = animView.getY() >= 0.0f ? 1739f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT; 1749f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.addListener(new AnimatorListener() { 1759f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationStart(Animator animation) { 1769f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1779f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationRepeat(Animator animation) { 1789f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1799f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationEnd(Animator animation) { 1809f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.removeView(mCurrentView); 1819f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback.handleSwipe(animView, swipeDirection); 1829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationCancel(Animator animation) { 1849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.removeView(mCurrentView); 1859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback.handleSwipe(animView, swipeDirection); 1869f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1879f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 1889f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setDuration(duration); 1899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } else { // Animate back to position 1903c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller long duration = Math.abs(velocityY) > 0.0f ? 1919f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY)) 1923c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller : Constants.SNAP_BACK_DURATION; 1933c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller duration = Math.min(duration, Constants.SNAP_BACK_DURATION); 1949f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f); 1959f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setInterpolator(new DecelerateInterpolator(2.0f)); 1969f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.setDuration(duration); 1979f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1999f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.addUpdateListener(new AnimatorUpdateListener() { 2009f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onAnimationUpdate(ValueAnimator animation) { 2019f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight())); 2029f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller invalidateGlobalRegion(animView); 2039f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2049f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 2059f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller anim.start(); 2069f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2079f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2089f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker.recycle(); 2099f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mVelocityTracker = null; 2109f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller break; 2119f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2129f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return true; 2139f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2149f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2159f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller void invalidateGlobalRegion(View view) { 2169f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller RectF childBounds 2179f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); 2189f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller childBounds.offset(view.getX(), view.getY()); 2199f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (DEBUG_INVALIDATE) Log.v(TAG, "-------------"); 2209f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller while (view.getParent() != null && view.getParent() instanceof View) { 2219f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view = (View) view.getParent(); 2229f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.getMatrix().mapRect(childBounds); 2239f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller view.invalidate((int) Math.floor(childBounds.left), 2249f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (int) Math.floor(childBounds.top), 2259f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (int) Math.ceil(childBounds.right), 2269f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller (int) Math.ceil(childBounds.bottom)); 2279f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (DEBUG_INVALIDATE) { 2289f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left) 2299f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller + "," + (int) Math.floor(childBounds.top) 2309f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller + "," + (int) Math.ceil(childBounds.right) 2319f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller + "," + (int) Math.ceil(childBounds.bottom)); 2329f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2339f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2349f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2379f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onFinishInflate() { 2389f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onFinishInflate(); 2399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller LayoutInflater inflater = (LayoutInflater) 2409f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 2419f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2429f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller setScrollbarFadingEnabled(true); 2439f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2449f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout); 2459f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2469f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller final int leftPadding = mContext.getResources() 2479f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); 2489f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller setOverScrollEffectPadding(leftPadding, 0); 2499f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2513c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller @Override 2523c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller protected void onConfigurationChanged(Configuration newConfig) { 2533c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller super.onConfigurationChanged(newConfig); 2543c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller mDensityScale = getResources().getDisplayMetrics().density; 2553c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); 2563c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller } 2573c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller 2589f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private void setOverScrollEffectPadding(int leftPadding, int i) { 2593c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller // TODO Add to (Vertical)ScrollView 2609f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2619f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2639f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onSizeChanged(int w, int h, int oldw, int oldh) { 2649f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onSizeChanged(w, h, oldw, oldh); 2659f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // Keep track of the last visible item in the list so we can restore it 2669f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // to the bottom when the orientation changes. 2679f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastScrollPosition = scrollPositionOfMostRecent(); 2689f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2699f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // This has to happen post-layout, so run it "in the future" 2709f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller post(new Runnable() { 2719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void run() { 2729f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller scrollTo(0, mLastScrollPosition); 2739f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2749f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 2759f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2769f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2779f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2789f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onVisibilityChanged(View changedView, int visibility) { 2799f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onVisibilityChanged(changedView, visibility); 2809f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // scroll to bottom after reloading 2819f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller if (visibility == View.VISIBLE && changedView == this) { 2829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller post(new Runnable() { 2839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void run() { 2849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 2859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2869f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 2879f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2889f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2903b1fc47d004f6b29af8f40d181baa3460b1e3b15Michael Jurka public void setAdapter(ActivityDescriptionAdapter adapter) { 2919f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mAdapter = adapter; 2929f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mAdapter.registerDataSetObserver(new DataSetObserver() { 2939f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onChanged() { 2949f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 2959f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2969f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2979f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onInvalidated() { 2989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 2999f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3009f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 3019f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3029f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3039f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 3049f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void setLayoutTransition(LayoutTransition transition) { 3059f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // The layout transition applies to our embedded LinearLayout 3069f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.setLayoutTransition(transition); 3079f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3089f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3099f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onClick(View view) { 3109f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback.handleOnClick(view); 3119f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3129f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3139f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void setCallback(RecentsCallback callback) { 3149f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback = callback; 3159f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3169f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3179f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onTouch(View v, MotionEvent event) { 3189f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCurrentView = v; 3199f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return false; 3209f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3219f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller} 322