2016-06-15 8 views
1

當多個指針位於不同視圖中時,如何獲取屏幕上的指針總數?我在屏幕上有多個視圖,如果指針不在視圖的相關區域,視圖將返回falseON_DOWN case onTouchEvent如何在指針位於多個視圖時獲取指針的總數?

當第一個手指在視圖上,第二個手指觸到另一個視圖時,兩個視圖將返回「1」爲getPointerCount方法。不管哪個視圖處理指針觸摸,是否有任何方法可以在整個屏幕上獲得總指針數?

編輯:Views不在同一個父ViewGroup,這就是爲什麼onInterceptTouch不會返回總指針數。我可以把onInterceptTouch設置爲非常根目錄ViewGroup,但是我希望Android可以提供指針的總數,而不需要像這樣的一些骯髒的解決方法。

+0

所有視圖都駐留在ViewGroup中作爲根視圖。 ViewGroup類有方法:['onInterceptTouch()'](https://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent))。只要你從它返回false,事件就會通過它,然後傳遞給子視圖。因此,理論上,視圖的父ViewGroup可以監視所有的指針。你需要測試是確定的。 –

回答

1

沒有直接的方法來使用Activity而是作爲@ S.D調用的方法。指出的那樣,你可以使用ViewGrouponInterceptTouchEvent做到這一點:

MyLinearLayout.java

public class MyLinearLayout extends LinearLayout { 
    public MyLinearLayout(Context context) { 
     super(context); 
    } 

    public MyLinearLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 


    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @TargetApi(21) 
    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
     super(context, attrs, defStyleAttr, defStyleRes); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(final MotionEvent ev) { 
     Log.e("TOUCHES", "num: " + ev.getPointerCount()); 

     return super.onInterceptTouchEvent(ev); 
    } 
} 

mylayout.xml

<mypackage.MyLinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 

    <TextView 
     android:id="@+id/t1" 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="0.5" 
     android:clickable="true" 
     android:gravity="center" 
     android:text="0"/> 

    <TextView 
     android:id="@+id/t2" 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="0.5" 
     android:clickable="true" 
     android:gravity="center" 
     android:text="0"/> 

</mypackage.MyLinearLayout> 

MyActivity.java

public class MapsActivity extends FragmentActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.mylayout); 

     final TextView t1 = (TextView) findViewById(R.id.t1); 
     final TextView t2 = (TextView) findViewById(R.id.t2); 

     t1.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(final View view, final MotionEvent motionEvent) { 
       t1.setText(""+motionEvent.getPointerCount()); 
       return true; 
      } 
     }); 

     t2.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(final View view, final MotionEvent motionEvent) { 
       t2.setText(""+motionEvent.getPointerCount()); 
       return true; 
      } 
     }); 
    } 
} 

這個例子將設置t1和t2 TextView s的每個TextView收到MotionEventgetPointerCount()的文本,將記錄由MyLinearLayout

1

你需要一個接受MotionEventgetPointerCount()總價值自定義的ViewGroup攔截所有傳遞的觸摸事件。

您需要了解這項工作如何在Android:

  • ViewGroup.onInterceptTouchEvent(MotionEvent)允許的ViewGroup他們到達前兒童攔截觸摸事件。如果返回true在這裏你會發現在onTouchEvent()接收後續觸摸事件,直到當前事件結束(指針刪除)
  • 兒童觀可以要求家長禁止攔截與ViewGroup.requestDisallowInterceptTouchEvent(boolean)孩子們將不再接收任何觸摸事件:通常他們當他們識別正在進行的觸摸事件並且他們不希望父母中斷它時。如果ViewGroup中收到這個請求時,它必須將其傳遞給家長和兌現它(=不從這裏截獲事件的)
  • 內部一個ViewGroup不會叫onInterceptTouchEventrequestDisallowInterceptTouchEvent(true)後收到

如果您需要聽每一個觸摸事件,即使孩子不允許攔截,你需要欺騙ViewGroup認爲它沒有被禁止,但你仍然需要尊重禁止(避免攔截觸摸事件)。

這是一類,我寫了我的項目之一是正是這麼做的:

public class InterceptTouchFrameLayout extends FrameLayout { 
    private boolean mDisallowIntercept; 

    public interface OnInterceptTouchEventListener { 
     /** 
     * If disallowIntercept is true the touch event can't be stealed and the return value is ignored. 
     * @see android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent) 
     */ 
     boolean onInterceptTouchEvent(InterceptTouchFrameLayout view, MotionEvent ev, boolean disallowIntercept); 

     /** 
     * @see android.view.View#onTouchEvent(android.view.MotionEvent) 
     */ 
     public boolean onTouchEvent(InterceptTouchFrameLayout view, MotionEvent event); 
    } 

    private static final class DummyInterceptTouchEventListener implements OnInterceptTouchEventListener { 
     @Override 
     public boolean onInterceptTouchEvent(InterceptTouchFrameLayout view, MotionEvent ev, boolean disallowIntercept) { 
      return false; 
     } 
     @Override 
     public boolean onTouchEvent(InterceptTouchFrameLayout view, MotionEvent event) { 
      return false; 
     } 
    } 

    private static final OnInterceptTouchEventListener DUMMY_LISTENER = new DummyInterceptTouchEventListener(); 

    private OnInterceptTouchEventListener mInterceptTouchEventListener = DUMMY_LISTENER; 

    public InterceptTouchFrameLayout(Context context) { 
     super(context); 
    } 

    public InterceptTouchFrameLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public InterceptTouchFrameLayout(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 
     getParent().requestDisallowInterceptTouchEvent(disallowIntercept); 
     mDisallowIntercept = disallowIntercept; 
    } 

    public void setOnInterceptTouchEventListener(OnInterceptTouchEventListener interceptTouchEventListener) { 
     mInterceptTouchEventListener = interceptTouchEventListener != null ? interceptTouchEventListener : DUMMY_LISTENER; 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     boolean stealTouchEvent = mInterceptTouchEventListener.onInterceptTouchEvent(this, ev, mDisallowIntercept); 
     return stealTouchEvent && !mDisallowIntercept || super.onInterceptTouchEvent(ev); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     boolean handled = mInterceptTouchEventListener.onTouchEvent(this, event); 
     return handled || super.onTouchEvent(event); 
    } 
} 

您只需設置你的聽衆:view.setOnInterceptTouchEventListener()

內部的聽衆可以保持指針倒計時(在onIntercetTouchEvent()方法內)。 只需將該佈局作爲佈局的根目錄(全屏)即可。

如果您嘗試在沒有禁止技巧的情況下做同樣的事情,您最終會得到不正確的信息,因爲您未被授予接收所有觸摸事件的權限。