1 /* 2 * Copyright (C) 2012 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.deskclock.widget.swipeablelistview; 19 20 import android.content.Context; 21 import android.content.res.Configuration; 22 import android.graphics.Rect; 23 import android.util.AttributeSet; 24 import android.view.MotionEvent; 25 import android.view.View; 26 import android.view.ViewConfiguration; 27 import android.widget.ListView; 28 29 import com.android.deskclock.widget.swipeablelistview.SwipeHelper.Callback; 30 31 /** 32 * Copy of packages/apps/UnifiedEmail - com.android.mail.ui.Swipeable with changes. 33 */ 34 public class SwipeableListView extends ListView implements Callback { 35 private SwipeHelper mSwipeHelper; 36 private boolean mEnableSwipe = false; 37 38 public static final String LOG_TAG = LogTag.getLogTag(); 39 40 private OnItemSwipeListener mOnItemSwipeListener; 41 42 public SwipeableListView(Context context) { 43 this(context, null); 44 } 45 46 public SwipeableListView(Context context, AttributeSet attrs) { 47 this(context, attrs, -1); 48 } 49 50 public SwipeableListView(Context context, AttributeSet attrs, int defStyle) { 51 super(context, attrs, defStyle); 52 float densityScale = getResources().getDisplayMetrics().density; 53 float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop(); 54 mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale, 55 pagingTouchSlop); 56 setItemsCanFocus(true); 57 } 58 59 @Override 60 protected void onConfigurationChanged(Configuration newConfig) { 61 super.onConfigurationChanged(newConfig); 62 float densityScale = getResources().getDisplayMetrics().density; 63 mSwipeHelper.setDensityScale(densityScale); 64 float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); 65 mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); 66 } 67 68 @Override 69 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 70 LogUtils.d(Utils.VIEW_DEBUGGING_TAG, 71 "START CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s", 72 isLayoutRequested(), getRootView().isLayoutRequested()); 73 super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 74 LogUtils.d(Utils.VIEW_DEBUGGING_TAG, new Error(), 75 "FINISH CLF-ListView.onFocusChanged layoutRequested=%s root.layoutRequested=%s", 76 isLayoutRequested(), getRootView().isLayoutRequested()); 77 } 78 79 @Override 80 public void requestLayout() { 81 Utils.checkRequestLayout(this); 82 super.requestLayout(); 83 } 84 85 /** 86 * Enable swipe gestures. 87 */ 88 public void enableSwipe(boolean enable) { 89 mEnableSwipe = enable; 90 } 91 92 public boolean isSwipeEnabled() { 93 return mEnableSwipe; 94 } 95 96 public void setOnItemSwipeListener(OnItemSwipeListener listener) { 97 mOnItemSwipeListener = listener; 98 } 99 100 @Override 101 public boolean onInterceptTouchEvent(MotionEvent ev) { 102 if (mEnableSwipe) { 103 return mSwipeHelper.onInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev); 104 } else { 105 return super.onInterceptTouchEvent(ev); 106 } 107 } 108 109 @Override 110 public boolean onTouchEvent(MotionEvent ev) { 111 if (mEnableSwipe) { 112 return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev); 113 } else { 114 return super.onTouchEvent(ev); 115 } 116 } 117 118 @Override 119 public View getChildAtPosition(MotionEvent ev) { 120 // find the view under the pointer, accounting for GONE views 121 final int count = getChildCount(); 122 int touchY = (int) ev.getY(); 123 int childIdx = 0; 124 View slidingChild; 125 for (; childIdx < count; childIdx++) { 126 slidingChild = getChildAt(childIdx); 127 if (slidingChild.getVisibility() == GONE) { 128 continue; 129 } 130 if (touchY >= slidingChild.getTop() && touchY <= slidingChild.getBottom()) { 131 return slidingChild; 132 } 133 } 134 return null; 135 } 136 137 @Override 138 public View getChildContentView(View view) { 139 return view; 140 } 141 142 @Override 143 public void onScroll() { 144 } 145 146 @Override 147 public boolean canChildBeDismissed(View v) { 148 return true; 149 } 150 151 @Override 152 public void onChildDismissed(final View v) { 153 if (v != null) { 154 if (mOnItemSwipeListener != null) { 155 mOnItemSwipeListener.onSwipe(v); 156 } 157 } 158 } 159 160 @Override 161 public void onDragCancelled(View v) { 162 } 163 164 private void redraw(View v) { 165 int start = getFirstVisiblePosition(); 166 for (int i=start, j = getLastVisiblePosition(); i <= j; i++) { 167 if (v == getItemAtPosition(i)) { 168 View view = getChildAt(i-start); 169 getAdapter().getView(i, view, this); 170 } 171 } 172 } 173 174 @Override 175 public void onBeginDrag(View v) { 176 // We do this so the underlying ScrollView knows that it won't get 177 // the chance to intercept events anymore 178 requestDisallowInterceptTouchEvent(true); 179 } 180 181 public interface OnItemSwipeListener { 182 public void onSwipe(View view); 183 } 184 } 185