میخوای وارد بازار کار بشی و محصولات خودت رو بفرشی همین الان ثبت نام کن
0

قابلیت single touch و multi touch در اندروید

کلاس استاندارد و پرکاربرد View کتابخانه های اندروید به راحتی قادر است از رخدادهای touch پشتیبانی کرده و به آن ها پاسخ دهد.

می توانید به رخدادهایی که توسط لمس نمایشگر فعال می شوند، در activity و view های پروژه ی خود پاسخ دهید. سیستم اندروید این قابلیت را دارد تا همزمان از چندین pointer که نشانگر انگشت بر روی نمایشگر و تعامل کاربر با چند نقطه از صفحه نمایش دستگاه می باشد، پشتیبانی کند.

قابلیت single touch و multi touch در اندروید
قابلیت single touch و multi touch در اندروید

 

کلاس پایه ای (پدر) که برای پشتیبانی از قابلیت لمس نمایشگر، توسعه می بایست از آن ارث بری کند، کلاس MotionEvent می باشد. این کلاس به واسطه ی متد onTouchEvent() به عنوان پارامتر به آبجکت های Views فرستاده می شود.

به منظور فراهم آوردن قابلیت پاسخ دهی و واکنش نشان دادن به event های مربوط به touch (لمس نمایشگر)، کافی است متد onTouchEvent() را بازنویسی (override) نمایید.

کلاس MotionEvent تمامی اطلاعات مربوط به قابلیت touch نظیر تعداد pointer ها، مختصات X/Y، میزان اندازه و pressure هر pointer را در بردارد.

چنانچه event فعال شده توسط لمس نمایشگر را view مدیریت کند، آنگاه متد نام برده مقدار بولی true را در خروجی برمی گرداند. لازم به ذکر است که سیستم اندروید تلاش می کند تودرتوترین (deepest) کلاس view ای که event مربوط به touch را مدیریت کرده و مقدار true را برگردانده، پیدا کند.در صورتی که view خود داخل view دیگر (parent view یا view میزبان) جای گرفته باشد، آنگاه view میزبان می تواند با بازگردانی true از تابع onInterceptTouchEvent() ، جلوی ارسال رخداد به view زیرمجموعه را بگیرد. در نتیجه ی این عملیات، رخداد MotionEvent.Action_CANCEL به view ای که قبلا قرار بود رخداد اصلی را دریافت کند، ارسال شده و view میزبان خود مدیریت event را بر عهده می گیرد.

برای واکنش نشان دادن به رخدادهای لمس نمایشگر در سطح یک activity، کافی است OnTouchListener را برای View های مربوطه اعلان نمایید.

 


وضعیت لمس یک نقطه از نمایشگر (single touch)

چنانچه تنها یک انگشت در آن واحد با سطح نمایشگر برخورد داشته و سیستم اندروید تنها یک ورودی دریافت کرده باشد، در آن صورت توسعه دهنده می تواند با فراخوانی متد getX() و getY()، مقادیر و اطلاعات مربوط به موقعیت فعلی (مختصات) اولین انگشتی که با صفحه تعامل داشته را بازیابی کند.

با فراخوانی متد getAction() توسعه دهنده action و فعلی که اجرا شده را در خروجی دریافت می کند.

 

Event شرح
MotionEvent.ACTION_DOWNNew touch started(انگشت با سطح نمایشگر برخورد کرده و در نتیجه touch یا لمس دیگری آغاز شده است)
MotionEvent.ACTION_MOVEFinger is moving(انگشت کاربر در سطح نمایشگر در حال حرکت است)
MotionEvent.ACTION_UPFinger went up(انگشت کاربر دیگر با نمایشگر تعامل ندارد)
MotionEvent.ACTION_CANCELرخداد جاری لغو شده (به view زیرمجموعه یا فرزند ارسال نمی شود) و view دیگری مدیریت event مربوطه را برعهده می گیرد.
MotionEvent.ACTION_POINTER_DOWNPointer down (multi-touch)انگشت کاربر با سطح نمایشگر برخورد کرده و بر روی آن قرار دارد (وضعیت پشتیبانی از لمس همزمان چند نقطه از نمایشگر).
MotionEvent.ACTION_POINTER_UPPointer up (multi-touch)انگشت کاربر از روی سطح نمایشگر برداشته شده است (وضعیت پشتیبانی از لمس همزمان چند نقطه از نمایشگر).

 


