Guest User

Untitled

a guest
Jun 23rd, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.40 KB | None | 0 0
  1. import java.util.concurrent.TimeUnit;
  2.  
  3. import io.reactivex.Observable;
  4. import io.reactivex.android.schedulers.AndroidSchedulers;
  5. import io.reactivex.disposables.Disposable;
  6. import io.reactivex.observers.DisposableObserver;
  7. import io.reactivex.schedulers.Schedulers;
  8. import io.reactivex.subjects.PublishSubject;
  9. import io.reactivex.subjects.Subject;
  10.  
  11. public class DoubleClickDetector {
  12.  
  13. private static final long DEFAULT_TIME_SLOP_IN_MILLISECOND = 390;
  14. private static final long EXPIRE_TICK_FRAME_COUNT = 4;
  15.  
  16. private static final char TICK = 'a';
  17. private static final char CLICK = 'b';
  18. private static final char DETERMINE = 'c';
  19.  
  20. private static final char COOL_DOWN_2 = 'd';
  21. private static final char COOL_DOWN_1 = 'e';
  22.  
  23. private static Subject<Character> bus = PublishSubject.create();
  24.  
  25. private final Observable<Character> detector;
  26.  
  27. private Disposable disposable;
  28. private int expireAccumulation = 0;
  29.  
  30. public DoubleClickDetector(OnClickListener onClickListener) {
  31. this(DEFAULT_TIME_SLOP_IN_MILLISECOND, onClickListener);
  32. }
  33.  
  34. public DoubleClickDetector(final long timeSlopInMillisecond, final OnClickListener onClickListener) {
  35. Observable<Character> tickSignals =
  36. Observable.interval(timeSlopInMillisecond / 2, TimeUnit.MILLISECONDS, Schedulers.computation())
  37. .map(aLong -> TICK);
  38.  
  39. this.detector = bus.mergeWith(tickSignals)
  40. .doOnNext(character -> {
  41. if (character != TICK) {
  42. expireAccumulation = 0;
  43. } else if (expireAccumulation >= EXPIRE_TICK_FRAME_COUNT) {
  44. expireAccumulation = 0;
  45. stopDetecting();
  46. } else {
  47. ++expireAccumulation;
  48. }
  49. })
  50. .observeOn(AndroidSchedulers.mainThread())
  51. .reduce((previous, current) -> {
  52. switch (previous) {
  53. case TICK:
  54. return current;
  55. case CLICK:
  56. if (current == CLICK) {
  57. onClickListener.onDoubleClick();
  58. return COOL_DOWN_2;
  59. } else {
  60. return DETERMINE;
  61. }
  62. case DETERMINE:
  63. if (current == TICK) {
  64. onClickListener.onSingleClick();
  65. return current;
  66. } else if (current == CLICK) {
  67. onClickListener.onDoubleClick();
  68. return COOL_DOWN_2;
  69. } else {
  70. return previous;
  71. }
  72. case COOL_DOWN_2:
  73. if (current == TICK) {
  74. return COOL_DOWN_1;
  75. } else if (current == CLICK) {
  76. onClickListener.onDoubleClick();
  77. return COOL_DOWN_2;
  78. } else {
  79. return previous;
  80. }
  81. case COOL_DOWN_1:
  82. if (current == TICK) {
  83. return current;
  84. } else if (current == CLICK) {
  85. onClickListener.onDoubleClick();
  86. return COOL_DOWN_2;
  87. } else {
  88. return previous;
  89. }
  90. default:
  91. return current;
  92. }
  93. })
  94. .toObservable();
  95. }
  96.  
  97. public void click() {
  98. if (disposable == null || disposable.isDisposed()) {
  99. disposable = detector.subscribeWith(new DisposableObserver<Character>() {
  100. @Override
  101. public void onNext(Character character) {
  102.  
  103. }
  104.  
  105. @Override
  106. public void onError(Throwable e) {
  107.  
  108. }
  109.  
  110. @Override
  111. public void onComplete() {
  112.  
  113. }
  114. });
  115. }
  116. bus.onNext(CLICK);
  117. }
  118.  
  119. private void stopDetecting() {
  120. if (disposable != null && !disposable.isDisposed()) {
  121. disposable.dispose();
  122. }
  123. disposable = null;
  124. }
  125.  
  126. public interface OnClickListener {
  127.  
  128. void onSingleClick();
  129.  
  130. void onDoubleClick();
  131. }
  132. }
Add Comment
Please, Sign In to add comment