Xử lý đa chạm Multi Touch trong Android

Dịch vụ dạy kèm gia sư lập trình

Hầu hết các thiết bị Android bây giờ đang dùng màn hình hỗ trợ cảm ứng đa điểm. Việc phát hiện ra các vị trí touch (sự kiện chạm cảm ứng vào màn hình) hay gọi là multi touch. Multi touch trong Android là một tính năng rất hay, với nhiều ứng dụng trong thực tế.

Multi touch trong android giúp chúng ta biết được vị trí ngón tay thao tác. Từ đó giúp chúng ta tuỳ chỉnh theo yêu cầu của bài toán ứng dụng. Ví dụ như tính năng Zoom trong ứng dụng Gallery.

Bài viết này, mình sẽ hướng dẫn các bạn về xử lý Multi Touch để zoom ảnh trong ứng dụng Gallery.

Hướng dẫn viết code xử lý Multi touch trong Android

Ở bài viết viết này, mình sẽ hướng dẫn các bạn zoom ảnh bằng 2 ngón tay trong android.

Bản chất multi touch vẫn là xử lý sự kiện chạm vào màn hình cảm ứng, chỉ khác là dùng một ngón thì multi touch sẽ dùng nhiều ngón tay. Vì vậy, để hiển thị ảnh thì mình phải sử dụng một view nào đó như ImageView.

Tuy nhiên, ImageView theo mặc định thì lại không hỗ trợ multi touch. Đó là lý do mình sẽ tạo một custom view để build một view hiển thị ảnh có hỗ trợ multi touch.

👏 Bạn có thể đọc thêm về cách tạo một custom view cơ bản tại đây: Hướng dẫn tạo Custom View trong Android cho người mới

Đây là giao diện ứng dụng sau khi hoàn thành bài viết này. Nhìn giao diện rất cơ bản phải không?

Các sử dụng ứng dụng là bạn dụng 2 ngón tay để có thể zoom to nhỏ ảnh.

#1. Tạo một custom view

Đầu tiên các bạn tạo class ZoomImageView kế thừa từ ImageView để chúng ta bắt đầu customView.

public class ZoomImageView extends ImageView {
    public ZoomImageView(Context context) {
        super(context);
    }

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

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

    @SuppressLint("NewApi")
    public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
}

Android cung cấp lớp MotionEvent để hỗ trợ cảm ứng khi người dùng chạm vào màn hình thông qua view với phương thức onTouch().

Bạn chỉ cần overide lại phương thức onTouch() đối với view mà bạn muốn.

#2. Tìm hiểu hàm onTouch()

Lớp MotionEvent chứa các thông tin liên quan như: số lượng con trỏ, tọa độ X / Y, kích thước và áp lực của mỗi con trỏ.

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (mGestureDetector.onTouchEvent(event)) return true;
    mScaleGestureDetetor.onTouchEvent(event);
    float x = 0;
    float y = 0;
    int pointCount = event.getPointerCount();
    for (int i = 0; i < pointCount; i++) {
        x = x + event.getX(i);
        y = y + event.getY(i);
    }
    x /= pointCount;
    y /= pointCount;

    if (mLastPointCount != pointCount) {
        isCanDrag = false;
        mLastX = x;
        mLastY = y;
    }
    mLastPointCount = pointCount;
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_MOVE:
            float dx = x - mLastX;
            float dy = y - mLastY;
            if (!isCanDrag) {
                isCanDrag = isMoveAction(dx, dy);
            }
            if (isCanDrag) {
                RectF rectF = getMatrixRectF();
                if (getDrawable() != null) {
                    if (rectF.width() < getWidth()) {
                        dx = 0;
                    }
                    if (rectF.height() < getHeight()) {
                        dy = 0;
                    }
                    mMatrix.postTranslate(dx, dy);
                    checkBorderAndCenterWhenScale();
                    setImageMatrix(mMatrix);
                }
            }
            mLastX = x;
            mLastY = y;
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            mLastPointCount = 0;
            break;
    }
    return true;
}

