Let MessageViewFragment own bottom buttons.

Create a custom view containing the bottons below MVF
(delete, move, reply, etc) and let MVF own this.

These buttons used to be owned by the XL activity itself, because
the UI for these commands will most likely be totally different
from the tablet UI, so the fragment having them looked wrong.

However, this made it harder to make changes suggested by the latest
mock, such as "put reply/forward in the message header".
I think the buttons are semantically part of the message view anyway,
so the fragment owning UI for these commands is probably the way to go.
(And let's worry about the phone UI later.)

Reason for the use of a custom view is that it will make it easier
to make non-trivial UI changes, e.g. "combine reply, reply-all and
forward and make it dropdown."

Also removed obsolete TODOs from MessageListXL.

Change-Id: Ibf93f4c70fe07bdbbe33d2adb6bbd2b96812830d
This commit is contained in:
Makoto Onuki 2010-09-16 11:16:46 -07:00
parent 2039cba065
commit 0435a0775e
8 changed files with 647 additions and 402 deletions

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<!-- It extends LinearLayout -->
<com.android.email.activity.MessageCommandButtonView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:paddingTop="5dip"
android:paddingLeft="4dip"
android:paddingRight="4dip"
android:paddingBottom="1dip"
android:background="@android:drawable/bottom_bar"
>
<Button
android:id="@+id/move_button"
android:text="@string/move_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/delete_button"
android:text="@string/delete_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/unread_button"
android:text="@string/unread_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/reply_button"
android:text="@string/reply_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/reply_all_button"
android:text="@string/reply_all_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/forward_button"
android:text="@string/forward_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/move_to_newer_button"
android:text="@string/message_view_move_to_newer"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/move_to_older_button"
android:text="@string/message_view_move_to_older"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
</com.android.email.activity.MessageCommandButtonView>

View File

@ -21,105 +21,14 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- We put MailboxListFragment here at runtime. -->
<FrameLayout
android:id="@+id/left_pane"
android:layout_width="360dip"
android:layout_height="match_parent"
/>
<!--
Right pane.
Because we need to show buttons for MessageView by ourselves, we need a linear layout here.
See also the comment below.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
<FrameLayout
android:id="@+id/right_pane"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
>
<!-- We put MessageList/MessageViewFragment here at runtime. -->
<FrameLayout
android:id="@+id/right_pane"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<!--
Bottom buttons
These buttons can't be in MessageViewFragment, because the button
layout changes on the phone layout.
(We can (probably) create a separate layout for XL devices, but not sure if that'd be
a good idea, at this point.)
However, putting these buttons means we have to show/hide them
according to the screen state, which means we can't just use the
fragment transaction to replace fragments.
Maybe we should create another fragment, MessageViewWithCommandsFragment,
on top of MessageViewFragment.
-->
<LinearLayout
android:id="@+id/message_view_buttons"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:paddingLeft="4dip"
android:paddingRight="4dip"
android:paddingBottom="1dip"
android:background="@android:drawable/bottom_bar"
android:visibility="gone"
>
<Button
android:id="@+id/move"
android:text="@string/move_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/delete"
android:text="@string/delete_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/unread"
android:text="@string/unread_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/reply"
android:text="@string/reply_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/reply_all"
android:text="@string/reply_all_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/forward"
android:text="@string/forward_action"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/moveToNewer"
android:text="@string/message_view_move_to_newer"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
<Button
android:id="@+id/moveToOlder"
android:text="@string/message_view_move_to_older"
android:layout_height="match_parent"
android:layout_width="0dip"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
android:layout_weight="1" />
</LinearLayout>

View File

@ -14,193 +14,222 @@
limitations under the License.
-->
<ScrollView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollview"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="outsideOverlay"
android:fadingEdge="none"
android:fillViewport="true"
>
<LinearLayout
android:orientation="vertical"
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:scrollbarStyle="outsideOverlay"
android:fadingEdge="none"
android:fillViewport="true"
>
<!-- header area -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/header_card"
android:paddingTop="3dip"
android:paddingBottom="3dip"
android:paddingLeft="3dip"
android:paddingRight="6dip">
<LinearLayout
android:id="@+id/from_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="true" >
<android.widget.QuickContactBadge
android:id="@+id/badge"
android:layout_gravity="center_vertical"
android:layout_marginRight="8dip"
android:layout_marginLeft="2dip"
style="@*android:style/Widget.QuickContactBadge.WindowSmall" />
/>
<ImageView
android:id="@+id/presence"
android:src="@drawable/presence_inactive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dip"
android:layout_gravity="center_vertical"
android:background="@drawable/quickcontact_presence_bg" />
<TextView
android:id="@+id/from"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:singleLine="true"
android:ellipsize="end"
android:paddingRight="6dip" />
<ImageView
android:id="@+id/attachment"
android:src="@drawable/ic_email_attachment_small"
android:layout_width="22dip"
android:layout_height="22dip"
android:baselineAlignBottom="true" />
<TextView
android:id="@+id/date"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/to_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_to_label" />
<TextView
android:id="@+id/to"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="false"
android:ellipsize="none" />
<TextView
android:id="@+id/time"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/cc_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_cc_label" />
<TextView
android:id="@+id/cc"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="false"
android:ellipsize="none" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/subject"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:textStyle="bold"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:singleLine="false"
android:ellipsize="none" />
<!-- TODO: Move this to wherever it really belongs -->
<ImageView
android:id="@+id/favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/btn_star_big_buttonless_off" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/show_pictures_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffefefef"
android:layout_marginTop="6dip"
android:paddingLeft="6dip"
android:paddingRight="3dip"
android:paddingTop="4dip"
android:paddingBottom="4dip"
android:baselineAligned="false"
android:visibility="gone">
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/message_view_show_pictures_instructions"
android:layout_gravity="center"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
<Button
android:id="@+id/show_pictures"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_show_pictures_action" />
</LinearLayout>
<!-- content area -->
<include layout="@layout/message_view_invitation" />
<WebView
android:id="@+id/message_content"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#ffffff" />
<!-- attachments area -->
<LinearLayout
android:id="@+id/attachments"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dip"
android:background="#ffffff">
android:layout_height="match_parent"
>
<!-- header area -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/header_card"
android:paddingTop="3dip"
android:paddingBottom="3dip"
android:paddingLeft="3dip"
android:paddingRight="6dip">
<LinearLayout
android:id="@+id/from_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="true" >
<android.widget.QuickContactBadge
android:id="@+id/badge"
android:layout_gravity="center_vertical"
android:layout_marginRight="8dip"
android:layout_marginLeft="2dip"
style="@*android:style/Widget.QuickContactBadge.WindowSmall" />
/>
<ImageView
android:id="@+id/presence"
android:src="@drawable/presence_inactive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dip"
android:layout_gravity="center_vertical"
android:background="@drawable/quickcontact_presence_bg" />
<TextView
android:id="@+id/from"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:singleLine="true"
android:ellipsize="end"
android:paddingRight="6dip" />
<ImageView
android:id="@+id/attachment"
android:src="@drawable/ic_email_attachment_small"
android:layout_width="22dip"
android:layout_height="22dip"
android:baselineAlignBottom="true" />
<TextView
android:id="@+id/date"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/to_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_to_label" />
<TextView
android:id="@+id/to"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="false"
android:ellipsize="none" />
<TextView
android:id="@+id/time"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/cc_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_cc_label" />
<TextView
android:id="@+id/cc"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:singleLine="false"
android:ellipsize="none" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/subject"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:textStyle="bold"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content"
android:singleLine="false"
android:ellipsize="none" />
<!-- TODO: Move this to wherever it really belongs -->
<ImageView
android:id="@+id/favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/btn_star_big_buttonless_off" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/show_pictures_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffefefef"
android:layout_marginTop="6dip"
android:paddingLeft="6dip"
android:paddingRight="3dip"
android:paddingTop="4dip"
android:paddingBottom="4dip"
android:baselineAligned="false"
android:visibility="gone">
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/message_view_show_pictures_instructions"
android:layout_gravity="center"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
<Button
android:id="@+id/show_pictures"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/message_view_show_pictures_action" />
</LinearLayout>
<!-- content area -->
<include layout="@layout/message_view_invitation" />
<WebView
android:id="@+id/message_content"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#ffffff" />
<!-- attachments area -->
<LinearLayout
android:id="@+id/attachments"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dip"
android:background="#ffffff">
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</ScrollView>
<!--
Buttons such as delete, mark unread. Only MessageViewFragment uses these.
MessageFileViewFragment doesn't.
-->
<include
layout="@layout/message_command_button_view"
android:id="@+id/message_command_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:visibility="gone"
/>
<!--
<com.android.email.activity.MessageCommandButtonView
android:id="@+id/message_command_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="horizontal"
android:visibility="gone"
/>
-->
</LinearLayout>

View File

@ -0,0 +1,148 @@
/*
* Copyright (C) 2010 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;
import com.android.email.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
/**
* A View that is shown at the bottom of {@link MessageViewFragment} and contains buttons such
* as "Delete" "Mark unread".
*
* This class is meant to hide layout differences between portrait and landscape, if any.
* e.g. We might combine some of the buttons when we have small real estate.
*/
public class MessageCommandButtonView extends LinearLayout implements View.OnClickListener {
private View mMoveToNewerButton;
private View mMoveToOlderButton;
private View mForwardButton;
private View mReplyButton;
private View mReplyAllButton;
private View mDeleteButton;
private View mMarkUneadButton;
private View mMoveButton;
private Callback mCallback = EmptyCallback.INSTANCE;
public interface Callback {
public void onMoveToNewer();
public void onMoveToOlder();
public void onForward();
public void onReply();
public void onReplyAll();
public void onDelete();
public void onMarkUnread();
public void onMove();
}
private static class EmptyCallback implements Callback {
public static final Callback INSTANCE = new EmptyCallback();
@Override public void onDelete() {}
@Override public void onForward() {}
@Override public void onMarkUnread() {}
@Override public void onMove() {}
@Override public void onMoveToNewer() {}
@Override public void onMoveToOlder() {}
@Override public void onReply() {}
@Override public void onReplyAll() {}
}
public MessageCommandButtonView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MessageCommandButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MessageCommandButtonView(Context context) {
super(context);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMoveToNewerButton = findViewById(R.id.move_to_newer_button);
mMoveToOlderButton = findViewById(R.id.move_to_older_button);
mForwardButton = findViewById(R.id.forward_button);
mReplyButton = findViewById(R.id.reply_button);
mReplyAllButton = findViewById(R.id.reply_all_button);
mDeleteButton = findViewById(R.id.delete_button);
mMarkUneadButton = findViewById(R.id.unread_button);
mMoveButton = findViewById(R.id.move_button);
mMoveToNewerButton.setOnClickListener(this);
mMoveToOlderButton.setOnClickListener(this);
mForwardButton.setOnClickListener(this);
mReplyButton.setOnClickListener(this);
mReplyAllButton.setOnClickListener(this);
mDeleteButton.setOnClickListener(this);
mMarkUneadButton.setOnClickListener(this);
mMoveButton.setOnClickListener(this);
}
public void setCallback(Callback callback) {
mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
}
public void enableReplyForwardButtons(boolean enabled) {
mForwardButton.setEnabled(enabled);
mReplyButton.setEnabled(enabled);
mReplyAllButton.setEnabled(enabled);
}
public void enableNavigationButons(boolean enableMoveToNewer, boolean enableMoveToOlder) {
mMoveToNewerButton.setEnabled(enableMoveToNewer);
mMoveToOlderButton.setEnabled(enableMoveToOlder);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.move_to_newer_button:
mCallback.onMoveToNewer();
break;
case R.id.move_to_older_button:
mCallback.onMoveToOlder();
break;
case R.id.forward_button:
mCallback.onForward();
break;
case R.id.reply_button:
mCallback.onReply();
break;
case R.id.reply_all_button:
mCallback.onReplyAll();
break;
case R.id.delete_button:
mCallback.onDelete();
break;
case R.id.unread_button:
mCallback.onMarkUnread();
break;
case R.id.move_button:
mCallback.onMove();
break;
}
}
}

