在自定义视图中延迟时间重复执行任务 [英] Repeat a task with a time delay inside a custom view

查看:94
本文介绍了在自定义视图中延迟时间重复执行任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题重复执行某项任务有时间延迟吗?会谈关于活动中重复的任务.在这种情况下,票数最高的答案看起来不错.我试图在完全自定义的EditText中使光标闪烁.我尝试从Android TextView Editor 代码,但我什么都没眨眼.

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();
}

我认为我需要退一步并用一个简单的示例解决问题,因此我正在创建一个MCVE.我的回答(假设我可以做到)如下.我的目标如下:

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:

  • 单击该视图将启动重复任务.
  • 在销毁视图时,应取消处理程序的可运行代码.

我的基本问题是如何使视图开始自己的重复任务,从而改变其外观? (例如闪烁的灯光)

My basic question is how to make the view start its own repeating task which changes its appearance? (like blinking on and off)

推荐答案

下面的示例演示如何在自定义视图上设置重复任务.该任务通过使用每秒运行一些代码的处理程序来工作.触摸视图将启动和停止任务.

The following example shows how to set a repeating task on a custom view. The task works by using a handler that runs some code every second. Touching the view starts and stops the task.

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();
    }
}

这是单击后视图的外观.

Here is what the view looks like after being clicked.

感谢此答案以获取想法.

这篇关于在自定义视图中延迟时间重复执行任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