I have a custom view that has a blinking cursor. I make the blinking cursor using a Handler
and posting a Runnable
to it after a 500 milisecond delay.
When the activity that the view is in, I want to stop the blinking by removing the callbacks on the handler. However, I've noticed that when I switch to another app, the handler/runnable keep going, ie, the log says it is still blinking.
If I had control of the view I would just do something like this
@Override
protected void onPause() {
handler.removeCallbacks(runnable);
super.onPause();
}
But my custom view will be part of a library and so I don't have control over the Activities that other developers use my custom view in.
I tried onFocusChanged
, onScreenStateChanged
, and onDetachedFromWindow
but none of these work for when the user switches to another app.
Here is my code. I simplified it by removing anything not pertinent to the problem.
public class MyCustomView extends View {
static final int BLINK = 500;
private Handler mBlinkHandler;
private void init() {
// ...
mBlinkHandler = new Handler();
mTextStorage.setOnChangeListener(new MongolTextStorage.OnChangeListener() {
@Override
public void onTextChanged(/*...*/) {
// ...
startBlinking();
}
});
}
Runnable mBlink = new Runnable() {
@Override
public void run() {
mBlinkHandler.removeCallbacks(mBlink);
if (shouldBlink()) {
// ...
Log.i("TAG", "Still blinking...");
mBlinkHandler.postDelayed(mBlink, BLINK);
}
}
};
private boolean shouldBlink() {
if (!mCursorVisible || !isFocused()) return false;
final int start = getSelectionStart();
if (start < 0) return false;
final int end = getSelectionEnd();
if (end < 0) return false;
return start == end;
}
void startBlinking() {
mBlink.run();
}
void stopBlinking() {
mBlinkHandler.removeCallbacks(mBlink);
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (focused) {
startBlinking();
} else {
stopBlinking();
}
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
@Override
public void onScreenStateChanged(int screenState) {
switch (screenState) {
case View.SCREEN_STATE_ON:
startBlinking();
break;
case View.SCREEN_STATE_OFF:
stopBlinking();
break;
}
}
public void onAttachedToWindow() {
super.onAttachedToWindow();
startBlinking();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopBlinking();
}
}