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

Commit 1d3d6a44 authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Implement lift-to-type for phone dialer accessibility." into jb-mr1-dev

parents 2ce27f49 a0d05523
Loading
Loading
Loading
Loading
+68 −4
Original line number Diff line number Diff line
@@ -17,19 +17,26 @@
package com.android.contacts.dialpad;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.widget.ImageButton;

/**
 * Custom {@link ImageButton} for dialpad buttons.
 *
 * During horizontal swipe, we want to exit "fading out" animation offered by its background
 * just after starting the swipe.This class overrides {@link #onTouchEvent(MotionEvent)} to achieve
 * the behavior.
 * <p>
 * This class implements lift-to-type interaction when touch exploration is
 * enabled.
 */
public class DialpadImageButton extends ImageButton {
    /** Accessibility manager instance used to check touch exploration state. */
    private AccessibilityManager mAccessibilityManager;

    /** Bounds used to filter HOVER_EXIT events. */
    private Rect mHoverBounds = new Rect();

    public interface OnPressedListener {
        public void onPressed(View view, boolean pressed);
    }
@@ -42,10 +49,17 @@ public class DialpadImageButton extends ImageButton {

    public DialpadImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initForAccessibility(context);
    }

    public DialpadImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initForAccessibility(context);
    }

    private void initForAccessibility(Context context) {
        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
                Context.ACCESSIBILITY_SERVICE);
    }

    @Override
@@ -55,4 +69,54 @@ public class DialpadImageButton extends ImageButton {
            mOnPressedListener.onPressed(this, pressed);
        }
    }

    @Override
    public void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mHoverBounds.left = getPaddingLeft();
        mHoverBounds.right = w - getPaddingRight();
        mHoverBounds.top = getPaddingTop();
        mHoverBounds.bottom = h - getPaddingBottom();
    }

    @Override
    public boolean performClick() {
        // When accessibility is on, simulate press and release to preserve the
        // semantic meaning of performClick(). Required for Braille support.
        if (mAccessibilityManager.isEnabled()) {
            // Checking the press state prevents double activation.
            if (!isPressed()) {
                setPressed(true);
                setPressed(false);
            }

            return true;
        }

        return super.performClick();
    }

    @Override
    public boolean onHoverEvent(MotionEvent event) {
        // When touch exploration is turned on, lifting a finger while inside
        // the button's hover target bounds should perform a click action.
        if (mAccessibilityManager.isEnabled()
                && mAccessibilityManager.isTouchExplorationEnabled()) {
            switch (event.getActionMasked()) {
                case MotionEvent.ACTION_HOVER_ENTER:
                    // Lift-to-type temporarily disables double-tap activation.
                    setClickable(false);
                    break;
                case MotionEvent.ACTION_HOVER_EXIT:
                    if (mHoverBounds.contains((int) event.getX(), (int) event.getY())) {
                        performClick();
                    }
                    setClickable(true);
                    break;
            }
        }

        return super.onHoverEvent(event);
    }
}