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

Commit 6a0b7229 authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Fix EBT helper initialization in LabeledSeekBar class" into nyc-dev

parents 1ef31644 3550a32c
Loading
Loading
Loading
Loading
+82 −124
Original line number Diff line number Diff line
@@ -24,12 +24,10 @@ import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.widget.ExploreByTouchHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

import java.util.List;

@@ -40,9 +38,90 @@ import java.util.List;
 */
public class LabeledSeekBar extends SeekBar {

    private final ExploreByTouchHelper mAccessHelper;

    /** Seek bar change listener set via public method. */
    private OnSeekBarChangeListener mOnSeekBarChangeListener;

    /** Labels for discrete progress values. */
    private String[] mLabels;

    public LabeledSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.seekBarStyle);
    }

    public LabeledSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public LabeledSeekBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        mAccessHelper = new LabeledSeekBarExploreByTouchHelper(this);
        ViewCompat.setAccessibilityDelegate(this, mAccessHelper);

        super.setOnSeekBarChangeListener(mProxySeekBarListener);
    }

    @Override
    public synchronized void setProgress(int progress) {
        // This method gets called from the constructor, so mAccessHelper may
        // not have been assigned yet.
        if (mAccessHelper != null) {
            mAccessHelper.invalidateRoot();
        }

        super.setProgress(progress);
    }

    public void setLabels(String[] labels) {
        mLabels = labels;
    }

    @Override
    public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
        // The callback set in the constructor will proxy calls to this
        // listener.
        mOnSeekBarChangeListener = l;
    }

    @Override
    protected boolean dispatchHoverEvent(MotionEvent event) {
        return mAccessHelper.dispatchHoverEvent(event) || super.dispatchHoverEvent(event);
    }

    private void sendClickEventForAccessibility(int progress) {
        mAccessHelper.invalidateRoot();
        mAccessHelper.sendEventForVirtualView(progress, AccessibilityEvent.TYPE_VIEW_CLICKED);
    }

    private final OnSeekBarChangeListener mProxySeekBarListener = new OnSeekBarChangeListener() {
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (mOnSeekBarChangeListener != null) {
                mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            if (mOnSeekBarChangeListener != null) {
                mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
            }
        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (mOnSeekBarChangeListener != null) {
                mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
                sendClickEventForAccessibility(progress);
            }
        }
    };

    private class LabeledSeekBarExploreByTouchHelper extends ExploreByTouchHelper {

        public LabeledSeekBarExploreByTouchHelper(View forView) {
        public LabeledSeekBarExploreByTouchHelper(LabeledSeekBar forView) {
            super(forView);
        }

@@ -134,125 +213,4 @@ public class LabeledSeekBar extends SeekBar {
            return r;
        }
    }

    private String[] mLabels;

    private ExploreByTouchHelper mAccessHelper;

    private boolean mOnMeasureCalled;
    private boolean mOnAttachedWindowCalled;

    public LabeledSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.seekBarStyle);
    }

    public LabeledSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public LabeledSeekBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        super.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                // Do nothing
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                // Do nothing
            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                sendClickEventForAccessibility(progress);
            }
        });
    }

    @Override
    public synchronized void setProgress(int progress) {
        if (mAccessHelper != null) {
            mAccessHelper.invalidateRoot();
        }

        super.setProgress(progress);
    }

    public void setLabels(String[] labels) {
        mLabels = labels;
    }

    @Override
    public void setOnSeekBarChangeListener(final OnSeekBarChangeListener l) {
        // Tweak the listener to send accessibility event on progress changed.
        OnSeekBarChangeListener l2 = new OnSeekBarChangeListener() {
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                l.onStopTrackingTouch(seekBar);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                l.onStartTrackingTouch(seekBar);
            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                l.onProgressChanged(seekBar, progress, fromUser);
                sendClickEventForAccessibility(progress);
            }
        };

        super.setOnSeekBarChangeListener(l2);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mOnMeasureCalled = true;
        tryInitAccessHelper();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mOnAttachedWindowCalled = true;
        tryInitAccessHelper();
    }

    @Override
    protected void onDetachedFromWindow() {
        ViewCompat.setAccessibilityDelegate(this, null);
        mAccessHelper = null;
        super.onDetachedFromWindow();
    }

    @Override
    protected boolean dispatchHoverEvent(MotionEvent event) {
        if (mAccessHelper != null && mAccessHelper.dispatchHoverEvent(event)) {
            return true;
        }

        return super.dispatchHoverEvent(event);
    }

    /**
     * Initialize accessibility delegation only when both onAttachedWindow and onMeasure
     * has been called.
     */
    private void tryInitAccessHelper() {
        if (mOnAttachedWindowCalled && mOnMeasureCalled) {
            mAccessHelper = new LabeledSeekBarExploreByTouchHelper(this);
            ViewCompat.setAccessibilityDelegate(this, mAccessHelper);
            mOnAttachedWindowCalled = mOnMeasureCalled = false;
        }
    }

    private void sendClickEventForAccessibility(int progress) {
        if (mAccessHelper != null) {
            mAccessHelper.invalidateRoot();
            mAccessHelper.sendEventForVirtualView(progress, AccessibilityEvent.TYPE_VIEW_CLICKED);
        }
    }
}