[Học Android] Hướng dẫn tạo Floating View như ứng dụng Messenger

[Học Android] Hướng dẫn tạo Floating View như ứng dụng Messenger

Floating View là view trôi trên màn hình, thường gặp ở một số ứng dụng nhắn tin như Messenger, Zalo,… dưới dạng bong bóng chat. Người dùng có thể dễ dàng kéo thả, thao tác với view này ngay cả khi đang mở ứng dụng khác. Trong bài viết này, mình sẽ hướng dẫn các bạn tạo floating view tương tự như Messenger của Facebook.

1. Giới thiệu

Floating view là view trôi trên màn hình, nó rất thuận tiện cho việc thao tác đa nhiệm, 1 người có thể làm việc trên các ứng dụng khác nhau và kiểm soát chúng cùng 1 lúc. Điều đó có nghĩa là nếu bạn đang ở trong các ứng dụng tính toán, bạn có thể thấy được tin nhắn đến và trả lời tin nhắn thông qua bong bóng chat của Messenger nổi trên màn hình

Trong bài viết này, chúng ta sẽ tìm hiểu làm thế nào để tạo floating view đơn giản và cho phép người sử dụng để kéo chúng trên màn hình.

2. Bắt đầu

2.1. Tạo mới Project

Các bạn mở Android Studio, tạo mới ứng dụng với một activity: MainActivity và layout là activity_main.xml như sau :

activity_main.xml



    

Trong MainActivity, chúng ta sẽ có 2 button START, STOP để mở và tắt view giống MessengerFacebook.

2.2 “Draw over other apps” permission

Để view có thể kéo thả lên trên các ứng dụng khác, bạn phải yêu cầu ứng dụng của mình được sử dụng permison ACTION_MANAGE_OVERLAY_PERMISSION. Do đó, xử lý trong MainActivity như sau :

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, 0);
        }

    }

Ngoài ra, bạn cần phải thêm permission trong AndroidManifest.xml như sau :

    

Lúc này, khi chạy ứng dụng, app mở lên sẽ chuyển sang màn hình setting, để bạn có thể cho phép ứng dụng của mình được hiển thị đè lên các ứng dụng khác như sau :

Bạn hãy enable permission này lên để chúng ta tiếp tục các phần sau.

2.3. Service

Chúng ta sẽ tạo một Service để điểu khiển view mà chúng ta mong muốn. Các bạn hãy tạo một class mới, đặt tên là MyService.

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import androidx.annotation.Nullable;

public class MyService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Nhớ khai báo trong AndroidManifest.xml như sau :

      

Trong MyService, chúng ta sẽ tạo ra một ImageView, hiển thị icon của app, và xử lý logic khi người dùng kéo thả như sau :

package com.demo.floating;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

import androidx.annotation.Nullable;

public class MyService extends Service {

    private WindowManager mWindowManager;
    private ImageView image;

    @Override
    public void onCreate() {
        super.onCreate();

        image = new ImageView(this);

        image.setImageResource(R.mipmap.ic_launcher);

        mWindowManager = (WindowManager)getSystemService(WINDOW_SERVICE);

        final WindowManager.LayoutParams paramsF = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        paramsF.gravity = Gravity.TOP | Gravity.LEFT;
        paramsF.x=0;
        paramsF.y=100;
        mWindowManager.addView(image, paramsF);

        try{

            image.setOnTouchListener(new View.OnTouchListener() {
                WindowManager.LayoutParams paramsT = paramsF;
                private int initialX;
                private int initialY;
                private float initialTouchX;
                private float initialTouchY;
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch(event.getAction()){
                        case MotionEvent.ACTION_DOWN:
                            initialX = paramsF.x;
                            initialY = paramsF.y;
                            initialTouchX = event.getRawX();
                            initialTouchY = event.getRawY();
                            break;
                        case MotionEvent.ACTION_UP:
                            break;
                        case MotionEvent.ACTION_MOVE:
                            paramsF.x = initialX + (int) (event.getRawX() - initialTouchX);
                            paramsF.y = initialY + (int) (event.getRawY() - initialTouchY);
                            mWindowManager.updateViewLayout(v, paramsF);
                            break;
                    }
                    return false;
                }
            });
        } catch (Exception e){
            e.printStackTrace();
        }

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

2.4. Xử lý trong MainActivity

Chúng ta sẽ xử lý khi click vào button START , STOP trong MainActivity như sau :

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, 0);
        }

        findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //toast
                startService(new Intent(MainActivity.this, MyService.class));
            }
        });

        findViewById(R.id.btn_stop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(new Intent(MainActivity.this, MyService.class));
            }
        });

    }
}

Chạy ứng dụng, khi bạn click vào START, sẽ xuất hiện 1 view chính là icon của app. Bạn có thể kéo thả nó toàn màn hình, ngay cả khi thoát app như sau :

3. Kết luận

Qua bài viết hy vọng bạn đã biết cách tạo Floating View và có thể ứng dụng cho các dự án trong tương lai.

Cảm ơn bạn đã đọc bài viết.

Chào thân ái và quyết thắng!

admin

Leave a Reply

Your email address will not be published. Required fields are marked *