Make search interaction match gmail.

shows results list in portrait on tablet.
shows split in landscape on portrait.

Since email currently has no concept of saving the currently
selected message on orientation changes, there are some issues changing orientation
and restoring to the correct search state.

fixes coming in the next cl.
Change-Id: Ib0b98c4018c2ae0fabc2c78dfce4d3a197837d4f
This commit is contained in:
Mindy Pereira 2012-04-30 15:48:45 -07:00
parent 61099d5ea3
commit d6decef1d2
16 changed files with 137 additions and 35 deletions

View File

@ -215,3 +215,8 @@
*** toByteArray(java.io.Reader, java.lang.String);
*** toByteArray(java.lang.String);
}
-keepclasseswithmembers class com.android.email.activity.ThreePaneLayout {
*** setMessageListWidthAnim(...);
*** setMailboxListLeftAnim(...);
}

View File

@ -17,4 +17,6 @@
<resources>
<!-- Expand the middle view when showing the right hand pane -->
<bool name="expand_middle_view">false</bool>
<!-- Boolean value indicating whether to automatically select and show the first search result -->
<bool name="show_two_pane_search_result">false</bool>
</resources>

View File

@ -38,6 +38,11 @@
<dimen name="setup_padding_left">32dip</dimen>
<dimen name="setup_padding_right">32dip</dimen>
<<<<<<< HEAD
<dimen name="compose_area_left_padding">76dip</dimen>
<dimen name="compose_area_right_padding">78dip</dimen>
=======
<!-- Integer value indicating whether to show the message list in wide or normal mode when viewing search results -->
<integer name="message_search_list_header_mode">1</integer>
>>>>>>> Make search interaction match gmail.
</resources>

View File

@ -19,4 +19,7 @@
<!-- Reply/Reply All/Forward switcher in action bar -->
<bool name="message_compose_action_tabs">true</bool>
<!-- Boolean value indicating whether to automatically select and show the first search result -->
<bool name="show_two_pane_search_result">true</bool>
</resources>

View File

@ -20,5 +20,8 @@
<dimen name="mailbox_list_width">200dip</dimen>
<!-- width of the message list, on the message list + message view mode. -->
<dimen name="message_list_width">0dip</dimen>
<!-- Integer value indicating whether to show the message list in wide or normal mode when viewing search results -->
<integer name="message_search_list_header_mode">0</integer>
</resources>

View File

@ -22,4 +22,7 @@
<!-- Expand the middle view when showing the right hand pane -->
<bool name="expand_middle_view">true</bool>
<!-- Boolean value indicating whether to automatically select and show the first search result -->
<bool name="show_two_pane_search_result">false</bool>
</resources>

View File

@ -78,4 +78,7 @@
<dimen name="checkmark_margin_top">3sp</dimen>
<dimen name="star_margin_top">28sp</dimen>
<dimen name="date_margin_top">9sp</dimen>
<!-- Integer value indicating whether to show the message list in wide or normal mode when viewing search results -->
<integer name="message_search_list_header_mode">1</integer>
</resources>

View File

@ -156,8 +156,17 @@ public class EmailActivity extends Activity implements View.OnClickListener, Fra
* Initialize {@link #mUIController}.
*/
private void initUIController() {
mUIController = UiUtilities.useTwoPane(this)
? new UIControllerTwoPane(this) : new UIControllerOnePane(this);
if (UiUtilities.useTwoPane(this)) {
if (getIntent().getAction() != null
&& Intent.ACTION_SEARCH.equals(getIntent().getAction())
&& !UiUtilities.showTwoPaneSearchResults(this)) {
mUIController = new UIControllerSearchTwoPane(this);
} else {
mUIController = new UIControllerTwoPane(this);
}
} else {
mUIController = new UIControllerOnePane(this);
}
}
@Override

View File

@ -355,7 +355,7 @@ public class MessageListFragment extends ListFragment
mController = Controller.getInstance(mActivity);
mRefreshManager = RefreshManager.getInstance(mActivity);
mListAdapter = new MessagesAdapter(mActivity, this);
mListAdapter = new MessagesAdapter(mActivity, this, getListContext().isSearch());
mIsFirstLoad = true;
}
@ -1326,7 +1326,8 @@ public class MessageListFragment extends ListFragment
// If this is a search result, open the first message.
if (UiUtilities.useTwoPane(getActivity()) && mIsFirstLoad && mListContext.isSearch()
&& cursor.getCount() > 0) {
&& cursor.getCount() > 0
&& UiUtilities.showTwoPaneSearchResults(getActivity())) {
cursor.moveToFirst();
onMessageOpen(getMailboxId(), cursor.getLong(MessagesAdapter.COLUMN_ID));
}

View File

