欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Android實(shí)現(xiàn)跨頁(yè)面懸浮窗效果

 更新時(shí)間:2024年11月08日 10:09:00   作者:xiaoerbuyu1233  
這篇文章主要為大家詳細(xì)介紹了如何使用Android實(shí)現(xiàn)跨頁(yè)面懸浮窗效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

實(shí)現(xiàn)效果

在 Application#onCreate初始化

 FloatingWindowManager
                .getInstance(App.this).setImg(R.drawable.ic_test).setWidthHeight(280,280)
                .setOnFloatingClickListener(new FloatingWindowManager.OnFloatingClickListener() {
                    @Override
                    public void onClick(FrameLayout floatingView) {
                        Toast.makeText(floatingView.getContext(), "測(cè)試點(diǎn)擊懸浮窗", Toast.LENGTH_SHORT).show();
                    }
                });

完整代碼

import android.app.Activity;
import android.app.Application;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast;
 
import androidx.appcompat.app.AlertDialog;
 
import java.util.List;
 
/**
 * https://blog.csdn.net/xiaoerbuyu1233/article/details/143595475
 * <p>
 * 跨頁(yè)面懸浮窗 Application#onCreate 初始化
 * <p>
 * FloatingWindowManager
 * .getInstance(App.this).setImg(R.drawable.ic_test).setWidthHeight(280,280)
 * .setOnFloatingClickListener(new FloatingWindowManager.OnFloatingClickListener() {
 *
 * @Override public void onClick(FrameLayout floatingView) {
 * Toast.makeText(floatingView.getContext(), "測(cè)試點(diǎn)擊懸浮窗", Toast.LENGTH_SHORT).show();
 * }
 * });
 */
public class FloatingWindowManager {
    private static FloatingWindowManager instance;
    private final Context context;
    private FrameLayout floatingView;
    private ViewGroup rootView;
    private OnFloatingClickListener listener;
    private int width = 200, height = 200;
    private Application.ActivityLifecycleCallbacks activityLifecycleCallbacks;
 
    private FloatingWindowManager(Context context) {
        this.context = context;
        initFloatingView();
        registerActivityLifecycleCallbacks();
    }
 
    public static synchronized FloatingWindowManager getInstance(Context context) {
        if (instance == null) {
            instance = new FloatingWindowManager(context);
        }
        return instance;
    }
 
    private void registerActivityLifecycleCallbacks() {
        Application application = (Application) context.getApplicationContext();
        activityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                Log.d("FloatingWindowManager", "onActivityCreated: " + activity.getLocalClassName());
                // 可以在這里附加懸浮窗口到新創(chuàng)建的 Activity
                attachToActivity(activity);
            }
 
            @Override
            public void onActivityStarted(Activity activity) {
                Log.d("FloatingWindowManager", "onActivityStarted: " + activity.getLocalClassName());
            }
 
            @Override
            public void onActivityResumed(Activity activity) {
                Log.d("FloatingWindowManager", "onActivityResumed: " + activity.getLocalClassName());
                attachToActivity(activity);
            }
 
            @Override
            public void onActivityPaused(Activity activity) {
                detachFromActivity();
                Log.d("FloatingWindowManager", "onActivityPaused: " + activity.getLocalClassName());
            }
 