Giống như các sự kiện khác, sự kiện Touch của một view có thể được phát hiện và xử lý thông qua việc đăng ký với trình lắng nghe sự kiện onTouchListener và thực thi phương thức onTouch() tương ứng.

Các phương thức onTouch trả về giá trị true nếu người dùng nhấn xuống hoặc nâng lên để chỉ ra rằng nó đã tiêu thụ các sự kiện. Tuy nhiên, đối với tất cả các hành động cảm ứng khác, phương thức này trả về giá trị false để chỉ ra rằng nó đã không nhận các sự kiện và các yếu tố khác có thể tiếp tục xử lý sự kiện này.

Khi xảy ra nhiều lần chạm vào màn hình tại cùng một thời điểm, mỗi một lần chạm được xem như là một con trỏ (pointer).

Mỗi con trỏ sẽ được tham chiếu đến một index và được gán một ID. Số con trỏ hay số lần chạm có thể được xác định nhờ phương thức getPointerCount() của đối tượng MotionEvent.

Giá trị trả về của hàm onTouch()

  • MotionEvent.ACTION_DOWN : Trả về với sự kiện khi bạn bắt đầu chạm vào view
  • MotionEvent.ACTION_MOVE : Trả về khi bạn di chuyển trên view đó.
  • MotionEvent.ACTION_UP : Trả về khi bạn nhấc tay ra khỏi view.
  • MotionEvent.ACTION_CANCEL : Trả về khi event touch cancel.
  • MotionEvent.ACTION_POINTER_DOWN : Chỉ có với multi-touch, trả về vị trí của mới khi bạn multiple touch
  • MotionEvent.ACTION_POINTER_UP : Chỉ có với multi-touch, trả ra khi bạn cancel một điểm mà bạn đã chạm trước đó.

💦 Bài viết khác có ích cho bạn: Xử lý sự kiện trong Android (Event Listeners)

#3. Xử lý scale ảnh khi phát hiện Multi touch trong android

Để scale được hình ảnh các bạn  kế thừa từ lớp ScaleGestureDetector.

public class ZoomImageView extends ImageView implements View.OnTouchListener, ScaleGestureDetector.OnScaleGestureListener

và chúng ta sẽ viết các tính toán trong hàm onScall().

@Override
public boolean onScale(ScaleGestureDetector detector) {
    float scale = getScale();
    float factor = detector.getScaleFactor();

    if (getDrawable() == null) return true;

    float dx = detector.getFocusX();
    float dy = detector.getFocusY();

    if ((scale < mMaxScale && factor > 1.0) || (scale > mInitScale && factor < 1.0f)) {
        if (scale * factor < mInitScale) {
            factor = mInitScale / scale;
        }

        if (scale * factor > mMaxScale) {
            factor = mMaxScale / scale;
        }

        mMatrix.postScale(factor, factor, dx, dy);

        checkBorderAndCenterWhenScale();

        setImageMatrix(mMatrix);
    }
    return true;
}

#4. Sử dụng ZoomImageView

Cuối cùng chúng ta chỉ cần khai báo trong file xml, giống bài trước mình đã hướng dẫn các bạn custom 1 view là xong và run project là chạy.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.zoomimageview.ZoomImageView
        android:id="@+id/action_infolinks_splash"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:src="@mipmap/bg_sontung" />

</LinearLayout>

Tổng kết

Như vậy là chúng ta đã hoàn thành việc tạo một custom view có hỗ trợ multi touch trong android.

Các bạn có thể download toàn bộ source code của bài hướng dẫn tại đây nhé.

Hy vọng bài viết này sẽ giúp bạn phần nào hiểu và có thể tự xử lý MultiTouch  cho ứng dụng của mình.

Ứng dụng của bạn có sử dụng Multi touch không? Để lại ý kiến của bạn ở bên dưới nhé.

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcKotlin trên Android – từ cơ bản tới nâng cao
Bài tiếp theoHeadless CMS là gì? Có nên quan tâm tới Headless CMS lúc này?
Tất cả lập trình viên đều là những nhà viết kịch và tất cả máy tính đều là những diễn viên tồi.

