mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-30 05:02:26 -05:00
Scroll to the last known position in the MessageView when rotating the screen.
This commit is contained in:
parent
5ff6341a84
commit
763ff2752d
@ -38,6 +38,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
private static final String EXTRA_MESSAGE_REFERENCES = "com.fsck.k9.MessageView_messageReferences";
|
||||
private static final String EXTRA_ORIGINATING_INTENT = "com.fsck.k9.MessageView_originatingIntent";
|
||||
private static final String EXTRA_NEXT = "com.fsck.k9.MessageView_next";
|
||||
private static final String EXTRA_SCROLL_PERCENTAGE = "com.fsck.k9.MessageView_scrollPercentage";
|
||||
private static final String SHOW_PICTURES = "showPictures";
|
||||
private static final String STATE_PGP_DATA = "pgpData";
|
||||
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
|
||||
@ -96,6 +97,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
private Listener mListener = new Listener();
|
||||
private MessageViewHandler mHandler = new MessageViewHandler();
|
||||
private StorageManager.StorageListener mStorageListener = new StorageListenerImplementation();
|
||||
private MessagingListener mLoadCompleteListener = new ScrollToLastLocationListener();
|
||||
|
||||
/** this variable is used to save the calling AttachmentView
|
||||
* until the onActivityResult is called.
|
||||
@ -109,6 +111,11 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
*/
|
||||
private String mDstFolder;
|
||||
|
||||
/**
|
||||
* Used after restore/rotation to scroll our message to the last known location.
|
||||
*/
|
||||
private double mScrollPercentage;
|
||||
|
||||
private final class StorageListenerImplementation implements StorageManager.StorageListener {
|
||||
@Override
|
||||
public void onUnmount(String providerId) {
|
||||
@ -408,8 +415,14 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
mMessageView.initialize(this);
|
||||
|
||||
// Add listener for message load completion. We'll use this to scroll the page to user's last known
|
||||
// location.
|
||||
mController.addListener(mLoadCompleteListener);
|
||||
mMessageView.setListeners(mController.getListeners());
|
||||
|
||||
setTitle("");
|
||||
final Intent intent = getIntent();
|
||||
|
||||
@ -530,6 +543,9 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
outState.putParcelableArrayList(EXTRA_MESSAGE_REFERENCES, mMessageReferences);
|
||||
outState.putSerializable(STATE_PGP_DATA, mPgpData);
|
||||
outState.putBoolean(SHOW_PICTURES, mMessageView.showPictures());
|
||||
if(mTopView != null) {
|
||||
outState.putDouble(EXTRA_SCROLL_PERCENTAGE, mTopView.getScrollPercentage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -538,6 +554,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
|
||||
mMessageView.updateCryptoLayout(mAccount.getCryptoProvider(), mPgpData, mMessage);
|
||||
mMessageView.setLoadPictures(savedInstanceState.getBoolean(SHOW_PICTURES));
|
||||
mScrollPercentage = savedInstanceState.getDouble(EXTRA_SCROLL_PERCENTAGE);
|
||||
}
|
||||
|
||||
private void displayMessage(MessageReference ref) {
|
||||
@ -657,11 +674,13 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
onAccountUnavailable();
|
||||
return;
|
||||
}
|
||||
mController.addListener(mLoadCompleteListener);
|
||||
StorageManager.getInstance(getApplication()).addListener(mStorageListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
mController.removeListener(mLoadCompleteListener);
|
||||
StorageManager.getInstance(getApplication()).removeListener(mStorageListener);
|
||||
super.onPause();
|
||||
}
|
||||
@ -873,6 +892,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
|
||||
@Override
|
||||
protected void onNext() {
|
||||
// Reset scroll percentage when we change messages
|
||||
mScrollPercentage = 0;
|
||||
if (mNextMessage == null) {
|
||||
Toast.makeText(this, getString(R.string.end_of_folder), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
@ -888,6 +909,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
|
||||
@Override
|
||||
protected void onPrevious() {
|
||||
// Reset scroll percentage when we change messages
|
||||
mScrollPercentage = 0;
|
||||
if (mPreviousMessage == null) {
|
||||
Toast.makeText(this, getString(R.string.end_of_folder), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
@ -1115,8 +1138,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
mTopView.scrollTo(0, 0);
|
||||
try {
|
||||
if (MessageView.this.mMessage != null
|
||||
&& MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)
|
||||
&& message.isSet(Flag.X_DOWNLOADED_FULL)) {
|
||||
&& MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)
|
||||
&& message.isSet(Flag.X_DOWNLOADED_FULL)) {
|
||||
mMessageView.setHeaders(message, account);
|
||||
}
|
||||
MessageView.this.mMessage = message;
|
||||
@ -1277,4 +1300,17 @@ public class MessageView extends K9Activity implements OnClickListener {
|
||||
mMessageView.loadBodyFromText(mAccount.getCryptoProvider(), mPgpData, mMessage, mPgpData.getDecryptedData(), "text/plain");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(mTopView != null && mScrollPercentage != 0.0) {
|
||||
Log.d(K9.LOG_TAG, "MessageView has finished loading, scrolling to last known location.");
|
||||
mTopView.setScrollPercentage(mScrollPercentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +112,11 @@ public class MessagingListener {
|
||||
public void loadMessageForViewFailed(Account account, String folder, String uid, Throwable t) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a message for view has been fully displayed on the screen.
|
||||
*/
|
||||
public void messageViewFinished() {}
|
||||
|
||||
public void checkMailStarted(Context context, Account account) {
|
||||
}
|
||||
|
||||
|
@ -26,11 +26,15 @@ import android.webkit.WebView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.fsck.k9.activity.AccessibleEmailContentActivity;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class AccessibleWebView extends TextView {
|
||||
private Context mContext;
|
||||
private String mHtmlSource;
|
||||
private WebView mDummyWebView;
|
||||
private Set<MessagingListener> mListeners = null;
|
||||
|
||||
public AccessibleWebView(Context context) {
|
||||
super(context);
|
||||
@ -68,6 +72,13 @@ public class AccessibleWebView extends TextView {
|
||||
String historyUrl) {
|
||||
mHtmlSource = data;
|
||||
this.setText(Html.fromHtml(mHtmlSource, null, null));
|
||||
|
||||
// Let everyone know that loading has finished.
|
||||
if (mListeners != null) {
|
||||
for (MessagingListener l : mListeners) {
|
||||
l.messageViewFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean zoomIn() {
|
||||
@ -92,4 +103,8 @@ public class AccessibleWebView extends TextView {
|
||||
i.putExtra("content", mHtmlSource);
|
||||
mContext.startActivity(i);
|
||||
}
|
||||
|
||||
public void setListeners(final Set<MessagingListener> listeners) {
|
||||
this.mListeners = listeners;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.fsck.k9.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Picture;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
@ -10,10 +11,15 @@ import android.webkit.WebView;
|
||||
import android.widget.Toast;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
public class MessageWebView extends WebView {
|
||||
// Store a reference to the listeners in MessagingController. We can't fetch it directly since
|
||||
// we don't know the application name.
|
||||
private Set<MessagingListener> mListeners = null;
|
||||
|
||||
/**
|
||||
* We use WebSettings.getBlockNetworkLoads() to prevent the WebView that displays email
|
||||
@ -97,6 +103,18 @@ public class MessageWebView extends WebView {
|
||||
|
||||
// Disable network images by default. This is overridden by preferences.
|
||||
blockNetworkData(true);
|
||||
|
||||
// Listen for when the screen has finished drawing.
|
||||
setPictureListener(new PictureListener() {
|
||||
@Override
|
||||
public void onNewPicture(WebView webView, Picture picture) {
|
||||
if (mListeners != null) {
|
||||
for (MessagingListener l : mListeners) {
|
||||
l.messageViewFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
@ -115,4 +133,8 @@ public class MessageWebView extends WebView {
|
||||
Log.e(K9.LOG_TAG, "Exception in emulateShiftHeld()", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListeners(final Set<MessagingListener> listeners) {
|
||||
this.mListeners = listeners;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mail.store.LocalStore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
@ -116,11 +117,10 @@ public class SingleMessageView extends LinearLayout {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean showPictures() {
|
||||
return mShowPictures;
|
||||
}
|
||||
|
||||
public void setShowPictures(Boolean show) {
|
||||
mShowPictures = show;
|
||||
}
|
||||
@ -312,4 +312,21 @@ public class SingleMessageView extends LinearLayout {
|
||||
AttachmentView.AttachmentFileDownloadCallback attachmentCallback) {
|
||||
this.attachmentCallback = attachmentCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a copy of the {@link com.fsck.k9.controller.MessagingController#getListeners()}. This method will also
|
||||
* pass along these listeners to the underlying views.
|
||||
* @param listeners Set of listeners.
|
||||
*/
|
||||
public void setListeners(final Set<MessagingListener> listeners) {
|
||||
if(!mScreenReaderEnabled) {
|
||||
if(mMessageContentView != null) {
|
||||
mMessageContentView.setListeners(listeners);
|
||||
}
|
||||
} else {
|
||||
if(mAccessibleMessageContentView != null) {
|
||||
mAccessibleMessageContentView.setListeners(listeners);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,19 @@ package com.fsck.k9.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ScrollView;
|
||||
import com.fsck.k9.K9;
|
||||
|
||||
/**
|
||||
* An extension of {@link ScrollView} that allows scrolling to be selectively disabled.
|
||||
*/
|
||||
public class ToggleScrollView extends ScrollView {
|
||||
private GestureDetector mDetector;
|
||||
private boolean mScrolling = true;
|
||||
private int currentYPosition;
|
||||
|
||||
public ToggleScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@ -59,4 +65,44 @@ public class ToggleScrollView extends ScrollView {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
if(computeVerticalScrollRange() == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (double)currentYPosition / computeVerticalScrollRange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll the screen to a specific percentage of the page. This is based on the top edge of the page.
|
||||
* @param percentage Percentage of page to scroll to.
|
||||
*/
|
||||
public void setScrollPercentage(final double percentage) {
|
||||
final int newY = (int)(percentage * computeVerticalScrollRange());
|
||||
Log.d(K9.LOG_TAG, "ToggleScrollView: requested " + (100 * percentage) + "%, scrolling to " + newY + "/" + computeVerticalScrollRange());
|
||||
scrollTo(0, newY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
this.currentYPosition = y;
|
||||
// I wish Android has a TRACE log level so I wouldn't have to comment this out. This one is really noisy.
|
||||
// Log.d(K9.LOG_TAG, "ToggleScrollView: currentYPosition=" + y + " scrollRange=" + computeVerticalScrollRange() + " pct=" + getScrollPercentage());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user