Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20a12da3 authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev
Browse files

Adjust tooltip layout

Position a mouse hover tooltip closer to the target.
Limit tooltip width and make it multiline (maxLines=3).
Show a long press tooltip above the target, not below.

Bug: 33352391
Bug: 33353823
Bug: 33354000

Test: manual
Change-Id: Ie00353d715d73d432b5d892a0a7c04508a003a78
parent 3a8eac54
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -2477,7 +2477,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *                   1               PFLAG3_ASSIST_BLOCKED
     *                  1                PFLAG3_CLUSTER
     *                 1                 PFLAG3_SECTION
     *           xxxxxx                  * NO LONGER NEEDED, SHOULD BE REUSED *
     *                1                  PFLAG3_FINGER_DOWN
     *           xxxxx                   * NO LONGER NEEDED, SHOULD BE REUSED *
     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
     *        1                          PFLAG3_TEMPORARY_DETACH
@@ -2691,6 +2692,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    private static final int PFLAG3_SECTION = 0x10000;
    /**
     * Indicates that the user is currently touching the screen.
     * Currently used for the tooltip positioning only.
     */
    private static final int PFLAG3_FINGER_DOWN = 0x20000;
    /**
     * Whether this view has rendered elements that overlap (see {@link
     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
@@ -10661,6 +10668,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (isPressed()) {
                setPressed(false);
            }
            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
                imm.focusOut(this);
            }
@@ -11562,6 +11570,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                setPressed(false);
            }
            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
            // A disabled view that is clickable still consumes the touch
            // events, it just doesn't respond to them.
            return clickable;
@@ -11575,6 +11584,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
                        handleTooltipUp();
                    }
@@ -11639,6 +11649,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    break;
                case MotionEvent.ACTION_DOWN:
                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
                    }
                    mHasPerformedLongPress = false;
                    if (!clickable) {
@@ -11679,6 +11692,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    mInContextButtonPress = false;
                    mHasPerformedLongPress = false;
                    mIgnoreNextUpEvent = false;
                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
                    break;
                case MotionEvent.ACTION_MOVE:
@@ -11695,6 +11709,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
                            setPressed(false);
                        }
                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
                    }
                    break;
            }
@@ -24440,7 +24455,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        hideTooltip();
        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
        mTooltipInfo.mTooltipPopup.show(this, x, y, tooltipText);
        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, tooltipText);
        mAttachInfo.mTooltipHost = this;
        return true;
    }
+24 −10
Original line number Diff line number Diff line
@@ -55,14 +55,15 @@ public class TooltipPopup {
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
    }

    public void show(View anchorView, int anchorX, int anchorY, CharSequence tooltipText) {
    public void show(View anchorView, int anchorX, int anchorY, boolean fromTouch,
            CharSequence tooltipText) {
        if (isShowing()) {
            hide();
        }

        mMessageView.setText(tooltipText);

        computePosition(anchorView, anchorX, anchorY, mLayoutParams);
        computePosition(anchorView, anchorX, anchorY, fromTouch, mLayoutParams);

        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        wm.addView(mContentView, mLayoutParams);
@@ -89,7 +90,7 @@ public class TooltipPopup {
        mMessageView.setText(tooltipText);
    }

    private void computePosition(View anchorView, int anchorX, int anchorY,
    private void computePosition(View anchorView, int anchorX, int anchorY, boolean fromTouch,
            WindowManager.LayoutParams outParams) {
        final int tooltipPreciseAnchorThreshold = mContext.getResources().getDimensionPixelOffset(
                com.android.internal.R.dimen.tooltip_precise_anchor_threshold);
@@ -107,8 +108,10 @@ public class TooltipPopup {
        final int offsetAbove;
        if (anchorView.getHeight() >= tooltipPreciseAnchorThreshold) {
            // Tall view. Align the tooltip vertically to the precise Y position.
            offsetBelow = anchorY;
            offsetAbove = anchorY;
            final int offsetExtra = mContext.getResources().getDimensionPixelOffset(
                    com.android.internal.R.dimen.tooltip_precise_anchor_extra_offset);
            offsetBelow = anchorY + offsetExtra;
            offsetAbove = anchorY - offsetExtra;
        } else {
            // Otherwise anchor the tooltip to the view center.
            offsetBelow = anchorView.getHeight();  // Place below the view in most cases.
@@ -118,20 +121,31 @@ public class TooltipPopup {
        outParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;

        final int tooltipOffset = mContext.getResources().getDimensionPixelOffset(
                com.android.internal.R.dimen.tooltip_y_offset);
                fromTouch ? com.android.internal.R.dimen.tooltip_y_offset_touch
                        : com.android.internal.R.dimen.tooltip_y_offset_non_touch);

        anchorView.getWindowVisibleDisplayFrame(mTmpDisplayFrame);
        anchorView.getLocationInWindow(mTmpAnchorPos);
        outParams.x = mTmpAnchorPos[0] + offsetX - mTmpDisplayFrame.width() / 2;
        outParams.y = mTmpAnchorPos[1] + offsetBelow + tooltipOffset;

        final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        mContentView.measure(spec, spec);
        final int tooltipHeight = mContentView.getMeasuredHeight();

        if (outParams.y + tooltipHeight > mTmpDisplayFrame.height()) {
            // The tooltip does not fit below the anchor point, show above instead.
            outParams.y = mTmpAnchorPos[1] + offsetAbove - (tooltipOffset + tooltipHeight);
        final int yAbove = mTmpAnchorPos[1] + offsetAbove - tooltipOffset - tooltipHeight;
        final int yBelow = mTmpAnchorPos[1] + offsetBelow + tooltipOffset;
        if (fromTouch) {
            if (yAbove >= 0) {
                outParams.y = yAbove;
            } else {
                outParams.y = yBelow;
            }
        } else {
            if (yBelow + tooltipHeight <= mTmpDisplayFrame.height()) {
                outParams.y = yBelow;
            } else {
                outParams.y = yAbove;
            }
        }
    }
}
+5 −3
Original line number Diff line number Diff line
@@ -25,15 +25,17 @@
    <TextView
        android:id="@android:id/message"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/tooltip_height"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/tooltip_margin"
        android:paddingStart="@dimen/tooltip_horizontal_padding"
        android:paddingEnd="@dimen/tooltip_horizontal_padding"
        android:gravity="center"
        android:paddingTop="@dimen/tooltip_vertical_padding"
        android:paddingBottom="@dimen/tooltip_vertical_padding"
        android:maxWidth="256dp"
        android:background="?android:attr/tooltipFrameBackground"
        android:textAppearance="@style/TextAppearance.Tooltip"
        android:textColor="?android:attr/tooltipForegroundColor"
        android:singleLine="true"
        android:maxLines="3"
        android:ellipsize="end"
    />

+8 −4
Original line number Diff line number Diff line
@@ -489,17 +489,21 @@
    <dimen name="cascading_menus_min_smallest_width">720dp</dimen>

    <!-- Tooltip dimensions. -->
    <!-- Vertical offset from the edge of the anchor view. -->
    <dimen name="tooltip_y_offset">20dp</dimen>
    <!-- Height of the tooltip. -->
    <dimen name="tooltip_height">32dp</dimen>
    <!-- Vertical offset from the edge of the anchor view for a touch-triggered tooltip. -->
    <dimen name="tooltip_y_offset_touch">16dp</dimen>
    <!-- Vertical offset from the edge of the anchor view for a non-touch-triggered tooltip. -->
    <dimen name="tooltip_y_offset_non_touch">0dp</dimen>
    <!-- The tooltip does not get closer than this to the window edge -->
    <dimen name="tooltip_margin">8dp</dimen>
    <!-- Left/right padding of the tooltip text. -->
    <dimen name="tooltip_horizontal_padding">16dp</dimen>
    <!-- Top/bottom padding of the tooltip text. -->
    <dimen name="tooltip_vertical_padding">6.5dp</dimen>
    <!-- Border corner radius of the tooltip window. -->
    <dimen name="tooltip_corner_radius">2dp</dimen>
    <!-- View with the height equal or above this threshold will have a tooltip anchored
    to the mouse/touch position -->
    <dimen name="tooltip_precise_anchor_threshold">96dp</dimen>
    <!-- Extra tooltip offset used when anchoring to the mouse/touch position -->
    <dimen name="tooltip_precise_anchor_extra_offset">8dp</dimen>
</resources>
+3 −1
Original line number Diff line number Diff line
@@ -437,7 +437,9 @@
  <java-symbol type="dimen" name="textview_error_popup_default_width" />
  <java-symbol type="dimen" name="toast_y_offset" />
  <java-symbol type="dimen" name="tooltip_precise_anchor_threshold" />
  <java-symbol type="dimen" name="tooltip_y_offset" />
  <java-symbol type="dimen" name="tooltip_precise_anchor_extra_offset" />
  <java-symbol type="dimen" name="tooltip_y_offset_touch" />
  <java-symbol type="dimen" name="tooltip_y_offset_non_touch" />
  <java-symbol type="dimen" name="action_bar_stacked_max_height" />
  <java-symbol type="dimen" name="action_bar_stacked_tab_max_width" />
  <java-symbol type="dimen" name="notification_text_size" />