6

下の画像の例を考えると、

ここに画像の説明を入力

キャンバスViewからViewpagerにタッチ イベントを渡すソリューションを探しています。これは、両方のビューに同時に同じ量のズームを適用するために必要です。

何が起こっているかの技術的な説明は次のとおりです。

(ビューをAB & Cと考えてみましょう)

A. 親ビュー

B. ビュー

C. ページャーを表示

子 ( B & C ) でdispatchTouchEvent()が呼び出される前に、 A.dispatchTouchEvent()は最初にA.onInterceptTouchEvent()を呼び出して、ビュー グループがイベントのインターセプトに関心があるかどうかを確認します。

したがって、A.onTouchEvent()がfalseを返す場合、 B.onTouchEvent () に戻ります。それがfalseを返した場合、C.onTouchEvent()に戻り、通常どおりディスパッチが続行されます。

そしてtrueを返すと、

  1. ACTION_CANCELがすべての子にディスパッチされます。

  2. 後続のすべてのジェスチャ イベント ( ACTION_UP / ACTION_CANCELまで) は、イベント リスナー ( OnTouchListener.onTouch() ) によって消費されます (定義されている場合)

この時点で、親ビューから子ビューにイベントを渡すことはできますが、2 つの子ビューBを許可することはできません。& Cイベントを一緒に処理します (両方のビューに同じ量のズームを適用します)。

イベントを同時に処理できるように、親ビューから子ビューにタッチ イベントを渡す方法はありますか?

これが私のレイアウト設定です。

<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>
4

2 に答える 2

5

私が間違っていなければ、トップ ビューとボトム ビューの両方で同じタッチ イベントを処理する必要があります。Android タッチ アーキテクチャによると、同時に複数のビューからのタッチ イベントを処理することはできません。メソッド内で処理するonTouchEvent()か、次のビューに渡す必要があります。また、トップビューが ) の処理を​​終了するまで待機MotionEvent(し、子ビューに処理させる必要があります。

RxAndroidアプローチを使用した可能な解決策は次のとおりです。

キャンバス ビューの 内MotionEvent()で、

@Override
    public boolean onTouchEvent(MotionEvent event) {

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

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

    return true;
}

これにより、モーション イベントが監視され、すべてのオブザーバーに通知されます。

ここで、viewpager のonResume()モーション イベントのサブスクライブ内で、キャンバスから変更が行われるたびにすぐにイベントを渡すようにします。

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クラスを以下に示します

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(motionEvent);
    }

    public Observable<MotionEvent> getMotionEvent() {
        return motion_event;
    }
}
于 2016-12-13T05:46:41.853 に答える
2

コールバックを使用して実装するのは非常に簡単です。必要なメソッドを使用してインターフェイスを作成し、Viewpager に実装するだけです。タッチ イベントに基づいて View クラスで呼び出しが呼び出され、応答が Viewpager に送られます。MainActivity で ImageView を使用して例を作成し、別のフラグメントからサイズを変更するように呼び出しましたが、機能します。以下は私のコードです:

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

 }

主な活動:

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

}
 }

シンプルなボタンを持つ私の Fragment クラス:

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;
}
}

xmlファイルは必要ないと思います。誰かが必要な場合に共有しました:

アクティビティ_メイン:

<?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>

マイボタン:

 <?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>
于 2016-12-08T04:28:04.813 に答える