Edited at

ボタンのロングタップ対応UniRx版 v0.3 [パフォーマンスに難有り]

More than 3 years have passed since last update.

できること。

短いタップだったらShortTapを呼ぶ

IntervalAction秒長押しするとLongTapが呼ばれる。

ちょっとまだスマートじゃないのとこれだとチョンッってタップしただけでShortTapが呼ばれちゃうのでそこも何とかしたい。

あと長押ししていても指やカーソルが動きながらPressしてたらLongTapもShortTapも呼ばないようにしたい。

むずいぞ!

using UnityEngine;

using System.Collections;
using System;
using UniRx;
using System.Collections.Generic;

[RequireComponent(typeof(UIButton))]
public class UIButtonLongTapComponent : ObservableMonoBehaviour
{

[SerializeField]
float intervalAction = 3.0f;
public UIScrollView scroll = null;
float firstTapTime = 0f;
bool isHoldAction = true;
// 押しっぱなし時に呼び出すAction
public Action OnLongTap = null;
public Action OnShortTap = null;

Vector3 tapPosition = Vector3.zero;

BoolReactiveProperty isPressing = new BoolReactiveProperty();
bool IsPressing { get { return isPressing.Value; } set { isPressing.Value = value; } }

void Start()
{
scroll = this.transform.GetComponentInParents<UIScrollView> ();
IsPressing = false;

var tapInStream = this.UpdateAsObservable().Select(_=>IsPressing).Where (_ => _);
var tapOutStream = this.UpdateAsObservable().Select(_=>IsPressing).Where (_ => !_);
var tapInOutStream = this.UpdateAsObservable ().SkipUntil (tapInStream).TakeUntil (tapOutStream).Repeat ();

var moveStream = tapInOutStream
.Select(x=>scroll.currentMomentum.magnitude)
.Scan((sum,current)=>sum+current)
// .Do(x=>Debug.Log("currentMomentum: "+x))
.FirstOrDefault(x=>x>0.1f)
.Select(_=> "Move");

var longTapStream =
tapInOutStream.TakeUntil(moveStream).SelectMany(_ => Observable.Timer(TimeSpan.FromSeconds(intervalAction))).Select(_ => "LongTap");

longTapStream.Subscribe (_ => IsPressing = false);
moveStream.Subscribe (_ => IsPressing = false);

tapInStream.TakeUntil(moveStream).Timestamp()
.SelectMany(_ => tapOutStream.Timestamp(), (s, e) => (e.Timestamp - s.Timestamp).Seconds >= intervalAction)
.Select(x => x ? "LongTap" : "ShortTap")
.Merge(longTapStream)
.FirstOrDefault()
.RepeatUntilDestroy(gameObject)
.Subscribe(x =>{
Debug.Log(x);
if (x == "LongTap")
LongTap();
if (x == "ShortTap")
ShortTap();
});

}

void OnPress (bool pressed)
{
IsPressing = pressed;
}

public void SetButtonAction(Action shortTap, Action longTap, bool isHoldLongTap) {
isHoldAction = isHoldLongTap;
OnLongTap = longTap;
OnShortTap = shortTap;
}

public void CleanAction()
{
OnLongTap = null;
}

public void LongTap()
{
Debug.Log ("LongTap!!");
if (OnLongTap != null)
OnLongTap ();
}
public void ShortTap()
{
Debug.Log ("ShortTap!!");
if (OnShortTap != null)
OnShortTap ();
}

}