15c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng/* 25c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * Copyright (C) 2012 Google Inc. 35c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * Licensed to The Android Open Source Project. 45c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * 55c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 65c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * you may not use this file except in compliance with the License. 75c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * You may obtain a copy of the License at 85c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * 95c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 105c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * 115c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * Unless required by applicable law or agreed to in writing, software 125c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 135c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * See the License for the specific language governing permissions and 155c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * limitations under the License. 165c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng */ 175c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 185c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengpackage com.android.deskclock.widget.swipeablelistview; 195c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 205c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.content.Context; 215c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.content.res.Configuration; 225c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.graphics.Rect; 235c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.util.AttributeSet; 245c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.view.MotionEvent; 255c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.view.View; 265c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.view.ViewConfiguration; 275c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.widget.ListView; 285c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 295c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport com.android.deskclock.widget.swipeablelistview.SwipeHelper.Callback; 305c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 315c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng/** 325c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * Copy of packages/apps/UnifiedEmail - com.android.mail.ui.Swipeable with changes. 335c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng */ 345c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengpublic class SwipeableListView extends ListView implements Callback { 355c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng private SwipeHelper mSwipeHelper; 365c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng private boolean mEnableSwipe = false; 375c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 385c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public static final String LOG_TAG = LogTag.getLogTag(); 395c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 405c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng private OnItemSwipeListener mOnItemSwipeListener; 415c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 425c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public SwipeableListView(Context context) { 435c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng this(context, null); 445c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 455c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 465c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public SwipeableListView(Context context, AttributeSet attrs) { 475c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng this(context, attrs, -1); 485c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 495c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 505c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public SwipeableListView(Context context, AttributeSet attrs, int defStyle) { 515c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng super(context, attrs, defStyle); 525c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng float densityScale = getResources().getDisplayMetrics().density; 535c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop(); 545c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale, 555c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng pagingTouchSlop); 565c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng setItemsCanFocus(true); 575c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 585c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 595c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 605c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng protected void onConfigurationChanged(Configuration newConfig) { 615c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng super.onConfigurationChanged(newConfig); 625c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng float densityScale = getResources().getDisplayMetrics().density; 635c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng mSwipeHelper.setDensityScale(densityScale); 645c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); 655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); 665c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 675c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 685c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 695c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng LogUtils.d(Utils.VIEW_DEBUGGING_TAG, 715c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng "START CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s", 725c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng isLayoutRequested(), getRootView().isLayoutRequested()); 735c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 745c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng LogUtils.d(Utils.VIEW_DEBUGGING_TAG, new Error(), 755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng "FINISH CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s", 765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng isLayoutRequested(), getRootView().isLayoutRequested()); 775c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 785c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 795c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 805c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void requestLayout() { 815c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng Utils.checkRequestLayout(this); 825c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng super.requestLayout(); 835c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 845c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 855c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng /** 865c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * Enable swipe gestures. 875c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng */ 885c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void enableSwipe(boolean enable) { 895c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng mEnableSwipe = enable; 905c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 915c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 925c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public boolean isSwipeEnabled() { 935c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return mEnableSwipe; 945c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 955c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 965c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void setOnItemSwipeListener(OnItemSwipeListener listener) { 975c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng mOnItemSwipeListener = listener; 985c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 995c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1005c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1015c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public boolean onInterceptTouchEvent(MotionEvent ev) { 1025c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (mEnableSwipe) { 1035c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev); 1045c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } else { 1055c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return super.onInterceptTouchEvent(ev); 1065c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1075c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1085c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1095c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1105c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public boolean onTouchEvent(MotionEvent ev) { 1115c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (mEnableSwipe) { 1125c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev); 1135c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } else { 1145c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return super.onTouchEvent(ev); 1155c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1165c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1175c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1185c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1195c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public View getChildAtPosition(MotionEvent ev) { 1205c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng // find the view under the pointer, accounting for GONE views 1215c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng final int count = getChildCount(); 1225c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng int touchY = (int) ev.getY(); 1235c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng int childIdx = 0; 1245c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng View slidingChild; 1255c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng for (; childIdx < count; childIdx++) { 1265c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng slidingChild = getChildAt(childIdx); 1275c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (slidingChild.getVisibility() == GONE) { 1285c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng continue; 1295c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1305c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (touchY >= slidingChild.getTop() && touchY <= slidingChild.getBottom()) { 1315c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return slidingChild; 1325c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1335c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1345c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return null; 1355c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1365c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1375c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1385c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public View getChildContentView(View view) { 1395c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return view; 1405c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1415c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1425c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1435c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void onScroll() { 1445c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1455c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1465c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1475c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public boolean canChildBeDismissed(View v) { 1485c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return true; 1495c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1505c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1515c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1525c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void onChildDismissed(final View v) { 1535c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (v != null) { 1545c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (mOnItemSwipeListener != null) { 1555c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng mOnItemSwipeListener.onSwipe(v); 1565c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1575c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1585c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1595c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1605c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1615c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void onDragCancelled(View v) { 1625c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1635c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1645c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng private void redraw(View v) { 1655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng int start = getFirstVisiblePosition(); 1665c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng for (int i=start, j = getLastVisiblePosition(); i <= j; i++) { 1675c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (v == getItemAtPosition(i)) { 1685c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng View view = getChildAt(i-start); 1695c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng getAdapter().getView(i, view, this); 1705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1715c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1725c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1735c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1745c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng @Override 1755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void onBeginDrag(View v) { 1765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng // We do this so the underlying ScrollView knows that it won't get 1775c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng // the chance to intercept events anymore 1785c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng requestDisallowInterceptTouchEvent(true); 1795c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1805c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1815c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public interface OnItemSwipeListener { 1825c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public void onSwipe(View view); 1835c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1845c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng} 185