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 199f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.animation.LayoutTransition; 209f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.content.Context; 213c728fe61dcf49354ea761a3e4ef6032ec271630Jim Millerimport android.content.res.Configuration; 229f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.database.DataSetObserver; 233cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurkaimport android.graphics.Canvas; 249f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.util.AttributeSet; 2599a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurkaimport android.util.DisplayMetrics; 2699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurkaimport android.util.FloatMath; 279f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.util.Log; 289f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.MotionEvent; 299f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.view.View; 3099a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurkaimport android.view.ViewConfiguration; 3199a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurkaimport android.view.ViewTreeObserver; 3299a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurkaimport android.view.ViewTreeObserver.OnGlobalLayoutListener; 339f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.widget.HorizontalScrollView; 349f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport android.widget.LinearLayout; 359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Millerimport com.android.systemui.R; 3707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkaimport com.android.systemui.SwipeHelper; 38ab48b681401628a191a4a90d4906fa88edde95baMichael Jurkaimport com.android.systemui.recent.RecentsPanelView.TaskDescriptionAdapter; 399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 40d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurkaimport java.util.HashSet; 41d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurkaimport java.util.Iterator; 4299a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka 4307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurkapublic class RecentsHorizontalScrollView extends HorizontalScrollView 444eaa983f253d0215d4de777edd8616318610ea22Michael Jurka implements SwipeHelper.Callback, RecentsPanelView.RecentsScrollView { 453c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller private static final String TAG = RecentsPanelView.TAG; 463c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller private static final boolean DEBUG = RecentsPanelView.DEBUG; 479f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private LinearLayout mLinearLayout; 48ab48b681401628a191a4a90d4906fa88edde95baMichael Jurka private TaskDescriptionAdapter mAdapter; 499f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private RecentsCallback mCallback; 509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected int mLastScrollPosition; 5107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka private SwipeHelper mSwipeHelper; 524a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka private FadedEdgeDrawHelper mFadedEdgeDrawHelper; 53d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurka private HashSet<View> mRecycledViews; 5499a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka private int mNumItemsInOneScreenful; 554a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka private Runnable mOnScrollListener; 563cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 579f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public RecentsHorizontalScrollView(Context context, AttributeSet attrs) { 589f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super(context, attrs, 0); 59eceda3d83814e20cabddc4f0755d475fa2f3d8ffDan Sandler mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, context); 604a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka mFadedEdgeDrawHelper = FadedEdgeDrawHelper.create(context, attrs, this, false); 61d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurka mRecycledViews = new HashSet<View>(); 629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 639f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 644eaa983f253d0215d4de777edd8616318610ea22Michael Jurka public void setMinSwipeAlpha(float minAlpha) { 655d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos mSwipeHelper.setMinSwipeProgress(minAlpha); 664eaa983f253d0215d4de777edd8616318610ea22Michael Jurka } 674eaa983f253d0215d4de777edd8616318610ea22Michael Jurka 689f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private int scrollPositionOfMostRecent() { 699f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller return mLinearLayout.getWidth() - getWidth(); 709f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 72261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka private void addToRecycledViews(View v) { 73261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka if (mRecycledViews.size() < mNumItemsInOneScreenful) { 74261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka mRecycledViews.add(v); 75261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka } 76261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka } 77261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka 78e5923631f06406f5f5e23a3a2ab4b24bb53a9094Michael Jurka public View findViewForTask(int persistentTaskId) { 79cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka for (int i = 0; i < mLinearLayout.getChildCount(); i++) { 80cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka View v = mLinearLayout.getChildAt(i); 81cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) v.getTag(); 82e5923631f06406f5f5e23a3a2ab4b24bb53a9094Michael Jurka if (holder.taskDescription.persistentTaskId == persistentTaskId) { 83cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka return v; 84cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka } 85cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka } 86cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka return null; 87cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka } 88cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka 89c0d2731047e2da4eff84a40615e29e08dcb708c5Jim Miller private void update() { 9099a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka for (int i = 0; i < mLinearLayout.getChildCount(); i++) { 9199a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka View v = mLinearLayout.getChildAt(i); 92261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka addToRecycledViews(v); 9399a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka mAdapter.recycleView(v); 9499a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka } 9599a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka LayoutTransition transitioner = getLayoutTransition(); 9699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka setLayoutTransition(null); 9799a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka 989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.removeAllViews(); 99d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurka Iterator<View> recycledViews = mRecycledViews.iterator(); 1009f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller for (int i = 0; i < mAdapter.getCount(); i++) { 10199a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka View old = null; 102d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurka if (recycledViews.hasNext()) { 103d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurka old = recycledViews.next(); 104d1a040c3e1dc30b26f4dfee8c9de2c802ac134b8Michael Jurka recycledViews.remove(); 10599a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka old.setVisibility(VISIBLE); 10699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka } 10799a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka 10899a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka final View view = mAdapter.getView(i, old, mLinearLayout); 10907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 1104a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka if (mFadedEdgeDrawHelper != null) { 1114a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka mFadedEdgeDrawHelper.addViewCallback(view); 1123cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 1133cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 1147daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka OnTouchListener noOpListener = new OnTouchListener() { 1157daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka @Override 1167daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka public boolean onTouch(View v, MotionEvent event) { 1177daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka return true; 1187daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka } 1197daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka }; 1207daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka 1217725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka view.setOnClickListener(new OnClickListener() { 12207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void onClick(View v) { 1237725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka mCallback.dismiss(); 12407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 12507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka }); 1260e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka // We don't want a click sound when we dimiss recents 1270e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka view.setSoundEffectsEnabled(false); 1287725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka 1297725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka OnClickListener launchAppListener = new OnClickListener() { 1307725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka public void onClick(View v) { 1317725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka mCallback.handleOnClick(view); 1327725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka } 1337725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka }; 1347daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka 13599a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) view.getTag(); 13699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka final View thumbnailView = holder.thumbnailView; 1370e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka OnLongClickListener longClickListener = new OnLongClickListener() { 1380e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka public boolean onLongClick(View v) { 1390e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka final View anchorView = view.findViewById(R.id.app_description); 1400e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka mCallback.handleLongPress(view, anchorView, thumbnailView); 1410e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka return true; 1420e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka } 1430e8063a3b447e1aa5cc3171db42f735b3b6ae78eMichael Jurka }; 1447daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka thumbnailView.setClickable(true); 1457daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka thumbnailView.setOnClickListener(launchAppListener); 1467daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka thumbnailView.setOnLongClickListener(longClickListener); 1477daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka 1487daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka // We don't want to dismiss recents if a user clicks on the app title 1497daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka // (we also don't want to launch the app either, though, because the 1507daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka // app title is a small target and doesn't have great click feedback) 1517725a4e3071c6450deb89dcb1e234ed96142edc9Michael Jurka final View appTitle = view.findViewById(R.id.app_label); 1527daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka appTitle.setContentDescription(" "); 1537daf95d5526e3b60f5db29cbacd9a4852d99a6f4Michael Jurka appTitle.setOnTouchListener(noOpListener); 1549f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.addView(view); 1559f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 15699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka setLayoutTransition(transitioner); 15799a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka 158841594b2dbb4445ea84d9c9d617d5db3a28bb04bMichael Jurka // Scroll to end after initial layout. 15999a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka 16099a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka final OnGlobalLayoutListener updateScroll = new OnGlobalLayoutListener() { 16199a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka public void onGlobalLayout() { 16299a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka mLastScrollPosition = scrollPositionOfMostRecent(); 16399a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka scrollTo(mLastScrollPosition, 0); 164841594b2dbb4445ea84d9c9d617d5db3a28bb04bMichael Jurka final ViewTreeObserver observer = getViewTreeObserver(); 16599a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka if (observer.isAlive()) { 16699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka observer.removeOnGlobalLayoutListener(this); 16799a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka } 16899a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka } 16999a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka }; 170841594b2dbb4445ea84d9c9d617d5db3a28bb04bMichael Jurka getViewTreeObserver().addOnGlobalLayoutListener(updateScroll); 1719f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1729f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1739f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 174c0d2731047e2da4eff84a40615e29e08dcb708c5Jim Miller public void removeViewInLayout(final View view) { 17507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka dismissChild(view); 176c0d2731047e2da4eff84a40615e29e08dcb708c5Jim Miller } 177c0d2731047e2da4eff84a40615e29e08dcb708c5Jim Miller 1789f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onInterceptTouchEvent(MotionEvent ev) { 179c0d2731047e2da4eff84a40615e29e08dcb708c5Jim Miller if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); 18007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return mSwipeHelper.onInterceptTouchEvent(ev) || 18107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka super.onInterceptTouchEvent(ev); 1829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 1839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 1849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 1859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public boolean onTouchEvent(MotionEvent ev) { 18607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return mSwipeHelper.onTouchEvent(ev) || 18707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka super.onTouchEvent(ev); 18807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 1899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 19007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public boolean canChildBeDismissed(View v) { 19107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return true; 19207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 1939f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 19419c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek @Override 19519c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek public boolean isAntiFalsingNeeded() { 19619c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek return false; 19719c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek } 19819c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek 19934cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek @Override 20034cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek public float getFalsingThresholdFactor() { 20134cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek return 1.0f; 20234cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek } 20334cf5c4bfc7c4918b8155c47eb905782902016d6Selim Cinek 20407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void dismissChild(View v) { 20507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mSwipeHelper.dismissChild(v, 0); 20607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 2079f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 20807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void onChildDismissed(View v) { 209261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka addToRecycledViews(v); 21007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mLinearLayout.removeView(v); 21107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mCallback.handleSwipe(v); 2122db72fce6cfc0081583b9726ad80a7d95e064891Michael Jurka // Restore the alpha/translation parameters to what they were before swiping 2132db72fce6cfc0081583b9726ad80a7d95e064891Michael Jurka // (for when these items are recycled) 2142db72fce6cfc0081583b9726ad80a7d95e064891Michael Jurka View contentView = getChildContentView(v); 2152db72fce6cfc0081583b9726ad80a7d95e064891Michael Jurka contentView.setAlpha(1f); 2162db72fce6cfc0081583b9726ad80a7d95e064891Michael Jurka contentView.setTranslationY(0); 2179f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2189f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 21907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public void onBeginDrag(View v) { 22013451a476a1951a19d3cb531c47bf5a51587800aMichael Jurka // We do this so the underlying ScrollView knows that it won't get 22113451a476a1951a19d3cb531c47bf5a51587800aMichael Jurka // the chance to intercept events anymore 22213451a476a1951a19d3cb531c47bf5a51587800aMichael Jurka requestDisallowInterceptTouchEvent(true); 223622a97646d316ca753c577752ac9010415e9a472Peter Ng } 224622a97646d316ca753c577752ac9010415e9a472Peter Ng 225622a97646d316ca753c577752ac9010415e9a472Peter Ng public void onDragCancelled(View v) { 226c0d2731047e2da4eff84a40615e29e08dcb708c5Jim Miller } 227c0d2731047e2da4eff84a40615e29e08dcb708c5Jim Miller 228eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek @Override 229eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek public void onChildSnappedBack(View animView) { 230eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek } 231eb973565f3efc6417ca35363e4d6c642947775d8Selim Cinek 2325d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos @Override 2335d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) { 2345d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos return false; 2355d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos } 2365d9cc668e16abf1306d82218cd3da29e28a454aeAdrian Roos 23707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public View getChildAtPosition(MotionEvent ev) { 23807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka final float x = ev.getX() + getScrollX(); 23907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka final float y = ev.getY() + getScrollY(); 24007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka for (int i = 0; i < mLinearLayout.getChildCount(); i++) { 24107d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka View item = mLinearLayout.getChildAt(i); 24207d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka if (x >= item.getLeft() && x < item.getRight() 24307d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka && y >= item.getTop() && y < item.getBottom()) { 24407d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return item; 2459f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2469f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 24707d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka return null; 24807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka } 24907d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka 25007d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka public View getChildContentView(View v) { 2513cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return v.findViewById(R.id.recent_item); 2523cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 2533cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 2543cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka @Override 2554a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka public void drawFadedEdges(Canvas canvas, int left, int right, int top, int bottom) { 2564a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka if (mFadedEdgeDrawHelper != null) { 2573cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 2584a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka mFadedEdgeDrawHelper.drawCallback(canvas, 25901534780dfaf81c9f89a6e19fe2fe42cfdd01ff7John Spurlock left, right, top, bottom, getScrollX(), getScrollY(), 2603cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 0, 0, 26101534780dfaf81c9f89a6e19fe2fe42cfdd01ff7John Spurlock getLeftFadingEdgeStrength(), getRightFadingEdgeStrength(), getPaddingTop()); 2623cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 2633cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 2643cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 2653cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka @Override 2664a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka protected void onScrollChanged(int l, int t, int oldl, int oldt) { 2674a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka super.onScrollChanged(l, t, oldl, oldt); 2684a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka if (mOnScrollListener != null) { 2694a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka mOnScrollListener.run(); 2704a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka } 2714a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka } 2724a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka 2734a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka public void setOnScrollListener(Runnable listener) { 2744a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka mOnScrollListener = listener; 2754a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka } 2764a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka 2774a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka @Override 2783cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public int getVerticalFadingEdgeLength() { 2794a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka if (mFadedEdgeDrawHelper != null) { 2804a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka return mFadedEdgeDrawHelper.getVerticalFadingEdgeLength(); 2813cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } else { 2823cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return super.getVerticalFadingEdgeLength(); 2833cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 2843cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 2853cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 2863cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka @Override 2873cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public int getHorizontalFadingEdgeLength() { 2884a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka if (mFadedEdgeDrawHelper != null) { 2894a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka return mFadedEdgeDrawHelper.getHorizontalFadingEdgeLength(); 2903cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } else { 2913cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka return super.getHorizontalFadingEdgeLength(); 2923cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 2939f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 2949f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 2959f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 2969f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onFinishInflate() { 2979f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onFinishInflate(); 2989f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller setScrollbarFadingEnabled(true); 2999f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout = (LinearLayout) findViewById(R.id.recents_linear_layout); 30001534780dfaf81c9f89a6e19fe2fe42cfdd01ff7John Spurlock final int leftPadding = getContext().getResources() 3019f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin); 3029f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller setOverScrollEffectPadding(leftPadding, 0); 3039f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3049f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3053c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller @Override 3063cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka public void onAttachedToWindow() { 3074a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka if (mFadedEdgeDrawHelper != null) { 3084a6bc55cd5b2e1fdd04347813842d5bce64ee3feMichael Jurka mFadedEdgeDrawHelper.onAttachedToWindowCallback(mLinearLayout, isHardwareAccelerated()); 3093cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 3103cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka } 3113cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka 3123cd0a593937c0724d77db1e2e3995255cfae61acMichael Jurka @Override 3133c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller protected void onConfigurationChanged(Configuration newConfig) { 3143c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller super.onConfigurationChanged(newConfig); 31507d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka float densityScale = getResources().getDisplayMetrics().density; 31607d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mSwipeHelper.setDensityScale(densityScale); 31701534780dfaf81c9f89a6e19fe2fe42cfdd01ff7John Spurlock float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); 31807d4046ea914c999b7aaa587b7bfe81d548121f7Michael Jurka mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); 3193c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller } 3203c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller 3219f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller private void setOverScrollEffectPadding(int leftPadding, int i) { 3223c728fe61dcf49354ea761a3e4ef6032ec271630Jim Miller // TODO Add to (Vertical)ScrollView 3239f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3249f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3259f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 3269f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller protected void onSizeChanged(int w, int h, int oldw, int oldh) { 3279f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller super.onSizeChanged(w, h, oldw, oldh); 32881abe87dcc829c4c01473126c8664aa03385dc7cChet Haase 32981abe87dcc829c4c01473126c8664aa03385dc7cChet Haase // Skip this work if a transition is running; it sets the scroll values independently 33081abe87dcc829c4c01473126c8664aa03385dc7cChet Haase // and should not have those animated values clobbered by this logic 33181abe87dcc829c4c01473126c8664aa03385dc7cChet Haase LayoutTransition transition = mLinearLayout.getLayoutTransition(); 33281abe87dcc829c4c01473126c8664aa03385dc7cChet Haase if (transition != null && transition.isRunning()) { 33381abe87dcc829c4c01473126c8664aa03385dc7cChet Haase return; 33481abe87dcc829c4c01473126c8664aa03385dc7cChet Haase } 3359f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // Keep track of the last visible item in the list so we can restore it 3369f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // to the bottom when the orientation changes. 3379f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLastScrollPosition = scrollPositionOfMostRecent(); 3389f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3399f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // This has to happen post-layout, so run it "in the future" 3409f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller post(new Runnable() { 3419f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void run() { 34281abe87dcc829c4c01473126c8664aa03385dc7cChet Haase // Make sure we're still not clobbering the transition-set values, since this 34381abe87dcc829c4c01473126c8664aa03385dc7cChet Haase // runnable launches asynchronously 34481abe87dcc829c4c01473126c8664aa03385dc7cChet Haase LayoutTransition transition = mLinearLayout.getLayoutTransition(); 34581abe87dcc829c4c01473126c8664aa03385dc7cChet Haase if (transition == null || !transition.isRunning()) { 34681abe87dcc829c4c01473126c8664aa03385dc7cChet Haase scrollTo(mLastScrollPosition, 0); 34781abe87dcc829c4c01473126c8664aa03385dc7cChet Haase } 3489f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3499f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 3509f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3519f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 352ab48b681401628a191a4a90d4906fa88edde95baMichael Jurka public void setAdapter(TaskDescriptionAdapter adapter) { 3539f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mAdapter = adapter; 3549f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mAdapter.registerDataSetObserver(new DataSetObserver() { 3559f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onChanged() { 3569f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 3579f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3589f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3599f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void onInvalidated() { 3609f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller update(); 3619f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3629f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller }); 36399a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka DisplayMetrics dm = getResources().getDisplayMetrics(); 36499a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka int childWidthMeasureSpec = 36599a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.AT_MOST); 36699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka int childheightMeasureSpec = 36799a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.AT_MOST); 36899a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka View child = mAdapter.createView(mLinearLayout); 36999a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka child.measure(childWidthMeasureSpec, childheightMeasureSpec); 37099a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka mNumItemsInOneScreenful = 37199a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka (int) FloatMath.ceil(dm.widthPixels / (float) child.getMeasuredWidth()); 372261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka addToRecycledViews(child); 37399a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka 37499a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka for (int i = 0; i < mNumItemsInOneScreenful - 1; i++) { 375261277e1783ccebe5cb40763f8ef20d988dfe4caMichael Jurka addToRecycledViews(mAdapter.createView(mLinearLayout)); 37699a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka } 37799a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka } 37899a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka 37999a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka public int numItemsInOneScreenful() { 38099a9655b9333c3bff6e462b12baa56a5fcd4cb20Michael Jurka return mNumItemsInOneScreenful; 3819f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3829f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3839f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller @Override 3849f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void setLayoutTransition(LayoutTransition transition) { 3859f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller // The layout transition applies to our embedded LinearLayout 3869f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mLinearLayout.setLayoutTransition(transition); 3879f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3889f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller 3899f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller public void setCallback(RecentsCallback callback) { 3909f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller mCallback = callback; 3919f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller } 3929f0f0e0e3100caec459a5b5ef836317844c83b3fJim Miller} 393