以下は、ビューをクリックした後に通過したイベントの例です。
まず、ビューでDispatchTouchevent()メソッドを分析します。これは、ビューをクリックして最初に実行する方法です。
public boolean dispatchTouchevent(MotionEvent Event){if(montouchListener!= null &&(mviewflags&enabled_mask)== enabled && montouchlistener.ontouch(this、event)){return true; } return ontouchevent(event);}注:2つのコールバック関数ontouch()とontouchevent()が含まれています。コントロールがOntouchListenerにバインドされ、コントロールが有効になっている場合は、OnTouch()メソッドを実行します。メソッドがtrueを返す場合、TouchListenerリスナーによってタッチイベントが消費され、下方に分配されないことを意味します。しかし、誤った場合、それはそれが消費されておらず、処理のためにコントロールのontouchevent()に下方に分配され続けていることを意味します。
次に、ontouchevent()メソッドを分析し、さらにタッチイベント処理を実行します。
if(((viewflags&clickable)== clickable ||(viewflags&long_clickable)== long_clickable)){switch(event.getAction()){case motionevent.action_up:..... performclick(); //クリックイベントブレークに応答します。 case motionevent.action_down:.... break; case motionevent.action_cancel:.... break; case motionevent.action_move:..... break; } trueを返します。 } falseを返します。コントロールがクリック可能またはlong_clickableである場合、対応するイベントに応答し、応答が完了して応答を継続する後にtrueを返すことができます。たとえば、イベントをクリックするときは、最初にAction_Downに応答し、次にブレークしてtrueを返し、次に手を上げてからDispatchTouchevent()から配布し、Action_upに応答し、performclick()がクリックイベントに応答します。
クリックイベントに応答します
public boolean performclick(){sendaccessibilityevent(accessibilityevent.type_view_clicked); if(monclicklistener!= null){playsundeffect(soundeffectconstants.click); monclicklistener.onclick(this); trueを返します。 } falseを返します;}MonclickListener.onclickを実行する(this);つまり、リスナーをバインドするonClick()関数。
キーポイント:
OntouchとOntoucheventの違いを使用する方法は?
答え:
ビューコントロールがタッチイベントを受信した場合、コントロールがOntouchListenerリスナーにバインドされ、コントロールが有効になっている場合、OnTouch()メソッドを実行します。真実の場合、タッチイベントが消費され、もはや受け継がれません。 falseが返された場合は、ontouchevent()イベントを呼び出し続けます。
Android Touchイベントがアクティビティの上部にあるDecorview(framelayout)に渡された後、ビューグラップからビューツリーまでレイヤーでレイヤーを渡し、最後にイベントを実際の受信ビューに渡します。ここにいくつかの重要な方法があります。
DispatchTouchEvent
イベントがビューグループに渡されると、DispatchToucheventが呼び出されます。コードが削除されました
public boolean dispatchTouchevent(MotionEvent ev){boolean handled = false; if(onfiltertoucheventforsecurity(ev)){final int action = ev.getAction(); final int actionmasked = action&motionevent.action_mask; //注意1:押されたときにいくつかの状態をクリアするif(actionmasked == motionevent.action_down){cancelandcleartouchTargets(ev); //この方法に注意してくださいResettouchState(); } //注意2:最終的なブールインターセプトされたインターセプトを傍受する必要があるかどうかを確認します。 //(actionmasked == motionevent.action_down || mfirsttouchtarget!= null){final boolean disallowintercept =(mgroupflags&flag_disallow_intercept)!= 0; = 0; = 0; if(!disallowIntercept){intercepted = onEnterceptTouchevent(ev); EV.Setaction(アクション); //変更された場合のアクションを復元} else {intercepted = false; }} else {//アクションシーケンスの始まりではなく、それを処理するサブビューはありません。直接傍受= true; } //イベントはキャンセルされず、現在のビューグループによって傍受されません。 (!canceled &&!intercted){//これが一連のアクションの始まりである場合、または新しいポインターが押されている場合、サブビューが引き継がれるかどうかを確認します。 MotionEvent.action_hover_move){final int actionindex = ev.getActionIndex(); //常に0ダウンの場合//上記のタッチポイント32の制限は、最終的なintidbitStoAssign = splitを引き起こすことです。 1 << ev.getpointerid(actionindex):touchtarget.all_pointer_ids; final int childrencount = mchildrencount; if(newtouchTarget == null && childRencount!= 0){final float x = ev.getx(actionindex); final float y = ev.gety(actionindex); //現在のViewGroupのすべてのチャイルドビューを並べ替え、それらを上層に配置して開始します。 final arrayList <view> preorderedList = buildOrderEdChildList(); final boolean custom Order = preorderedList == null && ischildRendRawingOrderEnabled();最終的なビュー[]子供= mchildren; for(int i = ChildRencount-1; i> = 0; i-){final int childindex = customorord? GetChildDrawing Order(ChildCount、i):i; final View child =(preorderedlist == null)?子供[ChildIndex]:PreorderedList.get(ChildIndex); // canviewreceivepointerevents可視ビューはイベントを受け入れることができます続く; } //このポインターのビューが以前のポインターを処理したかどうかを処理し、newTouchTarget = getTouchTarget(child)を使用します。 if(newtouchTarget!= null){//子供はすでにその範囲内でタッチを受けています。 //処理しているものに加えて、新しいポインターを与えます。 newtouchtarget.pointeridbits | = idbitStoAssign;壊す; }} //注意3:子供のビューに直接送信する場合(dispatchtransformedtouchevent(ev、false、child、idbitstoassign)){//子供はその境界内でタッチを受け取りたい。 mlasttouchdowntime = ev.getDownTime(); if(preorderedlist!= null){// childindexを事前に事前に指して、(int j = 0; j <childrencount; j ++)の元のインデックスを見つけます(children [childindex] == mchildren [j]){mlasttouchdownindex = j;壊す; }}} else {mlasttouchdownindex = childindex; } mlasttouchdownx = ev.getx(); mlasttouchdowny = ev.gety(); NewTouchTarget = addTouchTarget(child、idbitStoAssign);既にdispatchedtonewtouchtarget = true;壊す; }}}}}} //イベントを受け取った子ビューは以前に見つかりました。それがnullの場合、それは子供の視点が引き継がれていないことを意味します。現在のViewGroupは、(mfirsttouchtarget == null){// viewgroup handled = dispatchtransformedtouchevent(ev、cancelchild、null、touchtarget.all_pointer_ids)を処理する必要があります。 } else {if(letweendispatchedtonewtouchtarget){//いくつかのコードを無視するif(dispatchtransformedtouchevent(ev、cancelChild、target.child、target.pointeridbits)){handled = true; }}} return handled;}上記のコードの注意は後の部分に関与するので、それに注意してください。
ここでは、一連のアクションのさまざまなポインターをさまざまなビューに割り当てることができることを指摘する必要があります。 ViewGroupは、Viewsを処理するPointeridとTouchTargetsのリストを維持します。 TouchTargetは、ポインターを処理できるサブビューを表します。もちろん、ビューでは、両方の指がサブビュー領域にあるなど、複数のポインターを処理できます。 TouchTargetは、INTを内部的に使用してPointerID Process ProcessとInt32ビットを保存します。そのため、上層は同時に最大32ポイントのタッチしか許容できません。
注意3のコードを見てみましょう。ビューのDispatchToucheventがFalseを返した場合、アクションが続くことはできないとよく言います。なぜこれがなぜですか? falseが注意3で返された場合、それはtouchtargetに記録されないため、ビューグループは、このイベントを処理する能力がないと考えています。
ここでは、ViewGroupが実際にDispatchTransformedToucheventでイベントを処理し、フォローして見てみましょう。
DispatchTransformedToucheventPrivate boolean DispatchedTransformedTouchevent(MotionEvent Event、Boolean Cancel、View Child、Int desiredpointeridbits){//サブクラス処理なし、その後、処理のためにビューグループに残してください。 } else {final float offsetx = mscrollx -child.mleft;最終的なフロートoffsety = mscrolly -child.mtop; TransforedEvent.OffsetLocation(offsetx、offsety); if(!child.hasidentitymatrix()){transformedevent.transform(child.getinversematrix()); } handled = child.dispatchtouchevent(transformedevent); }返された処理;}何があっても、ビューのDispatchToucheventが呼び出されることがわかります。これは、クリックイベントが実際に処理される場所です。
DispatchTouchEvent Public Boolean DispatchTouchEvent(MotionEvent Event){if(onfiltertoucheventforsecurity(event)){//最初にビューのOntouchイベントを取得します。 if(li!= null && li.montouchlistener!= null &&(mviewflags&enabled_mask)== enabled && li.montouchlistener.ontouch(this、event)){result = true; } if(!result && ontouchevent(event)){result = true; }} return result; }ビュー用に設定したOntouchイベントは、優先度が高いです。 Ontouchの実行がtrueを返す場合、ビューのOntoucheventはビューに移動しません。 Clickイベントの一部はOntoucheventで処理されているため、OntouchがTrueを返し、ビューのクリック関連イベントは処理されません。
このプロセスの簡単な要約
ViewGroupが上司に渡されたイベントを受け入れると、一連のタッチイベント(Action_Down)の始まりである場合、ViewGroupは最初にイベントをインターセプトする必要があるかどうかを確認します(InterceptToucheventでは、viewgroupのデフォルトの実装は虚偽を直接返すために直接返します)。現在クリックしているビューを見つけて、すぐにターゲットビューのDispatchToucheventを呼び出します。ターゲットビューのDispatchToucheventがFalseを返す場合、ターゲットビューはその位置にのみあると考えます。このイベントを受け入れたくありませんが、静かにビューを作りたいだけです(私はあなたがふりをするのを静かに見ています*)。この時点で、ViewGroupはDispatchToucheventにも行きます!