قابلیت لمس چندین نقطه از صفحه (Multi touch)

قابلیت پیاده سازی و پشتیبانی از وضعیت لمس چندین نقطه از نمایشگر به طور همزمان در اپلیکیشن های اندرویدی از ویرایش ۲٫۰ کتابخانه های اندروید اضافه شده و ورژن ۲٫۲ به مراتب ارتقا یافت.

MotionEvent.ACTION_POINTER_DOWN و MotionEvent.ACTION_POINTER_UP زمانی ارسال می شوند که انگشت دوم با سطح نمایشگر تعامل برقرار کند.

دو رخداد MotionEvent.ACTION_DOWN و MotionEvent.ACTION_UP نیز به هنگام برخورد انگشت اول با سطح نمایشگر مورد استفاده قرار می گیرند.

متد getPointerCount() که در سطح کلاس MotionEvent موجود است، به شما این اجازه را می دهد تا تعداد pointer ها (انگشت یا شی دیگری که با نمایشگر ارتباط داشته) را بازیابی نمایید. تمامی رخدادهای مربوطه، به همراه موقعیت و مختصات pointer ها همگی در نمونه ی ایجاد شده از MotionEvent که به عنوان پارامتر متد onTouch() دریافت می کنید، موجود می باشد.

جهت رصد (track) و ردیابی اطلاعات مربوط به تمامی pointer ها، لازم است دو متد MotionEvent.getActionIndex() و MotionEvent.getActionMasked() را فراخوانی کنید و از طریق آن ها اندیس pointer و رخداد مربوط به touch که از برخورد این pointer فعال شده، شناسایی نمایید.

اندیس pointer ممکن است در طول زمان تغییر کند. به طور مثال می توان به زمانی اشاره کرد که یک انگشت از سطح نمایشگر برداشته می شود. نسخه ی پایدار از pointer همان pointer id است که با متد getPointerId(pointerIndex) از آبجکت MotionEvent قابل شناسایی و بازیابی می باشد.

کاربرد آن به صورت عملی در زیر نمایش داده شده است.

 

@Override
public boolean onTouchEvent(MotionEvent event) {
                // get pointer index from the event object
                int pointerIndex = event.getActionIndex();
                // get pointer ID
                int pointerId = event.getPointerId(pointerIndex);
                // get masked (not specific to a pointer) action
                int maskedAction = event.getActionMasked();
                switch (maskedAction) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_POINTER_DOWN: {
                        // TODO use data
                        break;
                }
                case MotionEvent.ACTION_MOVE: { // a pointer was moved
                        // TODO use data
                        break;
                }
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                case MotionEvent.ACTION_CANCEL: {
                        // TODO use data
                        break;
                }
                }
                invalidate();
                return true;
}

 

نکته : امکان تست قابلیت Multitouch در شبیه ساز وجود ندارد. برای آزمودن قابلیت لمس چندین نقطه از نمایشگر به طور همزمان، نیاز به یک دستگاه واقعی اندروید دارید (دستگاهی که ورودی را دریافت می کند باید یک دستگاه حقیقی اندروید باشد).

 


کلاس GestureDetectors

چارچوب نرم افزاری اندروید کلاسی به نام GestureDetector را ارائه می دهد که از اطلاعات و اعضای آبجکت (نمونه ی ساخته شده از کلاس) MotionEvents استفاده می نماید. این کلاس قادر است انواع حرکت ها (gesture) و رخدادها (event ها) را با استفاده از نمونه ی کلاس MotionEvents که به عنوان پارامتر ارائه می شود، شناسایی کند. تابع بازفراخوان GestureDetector.OnGestureListener (callback) کاربران را به محض رخداد مربوطه از motion event (رخدادی که بر اثر حرکت فعال می شود) مورد نظر مطلع می سازد.

به طور مثال کلاس ScaleGestureDetector این امکان را به شما می دهد تا حرکت از پیش تعیین شده ی کوچک و بزرگ کردن یک آّبجکت با دو انگشت را تعریف نمایید.

 


تمرین: پیاده سازی view اختصاصی و مدیریت رخدادهای مربوط به لمس یک نقطه از نمایشگر (single touch event)

 

 ترسیم با استفاده از قابلیت لمس نمایشگر

