Correct drag & drop mechanics; implement multiple selection
* This CL brings drag&drop move in line with the current document describing its functionality in the Email app Bug: 3135124 TODO: Assets and proper creation of the drag thumbnail based on those assets TODO: Review long-press behavior re: press on subject vs sender Change-Id: I6e1ee1a1f055feb041a0338f2f5c775a88620595
This commit is contained in:
parent
138abe82e6
commit
bad09c18d9
@ -30,19 +30,9 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerVertical="true"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/handle"
|
||||
android:layout_toRightOf="@id/chip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="10dip"
|
||||
android:paddingRight="5dip"
|
||||
android:src="@drawable/drag_handle"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/selected"
|
||||
android:layout_toRightOf="@id/handle"
|
||||
android:layout_toRightOf="@id/chip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
|
@ -24,34 +24,47 @@ import com.android.email.Utility;
|
||||
import com.android.email.Utility.ListStateSaver;
|
||||
import com.android.email.data.MailboxAccountLoader;
|
||||
import com.android.email.provider.EmailContent;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.provider.EmailContent.Account;
|
||||
import com.android.email.provider.EmailContent.Mailbox;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
import com.android.email.service.MailService;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ListFragment;
|
||||
import android.app.LoaderManager;
|
||||
import android.content.ClipData;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextPaint;
|
||||
import android.util.Log;
|
||||
import android.view.ActionMode;
|
||||
import android.view.DragEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.DragThumbnailBuilder;
|
||||
import android.view.View.OnDragListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.AdapterView.OnItemLongClickListener;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.AdapterView.OnItemLongClickListener;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.HashSet;
|
||||
@ -75,7 +88,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class MessageListFragment extends ListFragment
|
||||
implements OnItemClickListener, OnItemLongClickListener, MessagesAdapter.Callback,
|
||||
MoveMessageToDialog.Callback {
|
||||
MoveMessageToDialog.Callback, OnDragListener {
|
||||
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";
|
||||
@ -425,9 +438,89 @@ 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 ThumbnailBuilder extends DragThumbnailBuilder {
|
||||
private static Drawable sBackground;
|
||||
private static TextPaint sPaint;
|
||||
|
||||
// TODO Get actual dimention from UI
|
||||
private static final int mWidth = 250;
|
||||
private final int mHeight;
|
||||
private String mDragDesc;
|
||||
private float mDragDescX;
|
||||
private float mDragDescY;
|
||||
|
||||
public ThumbnailBuilder(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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
|
||||
thumbnailSize.set(mWidth, (int) mHeight);
|
||||
thumbnailTouchPoint.set((int) 20, (int) mHeight / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawThumbnail(Canvas canvas) {
|
||||
super.onDrawThumbnail(canvas);
|
||||
sBackground.draw(canvas);
|
||||
canvas.drawText(mDragDesc, mDragDescX, mDragDescY, sPaint);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onDrag(View view, DragEvent event) {
|
||||
switch(event.getAction()) {
|
||||
case DragEvent.ACTION_DRAG_ENDED:
|
||||
if (event.getResult()) {
|
||||
finishSelectionMode();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (view != mListFooterView) {
|
||||
toggleSelection((MessageListItem) view);
|
||||
MessageListItem listItem = (MessageListItem)view;
|
||||
if (!mListAdapter.isSelected(listItem)) {
|
||||
toggleSelection(listItem);
|
||||
}
|
||||
// Create ClipData with the Uri of the message we're long clicking
|
||||
ClipData data = ClipData.newUri(mActivity.getContentResolver(),
|
||||
MessageListItem.MESSAGE_LIST_ITEMS_CLIP_LABEL, null,
|
||||
Message.CONTENT_URI.buildUpon()
|
||||
.appendPath(Long.toString(listItem.mMessageId))
|
||||
.appendQueryParameter(
|
||||
EmailProvider.MESSAGE_URI_PARAMETER_MAILBOX_ID,
|
||||
Long.toString(mMailboxId))
|
||||
.build());
|
||||
Set<Long> selectedMessageIds = mListAdapter.getSelectedSet();
|
||||
int size = selectedMessageIds.size();
|
||||
// Add additional Uri's for any other selected messages
|
||||
for (Long messageId: selectedMessageIds) {
|
||||
if (messageId.longValue() != listItem.mMessageId) {
|
||||
data.addItem(new ClipData.Item(
|
||||
ContentUris.withAppendedId(Message.CONTENT_URI, messageId)));
|
||||
}
|
||||
}
|
||||
// Start dragging now
|
||||
listItem.setOnDragListener(this);
|
||||
listItem.startDrag(data, new ThumbnailBuilder(listItem, size), false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -17,22 +17,10 @@
|
||||
package com.android.email.activity;
|
||||
|
||||
import com.android.email.R;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.provider.EmailContent.Message;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
/**
|
||||
@ -41,7 +29,6 @@ import android.widget.RelativeLayout;
|
||||
* 2. It handles internal clicks such as the checkbox or the favorite star
|
||||
*/
|
||||
public class MessageListItem extends RelativeLayout {
|
||||
private static final String TAG = "MessageListItem";
|
||||
// Note: messagesAdapter directly fiddles with these fields.
|
||||
/* package */ long mMessageId;
|
||||
/* package */ long mMailboxId;
|
||||
@ -53,7 +40,6 @@ public class MessageListItem extends RelativeLayout {
|
||||
|
||||
private boolean mDownEvent;
|
||||
private boolean mCachedViewPositions;
|
||||
private int mDragRight = -1;
|
||||
private int mCheckRight;
|
||||
private int mStarLeft;
|
||||
|
||||
@ -86,59 +72,6 @@ public class MessageListItem extends RelativeLayout {
|
||||
mCachedViewPositions = false;
|
||||
}
|
||||
|
||||
// This is tentative drag & drop UI
|
||||
// STOPSHIP this entire class needs to be rewritten based on the actual UI design
|
||||
private static class ThumbnailBuilder extends DragThumbnailBuilder {
|
||||
private static Drawable sBackground;
|
||||
private static TextPaint sPaint;
|
||||
|
||||
private View mView;
|
||||
private static final int mWidth = 250;
|
||||
private final Bitmap mDragHandle;
|
||||
private final float mDragHandleX;
|
||||
private final float mDragHandleY;
|
||||
private String mDragDesc;
|
||||
private float mDragDescX;
|
||||
private float mDragDescY;
|
||||
|
||||
public ThumbnailBuilder(View view, int count) {
|
||||
super(view);
|
||||
Resources resources = view.getResources();
|
||||
mView = view;
|
||||
mDragHandle = BitmapFactory.decodeResource(resources, R.drawable.drag_handle);
|
||||
mDragHandleY = view.getHeight() - (mDragHandle.getHeight() / 2);
|
||||
View handleView = view.findViewById(R.id.handle);
|
||||
mDragHandleX = handleView.getLeft() + handleView.getPaddingLeft();
|
||||
mDragDesc = resources.getQuantityString(R.plurals.move_messages, count, count);
|
||||
mDragDescX = handleView.getRight() + 50;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
|
||||
//float width = mView.getWidth();
|
||||
float height = mView.getHeight();
|
||||
thumbnailSize.set(mWidth, (int) height);
|
||||
thumbnailTouchPoint.set((int) mDragHandleX, (int) mDragHandleY / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawThumbnail(Canvas canvas) {
|
||||
super.onDrawThumbnail(canvas);
|
||||
sBackground.draw(canvas);
|
||||
canvas.drawBitmap(mDragHandle, mDragHandleX, mDragHandleY, sPaint);
|
||||
canvas.drawText(mDragDesc, mDragDescX, mDragDescY, sPaint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overriding this method allows us to "catch" clicks in the checkbox or star
|
||||
* and process them accordingly.
|
||||
@ -152,10 +85,6 @@ public class MessageListItem extends RelativeLayout {
|
||||
final float paddingScale = getContext().getResources().getDisplayMetrics().density;
|
||||
final int checkPadding = (int) ((CHECKMARK_PAD * paddingScale) + 0.5);
|
||||
final int starPadding = (int) ((STAR_PAD * paddingScale) + 0.5);
|
||||
View dragHandle = findViewById(R.id.handle);
|
||||
if (dragHandle != null) {
|
||||
mDragRight = dragHandle.getRight();
|
||||
}
|
||||
mCheckRight = findViewById(R.id.selected).getRight() + checkPadding;
|
||||
mStarLeft = findViewById(R.id.favorite).getLeft() - starPadding;
|
||||
mCachedViewPositions = true;
|
||||
@ -163,20 +92,7 @@ public class MessageListItem extends RelativeLayout {
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (touchX < mDragRight) {
|
||||
Context context = getContext();
|
||||
// Drag
|
||||
ClipData data = ClipData.newUri(context.getContentResolver(),
|
||||
MessageListItem.MESSAGE_LIST_ITEMS_CLIP_LABEL, null,
|
||||
Message.CONTENT_URI.buildUpon()
|
||||
.appendPath(Long.toString(mMessageId))
|
||||
.appendQueryParameter(
|
||||
EmailProvider.MESSAGE_URI_PARAMETER_MAILBOX_ID,
|
||||
Long.toString(mMailboxId))
|
||||
.build());
|
||||
startDrag(data, new ThumbnailBuilder(this, 1), false);
|
||||
handled = true;
|
||||
} else {
|
||||
if (touchX < mCheckRight) {
|
||||
mDownEvent = true;
|
||||
if ((touchX < mCheckRight) || (touchX > mStarLeft)) {
|
||||
handled = true;
|
||||
|
Loading…
Reference in New Issue
Block a user