Merge "Try adjustments to the archive animation per danship." into jb-ub-mail
diff --git a/res/layout/cc_bcc_view.xml b/res/layout/cc_bcc_view.xml
index 5681cb1..acc957b 100644
--- a/res/layout/cc_bcc_view.xml
+++ b/res/layout/cc_bcc_view.xml
@@ -38,7 +38,8 @@
<com.android.ex.chips.RecipientEditTextView
android:id="@+id/cc"
- style="@style/RecipientEditTextViewStyle"/>
+ style="@style/RecipientEditTextViewStyle"
+ android:contentDescription="@string/cc"/>
</LinearLayout>
<View style="@style/RecipientComposeFieldSpacer"/>
@@ -62,7 +63,8 @@
<com.android.ex.chips.RecipientEditTextView
android:id="@+id/bcc"
- style="@style/RecipientEditTextViewStyle"/>
+ style="@style/RecipientEditTextViewStyle"
+ android:contentDescription="@string/bcc"/>
</LinearLayout>
diff --git a/res/layout/compose_recipients.xml b/res/layout/compose_recipients.xml
index 0873b18..4211a0b 100644
--- a/res/layout/compose_recipients.xml
+++ b/res/layout/compose_recipients.xml
@@ -37,7 +37,8 @@
<com.android.ex.chips.RecipientEditTextView
android:id="@+id/to"
- style="@style/RecipientEditTextViewStyle"/>
+ style="@style/RecipientEditTextViewStyle"
+ android:contentDescription="@string/to"/>
</LinearLayout>
diff --git a/res/layout/conversation_view.xml b/res/layout/conversation_view.xml
index 208a42e..438e2b8 100644
--- a/res/layout/conversation_view.xml
+++ b/res/layout/conversation_view.xml
@@ -36,7 +36,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <include layout="@layout/new_message_notification_bar" />
+ <include layout="@layout/conversation_message_header"
+ android:id="@+id/snap_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:visibility="gone" />
+
+ <include layout="@layout/new_message_notification_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom" />
<!-- TODO: scroll indicators go on top of all other layers (or the parent draws it) -->
</FrameLayout>
diff --git a/res/layout/new_message_notification_bar.xml b/res/layout/new_message_notification_bar.xml
index d08ed42..b14f607 100644
--- a/res/layout/new_message_notification_bar.xml
+++ b/res/layout/new_message_notification_bar.xml
@@ -17,9 +17,6 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
android:layout_marginBottom="12dp"
android:layout_marginLeft="@dimen/new_message_notification_margin_side"
android:layout_marginRight="@dimen/new_message_notification_margin_side"
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index 0f7fce3..8c530e7 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -57,4 +57,7 @@
<style name="AccountSpinnerAnchorTextPrimary" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
</style>
+ <style name="AccountSpinnerStyle">
+ <item name="android:layout_width">@dimen/spinner_frame_width</item>
+ </style>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 46a5f72..5973db3 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -452,6 +452,6 @@
</style>
<style name="AccountSpinnerStyle">
- <item name="android:layout_width">@dimen/spinner_frame_width</item>
+ <item name="android:layout_width">wrap_content</item>
</style>
</resources>
diff --git a/src/com/android/mail/browse/ConversationContainer.java b/src/com/android/mail/browse/ConversationContainer.java
index 9ce1acc..310a67e 100644
--- a/src/com/android/mail/browse/ConversationContainer.java
+++ b/src/com/android/mail/browse/ConversationContainer.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.database.DataSetObserver;
+import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.MotionEvent;
@@ -71,11 +72,25 @@
private static final int[] TOP_LAYER_VIEW_IDS = {
R.id.conversation_topmost_overlay
};
- private static final int TOP_LAYER_COUNT = TOP_LAYER_VIEW_IDS.length;
private ConversationViewAdapter mOverlayAdapter;
private int[] mOverlayBottoms;
private ConversationWebView mWebView;
+ private MessageHeaderView mSnapHeader;
+ private View mTopMostOverlay;
+
+ /**
+ * This is a hack.
+ *
+ * <p>Without this hack enabled, very fast scrolling can sometimes cause the top-most layers
+ * to skip being drawn for a frame or two. It happens specifically when overlay views are
+ * attached or added, and WebView happens to draw (on its own) immediately afterwards.
+ *
+ * <p>The workaround is to force an additional draw of the top-most overlay. Since the problem
+ * only occurs when scrolling overlays are added, restrict the additional draw to only occur
+ * if scrolling overlays were added since the last draw.
+ */
+ private boolean mAttachedOverlaySinceLastDraw;
private final List<View> mNonScrollingChildren = Lists.newArrayList();
@@ -146,6 +161,14 @@
private final DataSetObserver mAdapterObserver = new AdapterObserver();
/**
+ * The adapter index of the lowest overlay item that is above the top of the screen and reports
+ * {@link ConversationOverlayItem#canPushSnapHeader()}. We calculate this after a pass through
+ * {@link #positionOverlays(int, int)}.
+ *
+ */
+ private int mSnapIndex;
+
+ /**
* Child views of this container should implement this interface to be notified when they are
* being detached.
*
@@ -193,6 +216,11 @@
mWebView = (ConversationWebView) findViewById(R.id.webview);
mWebView.addScrollListener(this);
+ mTopMostOverlay = findViewById(R.id.conversation_topmost_overlay);
+
+ mSnapHeader = (MessageHeaderView) findViewById(R.id.snap_header);
+ mSnapHeader.setSnappy(true);
+
for (int id : BOTTOM_LAYER_VIEW_IDS) {
mNonScrollingChildren.add(findViewById(id));
}
@@ -201,6 +229,10 @@
}
}
+ public MessageHeaderView getSnapHeader() {
+ return mSnapHeader;
+ }
+
public void setOverlayAdapter(ConversationViewAdapter a) {
if (mOverlayAdapter != null) {
mOverlayAdapter.unregisterDataSetObserver(mAdapterObserver);
@@ -346,6 +378,8 @@
traceLayout("IN positionOverlays, spacerCount=%d overlayCount=%d", mOverlayBottoms.length,
mOverlayAdapter.getCount());
+ mSnapIndex = -1;
+
int adapterIndex = mOverlayAdapter.getCount() - 1;
int spacerIndex = mOverlayBottoms.length - 1;
while (spacerIndex >= 0 && adapterIndex >= 0) {
@@ -380,6 +414,22 @@
spacerIndex--;
}
+
+ // render and/or re-position snap header
+ ConversationOverlayItem snapItem = null;
+ if (mSnapIndex != -1) {
+ final ConversationOverlayItem item = mOverlayAdapter.getItem(mSnapIndex);
+ if (item.canBecomeSnapHeader()) {
+ snapItem = item;
+ }
+ }
+ if (snapItem == null) {
+ mSnapHeader.setVisibility(GONE);
+ mSnapHeader.unbind();
+ } else {
+ snapItem.bindView(mSnapHeader, false /* measureOnly */);
+ mSnapHeader.setVisibility(VISIBLE);
+ }
}
/**
@@ -516,6 +566,16 @@
}
@Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+
+ if (mAttachedOverlaySinceLastDraw) {
+ drawChild(canvas, mTopMostOverlay, getDrawingTime());
+ mAttachedOverlaySinceLastDraw = false;
+ }
+ }
+
+ @Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
@@ -575,6 +635,15 @@
traceLayout("ignore non-visible overlay %d", adapterIndex);
}
}
+
+ if (overlayTopY <= mOffsetY && item.canPushSnapHeader()) {
+ if (mSnapIndex == -1) {
+ mSnapIndex = adapterIndex;
+ } else if (adapterIndex > mSnapIndex) {
+ mSnapIndex = adapterIndex;
+ }
+ }
+
}
// layout an existing view
@@ -596,7 +665,7 @@
View view = mOverlayAdapter.getView(adapterIndex, convertView, this);
mOverlayViews.put(adapterIndex, new OverlayView(view, itemType));
- final int index = getChildCount() - TOP_LAYER_COUNT;
+ final int index = BOTTOM_LAYER_VIEW_IDS.length;
// Only re-attach if the view had previously been added to a view hierarchy.
// Since external components can contribute to the scrap heap (addScrapView), we can't
@@ -610,6 +679,8 @@
true /* preventRequestLayout */);
}
+ mAttachedOverlaySinceLastDraw = true;
+
return view;
}
diff --git a/src/com/android/mail/browse/ConversationOverlayItem.java b/src/com/android/mail/browse/ConversationOverlayItem.java
index 4c2d34a..c996184 100644
--- a/src/com/android/mail/browse/ConversationOverlayItem.java
+++ b/src/com/android/mail/browse/ConversationOverlayItem.java
@@ -91,4 +91,13 @@
public void invalidateMeasurement() {
mNeedsMeasure = true;
}
+
+ public boolean canBecomeSnapHeader() {
+ return false;
+ }
+
+ public boolean canPushSnapHeader() {
+ return false;
+ }
+
}
diff --git a/src/com/android/mail/browse/ConversationViewAdapter.java b/src/com/android/mail/browse/ConversationViewAdapter.java
index c1f8892..b5c1756 100644
--- a/src/com/android/mail/browse/ConversationViewAdapter.java
+++ b/src/com/android/mail/browse/ConversationViewAdapter.java
@@ -167,6 +167,17 @@
mExpanded = expanded;
}
}
+
+ @Override
+ public boolean canBecomeSnapHeader() {
+ return isExpanded();
+ }
+
+ @Override
+ public boolean canPushSnapHeader() {
+ return true;
+ }
+
}
public class MessageFooterItem extends ConversationOverlayItem {
@@ -256,15 +267,21 @@
public int getEnd() {
return mEnd;
}
+
+ @Override
+ public boolean canPushSnapHeader() {
+ return true;
+ }
}
public ConversationViewAdapter(Context context, Account account, LoaderManager loaderManager,
MessageHeaderViewCallbacks messageCallbacks,
ContactInfoSource contactInfoSource,
ConversationViewHeaderCallbacks convCallbacks,
- SuperCollapsedBlock.OnClickListener scbListener, Map<String, Address> addressCache) {
+ SuperCollapsedBlock.OnClickListener scbListener, Map<String, Address> addressCache,
+ FormattedDateBuilder dateBuilder) {
mContext = context;
- mDateBuilder = new FormattedDateBuilder(context);
+ mDateBuilder = dateBuilder;
mAccount = account;
mLoaderManager = loaderManager;
mMessageCallbacks = messageCallbacks;
diff --git a/src/com/android/mail/browse/MessageHeaderView.java b/src/com/android/mail/browse/MessageHeaderView.java
index e304c05..18ae53f 100644
--- a/src/com/android/mail/browse/MessageHeaderView.java
+++ b/src/com/android/mail/browse/MessageHeaderView.java
@@ -177,6 +177,8 @@
private AsyncQueryHandler mQueryHandler;
+ private boolean mObservingContactInfo;
+
private final DataSetObserver mContactInfoObserver = new DataSetObserver() {
@Override
public void onChanged() {
@@ -320,7 +322,10 @@
mMessageHeaderItem = null;
mMessage = null;
- mContactInfoSource.unregisterObserver(mContactInfoObserver);
+ if (mObservingContactInfo) {
+ mContactInfoSource.unregisterObserver(mContactInfoObserver);
+ mObservingContactInfo = false;
+ }
}
public void renderUpperHeaderFrom(MessageHeaderView other) {
@@ -350,6 +355,10 @@
public void bind(MessageHeaderItem headerItem, boolean defaultReplyAll,
boolean measureOnly) {
+ if (mMessageHeaderItem != null && mMessageHeaderItem == headerItem) {
+ return;
+ }
+
Timer t = new Timer();
t.start(HEADER_RENDER_TAG);
@@ -415,9 +424,15 @@
mStarView.setContentDescription(getResources().getString(
mStarView.isSelected() ? R.string.remove_star : R.string.add_star));
- if (!measureOnly) {
+ if (measureOnly) {
+ // avoid leaving any state around that would interfere with future regular bind() calls
+ unbind();
+ } else {
updateContactInfo();
- mContactInfoSource.registerObserver(mContactInfoObserver);
+ if (!mObservingContactInfo) {
+ mContactInfoSource.registerObserver(mContactInfoObserver);
+ mObservingContactInfo = true;
+ }
}
t.pause(HEADER_RENDER_TAG);
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index e2a9890..5fb806e 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -51,6 +51,7 @@
import com.android.mail.ContactInfo;
import com.android.mail.ContactInfoSource;
+import com.android.mail.FormattedDateBuilder;
import com.android.mail.R;
import com.android.mail.SenderInfoLoader;
import com.android.mail.browse.ConversationContainer;
@@ -64,6 +65,7 @@
import com.android.mail.browse.MessageCursor;
import com.android.mail.browse.MessageCursor.ConversationMessage;
import com.android.mail.browse.MessageCursor.ConversationController;
+import com.android.mail.browse.MessageHeaderView;
import com.android.mail.browse.MessageHeaderView.MessageHeaderViewCallbacks;
import com.android.mail.browse.SuperCollapsedBlock;
import com.android.mail.browse.WebViewContextMenu;
@@ -242,10 +244,20 @@
}
mTemplates = new HtmlConversationTemplates(mContext);
mAccount = mAccountObserver.initialize(mActivity.getAccountController());
+
+ final FormattedDateBuilder dateBuilder = new FormattedDateBuilder(mContext);
+
mAdapter = new ConversationViewAdapter(mActivity.getActivityContext(), mAccount,
- getLoaderManager(), this, mContactLoaderCallbacks, this, this, mAddressCache);
+ getLoaderManager(), this, mContactLoaderCallbacks, this, this, mAddressCache,
+ dateBuilder);
mConversationContainer.setOverlayAdapter(mAdapter);
+ // set up snap header (the adapter usually does this with the other ones)
+ final MessageHeaderView snapHeader = mConversationContainer.getSnapHeader();
+ snapHeader.initialize(dateBuilder, mAccount, mAddressCache);
+ snapHeader.setCallbacks(this);
+ snapHeader.setContactInfoSource(mContactLoaderCallbacks);
+
mMaxAutoLoadMessages = getResources().getInteger(R.integer.max_auto_load_messages);
mWebView.setOnCreateContextMenuListener(new WebViewContextMenu(activity));
diff --git a/src/com/android/mail/ui/MailActionBarView.java b/src/com/android/mail/ui/MailActionBarView.java
index 879456b..82ac5a3 100644
--- a/src/com/android/mail/ui/MailActionBarView.java
+++ b/src/com/android/mail/ui/MailActionBarView.java
@@ -453,7 +453,7 @@
mSearch.collapseActionView();
mSearchWidget.setQuery("", false);
}
- mActivity.onSearchRequested(query);
+ mActivity.onSearchRequested(query.trim());
return true;
}
@@ -507,7 +507,9 @@
return true;
}
collapseSearch();
+ // what is in the text field
String queryText = mSearchWidget.getQuery().toString();
+ // What the suggested query is
String query = c.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY));
if (!TextUtils.isEmpty(queryText)) {
final int queryTokenIndex = queryText
@@ -529,7 +531,7 @@
query = query.substring(0, start) + query.substring(start + queryText.length());
}
}
- mController.onSearchRequested(query);
+ mController.onSearchRequested(query.trim());
return true;
}