Implement proper drag-n-drop
Still some tweaks to be done, but, we're real close to what it should look like. Bug 3322756 Change-Id: I8549ab59677a344e8f259c88bed950169d7381a8
This commit is contained in:
parent
285fac8554
commit
07f5f60b8f
|
@ -44,6 +44,13 @@
|
|||
<color name="combined_view_account_color_4">#fff4fd04</color>
|
||||
<color name="combined_view_account_color_5">#ffe65020</color>
|
||||
|
||||
<!-- Drop target colors -->
|
||||
<!-- STOPSHIP Replace with final colors -->
|
||||
<color name="mailbox_drop_available_color">#ffd9e3bd</color>
|
||||
<color name="mailbox_drop_unavailable_color">#ffffffff</color>
|
||||
<color name="mailbox_drop_target_active_color">#ffbedc62</color>
|
||||
<color name="mailbox_drop_target_destructive_color">#ffff0000</color>
|
||||
|
||||
<!-- Widget colors -->
|
||||
<color name="widget_label_shadow_color">#0d0d0d</color>
|
||||
<color name="widget_account_color">#666666</color>
|
||||
|
|
|
@ -44,6 +44,12 @@
|
|||
<dimen name="widget_subject_font_size">14sp</dimen>
|
||||
<dimen name="widget_date_font_size">14sp</dimen>
|
||||
|
||||
<dimen name="message_list_drag_offset">16dip</dimen>
|
||||
<dimen name="message_list_drag_count_font_size">42sp</dimen>
|
||||
<dimen name="message_list_drag_count_left_margin">16dip</dimen>
|
||||
<dimen name="message_list_drag_message_font_size">18sp</dimen>
|
||||
<dimen name="message_list_drag_message_right_margin">16dip</dimen>
|
||||
|
||||
<dimen name="message_compose_header_button_area_width">120dip</dimen>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -129,10 +129,8 @@
|
|||
may be too large to view.</string>
|
||||
<!-- Text shown with dragged messages to indicate how many are being dragged [CHAR LIMIT=40]-->
|
||||
<plurals name="move_messages">
|
||||
<item quantity="one">Move <xliff:g id="num_message" example="1">%1$d</xliff:g> message
|
||||
</item>
|
||||
<item quantity="other">Move <xliff:g id="num_message" example="3">%1$d</xliff:g> messages
|
||||
</item>
|
||||
<item quantity="one">Move message</item>
|
||||
<item quantity="other">Move messages</item>
|
||||
</plurals>
|
||||
<!-- Toast shown when a message(s) can't be moved because it's not supported by the POP3
|
||||
protocol. [CHAR LIMIT=none]-->
|
||||
|
|
|
@ -31,6 +31,7 @@ import android.app.LoaderManager.LoaderCallbacks;
|
|||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.Loader;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
@ -69,6 +70,10 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
// Top and bottom scroll zone size, in pixels
|
||||
private static final int SCROLL_ZONE_SIZE = 64;
|
||||
|
||||
// Colors used for drop targets
|
||||
private static Integer sDropTrashColor;
|
||||
private static Integer sDropActiveColor;
|
||||
|
||||
private long mLastLoadedAccountId = -1;
|
||||
private long mAccountId = -1;
|
||||
private long mSelectedMailboxId = -1;
|
||||
|
@ -85,11 +90,6 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
private boolean mOpenRequested;
|
||||
private boolean mResumed;
|
||||
|
||||
// Color used when we're dragging over a valid drop target
|
||||
private static final int DROP_TARGET = 0xFFFFCC33;
|
||||
// Color used when we're dragging over a "delete" target (i.e. the trash mailbox)
|
||||
private static final int DROP_TARGET_TRASH = 0xFFFF0000;
|
||||
|
||||
// True if a drag is currently in progress
|
||||
private boolean mDragInProgress = false;
|
||||
// The mailbox id of the dragged item's mailbox. We use it to prevent that box from being a
|
||||
|
@ -161,6 +161,11 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
if (savedInstanceState != null) {
|
||||
restoreInstanceState(savedInstanceState);
|
||||
}
|
||||
if (sDropTrashColor == null) {
|
||||
Resources res = getResources();
|
||||
sDropTrashColor = res.getColor(R.color.mailbox_drop_target_destructive_color);
|
||||
sDropActiveColor = res.getColor(R.color.mailbox_drop_target_active_color);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -500,10 +505,10 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
return;
|
||||
} else if (newTarget.mMailboxType == Mailbox.TYPE_TRASH) {
|
||||
Log.d("onDragLocation", "=== Mailbox " + newTarget.mMailboxId + " TRASH");
|
||||
newTarget.setBackgroundColor(DROP_TARGET_TRASH);
|
||||
newTarget.setBackgroundColor(sDropTrashColor);
|
||||
} else if (newTarget.isDropTarget(mDragItemMailboxId)) {
|
||||
Log.d("onDragLocation", "=== Mailbox " + newTarget.mMailboxId + " TARGET");
|
||||
newTarget.setBackgroundColor(DROP_TARGET);
|
||||
newTarget.setBackgroundColor(sDropActiveColor);
|
||||
} else {
|
||||
Log.d("onDragLocation", "=== Mailbox " + newTarget.mMailboxId + " (CALL)");
|
||||
targetAdapterPosition = NO_DROP_TARGET;
|
||||
|
|
|
@ -16,20 +16,21 @@
|
|||
|
||||
package com.android.email.activity;
|
||||
|
||||
import com.android.email.R;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
public class MailboxListItem extends RelativeLayout {
|
||||
// STOPSHIP Need final color/ui
|
||||
// Color used for valid drop targets
|
||||
private static final int DROP_AVAILABLE = 0xFFFFFF33;
|
||||
private static final int DROP_UNAVAILABLE = 0xFFFFFFFF;
|
||||
// Colors used for drop targets
|
||||
private static Integer sDropAvailableColor;
|
||||
private static Integer sDropUnavailableColor;
|
||||
|
||||
public long mMailboxId;
|
||||
public Integer mMailboxType;
|
||||
|
@ -53,6 +54,11 @@ public class MailboxListItem extends RelativeLayout {
|
|||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mBackground = getBackground();
|
||||
if (sDropAvailableColor == null) {
|
||||
Resources res = getResources();
|
||||
sDropAvailableColor = res.getColor(R.color.mailbox_drop_available_color);
|
||||
sDropUnavailableColor = res.getColor(R.color.mailbox_drop_unavailable_color);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDropTarget(long itemMailbox) {
|
||||
|
@ -65,10 +71,10 @@ public class MailboxListItem extends RelativeLayout {
|
|||
public boolean setDropTargetBackground(boolean dragInProgress, long itemMailbox) {
|
||||
if (dragInProgress) {
|
||||
if (isDropTarget(itemMailbox)) {
|
||||
setBackgroundColor(DROP_AVAILABLE);
|
||||
setBackgroundColor(sDropAvailableColor);
|
||||
return true;
|
||||
} else {
|
||||
setBackgroundColor(DROP_UNAVAILABLE);
|
||||
setBackgroundColor(sDropUnavailableColor);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -37,10 +37,14 @@ import android.content.ClipData;
|
|||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -55,9 +59,11 @@ import android.view.LayoutInflater;
|
|||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.DragShadowBuilder;
|
||||
import android.view.View.OnDragListener;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
|
@ -88,7 +94,7 @@ import java.util.Set;
|
|||
*/
|
||||
public class MessageListFragment extends ListFragment
|
||||
implements OnItemClickListener, OnItemLongClickListener, MessagesAdapter.Callback,
|
||||
MoveMessageToDialog.Callback, OnDragListener {
|
||||
MoveMessageToDialog.Callback, OnDragListener, OnTouchListener {
|
||||
private static final String BUNDLE_LIST_STATE = "MessageListFragment.state.listState";
|
||||
private static final String BUNDLE_KEY_SELECTED_MESSAGE_ID
|
||||
= "messageListFragment.state.listState.selected_message_id";
|
||||
|
@ -240,6 +246,7 @@ public class MessageListFragment extends ListFragment
|
|||
mListView = getListView();
|
||||
mListView.setOnItemClickListener(this);
|
||||
mListView.setOnItemLongClickListener(this);
|
||||
mListView.setOnTouchListener(this);
|
||||
mListView.setItemsCanFocus(false);
|
||||
mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
|
||||
|
@ -457,47 +464,94 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
|
||||
// This is tentative drag & drop UI
|
||||
// STOPSHIP this entire class needs to be rewritten based on the actual UI design
|
||||
private static class ShadowBuilder extends DragShadowBuilder {
|
||||
private static Drawable sBackground;
|
||||
private static TextPaint sPaint;
|
||||
/** Paint information for the move message text */
|
||||
private static TextPaint sMessagePaint;
|
||||
/** Paint information for the message count */
|
||||
private static TextPaint sCountPaint;
|
||||
/** The x location of any touch event; used to ensure the drag overlay is drawn correctly */
|
||||
private static int sTouchX;
|
||||
|
||||
// TODO Get actual dimension from UI
|
||||
private static final int mWidth = 250;
|
||||
private final int mHeight;
|
||||
private String mDragDesc;
|
||||
private float mDragDescX;
|
||||
private float mDragDescY;
|
||||
/** Width of the draggable view */
|
||||
private final int mDragWidth;
|
||||
/** Height of the draggable view */
|
||||
private final int mDragHeight;
|
||||
|
||||
private String mMessageText;
|
||||
private PointF mMessagePoint;
|
||||
|
||||
private String mCountText;
|
||||
private PointF mCountPoint;
|
||||
private int mOldOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
|
||||
/** Margin applied to the right of count text */
|
||||
private static float sCountMargin;
|
||||
/** Margin applied to left of the message text */
|
||||
private static float sMessageMargin;
|
||||
/** Vertical offset of the drag view */
|
||||
private static int sDragOffset;
|
||||
|
||||
public ShadowBuilder(View view, int count) {
|
||||
super(view);
|
||||
Resources resources = view.getResources();
|
||||
// TODO Get actual dimension from UI
|
||||
mHeight = view.getHeight();
|
||||
mDragDesc = resources.getQuantityString(R.plurals.move_messages, count, count);
|
||||
mDragDescX = 60;
|
||||
// Use height of this font??
|
||||
mDragDescY = view.getHeight() / 2;
|
||||
if (sBackground == null) {
|
||||
sBackground = resources.getDrawable(R.drawable.drag_background_holo);
|
||||
sBackground.setBounds(0, 0, mWidth, view.getHeight());
|
||||
sPaint = new TextPaint();
|
||||
sPaint.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
sPaint.setTextSize(18);
|
||||
Resources res = view.getResources();
|
||||
int newOrientation = res.getConfiguration().orientation;
|
||||
|
||||
mDragHeight = view.getHeight();
|
||||
mDragWidth = view.getWidth();
|
||||
|
||||
// TODO: Can we define a layout for the contents of the drag area?
|
||||
if (sBackground == null || mOldOrientation != newOrientation) {
|
||||
mOldOrientation = newOrientation;
|
||||
|
||||
sBackground = res.getDrawable(R.drawable.drag_background_holo);
|
||||
sBackground.setBounds(0, 0, mDragWidth, mDragHeight);
|
||||
|
||||
sDragOffset = (int)res.getDimension(R.dimen.message_list_drag_offset);
|
||||
|
||||
sMessagePaint = new TextPaint();
|
||||
float messageTextSize;
|
||||
messageTextSize = res.getDimension(R.dimen.message_list_drag_message_font_size);
|
||||
sMessagePaint.setTextSize(messageTextSize);
|
||||
sMessagePaint.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
sMessagePaint.setAntiAlias(true);
|
||||
sMessageMargin = res.getDimension(R.dimen.message_list_drag_message_right_margin);
|
||||
|
||||
sCountPaint = new TextPaint();
|
||||
float countTextSize;
|
||||
countTextSize = res.getDimension(R.dimen.message_list_drag_count_font_size);
|
||||
sCountPaint.setTextSize(countTextSize);
|
||||
sCountPaint.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
sCountPaint.setAntiAlias(true);
|
||||
sCountMargin = res.getDimension(R.dimen.message_list_drag_count_left_margin);
|
||||
}
|
||||
|
||||
// Calculate layout positions
|
||||
Rect b = new Rect();
|
||||
|
||||
mMessageText = res.getQuantityString(R.plurals.move_messages, count, count);
|
||||
sMessagePaint.getTextBounds(mMessageText, 0, mMessageText.length(), b);
|
||||
mMessagePoint = new PointF(mDragWidth - b.right - sMessageMargin,
|
||||
(mDragHeight - b.top)/ 2);
|
||||
|
||||
mCountText = Integer.toString(count);
|
||||
sCountPaint.getTextBounds(mCountText, 0, mCountText.length(), b);
|
||||
mCountPoint = new PointF(sCountMargin,
|
||||
(mDragHeight - b.top) / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
|
||||
shadowSize.set(mWidth, mHeight);
|
||||
shadowTouchPoint.set(20, mHeight / 2);
|
||||
shadowSize.set(mDragWidth, mDragHeight);
|
||||
shadowTouchPoint.set(sTouchX, (mDragHeight / 2) + sDragOffset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawShadow(Canvas canvas) {
|
||||
super.onDrawShadow(canvas);
|
||||
sBackground.draw(canvas);
|
||||
canvas.drawText(mDragDesc, mDragDescX, mDragDescY, sPaint);
|
||||
canvas.drawText(mMessageText, mMessagePoint.x, mMessagePoint.y, sMessagePaint);
|
||||
canvas.drawText(mCountText, mCountPoint.x, mCountPoint.y, sCountPaint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -512,6 +566,16 @@ public class MessageListFragment extends ListFragment
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
// Save the touch location to draw the drag overlay at the correct location
|
||||
ShadowBuilder.sTouchX = (int)event.getX();
|
||||
}
|
||||
// don't do anything, let the system process the event
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (view != mListFooterView) {
|
||||
// We can't move from combined accounts view
|
||||
|
|
Loading…
Reference in New Issue