5

UIImageView を含む UIScrollView があります。UIScrollView を使用すると、UIImageView を介してズームとパンを行うことができます。

問題は、毎回指の動きを知りたいということで、 touchesMoved メソッドでイベントをキャッチしようとしています。しかし、正しく呼び出された touchesBegan と touchesEnded にもかかわらず、機能していません。

実際、指の動きが非常に小さい場合は touchesMoved が呼び出され、UIScrollView はパンを開始しません。UIScrollView が動き始めた瞬間に、イベントの呼び出しが停止します。

何が問題で、どのように修正するか知っている人はいますか? 内部の UIImageView がイベントなどをキャッチしている可能性があると思いました。

4

5 に答える 5

1

実際、UIScrollView はTouchesMovedイベントを"食べる"ため (最初のいくつかのイベントが伝播されたとしても)、これは非常に大きな問題です。

そのため、 UIWindow から直接イベントを取得する方法を思いつきました。これは確かに、アプリケーション構造の意味で最善のアプローチではありませんが、カスタムの状況 (まさに私が必要としていたもの) では問題ありません。

(例はMonoTouch C#にあります)。

カスタム UIWindowを作成します(カスタム ロジック (MvvmCross フレームワークを使用) のため、標準の UIWindow を MyWindow に置き換える方法はここでは示しませんが、これは非常に簡単で、通常は appDelegate 初期化ロジックで行われます。 ):

public class MyWindow : UIWindow
{
    public MyWindow(RectangleF bounds) : base(bounds)
    {

    }

    public override void SendEvent(UIEvent evt)
    {
        if (evt.Type == UIEventType.Touches) {
            var el = (UITouch)evt.AllTouches.AnyObject;

            if (el.Phase == UITouchPhase.Began)
            {
                if(OnTouchBegan != null)
                    OnTouchBegan(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

            if (el.Phase == UITouchPhase.Moved)
            {
                if(OnTouchMoved != null)
                    OnTouchMoved(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

            if (el.Phase == UITouchPhase.Ended)
            {
                if(OnTouchEnd != null)
                    OnTouchEnd(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

            if (el.Phase == UITouchPhase.Cancelled)
            {
                if(OnTouchCancel != null)
                    OnTouchCancel(el.View, new TouchCommandArgs(evt.AllTouches, evt));
            }

        } else
            MvxTrace.Trace (evt.Type == null ?  "-" : evt.ToString ());
        base.SendEvent(evt);
    }

    public event TouchCommand OnTouchBegan;
    public event TouchCommand OnTouchEnd;
    public event TouchCommand OnTouchCancel;
    public event TouchCommand OnTouchMoved;

}

public class TouchCommandArgs : EventArgs
{
    public NSSet Touches { get; set; }
    public UIEvent Evt { get; set; }

    public TouchCommandArgs(NSSet touches, UIEvent evt)
    {
        Touches = touches;
        Evt = evt;
    }
}

カスタム イベント ハンドラのイベント サブスクライブを処理する場所:

var window = (MyWindow) UIApplication.SharedApplication.KeyWindow;
window.OnTouchBegan += view_OnTouchBegan;
window.OnTouchMoved += view_OnTouchMoved;
window.OnTouchCancel += view_OnTouchCancel;
window.OnTouchEnd += view_OnTouchEnd;

のようなハンドラ (それはすべてあなた自身のものです):

void view_OnTouchBegan(object sender, TouchCommandArgs args)
{
    // do your logic
}

その場合、イベントは同時に処理されます (あなたの場所と UIScrollView の両方で)。さらに、必要に応じて、ウィンドウのイベントの伝播をキャンセルすることができます。たとえば、ハンドラへの Handled" フラグ)。

于 2013-08-01T12:25:59.723 に答える
1

scrollview プロパティcanCancelContentTouches = NOを使用すると、タッチ イベントをレスポンダー チェーンに渡すことができます。

于 2012-11-14T14:14:56.303 に答える
0

UIScrollViewDelegate を使用して、オフセットの変更またはズーム スケールの変更を追跡してみてください。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (void)scrollViewDidZoom:(UIScrollView *)scrollView;

または間のzoomScale値の変化を確認します。UIScrollViewtouchesBegan: & (touchesMoved: or touchesCancelled:) events

于 2014-01-20T02:44:57.543 に答える
0

UIScrollViewクラスのサブクラスを作成し、 touchesBegan:およびその他のタッチ メソッドを次のようにオーバーライドします。

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // If not dragging, send event to next responder
    if (!self.dragging)
    { 
        [self.nextResponder touchesBegan: touches withEvent:event]; 
    }
    else
    {
        [super touchesEnded: touches withEvent: event];
    }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // If not dragging, send event to next responder
    if(!self.dragging)
    { 
        [self.nextResponder touchesBegan: touches withEvent:event]; 
    }
    else
    {
        [super touchesEnded: touches withEvent: event];
    }
 }

 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // If not dragging, send event to next responder
    if (!self.dragging)
    { 
        [self.nextResponder touchesBegan: touches withEvent:event]; 
    }
    else
    {
        [super touchesEnded: touches withEvent: event];
    }
}
于 2012-09-04T08:26:11.367 に答える