6

Biorąc pod uwagę przykład z poniższego obrazu,jednoczesnych zdarzeń dotykowych przeładunku na wielu widoków w Androidzie

enter image description here

szukam rozwiązania przekazać zdarzeń dotykowych z płótna View do Viewpager. Jest to konieczne do równoczesnego stosowania tego samego zoomu w obu widokach.

Oto opis techniczny, co się dzieje,

(Pozwala rozważyć pogląd jako , B & C)

A. nadrzędna Zobacz

B. Wyświetl

C. Zobacz Pager

Przed dispatchTouchEvent() nazywa na dzieci (B & C), The A.dispatchTouchEvent() najpierw wywołuje A.onInterceptTouchEvent (), aby sprawdzić, czy grupa widoków jest zainteresowana przechwytywaniem zdarzenia.

Więc jeśli A.onTouchEvent() powraca fałszywy, to wraca do B.onTouchEvent(). Jeśli to zwróci false, to powróci do C.onTouchEvent(), a wysyłka będzie kontynuowana jak zwykle.

A po powrocie prawdziwą,

  1. ACTION_CANCEL będą wysyłane do wszystkich dzieci.

  2. Wszystkie późniejsze wydarzenia gest (do ACTION_UP/ACTION_CANCEL) będą spożywane przez słuchaczy zdarzeń (OnTouchListener.onTouch()), jeśli zdefiniowane, innego obsługi zdarzeń A.onTouchEvent() na poziomie A.

W tym momencie mogę przekazać zdarzenia z rodzicem do poglądów dziecka, ale nie mogę pozwolić widoku 2 dziecko b. & C poradzić sobie ze zdarzeniami razem (stosując taki sam zoom w obu widokach).

Czy istnieje sposób przekazywania zdarzeń dotykowych z widoku rodzica na dziecko, aby można było przetwarzać zdarzenia jednocześnie?

Oto mój setup układ,

<RelativeLayout 
    android:id="@+id/layoutParent" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#FFFFFFFF"> 

      <com.androidapp.NonSwipeableViewPager 
       android:id="@+id/pager" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:layout_gravity="center" 
       android:background="@color/transparent" /> 

      <com.androidapp.DrawingView 
       android:id="@+id/drawing" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:background="@color/transparent" /> 

</RelativeLayout> 
+0

Jak płótno jest umieszczony pod kontrolą viewpager? Czy pojawia się jako wyskakujące okienko lub w inny sposób? – ridoy

+0

Obszar roboczy i widok strony znajduje się w 2 osobnych widokach. Sprawdź mój kod układu, aby się lepiej przyjrzeć[email protected] –

+0

Tak więc twój DrawingView przechwytuje NonSwipeableViewPager (zgodnie z twoim kodem układu), nieprawdaż? – ridoy

Odpowiedz

4

Jeśli się nie mylę, chcesz przetworzyć to samo zdarzenie dotykowe zarówno w widoku górnym, jak i dolnym. Zgodnie z architekturą dotykową systemu Android nie można obsługiwać zdarzeń dotykowych z wielu widoków jednocześnie. Musisz to przetworzyć w metodzie onTouchEvent() lub przejść do następnego widoku. Musisz także poczekać do zakończenia widoku z góry przetwarzania MotionEvent() i pozwolić dziecku zobaczyć, jak sobie poradzi.

Oto możliwe rozwiązanie wykorzystujące RxAndroid podejście

wewnątrz płótno widok na MotionEvent(),

@Override 
    public boolean onTouchEvent(MotionEvent event) { 

    // process all touch events (UP/DOWN/MOVE) 

    //send events as observable 
    RxBus.getInstance().sendMotionEvent(event); 

    return true; 
} 

To będzie przestrzegać zdarzeń ruchu i powiadamia wszystkich obserwatorów.

Teraz subskrybuj zdarzenia ruchu, tak aby za każdym razem, gdy zmiana została wykonana z płótna, natychmiast przejdzie zdarzenia.

Subscription RxBus _rxBus = RxBus.getInstance(); 
     subscription = _rxBus.getMotionEvent() 
       .subscribe(new Action1<MotionEvent>() { 
        @Override 
        public void call(MotionEvent event) { 
         // call the onTouchEvent of your widget e.g. ImageView and pass the received event 
         // this will apply the same touch event that was applied in the canvas 

         // .onTouchEvent(event) is important to override the onTouchEvent() of your widget that will use the touch event 
         imageView.onTouchEvent(event); 
        } 
      }); 

RxBus klasa znajduje się poniżej,

public class RxBus { 

    private static RxBus instance; 

    private final PublishSubject<MotionEvent> motion_event = PublishSubject.create(); 

