问题Repeat a task with a time delay?讨论活动中的重复任务。最高投票的答案看起来很适合这种情况。我试图在完全自定义的EditText中制作一个闪烁的光标。我尝试复制和调整Android TextView
和Editor
代码中的代码,但我没有得到任何眨眼的内容。
以下是我一直试图开始工作的一些当前代码:
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();
}
我决定用一个更简单的例子退一步解决问题,所以我创建了一个MCVE。我的答案(假设我可以做到)如下。我的目标如下:
我的基本问题是如何让视图开始自己的重复任务,改变它的外观? (就像眨眼一样)
答案 0 :(得分:2)
以下示例说明如何在自定义视图上设置重复任务。该任务通过使用每秒运行一些代码的处理程序来工作。触摸视图会启动和停止任务。
public class MyCustomView extends View {
private static final int DELAY = 1000; // 1 second
private Handler mHandler;
// keep track of the current color and whether the task is running
private boolean isBlue = true;
private boolean isRunning = false;
// constructors
public MyCustomView(Context context) {
this(context, null, 0);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mHandler = new Handler();
}
// start or stop the blinking when the view is touched
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (isRunning) {
stopRepeatingTask();
} else {
startRepeatingTask();
}
isRunning = !isRunning;
}
return true;
}
// alternate the view's background color
Runnable mRunnableCode = new Runnable() {
@Override
public void run() {
if (isBlue) {
MyCustomView.this.setBackgroundColor(Color.RED);
}else {
MyCustomView.this.setBackgroundColor(Color.BLUE);
}
isBlue = !isBlue;
// repost the code to run again after a delay
mHandler.postDelayed(mRunnableCode, DELAY);
}
};
// start the task
void startRepeatingTask() {
mRunnableCode.run();
}
// stop running the task, cancel any current code that is waiting to run
void stopRepeatingTask() {
mHandler.removeCallbacks(mRunnableCode);
}
// make sure that the handler cancels any tasks left when the view is destroyed
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopRepeatingTask();
}
}
以下是点击后的视图。
感谢this answer提出想法。