تمرین حاضر نحوه ی مدیریت رخدادهای مربوط به لمس یک نقطه از نمایشگر را داخل یک view اختصاصی نمایش می دهد.

ابتدا یک پروژه و activity جدید به ترتیب به نام های com.vogella.android.touch.single و SingleTouchActivity ایجاد نمایید. این activity از کلاس DialogFragment برای تنظیم رنگ قابل استفاده برای ترسیم در سطح نمایشگر بهره می گیرد.

حال یک فایل layout به نام fragment_colorpicker.xml با محتوای زیر ایجاد نمایید.

 

<!--?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">
<view android:layout_width="match_parent" android:layout_height="40dp" android:layout_margin="20dp" android:background="#ff0000" android:id="@+id/preview">
<seekbar android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/red" android:progress="255" android:max="255">
<seekbar android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/green" android:max="255">
<seekbar android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/blue" android:max="255">
</seekbar></seekbar></seekbar></view></linearlayout>

 

کلاسی به نام TouchEventView تعریف کرده که یک آبجکت View با قابلیت پشتیبانی از لمس یک نقطه از نمایشگر در آن واحد را پیاده سازی می کند.

package com.vogella.android.touch.single;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
public class TouchEventView extends View {
  private Paint paint = new Paint();
  private Path path = new Path();
  Context context;
  GestureDetector gestureDetector;
  public TouchEventView(Context context, AttributeSet attrs) {
    super(context, attrs);
    gestureDetector = new GestureDetector(context, new GestureListener());
    this.context = context;
    paint.setAntiAlias(true);
    paint.setStrokeWidth(6f);
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
  }
  public void setColor(int r, int g, int b) {
    int rgb = Color.rgb(r, g, b);
    paint.setColor(rgb);
  }
  private class GestureListener extends GestureDetector.SimpleOnGestureListener {
    // event when double tap occurs
    @Override
    public boolean onDoubleTap(MotionEvent e) {
      float x = e.getX();
      float y = e.getY();
      // clean drawing area on double tap
      path.reset();
      Log.d("Double Tap", "Tapped at: (" + x + "," + y + ")");
      return true;
    }
  }
  @Override
  protected void onDraw(Canvas canvas) {
    canvas.drawPath(path, paint);
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float eventX = event.getX();
    float eventY = event.getY();
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      path.moveTo(eventX, eventY);
      return true;
    case MotionEvent.ACTION_MOVE:
      path.lineTo(eventX, eventY);
      break;
    case MotionEvent.ACTION_UP:
      break;
    default:
      return false;
    }
    // for demostraction purposes
    gestureDetector.onTouchEvent(event);
    // Schedules a repaint.
    invalidate();
    return true;
  }
}

محتوای فایل activity_main.xml را به صورت زیر اصلاح نمایید.

<!--?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">
<com.vogella.android.touch.single.singletoucheventview android:layout_width="match_parent" android:background="@drawable/dwarf" android:layout_height="match_parent" android:id="@+id/drawingview">
    </com.vogella.android.touch.single.singletoucheventview>
</linearlayout>
<picture></picture>

حال view مورد نظر را به کلاس activity خود اضافه نمایید.

package com.vogella.android.touch.single;
import android.app.Activity;
import android.os.Bundle;
public class SingleTouchActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(new SingleTouchEventView(this, null));
        }
}

اکنون زمانی که اپلیکیشن را اجرا می کنید، بایستی با توجه به کدی که نوشته اید قادر باشید با انگشت خود بر روی نمایشگر دستگاه اشکال مختلفی ترسیم کنید (در محیط شبیه ساز با استفاده از موس).

کد اپلیکیشن خود را طوری ویرایش کنید که از تعریف و محتوای یک فایل layout با فرمت XML برای تنظیم ظاهر خود استفاده کند.

 

نکته : به منظور اعلان view دلخواه خود در لایه ی XML اپیلکیشن، کد موجود در فایل layout، لازم است اسم و آدرس دقیق کلاس از جمله اطلاعات پکیج آن کلاس را ذکر نمایید.

افزودن قابلیت تنظیم پهنای خط ترسیم (line width)

یک منو به اپلیکیشن خود اضافه کنید (المان مربوطه را در لایه ی XML، داخل فایل layout به صورت زیر اعلان نمایید).

 

 

