2010-12-12 19:17:54 -05:00
|
|
|
package com.fsck.k9.view;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.util.AttributeSet;
|
2011-11-02 19:39:23 -04:00
|
|
|
import android.util.Log;
|
2011-01-19 12:05:56 -05:00
|
|
|
import android.view.GestureDetector;
|
2010-07-13 17:49:28 -04:00
|
|
|
import android.view.MotionEvent;
|
|
|
|
import android.widget.ScrollView;
|
2011-11-02 19:39:23 -04:00
|
|
|
import com.fsck.k9.K9;
|
2011-11-03 12:14:42 -04:00
|
|
|
import com.fsck.k9.controller.MessagingListener;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-11-02 19:39:23 -04:00
|
|
|
/**
|
|
|
|
* An extension of {@link ScrollView} that allows scrolling to be selectively disabled.
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public class ToggleScrollView extends ScrollView {
|
2011-01-19 12:05:56 -05:00
|
|
|
private GestureDetector mDetector;
|
2010-07-13 17:49:28 -04:00
|
|
|
private boolean mScrolling = true;
|
2011-11-03 12:14:42 -04:00
|
|
|
private int mCurrentYPosition;
|
|
|
|
private double mScrollPercentage;
|
|
|
|
private ScrollToLastLocationListener mListener;
|
2010-07-13 17:49:28 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public ToggleScrollView(Context context, AttributeSet attrs) {
|
2010-07-13 17:49:28 -04:00
|
|
|
super(context, attrs);
|
2011-01-19 12:05:56 -05:00
|
|
|
mDetector = new GestureDetector(new YScrollDetector());
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void setScrolling(boolean enable) {
|
2010-07-13 17:49:28 -04:00
|
|
|
mScrolling = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean onTouchEvent(MotionEvent ev) {
|
2010-07-13 17:49:28 -04:00
|
|
|
return (mScrolling) ? super.onTouchEvent(ev) : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
|
|
|
if (!mScrolling) {
|
2011-01-19 12:05:56 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This doesn't quite get us to diagonal scrolling, but it's somewhat better than what we've
|
|
|
|
// currently got. This is based on
|
|
|
|
// http://stackoverflow.com/questions/2646028/android-horizontalscrollview-within-scrollview-touch-handling
|
|
|
|
boolean result = super.onInterceptTouchEvent(ev);
|
2011-01-30 17:05:47 -05:00
|
|
|
// Let the original ScrollView handle ACTION_DOWN so we can stop the scroll when someone touches the screen.
|
2011-02-06 17:09:48 -05:00
|
|
|
if (ev.getAction() == MotionEvent.ACTION_DOWN || mDetector.onTouchEvent(ev)) {
|
2011-01-19 12:05:56 -05:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-30 17:05:47 -05:00
|
|
|
// Return false if we're scrolling in the x direction. That is, decline to consume the event and
|
|
|
|
// let the parent class take a stab at it.
|
2011-02-06 17:09:48 -05:00
|
|
|
class YScrollDetector extends GestureDetector.SimpleOnGestureListener {
|
2011-01-19 12:05:56 -05:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
|
|
|
try {
|
|
|
|
if (Math.abs(distanceY) > Math.abs(distanceX)) {
|
2011-01-19 12:05:56 -05:00
|
|
|
return true;
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2011-01-19 12:05:56 -05:00
|
|
|
return false;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2011-01-19 12:05:56 -05:00
|
|
|
// nothing
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|
2011-11-02 19:39:23 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch the current percentage by which this view has been scrolled.
|
|
|
|
* @return Scroll percentage based on the top edge of the screen, from 0 to 100. This number should never really
|
|
|
|
* be 100, unless the screen is of 0 height...
|
|
|
|
*/
|
|
|
|
public double getScrollPercentage() {
|
2011-11-03 12:14:42 -04:00
|
|
|
// We save only the Y coordinate instead of the percentage because I don't know how expensive the
|
|
|
|
// computeVerticalScrollRange() call is.
|
|
|
|
final int scrollRange = computeVerticalScrollRange();
|
|
|
|
if(scrollRange == 0) {
|
2011-11-02 19:39:23 -04:00
|
|
|
return 0;
|
|
|
|
}
|
2011-11-03 12:14:42 -04:00
|
|
|
return (double) mCurrentYPosition / scrollRange;
|
2011-11-02 19:39:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-11-03 12:14:42 -04:00
|
|
|
* Set the percentage by which we should scroll the page once we get the load complete event. This is
|
|
|
|
* based on the top edge of the view.
|
2011-11-02 19:39:23 -04:00
|
|
|
* @param percentage Percentage of page to scroll to.
|
|
|
|
*/
|
|
|
|
public void setScrollPercentage(final double percentage) {
|
2011-11-03 12:14:42 -04:00
|
|
|
Log.d(K9.LOG_TAG, "ToggleView: Setting last scroll percentage to " + percentage);
|
|
|
|
this.mScrollPercentage = percentage;
|
2011-11-02 19:39:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Override {@link ScrollView#onScrollChanged(int, int, int, int)} to record the current x/y position. We use this
|
|
|
|
* to save our current position for future scrolling.
|
|
|
|
*
|
|
|
|
* @param x
|
|
|
|
* @param y
|
|
|
|
* @param oldx
|
|
|
|
* @param oldy
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
|
|
|
|
super.onScrollChanged(x, y, oldx, oldy);
|
|
|
|
|
2011-11-03 12:14:42 -04:00
|
|
|
this.mCurrentYPosition = y;
|
2011-11-02 19:39:23 -04:00
|
|
|
// I wish Android has a TRACE log level so I wouldn't have to comment this out. This one is really noisy.
|
2011-11-03 12:14:42 -04:00
|
|
|
// Log.d(K9.LOG_TAG, "ToggleScrollView: mCurrentYPosition=" + y + " scrollRange=" + computeVerticalScrollRange() + " pct=" + getScrollPercentage());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is a {@link MessagingListener} which listens for when the a message has finished being displayed on the
|
|
|
|
* screen. We'll scroll the message to the user's last known location once it's done.
|
|
|
|
*/
|
|
|
|
class ScrollToLastLocationListener extends MessagingListener {
|
|
|
|
public void messageViewFinished() {
|
|
|
|
// Don't scroll if our last position was at the top.
|
|
|
|
if(mScrollPercentage != 0.0) {
|
|
|
|
final int scrollRange = computeVerticalScrollRange();
|
|
|
|
final int newY = (int)(mScrollPercentage * scrollRange);
|
|
|
|
Log.d(K9.LOG_TAG, "ToggleScrollView: requested " + (100 * mScrollPercentage) + "%, " +
|
|
|
|
"scrolling to " + newY + "/" + scrollRange);
|
|
|
|
scrollTo(0, newY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch the {@link MessagingListener} for this <code>ScrollView</code>.
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public MessagingListener getListener() {
|
|
|
|
if(this.mListener != null) {
|
|
|
|
return this.mListener;
|
|
|
|
} else {
|
|
|
|
return this.mListener = new ScrollToLastLocationListener();
|
|
|
|
}
|
2011-11-02 19:39:23 -04:00
|
|
|
}
|
2010-07-13 17:49:28 -04:00
|
|
|
}
|