Android WindowManager TYPE_SYSTEM_ALERT Diseño en el tacto

Mi aplicación muestra un botón para el usuario en determinados momentos como TYPE_SYSTEM_ALERT y estoy tratando de dejar que el usuario moverlo. La acción de tocar y mover se registra con el código debajo pero el botón no se mueve. ¿Qué me estoy perdiendo?

//create button mbtRec = new Button(ACR.getContext()); mbtRec.setText(R.string.start_recording); mbtRec.setTypeface(null, Typeface.BOLD); mbtRec.setBackgroundColor(Color.RED); //mbtRec.setBackgroundResource(R.drawable.ic_launcher); mbtRec.setOnClickListener(recButtonOnClickListener); mbtRec.setOnTouchListener(recButtonOnTouchListener); //create layout params recButtonLayoutParams = new WindowManager.LayoutParams(); recButtonLayoutParams.flags = WindowManager.LayoutParams.FORMAT_CHANGED; //8 recButtonLayoutParams.format = PixelFormat.RGBA_8888; //PixelFormat.TRANSLUCENT recButtonLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; recButtonLayoutParams.gravity = Gravity.TOP | Gravity.CENTER; //51 recButtonLayoutParams.width = WindowManager.LayoutParams.FILL_PARENT; recButtonLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; paramWindowManager.addView(this.mbtRec, recButtonLayoutParams); OnTouchListener recButtonOnTouchListener = new View.OnTouchListener() { @TargetApi(Build.VERSION_CODES.FROYO) @Override public boolean onTouch(View v, MotionEvent event) { switch(event.getActionMasked()) { case MotionEvent.ACTION_DOWN: Tools.Log("Drag", "Started Dragging"); break; case MotionEvent.ACTION_UP: Tools.Log("Drag", "Stopped Dragging"); break; case MotionEvent.ACTION_MOVE: Tools.Log("Drag", "Dragging"); recButtonLayoutParams.x =(int) event.getRawX(); recButtonLayoutParams.y= (int) event.getRawY(); mbtRec.setLayoutParams(recButtonLayoutParams); mbtRec.invalidate(); break; default: break; } return false; } }; 

    He conseguido conseguir lo que quiero con la punta de @ yoah y más investigación durante 10 días. Debo añadir @ pingpongboss ( https://github.com/pingpongboss/StandOut ) respuestas a mi correo electrónico ayudó mucho.

    Aquí es lo que he creado y aplicado a mi aplicación de grabación de llamadas ACR

     private WindowManager recButtonWindowManager; private Button recButton = null; WindowManager.LayoutParams prms; boolean touchconsumedbyMove = false; int recButtonLastX; int recButtonLastY; int recButtonFirstX; int recButtonFirstY; OnTouchListener recButtonOnTouchListener = new View.OnTouchListener() { @TargetApi(Build.VERSION_CODES.FROYO) @Override public boolean onTouch(View v, MotionEvent event) { WindowManager.LayoutParams prm = getRecbuttonLayout(); int totalDeltaX = recButtonLastX - recButtonFirstX; int totalDeltaY = recButtonLastY - recButtonFirstY; switch(event.getActionMasked()) { case MotionEvent.ACTION_DOWN: recButtonLastX = (int) event.getRawX(); recButtonLastY = (int) event.getRawY(); recButtonFirstX = recButtonLastX; recButtonFirstY = recButtonLastY; break; case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_MOVE: int deltaX = (int) event.getRawX() - recButtonLastX; int deltaY = (int) event.getRawY() - recButtonLastY; recButtonLastX = (int) event.getRawX(); recButtonLastY = (int) event.getRawY(); if (Math.abs(totalDeltaX) >= 5 || Math.abs(totalDeltaY) >= 5) { if (event.getPointerCount() == 1) { prm.x += deltaX; prm.y += deltaY; touchconsumedbyMove = true; recButtonWindowManager.updateViewLayout(getManualRecButton(), prm); } else{ touchconsumedbyMove = false; } }else{ touchconsumedbyMove = false; } break; default: break; } return touchconsumedbyMove; } }; private WindowManager.LayoutParams getRecbuttonLayout() { if (prms != null) { return prms; } prms = new WindowManager.LayoutParams(); prms.format = PixelFormat.TRANSLUCENT; prms.flags = LayoutParams.FORMAT_CHANGED; // 8 prms.type = LayoutParams.TYPE_SYSTEM_ALERT; prms.gravity = Gravity.TOP | Gravity.CENTER; prms.width = LayoutParams.WRAP_CONTENT; prms.height = LayoutParams.WRAP_CONTENT; // Tools.Log("getRecbuttonLayout", "return getRecbuttonLayout()"); return prms; } private Button getManualRecButton() { if (recButton != null) { return recButton; } recButton = new Button(ACR.getContext()); recButton.setText(R.string.start_recording); recButton.setTypeface(null, Typeface.BOLD); recButton.setGravity(Gravity.CENTER_VERTICAL); recButton.setBackgroundColor(Color.parseColor("#65FF0000")); recButton.setPadding(100, 30, 100, 30); recButton.setOnClickListener(recButtonOnClickListener); recButton.setOnTouchListener(recButtonOnTouchListener); return recButton; } 

    Estoy haciendo algo similar, pero usando marginLeft y marginTop. Después de cambiar el diseño, debe llamar al

      windowManager.updateViewLayout(recButton, recButtonLayoutParams); 

    Creo que es necesario utilizar mbtRec.postInvalidate() lugar, y eliminar la gravity

    Puesto que cambia los parámetros de diseño para el WindowManager, en lugar de llamar a:

     mbtRec.setLayoutParams(recButtonLayoutParams); mbtRec.invalidate(); 

    Usted debe llamar:

     paramWindowManager.updateLayout(this.mbtRec, recButtonLayoutParams); 

    Al final del caso ACTION_MOVE.

    Ajuste el botón para ajustarlo a la pantalla

     recButtonLayoutParams.width = WindowManager.LayoutParams.FILL_PARENT; 

    Así que no puede moverlo en la dirección x.

    ¿Cómo alguna vez se supone que ser capaz de moverlo en la dirección Y a menos que su padre está configurado para envolver el contenido, entonces también te bloqueará.

    Que lo que vi de alguna manera, espero que esto ayude.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.