移动位于WindowManager中的ImageView不能正常工作

use*_*094 2 ontouchlistener android-layout xamarin.android android-imageview android-windowmanager

我正在尝试在屏幕上的所有内容上绘制一个图标(TOP MOST),类似于新的Facebook Messenger的聊天标题。

我已经创建了一个在后台工作的服务,并根据特定条件我的图标应出现在屏幕上(就像有人在Facebook上向您发送消息时,Messenger服务将挂接该消息并在屏幕上显示聊天头以进行通知关于新消息的内容)

我做了什么:

我已经创建了该服务,并授予它显示系统警报窗口的权限(因为该头部实际上是系统警报窗口)

[assembly: UsesPermission(Name = Android.Manifest.Permission.SystemAlertWindow)]
Run Code Online (Sandbox Code Playgroud)

我已经从ImageView继承了一个类(StickyHeadView),并使用以下方式实现了OnTouchListener侦听器:

class StickyHeadView : ImageView, Android.Views.View.IOnTouchListener
{
    private StickyHeadService OwnerService;

    public StickyHeadView(StickyHeadService ContextService, Context context)
        : base(context)
    {
        OwnerService = ContextService;
        SetOnTouchListener(this);
    }

    float TouchMoveX;
    float TouchMoveY;

    public bool OnTouch(View v, MotionEvent e)
    {
        var windowService = OwnerService.GetSystemService(Android.Content.Context.WindowService);
        var windowManager = windowService.JavaCast<Android.Views.IWindowManager>();

        switch (e.Action & e.ActionMasked)
        {
            case MotionEventActions.Move:
                TouchMoveX = (int)e.GetX();
                TouchMoveY = (int)e.GetY();
                OwnerService.LOParams.X = (int)(TouchMoveX);
                OwnerService.LOParams.Y = (int)(TouchMoveY);
                windowManager.UpdateViewLayout(this, OwnerService.LOParams);                    
                Log.Debug("Point : ", "X: " + Convert.ToString(OwnerService.LOParams.X) + " Y: " + Convert.ToString(OwnerService.LOParams.Y));
                return true;                    
            case MotionEventActions.Down:
                return true;                    
            case MotionEventActions.Up:
                return true;
        }
        return false;
    }
}    
Run Code Online (Sandbox Code Playgroud)

该服务具有wiindow管理器以在其上显示图标...在服务“ OnStart”事件中,我初始化了Head:

        private StickyHeadView MyHead;
        public Android.Views.WindowManagerLayoutParams LOParams;
        public override void OnStart(Android.Content.Intent intent, int startId)
        {
            base.OnStart(intent, startId);

            var windowService = this.GetSystemService(Android.Content.Context.WindowService);
            var windowManager = windowService.JavaCast<Android.Views.IWindowManager>();

            MyHead = new StickyHeadView(this, this);
            MyHead.SetImageResource(Resource.Drawable.Icon);
            LOParams = new Android.Views.WindowManagerLayoutParams(Android.Views.WindowManagerLayoutParams.WrapContent,
                                Android.Views.WindowManagerLayoutParams.WrapContent,
                                Android.Views.WindowManagerTypes.Phone,
                                Android.Views.WindowManagerFlags.NotFocusable,
                                Android.Graphics.Format.Translucent);

            LOParams.Gravity = GravityFlags.Top | GravityFlags.Left;
            LOParams.X = 10;
            LOParams.Y = 10;
            windowManager.AddView(MyHead, LOParams);
        } 
Run Code Online (Sandbox Code Playgroud)

如您所见,我已经声明了WindowManager并使用特殊参数将视图(MyHead)添加到其中

我的问题 :

每当我尝试移动视图(我的头)时,它就不会稳定地移动,并且会不断发生地震!

我正在使用HTC Phone上的android 4.0.4对其进行测试

我正在使用monodroid

请帮助...如果触摸的实现不正确,请提出更好的方法...谢谢。

Ami*_*are 5

在您的代码中只需使用...

TYPE_SYSTEM_ALERT
Run Code Online (Sandbox Code Playgroud)

要么

TYPE_PHONE
Run Code Online (Sandbox Code Playgroud)

代替

TYPE_SYSTEM_OVERLAY
Run Code Online (Sandbox Code Playgroud)

希望这会帮助你。

一个有效的例子:

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

    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    chatHead = new ImageView(this);
    chatHead.setImageResource(R.drawable.ic_launcher);

    final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, //TYPE_PHONE
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.TOP | Gravity.LEFT;
    params.x = 0;
    params.y = 100;

    windowManager.addView(chatHead, params);

    chatHead.setOnTouchListener(new View.OnTouchListener() {
          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 = params.x;
                initialY = params.y;
                initialTouchX = event.getRawX();
                initialTouchY = event.getRawY();
                return true;
              case MotionEvent.ACTION_UP:
                return true;
              case MotionEvent.ACTION_MOVE:
                params.x = initialX + (int) (event.getRawX() - initialTouchX);
                params.y = initialY + (int) (event.getRawY() - initialTouchY);
                windowManager.updateViewLayout(chatHead, params);
                return true;
            }
            return false;
          }
        });
}
Run Code Online (Sandbox Code Playgroud)