summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/DownloadManager.java110
-rw-r--r--core/java/android/hardware/Camera.java54
-rw-r--r--core/java/android/provider/Downloads.java54
-rw-r--r--core/java/android/widget/PopupWindow.java30
-rw-r--r--core/java/android/widget/TextView.java60
5 files changed, 215 insertions, 93 deletions
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index c6fef4f..3ec21ff 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -100,16 +100,23 @@ public class DownloadManager {
public final static String COLUMN_STATUS = "status";
/**
- * Indicates the type of error that occurred, when {@link #COLUMN_STATUS} is
- * {@link #STATUS_FAILED}. If an HTTP error occurred, this will hold the HTTP status code as
- * defined in RFC 2616. Otherwise, it will hold one of the ERROR_* constants.
+ * Provides more detail on the status of the download. Its meaning depends on the value of
+ * {@link #COLUMN_STATUS}.
*
- * If {@link #COLUMN_STATUS} is not {@link #STATUS_FAILED}, this column's value is undefined.
+ * When {@link #COLUMN_STATUS} is {@link #STATUS_FAILED}, this indicates the type of error that
+ * occurred. If an HTTP error occurred, this will hold the HTTP status code as defined in RFC
+ * 2616. Otherwise, it will hold one of the ERROR_* constants.
+ *
+ * When {@link #COLUMN_STATUS} is {@link #STATUS_PAUSED}, this indicates why the download is
+ * paused. It will hold one of the PAUSED_* constants.
+ *
+ * If {@link #COLUMN_STATUS} is neither {@link #STATUS_FAILED} nor {@link #STATUS_PAUSED}, this
+ * column's value is undefined.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1">RFC 2616
* status codes</a>
*/
- public final static String COLUMN_ERROR_CODE = "error_code";
+ public final static String COLUMN_REASON = "reason";
/**
* Number of bytes download so far.
@@ -156,54 +163,77 @@ public class DownloadManager {
public final static int ERROR_UNKNOWN = 1000;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when a storage issue arises which doesn't fit under any
+ * Value of {@link #COLUMN_REASON} when a storage issue arises which doesn't fit under any
* other error code. Use the more specific {@link #ERROR_INSUFFICIENT_SPACE} and
* {@link #ERROR_DEVICE_NOT_FOUND} when appropriate.
*/
public final static int ERROR_FILE_ERROR = 1001;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when an HTTP code was received that download manager
+ * Value of {@link #COLUMN_REASON} when an HTTP code was received that download manager
* can't handle.
*/
public final static int ERROR_UNHANDLED_HTTP_CODE = 1002;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when an error receiving or processing data occurred at
+ * Value of {@link #COLUMN_REASON} when an error receiving or processing data occurred at
* the HTTP level.
*/
public final static int ERROR_HTTP_DATA_ERROR = 1004;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when there were too many redirects.
+ * Value of {@link #COLUMN_REASON} when there were too many redirects.
*/
public final static int ERROR_TOO_MANY_REDIRECTS = 1005;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when there was insufficient storage space. Typically,
+ * Value of {@link #COLUMN_REASON} when there was insufficient storage space. Typically,
* this is because the SD card is full.
*/
public final static int ERROR_INSUFFICIENT_SPACE = 1006;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when no external storage device was found. Typically,
+ * Value of {@link #COLUMN_REASON} when no external storage device was found. Typically,
* this is because the SD card is not mounted.
*/
public final static int ERROR_DEVICE_NOT_FOUND = 1007;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when some possibly transient error occurred but we can't
+ * Value of {@link #COLUMN_REASON} when some possibly transient error occurred but we can't
* resume the download.
*/
public final static int ERROR_CANNOT_RESUME = 1008;
/**
- * Value of {@link #COLUMN_ERROR_CODE} when the requested destination file already exists (the
+ * Value of {@link #COLUMN_REASON} when the requested destination file already exists (the
* download manager will not overwrite an existing file).
*/
public final static int ERROR_FILE_ALREADY_EXISTS = 1009;
/**
+ * Value of {@link #COLUMN_REASON} when the download is paused because some network error
+ * occurred and the download manager is waiting before retrying the request.
+ */
+ public final static int PAUSED_WAITING_TO_RETRY = 1;
+
+ /**
+ * Value of {@link #COLUMN_REASON} when the download is waiting for network connectivity to
+ * proceed.
+ */
+ public final static int PAUSED_WAITING_FOR_NETWORK = 2;
+
+ /**
+ * Value of {@link #COLUMN_REASON} when the download exceeds a size limit for downloads over
+ * the mobile network and the download manager is waiting for a Wi-Fi connection to proceed.
+ */
+ public final static int PAUSED_QUEUED_FOR_WIFI = 3;
+
+ /**
+ * Value of {@link #COLUMN_REASON} when the download is paused for some other reason.
+ */
+ public final static int PAUSED_UNKNOWN = 4;
+
+ /**
* Broadcast intent action sent by the download manager when a download completes.
*/
public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
@@ -236,7 +266,7 @@ public class DownloadManager {
COLUMN_TOTAL_SIZE_BYTES,
COLUMN_LOCAL_URI,
COLUMN_STATUS,
- COLUMN_ERROR_CODE,
+ COLUMN_REASON,
COLUMN_BYTES_DOWNLOADED_SO_FAR,
COLUMN_LAST_MODIFIED_TIMESTAMP
};
@@ -258,7 +288,7 @@ public class DownloadManager {
};
private static final Set<String> LONG_COLUMNS = new HashSet<String>(
- Arrays.asList(COLUMN_ID, COLUMN_TOTAL_SIZE_BYTES, COLUMN_STATUS, COLUMN_ERROR_CODE,
+ Arrays.asList(COLUMN_ID, COLUMN_TOTAL_SIZE_BYTES, COLUMN_STATUS, COLUMN_REASON,
COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP));
/**
@@ -617,8 +647,10 @@ public class DownloadManager {
parts.add(statusClause("=", Downloads.STATUS_RUNNING));
}
if ((mStatusFlags & STATUS_PAUSED) != 0) {
- parts.add(statusClause("=", Downloads.STATUS_PENDING_PAUSED));
- parts.add(statusClause("=", Downloads.STATUS_RUNNING_PAUSED));
+ parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_APP));
+ parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY));
+ parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK));
+ parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI));
}
if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) {
parts.add(statusClause("=", Downloads.STATUS_SUCCESS));
@@ -914,8 +946,8 @@ public class DownloadManager {
if (column.equals(COLUMN_STATUS)) {
return translateStatus((int) getUnderlyingLong(Downloads.COLUMN_STATUS));
}
- if (column.equals(COLUMN_ERROR_CODE)) {
- return translateErrorCode((int) getUnderlyingLong(Downloads.COLUMN_STATUS));
+ if (column.equals(COLUMN_REASON)) {
+ return getReason((int) getUnderlyingLong(Downloads.COLUMN_STATUS));
}
if (column.equals(COLUMN_BYTES_DOWNLOADED_SO_FAR)) {
return getUnderlyingLong(Downloads.COLUMN_CURRENT_BYTES);
@@ -924,10 +956,36 @@ public class DownloadManager {
return getUnderlyingLong(Downloads.COLUMN_LAST_MODIFICATION);
}
- private long translateErrorCode(int status) {
- if (translateStatus(status) != STATUS_FAILED) {
- return 0; // arbitrary value when status is not an error
+ private long getReason(int status) {
+ switch (translateStatus(status)) {
+ case STATUS_FAILED:
+ return getErrorCode(status);
+
+ case STATUS_PAUSED:
+ return getPausedReason(status);
+
+ default:
+ return 0; // arbitrary value when status is not an error
}
+ }
+
+ private long getPausedReason(int status) {
+ switch (status) {
+ case Downloads.Impl.STATUS_WAITING_TO_RETRY:
+ return PAUSED_WAITING_TO_RETRY;
+
+ case Downloads.Impl.STATUS_WAITING_FOR_NETWORK:
+ return PAUSED_WAITING_FOR_NETWORK;
+
+ case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
+ return PAUSED_QUEUED_FOR_WIFI;
+
+ default:
+ return PAUSED_UNKNOWN;
+ }
+ }
+
+ private long getErrorCode(int status) {
if ((400 <= status && status < Downloads.Impl.MIN_ARTIFICIAL_ERROR_STATUS)
|| (500 <= status && status < 600)) {
// HTTP status code
@@ -973,7 +1031,7 @@ public class DownloadManager {
return super.getString(super.getColumnIndex(column));
}
- private long translateStatus(int status) {
+ private int translateStatus(int status) {
switch (status) {
case Downloads.STATUS_PENDING:
return STATUS_PENDING;
@@ -981,8 +1039,10 @@ public class DownloadManager {
case Downloads.STATUS_RUNNING:
return STATUS_RUNNING;
- case Downloads.STATUS_PENDING_PAUSED:
- case Downloads.STATUS_RUNNING_PAUSED:
+ case Downloads.Impl.STATUS_PAUSED_BY_APP:
+ case Downloads.Impl.STATUS_WAITING_TO_RETRY:
+ case Downloads.Impl.STATUS_WAITING_FOR_NETWORK:
+ case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
return STATUS_PAUSED;
case Downloads.STATUS_SUCCESS:
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 0d8228c..7b930d5 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -181,6 +181,7 @@ public class Camera {
* value should be 90.
*
* @see #setDisplayOrientation(int)
+ * @see #setRotation(int)
*/
public int orientation;
};
@@ -1716,23 +1717,46 @@ public class Camera {
}
/**
- * Sets the orientation of the device in degrees. For example, suppose
- * the natural position of the device is landscape. If the user takes a
- * picture in landscape mode in 2048x1536 resolution, the rotation
- * should be set to 0. If the user rotates the phone 90 degrees
- * clockwise, the rotation should be set to 90. Applications can use
- * {@link android.view.OrientationEventListener} to set this parameter.
- *
- * The camera driver may set orientation in the EXIF header without
- * rotating the picture. Or the driver may rotate the picture and
- * the EXIF thumbnail. If the Jpeg picture is rotated, the orientation
- * in the EXIF header will be missing or 1 (row #0 is top and column #0
- * is left side).
- *
- * @param rotation The orientation of the device in degrees. Rotation
- * can only be 0, 90, 180 or 270.
+ * Sets the rotation angle in degrees relative to the orientation of
+ * the camera. This affects the pictures returned from JPEG {@link
+ * PictureCallback}. The camera driver may set orientation in the
+ * EXIF header without rotating the picture. Or the driver may rotate
+ * the picture and the EXIF thumbnail. If the Jpeg picture is rotated,
+ * the orientation in the EXIF header will be missing or 1 (row #0 is
+ * top and column #0 is left side).
+ *
+ * If appplications want to rotate the picture to match the
+ * orientation of what users see, apps should use {@link
+ * android.view.OrientationEventListener} and {@link CameraInfo}.
+ * The value from OrientationEventListener is relative to the natural
+ * orientation of the device. CameraInfo.mOrientation is the angle
+ * between camera orientation and natural device orientation. The sum
+ * of the two is the angle for rotation.
+ *
+ * For example, suppose the natural orientation of the device is
+ * portrait. The device is rotated 270 degrees clockwise, so the device
+ * orientation is 270. Suppose the camera sensor is mounted in landscape
+ * and the top side of the camera sensor is aligned with the right edge
+ * of the display in natural orientation. So the camera orientation is
+ * 90. The rotation should be set to 0 (270 + 90).
+ *
+ * The reference code is as follows.
+ *
+ * public void public void onOrientationChanged(int orientation) {
+ * if (orientation == ORIENTATION_UNKNOWN) return;
+ * android.hardware.Camera.CameraInfo info =
+ * new android.hardware.Camera.CameraInfo();
+ * android.hardware.Camera.getCameraInfo(cameraId, info);
+ * orientation = (orientation + 45) / 90 * 90;
+ * mParameters.setRotation((orientation + info.mOrientation) % 360);
+ * }
+ *
+ * @param rotation The rotation angle in degrees relative to the
+ * orientation of the camera. Rotation can only be 0,
+ * 90, 180 or 270.
* @throws IllegalArgumentException if rotation value is invalid.
* @see android.view.OrientationEventListener
+ * @see #getCameraInfo(int, CameraInfo)
*/
public void setRotation(int rotation) {
if (rotation == 0 || rotation == 90 || rotation == 180
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 1e358c9..8fd0e0a 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -378,16 +378,6 @@ public final class Downloads {
}
/**
- * Returns whether the download is suspended. (i.e. whether the download
- * won't complete without some action from outside the download
- * manager).
- * @hide
- */
- public static boolean isStatusSuspended(int status) {
- return (status == STATUS_PENDING_PAUSED || status == STATUS_RUNNING_PAUSED);
- }
-
- /**
* Returns whether the status is a success (i.e. 2xx).
* @hide
*/
@@ -435,24 +425,12 @@ public final class Downloads {
public static final int STATUS_PENDING = 190;
/**
- * This download hasn't stated yet and is paused
- * @hide
- */
- public static final int STATUS_PENDING_PAUSED = 191;
-
- /**
* This download has started
* @hide
*/
public static final int STATUS_RUNNING = 192;
/**
- * This download has started and is paused
- * @hide
- */
- public static final int STATUS_RUNNING_PAUSED = 193;
-
- /**
* This download has successfully completed.
* Warning: there might be other status values that indicate success
* in the future.
@@ -980,15 +958,6 @@ public final class Downloads {
}
/**
- * Returns whether the download is suspended. (i.e. whether the download
- * won't complete without some action from outside the download
- * manager).
- */
- public static boolean isStatusSuspended(int status) {
- return (status == STATUS_PENDING_PAUSED || status == STATUS_RUNNING_PAUSED);
- }
-
- /**
* Returns whether the status is a success (i.e. 2xx).
*/
public static boolean isStatusSuccess(int status) {
@@ -1030,19 +999,30 @@ public final class Downloads {
public static final int STATUS_PENDING = 190;
/**
- * This download hasn't stated yet and is paused
+ * This download has started
*/
- public static final int STATUS_PENDING_PAUSED = 191;
+ public static final int STATUS_RUNNING = 192;
/**
- * This download has started
+ * This download has been paused by the owning app.
*/
- public static final int STATUS_RUNNING = 192;
+ public static final int STATUS_PAUSED_BY_APP = 193;
+
+ /**
+ * This download encountered some network error and is waiting before retrying the request.
+ */
+ public static final int STATUS_WAITING_TO_RETRY = 194;
+
+ /**
+ * This download is waiting for network connectivity to proceed.
+ */
+ public static final int STATUS_WAITING_FOR_NETWORK = 195;
/**
- * This download has started and is paused
+ * This download exceeded a size limit for mobile networks and is waiting for a Wi-Fi
+ * connection to proceed.
*/
- public static final int STATUS_RUNNING_PAUSED = 193;
+ public static final int STATUS_QUEUED_FOR_WIFI = 196;
/**
* This download has successfully completed.
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 7fe6190..ed15e25 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -86,6 +86,7 @@ public class PopupWindow {
private boolean mOutsideTouchable = false;
private boolean mClippingEnabled = true;
private boolean mSplitTouchEnabled;
+ private boolean mLayoutInScreen;
private OnTouchListener mTouchInterceptor;
@@ -596,6 +597,29 @@ public class PopupWindow {
}
/**
+ * <p>Indicates whether the popup window will be forced into using absolute screen coordinates
+ * for positioning.</p>
+ *
+ * @return true if the window will always be positioned in screen coordinates.
+ * @hide
+ */
+ public boolean isLayoutInScreenEnabled() {
+ return mLayoutInScreen;
+ }
+
+ /**
+ * <p>Allows the popup window to force the flag
+ * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}, overriding default behavior.
+ * This will cause the popup to be positioned in absolute screen coordinates.</p>
+ *
+ * @param enabled true if the popup should always be positioned in screen coordinates
+ * @hide
+ */
+ public void setLayoutInScreenEnabled(boolean enabled) {
+ mLayoutInScreen = enabled;
+ }
+
+ /**
* <p>Change the width and height measure specs that are given to the
* window manager by the popup. By default these are 0, meaning that
* the current width or height is requested as an explicit size from
@@ -899,7 +923,8 @@ public class PopupWindow {
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
+ WindowManager.LayoutParams.FLAG_SPLIT_TOUCH);
if(mIgnoreCheekPress) {
curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
}
@@ -923,6 +948,9 @@ public class PopupWindow {
if (mSplitTouchEnabled) {
curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
}
+ if (mLayoutInScreen) {
+ curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ }
return curFlags;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6278192..8291d57 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3768,6 +3768,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mError != null) {
hideError();
}
+
+ hideControllers();
}
@Override
@@ -4118,6 +4120,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
canvas.restore();
+
+ if (mInsertionPointCursorController != null &&
+ mInsertionPointCursorController.isShowing()) {
+ mInsertionPointCursorController.updatePosition();
+ }
+ if (mSelectionModifierCursorController != null &&
+ mSelectionModifierCursorController.isShowing()) {
+ mSelectionModifierCursorController.updatePosition();
+ }
}
@Override
@@ -4736,6 +4747,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mInputMethodState != null) {
mInputMethodState.mExtracting = req;
}
+ hideControllers();
}
/**
@@ -6266,7 +6278,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
sendOnTextChanged(buffer, start, before, after);
onTextChanged(buffer, start, before, after);
- hideControllers();
+
+ // Hide the controller if the amount of content changed
+ if (before != after) {
+ hideControllers();
+ }
}
/**
@@ -6605,11 +6621,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mInputContentType != null) {
mInputContentType.enterDown = false;
}
+ hideControllers();
}
startStopMarquee(hasWindowFocus);
}
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ if (visibility != VISIBLE) {
+ hideControllers();
+ }
+ }
+
/**
* Use {@link BaseInputConnection#removeComposingSpans
* BaseInputConnection.removeComposingSpans()} to remove any IME composing
@@ -6679,8 +6704,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (hasSelection()) {
startTextSelectionMode();
- } else if (mInsertionPointCursorController != null) {
- mInsertionPointCursorController.show();
}
}
}
@@ -7645,6 +7668,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private int mPositionY;
private CursorController mController;
private boolean mIsDragging;
+ private int mOffsetX;
+ private int mOffsetY;
public HandleView(CursorController controller, Drawable handle) {
super(TextView.this.mContext);
@@ -7653,6 +7678,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mContainer = new PopupWindow(TextView.this.mContext, null,
com.android.internal.R.attr.textSelectHandleWindowStyle);
mContainer.setSplitTouchEnabled(true);
+ mContainer.setClippingEnabled(false);
+ mContainer.setLayoutInScreenEnabled(true);
}
@Override
@@ -7690,19 +7717,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int compoundPaddingRight = getCompoundPaddingRight();
final TextView hostView = TextView.this;
- final int right = hostView.mRight;
- final int left = hostView.mLeft;
- final int bottom = hostView.mBottom;
- final int top = hostView.mTop;
+ final int handleWidth = mDrawable.getIntrinsicWidth();
+ final int left = 0;
+ final int right = hostView.getWidth();
+ final int top = 0;
+ final int bottom = hostView.getHeight();
- final int clipLeft = left + compoundPaddingLeft;
+ final int clipLeft = left + compoundPaddingLeft - (int) (handleWidth * 0.75f);
final int clipTop = top + extendedPaddingTop;
- final int clipRight = right - compoundPaddingRight;
+ final int clipRight = right - compoundPaddingRight + (int) (handleWidth * 0.25f);
final int clipBottom = bottom - extendedPaddingBottom;
- final int handleWidth = mDrawable.getIntrinsicWidth();
- return mPositionX >= clipLeft - handleWidth * 0.75f &&
- mPositionX <= clipRight + handleWidth * 0.25f &&
+ return mPositionX >= clipLeft && mPositionX <= clipRight &&
mPositionY >= clipTop && mPositionY <= clipBottom;
}
@@ -7741,6 +7767,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
+ mOffsetX = (int) (ev.getX() - mDrawable.getIntrinsicWidth() / 2.f + 0.5f);
+ mOffsetY = (int) (ev.getY() - mDrawable.getIntrinsicHeight() / 2.f + 0.5f);
mIsDragging = true;
break;
@@ -7749,8 +7777,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final float rawY = ev.getRawY();
final int[] coords = mTempCoords;
TextView.this.getLocationOnScreen(coords);
- final int x = (int) (rawX - coords[0] + 0.5f);
- final int y = (int) (rawY - coords[1] + 0.5f);
+ final int x = (int) (rawX - coords[0] + 0.5f) - mOffsetX;
+ final int y = (int) (rawY - coords[1] + 0.5f) -
+ (int) (mDrawable.getIntrinsicHeight() * 0.8f) - mOffsetY;
+
mController.updatePosition(this, x, y);
break;
@@ -8059,7 +8089,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int previousLine = layout.getLineForOffset(previousOffset);
final int previousLineTop = layout.getLineTop(previousLine);
final int previousLineBottom = layout.getLineBottom(previousLine);
- final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 2;
+ final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 6;
// If new line is just before or after previous line and y position is less than
// hysteresisThreshold away from previous line, keep cursor on previous line.