            @Override
            public void onActivityStopped(Activity activity) {
                Log.d("FloatingWindowManager", "onActivityStopped: " + activity.getLocalClassName());
            }
 
            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                Log.d("FloatingWindowManager", "onActivitySaveInstanceState: " + activity.getLocalClassName());
            }
 
            @Override
            public void onActivityDestroyed(Activity activity) {
                Log.d("FloatingWindowManager", "onActivityDestroyed: " + activity.getLocalClassName());
            }
        };
 
        // 注冊(cè) Activity 生命周期回調(diào)
        application.registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
    }
 
 
    public FloatingWindowManager setImg(int icon) {
        // 使用資源ID直接設(shè)置背景
        if (floatingView != null) {
            floatingView.setBackgroundResource(icon);
        }
//        // 獲取Drawable對(duì)象
//        Drawable drawable = ContextCompat.getDrawable(context, R.drawable.ic_test);
//
//        // 設(shè)置背景
//        if (drawable != null) {
//            floatingView.setBackground(drawable);
//        }
        return this;
    }
 
    public FloatingWindowManager setWidthHeight(int width, int height) {
        this.width = width;
        this.height = height;
 
        // 設(shè)置布局參數(shù)
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(width, height); // 寬度和高度
        layoutParams.gravity = Gravity.TOP | Gravity.START;
        floatingView.setLayoutParams(layoutParams);
        return this;
    }
 
    private void initFloatingView() {
        // 初始化懸浮窗視圖
        floatingView = new FrameLayout(context) {
            @Override
            public boolean performClick() {
                if (super.performClick()) {
                    return true;
                }
                if (listener != null) {
                    floatingView.getHandler().post(() -> listener.onClick(floatingView));
                }
                return true;
            }
        };
 
        floatingView.setOnTouchListener(new View.OnTouchListener() {
            private int initialX, initialY;
            private float startX, startY;
            private static final int CLICK_DRAG_TOLERANCE = 40; // 點(diǎn)擊和拖動(dòng)之間的容差距離
 
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        initialX = (int) (event.getRawX() - v.getX());
                        initialY = (int) (event.getRawY() - v.getY());
                        startX = event.getRawX();
                        startY = event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        int newX = (int) (event.getRawX() - initialX);
                        int newY = (int) (event.getRawY() - initialY);
                        if (rootView != null) {
                            v.setX(newX);
                            v.setY(newY);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        float endX = event.getRawX();
                        float endY = event.getRawY();
                        float distanceX = Math.abs(endX - startX);
                        float distanceY = Math.abs(endY - startY);
                        if (distanceX < CLICK_DRAG_TOLERANCE && distanceY < CLICK_DRAG_TOLERANCE) {
                            // 如果移動(dòng)的距離小于容差,那么我們認(rèn)為這是一個(gè)點(diǎn)擊
                            if (floatingView.performClick()) {
                                return true; // 點(diǎn)擊已被處理
                            }
                        } else {
                            // 如果移動(dòng)的距離大于容差,那么我們認(rèn)為這是一個(gè)拖動(dòng)
                            snapToEdge();
                        }
                        break;
                    default:
                        break;
                }
                return true; // 消耗事件
            }
        });
 
        // 設(shè)置布局參數(shù)
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(width, height); // 寬度和高度
        layoutParams.gravity = Gravity.TOP | Gravity.START;
        floatingView.setLayoutParams(layoutParams);
    }
 
    public void attachToActivity(Activity activity) {
        if (activity == null || floatingView == null) return;
 
        rootView = (ViewGroup) activity.findViewById(android.R.id.content);
        if (rootView != null && floatingView.getParent() == null) {
            rootView.addView(floatingView);
        }
    }
 
    public void detachFromActivity() {
        if (rootView != null && floatingView != null && floatingView.getParent() != null) {
            rootView.removeView(floatingView);
        }
    }
 
    public void setOnFloatingClickListener(OnFloatingClickListener listener) {
        this.listener = listener;
    }
 
    private void snapToEdge() {
        // 實(shí)現(xiàn)貼邊功能
        // 這里只是一個(gè)簡(jiǎn)單的例子,你可以根據(jù)自己的需求調(diào)整貼邊的具體實(shí)現(xiàn)
        int[] location = new int[2];
        floatingView.getLocationOnScreen(location);
        int x = location[0];
        int y = location[1];
 
        int screenWidth = rootView.getWidth();
        int screenHeight = rootView.getHeight();
 
        int halfScreenWidth = screenWidth / 4; // 假設(shè)屏幕寬度的3/4處作為貼邊判斷點(diǎn)
        if (x < halfScreenWidth) {
            floatingView.setX(0);
        } else {
            floatingView.setX(screenWidth - floatingView.getWidth());
        }
    }
 
    public interface OnFloatingClickListener {
        void onClick(FrameLayout floatingView);
    }
 
    /**
     * 顯示一個(gè)列表對(duì)話框,用戶點(diǎn)擊列表項(xiàng)后會(huì)將該項(xiàng)內(nèi)容復(fù)制到剪貼板
     *
     * @param context 上下文
     * @param items   列表項(xiàng)數(shù)據(jù)
     */
    public static void showListDialogCopy(Context context, String title, List<String> items) {
        // 創(chuàng)建一個(gè)AlertDialog.Builder對(duì)象
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        // 設(shè)置對(duì)話框標(biāo)題
        builder.setTitle(title);
 
        // 設(shè)置列表項(xiàng)
        builder.setItems(items.toArray(new CharSequence[0]), (dialog, which) -> {
            // 獲取用戶選擇的項(xiàng)
            String selectedItem = items.get(which);
 
            // 復(fù)制文本到剪貼板
            ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
            ClipData clip = ClipData.newPlainText("label", selectedItem);
            clipboard.setPrimaryClip(clip);
 
            // 可選: 提示用戶已成功復(fù)制
            Toast.makeText(context, "已復(fù)制: " + selectedItem, Toast.LENGTH_SHORT).show();
 
            // 關(guān)閉對(duì)話框
            dialog.dismiss();
        });
 
        // 創(chuàng)建并顯示對(duì)話框
        AlertDialog dialog = builder.create();
        dialog.show();
    }
}

