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