The question Repeat a task with a time delay? talks about a repeated task within an activity. The top voted answer looks good for that situation. I am trying to make a blinking cursor inside a completely custom EditText. I tried copying and adapting code from the Android TextView
and Editor
code, but I wasn't getting anything to blink.
Here is some of the current code I have been trying to get to work:
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 makeBlink() {
if (shouldBlink()) {
mShowCursor = SystemClock.uptimeMillis();
if (mBlink == null) mBlink = new Blink();
this.removeCallbacks(mBlink);
this.postDelayed(mBlink, BLINK);
} else {
if (mBlink != null) this.removeCallbacks(mBlink);
}
}
private class Blink implements Runnable {
private boolean mCancelled;
public void run() {
if (mCancelled) {
return;
}
MongolEditText.this.removeCallbacks(this);
if (shouldBlink()) {
if (mLayout != null) {
MongolEditText.this.invalidateCursorPath();
}
MongolEditText.this.postDelayed(this, BLINK);
}
}
void cancel() {
if (!mCancelled) {
MongolEditText.this.removeCallbacks(this);
mCancelled = true;
}
}
void uncancel() {
mCancelled = false;
}
}
private void invalidateCursorPath() {
int start = getSelectionStart();
if (start < 0) return;
Rect cursorPath = getCursorPath(start);
invalidate(cursorPath.left, cursorPath.top, cursorPath.right, cursorPath.bottom);
}
private void suspendBlink() {
if (mBlink != null) {
mBlink.cancel();
}
}
private void resumeBlink() {
if (mBlink != null) {
mBlink.uncancel();
makeBlink();
}
}
@Override
public void onScreenStateChanged(int screenState) {
switch (screenState) {
case View.SCREEN_STATE_ON:
resumeBlink();
break;
case View.SCREEN_STATE_OFF:
suspendBlink();
break;
}
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
resumeBlink();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
suspendBlink();
}
I decided I needed to step back and solve the problem with an easier example, so I am creating an MCVE. My answer (assuming I can do it) is below. My goals are as follows:
- The view starts the repeating task when clicked on.
- The handler's runnable code should be canceled when the view is destroyed.
My basic question is how to make the view start its own repeating task which changes its appearance? (like blinking on and off)