View File

@ -41,28 +41,15 @@ import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import java.security.InvalidParameterException;
// TODO Where/when/how do we close loaders?? Do we have to? Getting this error:
// Finalizing a Cursor that has not been deactivated or closed.
// database = /data/data/com.google.android.email/databases/EmailProvider.db,
// table = Account, query = SELECT _id, displayName, emailAddress FROM Account
/**
* The main (two-pane) activity for XL devices.
*
* TODO Refresh account list when adding/removing/changing(e.g. display name) accounts.
* -> Need the MessageList.onResume logic. Figure out a clean way to do that.
*
* TODO Extract the message view buttons (move, reply, etc) into a custom view.
* That way it'll be easier to change the button layout on orientation changes.
* (We'll probably combine some buttons on portrait.)
*
* TODO Refine "move to". It also shouldn't work for special messages, like drafts.
* TODO Refine "move to".
*/
public class MessageListXL extends Activity implements View.OnClickListener,
public class MessageListXL extends Activity implements
MessageListXLFragmentManager.TargetActivity, MoveMessageToDialog.Callback {
private static final String EXTRA_ACCOUNT_ID = "ACCOUNT_ID";
private static final String EXTRA_MAILBOX_ID = "MAILBOX_ID";
@ -75,13 +62,6 @@ public class MessageListXL extends Activity implements View.OnClickListener,
private final RefreshListener mMailRefreshManagerListener
= new RefreshListener();
private View mMessageViewButtonPanel;
private View mMoveToNewerButton;
private View mMoveToOlderButton;
private View mForwardButton;
private View mReplyButton;
private View mReplyAllButton;
private AccountSelectorAdapter mAccountsSelectorAdapter;
private final ActionBarNavigationCallback mActionBarNavigationCallback
= new ActionBarNavigationCallback();
@ -143,23 +123,6 @@ public class MessageListXL extends Activity implements View.OnClickListener,
mFragmentManager.setMessageListFragmentCallback(new MessageListFragmentCallback());
mFragmentManager.setMessageViewFragmentCallback(new MessageViewFragmentCallback());
mMessageViewButtonPanel = findViewById(R.id.message_view_buttons);
mMoveToNewerButton = findViewById(R.id.moveToNewer);
mMoveToOlderButton = findViewById(R.id.moveToOlder);
mForwardButton = findViewById(R.id.forward);
mReplyButton = findViewById(R.id.reply);
mReplyAllButton = findViewById(R.id.reply_all);
mMoveToNewerButton.setOnClickListener(this);
mMoveToOlderButton.setOnClickListener(this);
mForwardButton.setOnClickListener(this);
mReplyButton.setOnClickListener(this);
mReplyAllButton.setOnClickListener(this);
findViewById(R.id.delete).setOnClickListener(this);
findViewById(R.id.unread).setOnClickListener(this);
findViewById(R.id.move).setOnClickListener(this);
mAccountsSelectorAdapter = new AccountSelectorAdapter(mContext, null);
if (isRestoring) {
@ -268,49 +231,6 @@ public class MessageListXL extends Activity implements View.OnClickListener,
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.moveToOlder:
moveToOlder();
break;
case R.id.moveToNewer:
moveToNewer();
break;
case R.id.delete:
onDeleteMessage();
break;
case R.id.unread:
onSetMessageUnread();
break;
case R.id.reply:
MessageCompose.actionReply(this, mFragmentManager.getMessageId(), false);
break;
case R.id.reply_all:
MessageCompose.actionReply(this, mFragmentManager.getMessageId(), true);
break;
case R.id.forward:
MessageCompose.actionForward(this, mFragmentManager.getMessageId());
break;
case R.id.move:
onMoveMessage();
break;
}
}
/**
* Called when the "delete" button on message view is pressed.
*/
private void onDeleteMessage() {
// the delete triggers mCursorObserver in MessageOrderManager.
// first move to older/newer before the actual delete
long messageIdToDelete = mFragmentManager.getMessageId();
onCurrentMessageGone();
ActivityHelper.deleteMessage(this, messageIdToDelete);
}
private void onCurrentMessageGone() {
switch (Preferences.getPreferences(this).getAutoAdvanceDirection()) {
case Preferences.AUTO_ADVANCE_NEWER:
@ -326,12 +246,6 @@ public class MessageListXL extends Activity implements View.OnClickListener,
mFragmentManager.goBackToMailbox();
}
private void onSetMessageUnread() {
MessageViewFragment f = mFragmentManager.getMessageViewFragment();
f.onMarkMessageAsRead(false);
mFragmentManager.goBackToMailbox();
}
private void onMoveMessage() {
long messageId = mFragmentManager.getMessageId();
MoveMessageToDialog dialog = MoveMessageToDialog.newInstance(this, new long[] {messageId},
@ -396,11 +310,19 @@ public class MessageListXL extends Activity implements View.OnClickListener,
}
/**
* Disable/enable the previous/next buttons for the message view.
* Disable/enable the move-to-newer/older buttons.
*/
private void updateNavigationArrows() {
mMoveToNewerButton.setEnabled((mOrderManager != null) && mOrderManager.canMoveToNewer());
mMoveToOlderButton.setEnabled((mOrderManager != null) && mOrderManager.canMoveToOlder());
MessageViewFragment f = mFragmentManager.getMessageViewFragment();
if (f == null) {
return;
}
if (mOrderManager == null) {
f.enableNavigationButons(false, false); // shouldn't happen, but just in case
} else {
f.enableNavigationButons(mOrderManager.canMoveToNewer(),
mOrderManager.canMoveToOlder());
}
}
private boolean moveToOlder() {
@ -448,15 +370,12 @@ public class MessageListXL extends Activity implements View.OnClickListener,
private class MessageViewFragmentCallback implements MessageViewFragment.Callback {
@Override
public void onMessageViewShown(int mailboxType) {
mMessageViewButtonPanel.setVisibility(View.VISIBLE);
updateMessageOrderManager();
updateNavigationArrows();
enableReplyForwardButtons(mailboxType != Mailbox.TYPE_TRASH);
}
@Override
public void onMessageViewGone() {
mMessageViewButtonPanel.setVisibility(View.GONE);
stopMessageOrderManager();
}
@ -503,12 +422,41 @@ public class MessageListXL extends Activity implements View.OnClickListener,
public void onCalendarLinkClicked(long epochEventStartTime) {
ActivityHelper.openCalendar(MessageListXL.this, epochEventStartTime);
}
}
private void enableReplyForwardButtons(boolean enabled) {
mForwardButton.setEnabled(enabled);
mReplyButton.setEnabled(enabled);
mReplyAllButton.setEnabled(enabled);
@Override
public void onMoveToNewer() {
moveToNewer();
}
@Override
public void onMoveToOlder() {
moveToOlder();
}
@Override
public void onBeforeMessageDelete() {
onCurrentMessageGone();
}
@Override
public void onMoveMessage() {
MessageListXL.this.onMoveMessage();
}
@Override
public void onForward() {
MessageCompose.actionForward(MessageListXL.this, mFragmentManager.getMessageId());
}
@Override
public void onReply() {
MessageCompose.actionReply(MessageListXL.this, mFragmentManager.getMessageId(), false);
}
@Override
public void onReplyAll() {
MessageCompose.actionReply(MessageListXL.this, mFragmentManager.getMessageId(), true);
}
}
@Override

View File

@ -18,12 +18,10 @@ package com.android.email.activity;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.Utility;
import com.android.email.provider.EmailContent.Mailbox;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
@ -85,6 +83,8 @@ public class MessageView extends MessageViewBase implements View.OnClickListener
mFragment = (MessageViewFragment) findFragmentById(R.id.message_view_fragment);
mFragment.setCallback(this);
// TODO Remove these bottom buttons, and make use of the ones in MessageViewFragments.
mMoveToNewer = findViewById(R.id.moveToNewer);
mMoveToOlder = findViewById(R.id.moveToOlder);
mMoveToNewer.setOnClickListener(this);
@ -94,6 +94,9 @@ public class MessageView extends MessageViewBase implements View.OnClickListener
findViewById(R.id.reply_all).setOnClickListener(this);
findViewById(R.id.delete).setOnClickListener(this);
// For now, we don't use the buttons in the fragment, so let's hide them manually...
mFragment.hideCommandButtons();
initFromIntent();
if (icicle != null) {
mMessageId = icicle.getLong(STATE_MESSAGE_ID, mMessageId);
@ -161,21 +164,6 @@ public class MessageView extends MessageViewBase implements View.OnClickListener
enableForwardReply(mailboxType != Mailbox.TYPE_TRASH);
}
private void onReply() {
MessageCompose.actionReply(this, mMessageId, false);
finish();
}
private void onReplyAll() {
MessageCompose.actionReply(this, mMessageId, true);
finish();
}
private void onForward() {
MessageCompose.actionForward(this, mMessageId);
finish();
}
private void onDeleteMessage() {
// the delete triggers mCursorObserver in MessageOrderManager.
// first move to older/newer before the actual delete
@ -340,4 +328,42 @@ public class MessageView extends MessageViewBase implements View.OnClickListener
public void onCalendarLinkClicked(long epochEventStartTime) {
ActivityHelper.openCalendar(this, epochEventStartTime);
}
@Override
public void onReply() {
MessageCompose.actionReply(this, mMessageId, false);
finish();
}
@Override
public void onReplyAll() {
MessageCompose.actionReply(this, mMessageId, true);
finish();
}
@Override
public void onForward() {
MessageCompose.actionForward(this, mMessageId);
finish();
}
@Override
public void onMoveToNewer() {
// TODO Implement this
}
@Override
public void onMoveToOlder() {
// TODO Implement this
}
@Override
public void onBeforeMessageDelete() {
// TODO Implement this
}
@Override
public void onMoveMessage() {
// TODO Implement this
}
}

View File

@ -21,6 +21,7 @@ import com.android.email.R;
import com.android.email.Utility;
import com.android.email.mail.MeetingInfo;
import com.android.email.mail.PackedString;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.Message;
import com.android.email.service.EmailServiceConstants;
@ -51,13 +52,20 @@ public class MessageViewFragment extends MessageViewFragmentBase {
private TextView mMeetingYes;
private TextView mMeetingMaybe;
private TextView mMeetingNo;
private MessageCommandButtonView mCommandButtons;
private int mPreviousMeetingResponse = -1;
private Drawable mFavoriteIconOn;
private Drawable mFavoriteIconOff;
/** ID of the message that will be loaded */
private long mMessageIdToOpen = -1;
/** ID of the currently shown message */
private long mCurrentMessageId = -1;
private final CommandButtonCallback mCommandButtonCallback = new CommandButtonCallback();
/**
* This class has more call backs than {@link MessageViewFragmentBase}.
*
@ -83,23 +91,43 @@ public class MessageViewFragment extends MessageViewFragmentBase {
/** Called when the current message is set unread. */
public void onMessageSetUnread();
/** Called when "move to newer" button is pressed. */
public void onMoveToNewer();
/** Called when "move to older" button is pressed. */
public void onMoveToOlder();
/**
* Called right before the current message will be deleted.
* Callees don't have to delete messages. The fragment does.
*/
public void onBeforeMessageDelete();
/** Called when the move button is pressed. */
public void onMoveMessage();
/** Called when the forward button is pressed. */
public void onForward();
/** Called when the reply button is pressed. */
public void onReply();
/** Called when the reply-all button is pressed. */
public void onReplyAll();
}
public static final class EmptyCallback extends MessageViewFragmentBase.EmptyCallback
implements Callback {
public static final Callback INSTANCE = new EmptyCallback();
@Override
public void onCalendarLinkClicked(long epochEventStartTime) {
}
@Override
public void onMessageSetUnread() {
}
@Override
public void onRespondedToInvite(int response) {
}
@Override public void onCalendarLinkClicked(long epochEventStartTime) { }
@Override public void onMessageSetUnread() { }
@Override public void onRespondedToInvite(int response) { }
@Override public void onMoveToNewer() { }
@Override public void onMoveToOlder() { }
@Override public void onBeforeMessageDelete() { }
@Override public void onMoveMessage() { }
@Override public void onForward() { }
@Override public void onReply() { }
@Override public void onReplyAll() { }
}
private Callback mCallback = EmptyCallback.INSTANCE;
@ -130,6 +158,12 @@ public class MessageViewFragment extends MessageViewFragmentBase {
mMeetingNo.setOnClickListener(this);
view.findViewById(R.id.invite_link).setOnClickListener(this);
// Show the command buttons at the bottom.
mCommandButtons =
(MessageCommandButtonView) view.findViewById(R.id.message_command_buttons);
mCommandButtons.setVisibility(View.VISIBLE);
mCommandButtons.setCallback(mCommandButtonCallback);
return view;
}
@ -138,6 +172,13 @@ public class MessageViewFragment extends MessageViewFragmentBase {
super.setCallback(mCallback);
}
/**
* @deprecated TODO Remove this call from MessageView
*/
public void hideCommandButtons() {
mCommandButtons.setVisibility(View.GONE);
}
/** Called by activities to set an id of a message to open. */
public void openMessage(long messageId) {
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
@ -160,6 +201,24 @@ public class MessageViewFragment extends MessageViewFragmentBase {
return Message.restoreMessageWithId(getActivity(), mMessageIdToOpen);
}
@Override
protected void onMessageShown(long messageId, int mailboxType) {
super.onMessageShown(messageId, mailboxType);
// Remember the currently shown message ID.
mCurrentMessageId = messageId;
// Disable forward/reply buttons as necessary.
// (Draft messages shouldn't be opened with this fragment in the first place, but currently
// it's possible due to a problem with "All Starred".)
mCommandButtons.enableReplyForwardButtons((mailboxType != Mailbox.TYPE_TRASH)
&& (mailboxType != Mailbox.TYPE_TRASH));
}
public void enableNavigationButons(boolean enableMoveToNewer, boolean enableMoveToOlder) {
mCommandButtons.enableNavigationButons(enableMoveToNewer, enableMoveToOlder);
}
/**
* Toggle favorite status and write back to provider
*/
@ -267,4 +326,48 @@ public class MessageViewFragment extends MessageViewFragmentBase {
mInviteSection.setVisibility((message.mFlags & Message.FLAG_INCOMING_MEETING_INVITE) != 0 ?
View.VISIBLE : View.GONE);
}
private class CommandButtonCallback implements MessageCommandButtonView.Callback {
@Override
public void onMoveToNewer() {
mCallback.onMoveToNewer();
}
@Override
public void onMoveToOlder() {
mCallback.onMoveToOlder();
}
@Override
public void onDelete() {
mCallback.onBeforeMessageDelete();
ActivityHelper.deleteMessage(getActivity(), mCurrentMessageId);
}
@Override
public void onMove() {
mCallback.onMoveMessage();
}
@Override
public void onForward() {
mCallback.onForward();
}
@Override
public void onReply() {
mCallback.onReply();
}
@Override
public void onReplyAll() {
mCallback.onReplyAll();
}
@Override
public void onMarkUnread() {
onMarkMessageAsRead(false);
mCallback.onMessageSetUnread();
}
}
}

View File

@ -678,10 +678,17 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
reloadUiFromMessage(message, mOkToFetch);
queryContactStatus();
mCallback.onMessageViewShown(mMailboxType);
onMessageShown(mMessageId, mMailboxType);
}
}
/**
* Called when a message is shown to the user.
*/
protected void onMessageShown(long messageId, int mailboxType) {
mCallback.onMessageViewShown(mailboxType);
}
/**
* Called when the message body is loaded.
*/