Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.concurrent.TimeUnit;
- import io.reactivex.Observable;
- import io.reactivex.android.schedulers.AndroidSchedulers;
- import io.reactivex.disposables.Disposable;
- import io.reactivex.observers.DisposableObserver;
- import io.reactivex.schedulers.Schedulers;
- import io.reactivex.subjects.PublishSubject;
- import io.reactivex.subjects.Subject;
- public class DoubleClickDetector {
- private static final long DEFAULT_TIME_SLOP_IN_MILLISECOND = 390;
- private static final long EXPIRE_TICK_FRAME_COUNT = 4;
- private static final char TICK = 'a';
- private static final char CLICK = 'b';
- private static final char DETERMINE = 'c';
- private static final char COOL_DOWN_2 = 'd';
- private static final char COOL_DOWN_1 = 'e';
- private static Subject<Character> bus = PublishSubject.create();
- private final Observable<Character> detector;
- private Disposable disposable;
- private int expireAccumulation = 0;
- public DoubleClickDetector(OnClickListener onClickListener) {
- this(DEFAULT_TIME_SLOP_IN_MILLISECOND, onClickListener);
- }
- public DoubleClickDetector(final long timeSlopInMillisecond, final OnClickListener onClickListener) {
- Observable<Character> tickSignals =
- Observable.interval(timeSlopInMillisecond / 2, TimeUnit.MILLISECONDS, Schedulers.computation())
- .map(aLong -> TICK);
- this.detector = bus.mergeWith(tickSignals)
- .doOnNext(character -> {
- if (character != TICK) {
- expireAccumulation = 0;
- } else if (expireAccumulation >= EXPIRE_TICK_FRAME_COUNT) {
- expireAccumulation = 0;
- stopDetecting();
- } else {
- ++expireAccumulation;
- }
- })
- .observeOn(AndroidSchedulers.mainThread())
- .reduce((previous, current) -> {
- switch (previous) {
- case TICK:
- return current;
- case CLICK:
- if (current == CLICK) {
- onClickListener.onDoubleClick();
- return COOL_DOWN_2;
- } else {
- return DETERMINE;
- }
- case DETERMINE:
- if (current == TICK) {
- onClickListener.onSingleClick();
- return current;
- } else if (current == CLICK) {
- onClickListener.onDoubleClick();
- return COOL_DOWN_2;
- } else {
- return previous;
- }
- case COOL_DOWN_2:
- if (current == TICK) {
- return COOL_DOWN_1;
- } else if (current == CLICK) {
- onClickListener.onDoubleClick();
- return COOL_DOWN_2;
- } else {
- return previous;
- }
- case COOL_DOWN_1:
- if (current == TICK) {
- return current;
- } else if (current == CLICK) {
- onClickListener.onDoubleClick();
- return COOL_DOWN_2;
- } else {
- return previous;
- }
- default:
- return current;
- }
- })
- .toObservable();
- }
- public void click() {
- if (disposable == null || disposable.isDisposed()) {
- disposable = detector.subscribeWith(new DisposableObserver<Character>() {
- @Override
- public void onNext(Character character) {
- }
- @Override
- public void onError(Throwable e) {
- }
- @Override
- public void onComplete() {
- }
- });
- }
- bus.onNext(CLICK);
- }
- private void stopDetecting() {
- if (disposable != null && !disposable.isDisposed()) {
- disposable.dispose();
- }
- disposable = null;
- }
- public interface OnClickListener {
- void onSingleClick();
- void onDoubleClick();
- }
- }
Add Comment
Please, Sign In to add comment