代碼很簡(jiǎn)單不多解釋  無(wú)非是添加隱藏 

到此這篇關(guān)于使用Android實(shí)現(xiàn)跨頁(yè)面懸浮窗效果的文章就介紹到這了,更多相關(guān)Android跨頁(yè)面懸浮窗內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Flutter的路由導(dǎo)航

    詳解Flutter的路由導(dǎo)航

    這篇文章主要介紹了Flutter的路由導(dǎo)航的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Flutter,感興趣的朋友可以了解下
    2021-04-04
  • Android zip4j壓縮、解壓、加解密的示例代碼

    Android zip4j壓縮、解壓、加解密的示例代碼

    本篇文章主要介紹了Android zip4j壓縮、解壓、加解密的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • 利用Flutter制作一個(gè)摸魚(yú)桌面版App

    利用Flutter制作一個(gè)摸魚(yú)桌面版App

    Win10商店上架了一款名為《摸魚(yú)》的App,在下載打開(kāi)之后,這個(gè)App會(huì)讓你的電腦進(jìn)入一個(gè)假更新的畫(huà)面。本文將為大家介紹如何通過(guò)Flutter制作一個(gè)桌面版的摸魚(yú)APP,快跟小編一起學(xué)習(xí)一下吧
    2021-12-12
  • Android基于OpenCV實(shí)現(xiàn)圖像金字塔

    Android基于OpenCV實(shí)現(xiàn)圖像金字塔

    圖像金字塔是圖像中多尺度表達(dá)的一種,最主要用于圖像的分割,是一種以多分辨率來(lái)解釋圖像的有效但概念簡(jiǎn)單的結(jié)構(gòu)。本文講解Android基于OpenCV實(shí)現(xiàn)圖像金字塔的步驟
    2021-06-06
  • Android Activity之間相互調(diào)用與傳遞參數(shù)的原理與用法分析

    Android Activity之間相互調(diào)用與傳遞參數(shù)的原理與用法分析

    這篇文章主要介紹了Android Activity之間相互調(diào)用與傳遞參數(shù)的原理與用法,較為詳細(xì)的分析了Android組件的構(gòu)成以及Activity的創(chuàng)建、調(diào)用、切換等相關(guān)操作技巧,需要的朋友可以參考下
    2016-08-08
  • Android實(shí)現(xiàn)圖像灰度化、線性灰度變化和二值化處理方法

    Android實(shí)現(xiàn)圖像灰度化、線性灰度變化和二值化處理方法

    這篇文章主要介紹了Android實(shí)現(xiàn)圖像灰度化、線性灰度變化和二值化處理方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • 用于cocos2d-x引擎(ndk)中為android項(xiàng)目生成編譯文件列表

    用于cocos2d-x引擎(ndk)中為android項(xiàng)目生成編譯文件列表

    在android的ndk項(xiàng)目中,添加很多源文件之后總要手動(dòng)編寫(xiě)makefile來(lái)添加所有的源文件, 很麻煩,所以寫(xiě)了一個(gè)自動(dòng)生成編譯源文件列表的小工具
    2014-05-05
  • 自定義一個(gè)theme在不同的sdk環(huán)境下繼承不同的值

    自定義一個(gè)theme在不同的sdk環(huán)境下繼承不同的值

    可能很多在高版本下編繹apk的同學(xué),可能都曾有和我一樣的困惑,就是如何讓低版本的用戶也能有高版本的體驗(yàn)?zāi)?/div> 2013-01-01
  • Android中通知Notification使用實(shí)例(振動(dòng)、燈光、聲音)

    Android中通知Notification使用實(shí)例(振動(dòng)、燈光、聲音)

    這篇文章主要介紹了Android中通知Notification使用實(shí)例,實(shí)現(xiàn)振動(dòng),燈光,聲音等效果,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Android Activity狀態(tài)與操作探究

    Android Activity狀態(tài)與操作探究

    Activity作為Android四大組件之一,他的啟動(dòng)絕對(duì)沒(méi)有那么簡(jiǎn)單。這里涉及到了系統(tǒng)服務(wù)進(jìn)程,啟動(dòng)過(guò)程細(xì)節(jié)很多,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值
    2022-12-12

最新評(píng)論