1

我想提请高于一切的图标类似于新的Facebook信使的chathead移动位于窗口管理器不能正常工作

我已创建一个服务到屏幕(最上面的)上的ImageView在后台工作,并根据特定的条件我的图标应该出现在屏幕上(就像当有人在Facebook上发送消息时,Messenger服务将钩住消息并在屏幕上显示聊天头以通知您新消息)

我所做的:

我已创建的服务,并给了它我从ImageView的继承一个类(StickyHeadView)显示系统警告窗口(因为头实际上是一个系统警报窗口)

[assembly: UsesPermission(Name = Android.Manifest.Permission.SystemAlertWindow)] 

许可和使用实施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; 
    } 
}  

服务有wiindow管理员显示其上的图标...在服务“的OnStart”事件中,我初始化头:

 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); 
     } 

,你可以看到我已经声明了一个窗口管理和有特殊参数

添加视图(MyHead)将其

我的问题:

当过我尝试移动搜索(我的头)没有关系”以稳定的方式移动并不断地震!

我使用的是真实的HTC Android手机4.0.4测试它

我使用MonoDroid的

请帮助......如果触摸的执行是不正确的,请提出一个更好的办法...谢谢。

+0

为什么没有身体的答复!我想这是一个问题的论坛! – user1512094 2013-05-06 16:49:42

+0

是那个java?你使用什么编译器? – 2014-03-24 18:42:51

回答

2

的e.GetX()/ eGetY()使用的是相对于查看位置,以便当移动与UpdateViewLayout视图的下一个值将是相对于所述移动。它使用GetRawX()/ GetRawY(),但你必须跟踪最初的down rawX和rawY。

这里是我的JAVA的作品:

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    switch (event.getAction()) { 
     case MotionEvent.ACTION_MOVE: 
      layoutParams.x = Math.round(event.getRawX() - downX); 
      layoutParams.y = Math.round(event.getRawY() - downY); 
      windowManager.updateViewLayout(floatingView, layoutParams); 
      return true;      
     case MotionEvent.ACTION_DOWN: 
      downX = event.getRawX() - layoutParams.x; 
      downY = event.getRawY() - layoutParams.y; 
      return true;      
     case MotionEvent.ACTION_UP: 
      return true; 
    } 
    return false; 
} 

一个评论,有一个在使用windowManager.updateViewLayout(...)一个很大的缺点这种方法将调用onLayout为每个移动浮动观点,并认为可能是一个性能问题,无论如何,直到现在我还没有找到另一种方法来移动浮动视图。

1

试试这可能有助于FUL

首先你的活动添加全局变量:

WindowManager wm; 
    LinearLayout lay; 
    float downX,downY; 

放于代码后的onCreate您的活动

Button btnstart=(Button)findViewById(R.id.button1); 
    Button btnstop=(Button)findViewById(R.id.button2); 

    btnstart.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 

      if(lay==null) 
      { 
       wm = (WindowManager) getApplicationContext().getSystemService(
         Context.WINDOW_SERVICE); 
       final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
         LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 
         WindowManager.LayoutParams.TYPE_SYSTEM_ALERT 
           | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 
         WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 
           | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
         PixelFormat.TRANSLUCENT); 
       params.x = (int) wm.getDefaultDisplay().getWidth(); 
       params.y = 0; 
       // params.height = wm.getDefaultDisplay().getHeight()/2; 
       params.width = LayoutParams.WRAP_CONTENT; 
       params.format = PixelFormat.TRANSLUCENT; 

       params.gravity = Gravity.TOP | Gravity.LEFT; 
       params.setTitle("Info"); 

       lay = null; 

       lay = new LinearLayout(getApplicationContext()); 
       lay.setOrientation(LinearLayout.VERTICAL); 
       // lay.setAlpha(0.5f); 

       TextView txt_no = new TextView(getApplicationContext()); 
       txt_no.setTextSize(10.0f); 
       txt_no.setText("Moving view by stack user!"); 

       txt_no.setTextColor(Color.BLACK); 
       // txt_no.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 
       // LayoutParams.WRAP_CONTENT)); 

       LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
         LinearLayout.LayoutParams.WRAP_CONTENT, 
         LinearLayout.LayoutParams.WRAP_CONTENT); 
       layoutParams.setMargins(0, 0, 0, 0); // margins as you wish 

       txt_no.setGravity(Gravity.RIGHT); 
       txt_no.setBackgroundColor(Color.WHITE); 
       txt_no.setLayoutParams(layoutParams); 
       txt_no.setPadding(10, 10, 10, 10); 

       lay.addView(txt_no); 

       AlphaAnimation alpha = new AlphaAnimation(0.5F, 0.5F); 
       alpha.setDuration(0); // Make animation instant 
       alpha.setFillAfter(true); // Tell it to persist after the animation ends 
       // And then on your layout 
       wm.addView(lay, params); 
       txt_no.startAnimation(alpha); 

       downX=params.x; 
       downY=params.y; 

       Log.v("MSES>", "x="+ downX +",y="+ downY); 

       lay.setOnTouchListener(new OnTouchListener() { 

        @Override 
        public boolean onTouch(View v, MotionEvent event) { 
         // TODO Auto-generated method stub 

         switch (event.getAction()) { 
         case MotionEvent.ACTION_MOVE: 

          params.x = Math.round(event.getRawX() - downX); 
          params.y = Math.round(event.getRawY() - downY); 
          wm.updateViewLayout(lay, params); 
          Log.v("MSES EVENT>", "x="+ event.getRawX() +",y="+ event.getRawY()); 
          Log.v("MSES MOVE>", "x="+ params.x +",y="+ params.y); 
          return true;      
         case MotionEvent.ACTION_DOWN: 
          downX = event.getRawX() - params.x; 
          downY = event.getRawY() - params.y; 
          Log.v("MSES DOWN>", "x="+ params.x +",y="+ params.y); 
          return true;      
         case MotionEvent.ACTION_UP: 
          //params.x = Math.round(event.getRawX() - downX); 
          //params.y = Math.round(event.getRawY() - downY); 
          //wm.updateViewLayout(lay, params); 
          return true;     

         } 
         return false; 
        } 
       }); 
      } 

     } 
    }); 

    btnstop.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      if (lay != null) { 
       lay.removeAllViews(); 
       wm.removeViewImmediate(lay); 
       lay = null; 
      } 
     } 
    }); 
4

在你的代码,只需使用...

TYPE_SYSTEM_ALERT 

TYPE_PHONE 

,而不是

TYPE_SYSTEM_OVERLAY 

希望这会帮助你。

工作示例:

@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; 
      } 
     }); 
}