2015年4月6日 星期一

Android中觸控動作的傳遞 dispatchTouchEvent()

在Android中,MotionEvent(動作事件)是可以被傳遞的,例如你可以把事件由一個元件接收,處理過後再把它傳給另一個元件去接收,這時侯接收事件的元件會當成事件在它之中發生。

下面我們用一個簡單的例子來體會,以下程式碼的成品中有兩個方塊,小方塊的長寬皆為大方塊的一半,小方塊在大方塊的下面,當使用者在小方塊上觸控時,會移動大方塊裡的星星圖型,而移動到的位置是小方塊以等比例的方式對應到大方塊的位置。

需要注意的是,此例只是直接地由小方塊傳送觸控動作事件給大方塊,大方塊並沒有去判斷此事件是由哪裡來的,所以如果直接觸控大方塊的話,一樣可以移動其中的星星圖型。

  1. 首先是佈局檔:
  2. activity_main.xml:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    
        xmlns:tools="http://schemas.android.com/tools" 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" tools:context=".MainActivity">
    
    
    
        <FrameLayout
    
            android:layout_width="300dp"
    
            android:layout_height="300dp"
    
            android:layout_alignParentTop="true"
    
            android:layout_centerHorizontal="true"
    
            android:id="@+id/frame1"
    
            android:background="#ff1aa4ff">
    
    
    
            <ImageView
    
                android:layout_width="76dp"
    
                android:layout_height="76dp"
    
                android:id="@+id/imageView"
    
                android:layout_gravity="center"
    
                android:src="@android:drawable/btn_star_big_on" />
    
        </FrameLayout>
    
    
    
        <FrameLayout
    
            android:layout_width="150dp"
    
            android:layout_height="150dp"
    
            android:layout_below="@+id/frame1"
    
            android:layout_centerHorizontal="true"
    
            android:id="@+id/frame2"
    
            android:background="#ff7aff10"></FrameLayout>
    
    </RelativeLayout>
  3. 再來是程式碼:
  4. MainActivity.java:
    package com.example.administrator.dispatchmotionevent_example;
    
    
    
    import android.support.v7.app.ActionBarActivity;
    
    import android.os.Bundle;
    
    import android.view.Menu;
    
    import android.view.MenuItem;
    
    import android.view.MotionEvent;
    
    import android.view.View;
    
    import android.widget.FrameLayout;
    
    import android.widget.ImageView;
    
    
    
    
    
    public class MainActivity extends ActionBarActivity {
    
        FrameLayout frame1;
    
        FrameLayout frame2;
    
        ImageView imageView;
    
        //frame1的尺寸為famre2的2倍
    
        float scale = 2;
    
    
    
        @Override
    
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.activity_main);
    
    
    
            frame1 = (FrameLayout) findViewById(R.id.frame1);
    
            frame2 = (FrameLayout) findViewById(R.id.frame2);
    
            imageView = (ImageView) findViewById(R.id.imageView);
    
    
    
            frame1.setOnTouchListener(new View.OnTouchListener() {
    
                @Override
    
                public boolean onTouch(View v, MotionEvent event) {
    
                    imageView.setX(event.getX()-(float)imageView.getWidth()/2);
    
                    imageView.setY(event.getY()-(float)imageView.getHeight()/2);
    
                    return true;
    
                }
    
            });
    
    
    
            frame2.setOnTouchListener(new View.OnTouchListener() {
    
                @Override
    
                public boolean onTouch(View v, MotionEvent event) {
    
                    // 將event的X和Y值修正成frame1的尺寸
    
                    event.setLocation(event.getX() * scale, event.getY() * scale);
    
                    //將Event傳給frame1
    
                    frame1.dispatchTouchEvent(event);
    
                    return true;
    
                }
    
            });
    
        }
    
    
    
    
    
        @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);
    
        }
    
    }
成品如下列影片所示:

沒有留言 :

張貼留言