    public static RxBus getInstance() { 
     if (instance == null) { 
      instance = new RxBus(); 
     } 
     return instance; 
    } 

    public void sendMotionEvent(MotionEvent motionEvent) { 
     motion_event.onNext(motion_event); 
    } 

    public Observable<MotionEvent> getMotionEvent() { 
     return motion_event; 
    } 
} 
2

Jest to dość łatwe do wykonania za pomocą oddzwonię. Po prostu utwórz interfejs z dowolnymi metodami, których potrzebujesz, a następnie zaimplementuj w swoim Viewpager. Połączenie zostanie wywołane w klasie Widok na podstawie zdarzeń dotykowych, a odpowiedzi przejdą do Viewpagera. Stworzyłem przykład z ImageView w mojej MainActivity i wywołałem, aby zmienić jego rozmiar z innego fragmentu i to działa. Oto mój kod poniżej:

public interface ICallBackForResize { 
    void resizeme(); 
    void actionUp(); 
    void actionDown(); 

} 

główną działalność:

public class MainActivity extends AppCompatActivity implements ICallBackForResize { 

ImageView img; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    img= (ImageView) findViewById(R.id.image); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 

@Override 
public void resizeme() { 
    Toast.makeText(MainActivity.this,"called",Toast.LENGTH_LONG).show(); 
    img.getLayoutParams().height += 20; 
    img.getLayoutParams().width += 20; 
    img.requestLayout(); 
} 

@Override 
public void actionUp() { 
    //do whatever 
} 

@Override 
public void actionDown() { 
    //do whatever 

} 
} 

Moja klasa Fragment z prostym przyciskiem:

public class MyFragmentButton extends Fragment { 
View view; 
ICallBackForResize callBackForResize; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    callBackForResize= (ICallBackForResize) getActivity(); 
} 

@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    view=inflater.inflate(R.layout.mybutton,container,false); 
    Button btn= (Button) view.findViewById(R.id.button); 
    btn.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      callBackForResize.resizeme(); 
     } 
    }); 
    return view; 
} 
} 

wierzę, że nie potrzebują pliku XML. Właśnie wspólne jeśli ktoś potrzebuje:

activity_main:

<?xml version="1.0" encoding="utf-8"?> 

<android.support.design.widget.AppBarLayout 
    android:layout_height="wrap_content" 
    android:layout_width="match_parent" 
    android:theme="@style/AppTheme.AppBarOverlay"> 

    <android.support.v7.widget.Toolbar 
     android:id="@+id/toolbar" 
     android:layout_width="match_parent" 
     android:layout_height="?attr/actionBarSize" 
     android:background="?attr/colorPrimary" 
     app:popupTheme="@style/AppTheme.PopupOverlay" /> 

</android.support.design.widget.AppBarLayout> 

<include layout="@layout/content_main"/> 


</android.support.design.widget.CoordinatorLayout> 

content_main:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:paddingLeft="@dimen/activity_horizontal_margin" 
android:paddingRight="@dimen/activity_horizontal_margin" 
android:paddingTop="@dimen/activity_vertical_margin" 
android:paddingBottom="@dimen/activity_vertical_margin" 
app:layout_behavior="@string/appbar_scrolling_view_behavior" 
tools:showIn="@layout/activity_main" 
tools:context="nanofaroque.com.addlistener.MainActivity"> 

<ImageView 
    android:id="@+id/image" 
    android:text="Hello World!" 
    android:layout_width="100dp" 
    android:layout_gravity="center" 
    android:src="@mipmap/ic_launcher" 
    android:layout_height="100dp" /> 


<fragment 
    android:name="nanofaroque.com.addlistener.MyFragmentButton" 
    android:id="@+id/headlines_fragment" 
    android:layout_width="100dp" 
    android:layout_height="100dp" /> 

</FrameLayout> 

myButton:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="match_parent" 
android:layout_height="match_parent"> 
<Button 
    android:id="@+id/button" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" /> 

</LinearLayout> 
+0

Dziękuję za krótką odpowiedź, ale jestem zainteresowany obsługą zdarzeń dotykowych w obu widokach w tym samym czasie (w tej chwili, jeśli przekazuję zdarzenie dotykowe z jednego widoku do drugiego, po prostu zignoruj ​​zdarzenie na najwyższym poziomie widok). Sprawdź zaktualizowane pytanie. –

+0

W takim przypadku ChildView powinien być w osobnym układzie, w co wierzę. Względny układ nie będzie działał w tym scenariuszu, ponieważ jedna pozycja jest wyświetlana względem innych. Dzięki i powodzenia. –

Powiązane problemy