summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Gilles Debunne <debunne@google.com> 2010-11-11 11:08:59 -0800
committer Gilles Debunne <debunne@google.com> 2010-11-11 11:09:02 -0800
commitf170a345b3effa57a545938f4624d9c7142694f5 (patch)
treea94f1ec9277aecaeb03ad26abd43ded9e73be9f0
parent8e93e4f3a8922cacc04a126711291f83112e0bf7 (diff)
Added drag and drop functionality in TextViews
Basic implementation. The finger is currently hiding the insertion position. An offset has to be added in DragThumbnailBuilder to prevent this. Change-Id: I4207c337a2a31162063fba191a5eb5d5856b24cf
-rw-r--r--core/java/android/widget/TextView.java104
-rw-r--r--core/res/res/layout/text_drag_thumbnail.xml26
2 files changed, 121 insertions, 9 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3838a02d1caa..acefe5db2153 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -23,6 +23,7 @@ import org.xmlpull.v1.XmlPullParserException;
import android.R;
import android.content.ClipData;
+import android.content.ClipData.Item;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -88,6 +89,7 @@ import android.util.Log;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ContextMenu;
+import android.view.DragEvent;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@@ -6731,10 +6733,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mMovement.onTakeFocus(this, (Spannable) mText, direction);
}
- if (mSelectAllOnFocus) {
- Selection.setSelection((Spannable) mText, 0, mText.length());
- }
-
// The DecorView does not have focus when the 'Done' ExtractEditText button is
// pressed. Since it is the ViewRoot's mView, it requests focus before
// ExtractEditText clears focus, which gives focus to the ExtractEditText.
@@ -6753,6 +6751,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
Selection.setSelection((Spannable) mText, selStart, selEnd);
}
+
+ if (mSelectAllOnFocus) {
+ Selection.setSelection((Spannable) mText, 0, mText.length());
+ }
+
mTouchFocusSelected = true;
}
@@ -7029,12 +7032,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|| windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
}
- // TODO Add an extra android:cursorController flag to disable the controller?
- if (windowSupportsHandles && mCursorVisible && mLayout != null) {
+ if (windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null) {
if (mInsertionPointCursorController == null) {
mInsertionPointCursorController = new InsertionPointCursorController();
}
} else {
+ hideInsertionPointCursorController();
mInsertionPointCursorController = null;
}
@@ -7044,7 +7047,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
} else {
// Stop selection mode if the controller becomes unavailable.
- stopSelectionActionMode();
+ if (mSelectionModifierCursorController != null) {
+ stopSelectionActionMode();
+ }
mSelectionModifierCursorController = null;
}
}
@@ -7053,7 +7058,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @return True iff this TextView contains a text that can be edited.
*/
private boolean isTextEditable() {
- return mText instanceof Editable && onCheckIsTextEditor();
+ return mText instanceof Editable && onCheckIsTextEditor() && isEnabled();
}
/**
@@ -7684,13 +7689,53 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return packRangeInLong(min, max);
}
+ private DragThumbnailBuilder getTextThumbnailBuilder(CharSequence text) {
+ TextView thumbnail = (TextView) inflate(mContext,
+ com.android.internal.R.layout.text_drag_thumbnail, null);
+
+ if (thumbnail == null) {
+ throw new IllegalArgumentException("Unable to inflate text drag thumbnail");
+ }
+
+ if (text.length() > DRAG_THUMBNAIL_MAX_TEXT_LENGTH) {
+ text = text.subSequence(0, DRAG_THUMBNAIL_MAX_TEXT_LENGTH);
+ }
+ thumbnail.setText(text);
+ thumbnail.setTextColor(getTextColors());
+
+ thumbnail.setTextAppearance(mContext, R.styleable.Theme_textAppearanceLarge);
+ thumbnail.setGravity(Gravity.CENTER);
+
+ thumbnail.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+ thumbnail.measure(size, size);
+
+ thumbnail.layout(0, 0, thumbnail.getMeasuredWidth(), thumbnail.getMeasuredHeight());
+ thumbnail.invalidate();
+ return new DragThumbnailBuilder(thumbnail);
+ }
+
@Override
public boolean performLongClick() {
if (super.performLongClick()) {
mEatTouchRelease = true;
return true;
}
-
+
+ if (mSelectionActionMode != null && touchPositionIsInSelection()) {
+ final int start = getSelectionStart();
+ final int end = getSelectionEnd();
+ CharSequence selectedText = mTransformed.subSequence(start, end);
+ ClipData data = ClipData.newPlainText(null, null, selectedText);
+ startDrag(data, getTextThumbnailBuilder(selectedText), false);
+ stopSelectionActionMode();
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ mEatTouchRelease = true;
+ return true;
+ }
+
if (startSelectionActionMode()) {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
mEatTouchRelease = true;
@@ -8728,6 +8773,46 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return getOffsetForHorizontal(line, x);
}
+ @Override
+ public boolean onDragEvent(DragEvent event) {
+ switch (event.getAction()) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ return mInsertionPointCursorController != null;
+
+ case DragEvent.ACTION_DRAG_ENTERED:
+ TextView.this.requestFocus();
+ return true;
+
+ case DragEvent.ACTION_DRAG_LOCATION: {
+ final int offset = getOffset((int)event.getX(), (int)event.getY());
+ Selection.setSelection((Spannable)mText, offset);
+ return true;
+ }
+
+ case DragEvent.ACTION_DROP: {
+ StringBuilder content = new StringBuilder("");
+ ClipData clipData = event.getClipData();
+ final int itemCount = clipData.getItemCount();
+ for (int i=0; i < itemCount; i++) {
+ Item item = clipData.getItem(i);
+ content.append(item.coerceToText(TextView.this.mContext));
+ }
+ final int offset = getOffset((int) event.getX(), (int) event.getY());
+ long minMax = prepareSpacesAroundPaste(offset, offset, content);
+ int min = extractRangeStartFromLong(minMax);
+ int max = extractRangeEndFromLong(minMax);
+ Selection.setSelection((Spannable) mText, max);
+ ((Editable) mText).replace(min, max, content);
+ return true;
+ }
+
+ case DragEvent.ACTION_DRAG_EXITED:
+ case DragEvent.ACTION_DRAG_ENDED:
+ default:
+ return true;
+ }
+ }
+
@ViewDebug.ExportedProperty(category = "text")
private CharSequence mText;
@@ -8822,4 +8907,5 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
private InputFilter[] mFilters = NO_FILTERS;
private static final Spanned EMPTY_SPANNED = new SpannedString("");
+ private static int DRAG_THUMBNAIL_MAX_TEXT_LENGTH = 20;
}
diff --git a/core/res/res/layout/text_drag_thumbnail.xml b/core/res/res/layout/text_drag_thumbnail.xml
new file mode 100644
index 000000000000..63d2c05b539e
--- /dev/null
+++ b/core/res/res/layout/text_drag_thumbnail.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 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.
+*/
+-->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Large"
+ android:gravity="center"
+ />