From 3550a32ca9044fbf05676d68e8b89987521ed121 Mon Sep 17 00:00:00 2001 From: Alan Viverette Date: Fri, 8 Apr 2016 15:23:29 -0400 Subject: [PATCH] Fix EBT helper initialization in LabeledSeekBar class Helper should have same lifecycle as the class itself. Also rearranges class to match up with standard Android class organization. Bug: 27674946 Change-Id: Ib2ab1e367d4ef1757321375bbb7e4c5f0dc8f46c --- .../settings/widget/LabeledSeekBar.java | 206 +++++++----------- 1 file changed, 82 insertions(+), 124 deletions(-) diff --git a/src/com/android/settings/widget/LabeledSeekBar.java b/src/com/android/settings/widget/LabeledSeekBar.java index 00df09c7d4a..bf6983ece6d 100644 --- a/src/com/android/settings/widget/LabeledSeekBar.java +++ b/src/com/android/settings/widget/LabeledSeekBar.java @@ -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); - } - } }