16
Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Mới nhất Cũ nhất Nhiều voted nhất
Thông báo
StevenBix
Guest
StevenBix

маг иннер отзывы Copyright (с) ООО «Шкулёв Диджитал Технологии», 2024. Любое воспроизведение материалов сайта без разрешения редакции воспрещается.Мама дорогая,вам в дурку надо,и всем остальным кто в это верит тоже.Приворот и порча это разные вещи. А у вас невроз походу. Надо хорошего психотерапевта. У приворота другие симптомы. А если порча, то надо к проведенному человеку идти, а то разведут на деньги. Ее можно самой проверить.Выражается порча в резких неприятных переменах, в серьезных проблемах со здоровьем, в разрушении отношений с окружающими, а также в депрессиях, в суицидальных наклонностях и в невозможности противостоять неблагоприятным обстоятельствам. Иногда, если наведенная порча очень сильна, то страдает… Đọc thêm »

JasonSup
Guest
JasonSup

альмарель маг отзывы андрей 17.11.2015 19:50 Хотим с женой сказать спасибо большое гинекологии. очень чуткие доктора,настоящие профессионалы своего дела. отдельное спасибо заведующей гинекологии Князевой Наталье Александровне! Огромное спасибо всем докторам. MatthewNuapy disse: Для этого наговора-приворота нужна вода, освященная в церкви. Очень сильным получится наговор, если набрать воду в ночь на Крещение Господне. Приворот на сигарете. Как сделать приворот на сигарете. Как приворожить человека при помощи сигареты. Самый простой приворот который можно сделать самостоятельно это приворот на сигарете. Курящему человеку дать сигарету на которую сделан приворотный обряд не составит особого труда. Сигарета на которую читали приворот ничем не отличается от 100… Đọc thêm »

Kellycal
Guest
Kellycal

lolita cp

==> 88nb.cc/aesiz url.epoch.tw/ZxQgz <==

lolita cp

Jamespog
Guest
Jamespog

Я хочу поделиться своим опытом использования услуг частного специалиста по озонированию, которого я нашла по номеру 8 909 826 3556 (Комсомольск-на-Амуре), для решения проблемы с запахом пота в фитнес зале, где я тренируюсь регулярно. Несмотря на то, что администрация зала предпринимала меры для борьбы с этим запахом, он продолжал оставаться и мешать моему комфорту во время тренировок. После того, как я нашла контактный номер частного специалиста по озонированию, я решила связаться с ним и узнать, сможет ли он помочь в решении моей проблемы. С первого же звонка я почувствовала, что имею дело с профессионалом, который понимает, как важно избавиться от… Đọc thêm »

TriptiaWap
Guest
TriptiaWap

Have you ever considered about including a little bit more than just your articles? I mean, what you say is fundamental and all. Nevertheless think of if you added some great graphics or videos to give your posts more, “pop”! Your content is excellent but with pics and video clips, this website could certainly be one of the most beneficial in its field. Good blog!

Brianlal
Guest
Brianlal

SEO-Ezoterica ru использует передовые технологии в управлении онлайн-репутацией. Их методы действенны и результативны!

StevenMop
Guest
StevenMop

настоящие и проверенные маги – отзывы Ангелина 89853905910 ______________________________________________________ Сотрудничество с Магом Ангелиной принесло мне невероятные результаты! Я обратился к ней с просьбой помочь мне в возвращении любимого человека. Она провела для меня ряд ритуалов и предложила мне несколько амулетов для привлечения любви. Я был поражен скоростью и эффективностью ее работы. Буквально через несколько недель мой любимый человек вернулся ко мне, и наша связь стала даже крепче, чем раньше. Я благодарен Магу Ангелине за ее помощь и настоятельно рекомендую ее всем, кто ищет помощи в области магии любви. Обращался к Магу Ангелине по ватсап 89853905910 – отзывы только хорошие найти… Đọc thêm »

betenovale
Guest
betenovale

interesting for a very long time

Stephanelido
Guest
Stephanelido

child porno

==> url.epoch.tw/K9M9j s.yjm.pl/3Eea <==

StevenShene
Guest
StevenShene

interesting news