@ -60,6 +60,7 @@ public class MessageListItem extends View {
private MessagesAdapter mAdapter;
private MessageListItemCoordinates mCoordinates;
private Context mContext;
private boolean mIsSearchResult = false;
private boolean mDownEvent;
@ -252,6 +253,7 @@ public class MessageListItem extends View {
}
long mTimeFormatted = 0;
public void setTimestamp(long timestamp) {
if (mTimeFormatted != timestamp) {
mFormattedDate = DateUtils.getRelativeTimeSpanString(mContext, timestamp).toString();
@ -266,7 +268,7 @@ public class MessageListItem extends View {
* @return The mode of the view
*/
private int getViewMode(int width) {
return MessageListItemCoordinates.getMode(mContext, width);
return MessageListItemCoordinates.getMode(mContext, width, mIsSearchResult);
}
private Drawable mCurentBackground = null; // Only used by updateBackground()
@ -413,7 +415,7 @@ public class MessageListItem extends View {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mCoordinates = MessageListItemCoordinates.forWidth(mContext, mViewWidth);
mCoordinates = MessageListItemCoordinates.forWidth(mContext, mViewWidth, mIsSearchResult);
calculateDrawingData();
}
@ -502,9 +504,11 @@ public class MessageListItem extends View {
* @param layout If this is a three pane implementation, the
* ThreePaneLayout. Otherwise, null.
*/
public void bindViewInit(MessagesAdapter adapter, ThreePaneLayout layout) {
public void bindViewInit(MessagesAdapter adapter, ThreePaneLayout layout,
boolean isSearchResult) {
mLayout = layout;
mAdapter = adapter;
mIsSearchResult = isSearchResult;
requestLayout();
}

View File

@ -109,8 +109,11 @@ public class MessageListItemCoordinates {
* Returns the mode of the header view (Wide/Normal/Narrow) given the its
* measured width.
*/
public static int getMode(Context context, int width) {
public static int getMode(Context context, int width, boolean isSearch) {
Resources res = context.getResources();
if (isSearch) {
return res.getInteger(R.integer.message_search_list_header_mode);
}
if (MINIMUM_WIDTH_WIDE_MODE <= 0) {
MINIMUM_WIDTH_WIDE_MODE = res.getDimensionPixelSize(R.dimen.minimum_width_wide_mode);
}
@ -239,7 +242,8 @@ public class MessageListItemCoordinates {
* Returns coordinates for elements inside a conversation header view given
* the view width.
*/
public static MessageListItemCoordinates forWidth(Context context, int width) {
public static MessageListItemCoordinates forWidth(Context context, int width,
boolean isSearchResult) {
MessageListItemCoordinates coordinates = mCache.get(width);
if (coordinates == null) {
coordinates = new MessageListItemCoordinates();
@ -247,7 +251,7 @@ public class MessageListItemCoordinates {
// TODO: make the field computation done inside of the constructor and mark fields final
// Layout the appropriate view.
int mode = getMode(context, width);
int mode = getMode(context, width, isSearchResult);
int height = getHeight(context, mode);
View view = LayoutInflater.from(context).inflate(getLayoutId(mode), null);
int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);

View File

@ -100,6 +100,8 @@ import java.util.Set;
private ThreePaneLayout mLayout;
private boolean mIsSearchResult = false;
/**
* The actual return type from the loader.
*/
@ -130,10 +132,11 @@ import java.util.Set;
}
}
public MessagesAdapter(Context context, Callback callback) {
public MessagesAdapter(Context context, Callback callback, boolean isSearchResult) {
super(context.getApplicationContext(), null, 0 /* no auto requery */);
mResourceHelper = ResourceHelper.getInstance(context);
mCallback = callback;
mIsSearchResult = isSearchResult;
}
public void setLayout(ThreePaneLayout layout) {
@ -188,7 +191,7 @@ import java.util.Set;
public void bindView(View view, Context context, Cursor cursor) {
// Reset the view (in case it was recycled) and prepare for binding
MessageListItem itemView = (MessageListItem) view;
itemView.bindViewInit(this, mLayout);
itemView.bindViewInit(this, mLayout, mIsSearchResult);
// TODO: just move thise all to a MessageListItem.bindTo(cursor) so that the fields can
// be private, and their inter-dependence when they change can be abstracted away.

View File

@ -119,6 +119,8 @@ public class ThreePaneLayout extends LinearLayout {
private Callback mCallback = EmptyCallback.INSTANCE;
private boolean mIsSearchResult = false;
public interface Callback {
/** Called when {@link ThreePaneLayout#getVisiblePanes()} has changed. */
public void onVisiblePanesChanged(int previousVisiblePanes);
@ -162,7 +164,7 @@ public class ThreePaneLayout extends LinearLayout {
mConvViewExpandList = getContext().getResources().getBoolean(R.bool.expand_middle_view);
View[][] stateRightVisible = new View[][] {
{
mMiddlePane, mMessageCommandButtons, mRightPane
mMiddlePane, mMessageCommandButtons, mRightPane
}, // Visible
{
mLeftPane
@ -182,7 +184,7 @@ public class ThreePaneLayout extends LinearLayout {
// STATE_LEFT_VISIBLE
{
{
mLeftPane, mMiddlePane
mLeftPane, mMiddlePane
}, // Visible
{
mRightPane
@ -209,6 +211,13 @@ public class ThreePaneLayout extends LinearLayout {
mMessageListWidth = getResources().getDimensionPixelSize(R.dimen.message_list_width);
}
public void setIsSearch(boolean isSearch) {
mIsSearchResult = isSearch;
}
private boolean shouldShowMailboxList() {
return !mIsSearchResult || UiUtilities.showTwoPaneSearchResults(getContext());
}
public void setCallback(Callback callback) {
mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
@ -225,21 +234,6 @@ public class ThreePaneLayout extends LinearLayout {
return mMessageCommandButtons;
}
@Override
protected Parcelable onSaveInstanceState() {
SavedState ss = new SavedState(super.onSaveInstanceState());
ss.mPaneState = mPaneState;
return ss;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
// Called after onFinishInflate()
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mInitialPaneState = ss.mPaneState;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
@ -298,6 +292,13 @@ public class ThreePaneLayout extends LinearLayout {
return changePaneState(STATE_RIGHT_VISIBLE, true);
}
private int getMailboxListWidth() {
if (!shouldShowMailboxList()) {
return 0;
}
return mMailboxListWidth;
}
private boolean changePaneState(int newState, boolean animate) {
if (!isPaneCollapsible() && (newState == STATE_MIDDLE_EXPANDED)) {
newState = STATE_RIGHT_VISIBLE;
@ -329,7 +330,7 @@ public class ThreePaneLayout extends LinearLayout {
final String animatorLabel; // for debug purpose
setViewWidth(mLeftPane, mMailboxListWidth);
setViewWidth(mLeftPane, getMailboxListWidth());
setViewWidth(mRightPane, totalWidth - getMessageListWidth());
switch (mPaneState) {
@ -337,18 +338,18 @@ public class ThreePaneLayout extends LinearLayout {
// mailbox + message list
animatorLabel = "moving to [mailbox list + message list]";
expectedMailboxLeft = 0;
expectedMessageListWidth = totalWidth - mMailboxListWidth;
expectedMessageListWidth = totalWidth - getMailboxListWidth();
break;
case STATE_RIGHT_VISIBLE:
// message list + message view
animatorLabel = "moving to [message list + message view]";
expectedMailboxLeft = -mMailboxListWidth;
expectedMailboxLeft = -getMailboxListWidth();
expectedMessageListWidth = getMessageListWidth();
break;
default:
throw new IllegalStateException();
}
setViewWidth(mMiddlePane, expectedMessageListWidth);
final View[][] showHideViews = mShowHideViews[mPaneState];
final AnimatorListener listener = new AnimatorListener(animatorLabel,
showHideViews[INDEX_VISIBLE],

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.activity;
/**
* TwoPane controller for search results in portrait.
*/
public class UIControllerSearchTwoPane extends UIControllerTwoPane {
public UIControllerSearchTwoPane(EmailActivity activity) {
super(activity);
}
/** {@inheritDoc} */
@Override
public boolean onBackPressed(boolean isSystemBackKey) {
if (isMessageViewInstalled() && mThreePane.showLeftPane()) {
return true;
}
return super.onBackPressed(isSystemBackKey);
}
@Override
public void onActivityViewReady() {
super.onActivityViewReady();
mThreePane.setIsSearch(true);
}
@Override
public void onVisiblePanesChanged(int previousVisiblePanes) {
super.onVisiblePanesChanged(previousVisiblePanes);
mThreePane.requestLayout();
}
}

View File

@ -54,7 +54,7 @@ class UIControllerTwoPane extends UIControllerBase implements ThreePaneLayout.Ca
static final int INBOX_AUTO_REFRESH_MIN_INTERVAL = 10 * 1000; // in milliseconds
// Other UI elements
private ThreePaneLayout mThreePane;
protected ThreePaneLayout mThreePane;
private MessageCommandButtonView mMessageCommandButtons;
@ -359,7 +359,7 @@ class UIControllerTwoPane extends UIControllerBase implements ThreePaneLayout.Ca
if (messageId != Message.NO_MESSAGE) {
updateMessageView(ft, messageId);
mThreePane.showRightPane();
} else if (mListContext.isSearch()) {
} else if (mListContext.isSearch() && UiUtilities.showTwoPaneSearchResults(mActivity)) {
mThreePane.showRightPane();
} else {
mThreePane.showLeftPane();

View File

@ -173,4 +173,11 @@ public class UiUtilities {
}
return context.getResources().getBoolean(R.bool.use_two_pane);
}
/**
* Return whether to show search results in a split pane.
*/
public static boolean showTwoPaneSearchResults(Context context) {
return context.getResources().getBoolean(R.bool.show_two_pane_search_result);
}
}