<!--?xml version="1.0" encoding="utf-8" ?-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Pick pen" android:id="@+id/action_pickpen">
</item></menu>


رصد و ردیابی مختصات جاری انگشت کاربر بر روی نمایشگر

حال کدی به اپلیکیشن خود اضافه نمایید که موقعیت فعلی انگشت کاربر بر روی نمایشگر را با استفاده از یک دایره نشانه گذاری و دنبال کند. به منظور ترسیم دایره، می توانید متد addCircle(x, y, 50, Path.Direction.CW) را بر روی نمونه ی ساخته شده از کلاس Path فراخوانی کنید یا المان canvas را مستقیما بکار ببرید.

اطمینان حاصل کنید که تنها موقعیت جاری انگشت کاربر بر روی نمایشگر با استفاده از شکل دایره نشانه گذاری و هایلایت می شود. شکل مزبور بایستی به مجرد برخورد انگشت کاربر با سطح نمایشگر دستگاه پدیدار شده و زمانی که تماس انگشت با صفحه قطع شد، محو گردد.

خروجی می بایست شمابه زیر باشد.

 

رصد و ردیابی مختصات جاری انگشت کاربر بر روی نمایشگر
رصد و ردیابی مختصات جاری انگشت کاربر بر روی نمایشگر

 


تمرین: پیاده سازی قابلیت پشتیبانی از لمس چندین نقطه از نمایشگر (Multitouch)

در تمرین جاری، توسعه دهنده می بایست یک view اعلان کند که از قابلیت multitouch پشتیبانی کرده و از این طریق امکان ردیابی و پاسخ دهی به چندین انگشت بر روی نمایشگر به طور همزمان را فراهم آورد. لازم به ذکر است که تمرین پیاده سازی قابلیت لمس چند نقطه از نمایشگر در آن واحد در بستر شبیه ساز ممکن نبوده و توسعه دهنده می بایست برای این منظور حتما از دستگاه واقعی اندروید استفاده کند.

همان طور که قبلا گفته شد، نرم افزار emulator اندروید تنها اجازه ی شبیه سازی singletouch را (با اشاره گر موس) برای برنامه نویس فراهم می کند.

یک پروژه و activity جدید به ترتیب به نام های com.vogella.android.multitouch و MainActivity ایجاد نمایید.

ابتدا کلاسی به نام MultitouchView را به صورت زیر پیاده سازی کنید.

 

package com.vogella.android.multitouch;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
public class MultitouchView extends View {
        private static final int SIZE = 60;
        private SparseArray<pointf> mActivePointers;
        private Paint mPaint;
        private int[] colors = { Color.BLUE, Color.GREEN, Color.MAGENTA,
                        Color.BLACK, Color.CYAN, Color.GRAY, Color.RED, Color.DKGRAY,
                        Color.LTGRAY, Color.YELLOW };
        private Paint textPaint;
        public MultitouchView(Context context, AttributeSet attrs) {
                super(context, attrs);
                initView();
        }
        private void initView() {
                mActivePointers = new SparseArray<pointf>();
                mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                // set painter color to a color you like
                mPaint.setColor(Color.BLUE);
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                textPaint.setTextSize(20);
        }
        @Override
        public boolean onTouchEvent(MotionEvent event) {
                // get pointer index from the event object
                int pointerIndex = event.getActionIndex();
                // get pointer ID
                int pointerId = event.getPointerId(pointerIndex);
                // get masked (not specific to a pointer) action
                int maskedAction = event.getActionMasked();
                switch (maskedAction) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_POINTER_DOWN: {
                        // We have a new pointer. Lets add it to the list of pointers
                        PointF f = new PointF();
                        f.x = event.getX(pointerIndex);
                        f.y = event.getY(pointerIndex);
                        mActivePointers.put(pointerId, f);
                        break;
                }
                case MotionEvent.ACTION_MOVE: { // a pointer was moved
                        for (int size = event.getPointerCount(), i = 0; i < size; i++) {
                                PointF point = mActivePointers.get(event.getPointerId(i));
                                if (point != null) {
                                        point.x = event.getX(i);
                                        point.y = event.getY(i);
                                }
                        }
                        break;
                }
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                case MotionEvent.ACTION_CANCEL: {
                        mActivePointers.remove(pointerId);
                        break;
                }
                }
                invalidate();
                return true;
        }
        @Override
        protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                // draw all pointers
                for (int size = mActivePointers.size(), i = 0; i < size; i++) {
                        PointF point = mActivePointers.valueAt(i);
                        if (point != null)
                                mPaint.setColor(colors[i % 9]);
                        canvas.drawCircle(point.x, point.y, SIZE, mPaint);
                }
                canvas.drawText("Total pointers: " + mActivePointers.size(), 10, 40 , textPaint);
        }
}
</pointf></pointf>

