创建覆盖其他应用程序的 Xamarin 应用程序

jul*_*old 2 android overlay xamarin android-picture-in-picture

我正在尝试创建一个 xamarin android 应用程序,它应该有一个小的覆盖窗口,显示在其他应用程序之上。

不幸的是,我还没有找到示例代码或文档。

我想要实现的目标类似于 Apple Control Dot、Facebook chat-dot 或 google 地图导航覆盖层。

我的手机上还安装了一个简单的 makro 记录器应用程序,只要启用了“在其他应用程序之上绘制”的辅助功能权限,该应用程序就可以执行此操作。 示例覆盖窗口

在上面的屏幕截图中,您可以看到右侧的小录制控件。可以在屏幕上拖动控制覆盖图、打开设置等。

有人知道如何做到这一点吗?

此致,

朱利安

Leo*_*SFT 7

这是一个简单的示例,您可以参考。

创建一个浮动服务

[Service]
class FloatingService : Service,Android.Views.View.IOnTouchListener
{
    WindowManagerLayoutParams layoutParams;
    IWindowManager windowManager;
    View floatView;
    public override void OnCreate()
    {
        base.OnCreate();
    }

    [return: GeneratedEnum]
    public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
    {
        showFloatingWindow();
        return StartCommandResult.NotSticky;
    }
    public override IBinder OnBind(Intent intent)
    {
        return null;
    }

    private void showFloatingWindow()
    {
        windowManager = GetSystemService(WindowService).JavaCast<IWindowManager>();
        LayoutInflater mLayoutInflater = LayoutInflater.From(ApplicationContext);
        floatView = mLayoutInflater.Inflate(Resource.Layout.floatview, null);
        floatView.SetBackgroundColor(Android.Graphics.Color.Transparent);
        floatView.SetOnTouchListener(this);
        ImageView iv1 = floatView.FindViewById<ImageView>(Resource.Id.iv1);
        ImageView iv2 = floatView.FindViewById<ImageView>(Resource.Id.iv2);
        ImageView iv3 = floatView.FindViewById<ImageView>(Resource.Id.iv3);
        iv1.Click += delegate { Toast.MakeText(ApplicationContext, "The first Image Click", ToastLength.Short).Show(); };
        iv2.Click += delegate { Toast.MakeText(ApplicationContext, "The second Image Click", ToastLength.Short).Show(); };
        iv3.Click += delegate { Toast.MakeText(ApplicationContext, "The third Image Click", ToastLength.Short).Show(); };
        
        // set LayoutParam
        layoutParams = new WindowManagerLayoutParams();
            if (Build.VERSION.SdkInt >= Build.VERSION_CODES.O)
            {
                layoutParams.Type = WindowManagerTypes.ApplicationOverlay;
            }
            else
            {
                layoutParams.Type = WindowManagerTypes.Phone;
            }
            layoutParams.Flags = WindowManagerFlags.NotTouchModal;
            layoutParams.Flags = WindowManagerFlags.NotFocusable;

            layoutParams.Width = 400;
            layoutParams.Height = 100;
            layoutParams.X = 300;
            layoutParams.Y = 300;
            windowManager.AddView(floatView, layoutParams);
            
        }
    private int x;
    private int y;
    public bool OnTouch(View v, MotionEvent e)
    {
        switch (e.Action)
        {
        
            case MotionEventActions.Down:
                x = (int)e.RawX;
                y = (int)e.RawY;
                break;

            case MotionEventActions.Move:
                int nowX = (int) e.RawX;
                int nowY = (int) e.RawY;
                int movedX = nowX - x;
                int movedY = nowY - y;
                x = nowX;
                y = nowY;
                layoutParams.X = layoutParams.X+ movedX;
                layoutParams.Y = layoutParams.Y + movedY;

        
            windowManager.UpdateViewLayout(floatView, layoutParams);
                break;

            default:
                break;
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

floatview.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="horizontal"
   android:layout_width="wrap_content"
   android:layout_height="match_parent">

  <ImageView
    android:id="@+id/iv1"
    android:src="@android:drawable/ic_media_play"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

  <ImageView
    android:id="@+id/iv2"
    android:src="@android:drawable/star_on"
    android:layout_marginLeft="10dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
  <ImageView
    android:id="@+id/iv3"
    android:src="@android:drawable/ic_menu_more"
    android:layout_marginLeft="10dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

然后在您的 Activity 中启动 FloatingService :

 button.Click += async delegate
      {
         if (!Settings.CanDrawOverlays(this))
          {
            StartActivityForResult(new Intent(Settings.ActionManageOverlayPermission, Android.Net.Uri.Parse("package:" + PackageName)), 0);
          }
         else
          {
            StartService(new Intent(this, typeof(FloatingService)));

          }
      }

 protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
    {
        if (requestCode == 0)
        {
            if (!Settings.CanDrawOverlays(this))
            {

            }
            else
            {
                StartService(new Intent(this, typeof(FloatingService)));
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

并添加<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />到你的Manifest.xml.

效果如下:

在此输入图像描述