2017-06-12 43 views
0

問題Repeat a task with a time delay?討論活動中的重複任務。頂尖的投票答案看起來不錯。我正試圖在完全自定義的EditText中製作一個閃爍的光標。我試着從Android TextViewEditor代碼中複製和修改代碼,但我沒有得到任何東西閃爍。在自定義視圖內重複延遲任務

下面是一些當前的代碼,我一直在努力去工作:

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。我的答案(假設我可以做到)在下面。我的目標如下:

  • 該視圖在點擊時開始重複任務。
  • 處理程序的可運行代碼應在視圖銷燬時取消。

我的基本問題是如何讓視圖開始自己的重複任務,改變它的外觀? (如閃爍開啓和關閉)

回答

1

以下示例顯示如何在自定義視圖上設置重複任務。該任務通過使用每秒運行一些代碼的處理程序來工作。觸摸視圖開始並停止任務。

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

下面是點擊後視圖的樣子。

enter image description here

感謝this answer的想法。