view زیر را به فایل layout متناظر activity خود اضافه نمایید.

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<com.vogella.android.multitouch.multitouchview android:layout_width="match_parent" android:layout_height="match_parent">
</com.vogella.android.multitouch.multitouchview></relativelayout>

کلاس activity ای که قبلا ایجاد شده نیازی به تغییر ندارد.

 

 

package com.vogella.android.multitouch;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        }
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                getMenuInflater().inflate(R.menu.activity_main, menu);
                return true;
        }
}

اپلیکیشن در زمان اجرا به شما این امکان را می دهد تا با انگشت خود بر روی نمایشگر اشکال مختلف ترسیم نمایید. در هر دستگاهی، محدودیت از پیش تعیین شده ای برای حداکثر تعداد نقاط قابل پشتیبانی در آن واحد در نمایشگر وجود دارد. لازم است بررسی کنید دستگاه شما حداکثر چه تعداد pointer را به طور همزمان پشتیبانی می کند. در پایان، اپلیکیشن بایستی ظاهری مشابه زیر داشته باشد.

 

قابلیت single touch و multi touch در اندروید

 


پیاده سازی قابلیت بزرگ نمایی / کوچک نمایی و استفاده از multitouch

یک پروژه و activity اندروید به ترتیب به نام های de.vogella.android.touch.scaledetector و ScaleDetectorTestActivity ایجاد نمایید.

کلاس زیر را پیاده سازی نمایید.

 

package de.vogella.android.touch.scaledetector;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
public class ImageViewWithZoom extends View {
        private Drawable image;
        private float scaleFactor = 1.0f;
        private ScaleGestureDetector scaleGestureDetector;
        public ImageViewWithZoom(Context context) {
                super(context);
                image = context.getResources().getDrawable(R.drawable.icon);
                setFocusable(true);
                image.setBounds(0, 0, image.getIntrinsicWidth(),
                                image.getIntrinsicHeight());
                scaleGestureDetector = new ScaleGestureDetector(context,
                                new ScaleListener());
        }
        @Override
        protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                // Set the image bounderies
                canvas.save();
                canvas.scale(scaleFactor, scaleFactor);
                image.draw(canvas);
                canvas.restore();
        }
        @Override
        public boolean onTouchEvent(MotionEvent event) {
                scaleGestureDetector.onTouchEvent(event);
                invalidate();
                return true;
        }
        private class ScaleListener extends
                        ScaleGestureDetector.SimpleOnScaleGestureListener {
                @Override
                public boolean onScale(ScaleGestureDetector detector) {
                        scaleFactor *= detector.getScaleFactor();
                        // don't let the object get too small or too large.
                        scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 5.0f));
                        invalidate();
                        return true;
                }
        }
}

این View را به activity خود اضافه نمایید.

package de.vogella.android.touch.scaledetector;
import android.app.Activity;
import android.os.Bundle;
public class ScaleDetectorTestActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(new ImageViewWithZoom(this));
        }
}

زمانی که اپلیکیشن را راه اندازی می کنید، بایستی بتوانید با استفاده از قابلیت multi-touch تصویر زیر را کوچک و بزرگ نمایید (pinch zoom).


امیدواریم آموزش قابلیت single touch و multi touch در اندروید نیز برای شما مفید واقع شده باشد و ادامه آموزش برنامه نویسی اندروید رو دنبال کنید . برای مطالعه پست‌ها بیشتر ، ما را در مدرسه کدنویسی تلگرام  و یا در تی جوان اینستاگرام دنبال کنید.

نظراتتون رو زیر همین پست با ما به اشتراک بگذارید.

 

ارسال دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

×

سلام کاربر عزیز

هر سوالی دارید در این بخش هستیم تا شما رو راهنمائی کنیم

روی لوگومون کلیک کنید

× چطور میتونم کمکتون کنم؟