Android jest dużym kombajnem, z którego możemy dużo wycisnąć. To nie tylko telefony, tv, ale też i normalny sprawny system operacyjny. Możemy z niego korzystać jak z każdego systemu zainstalowanego na komputerze. Prawie na każdym systemie mamy okna, które możemy przesuwać po ekranie. Android też to posiada, dlatego poniżej zobaczysz, w jaki sposób stworzyć pływające okna w Androidzie. Można to wykorzystać w powiadomieniach, takie zastosowanie możemy znaleźć w aplikacji Messenger od Facebooka jako dymki. Zaczynajmy!
Przygotowania
W przypadku wersji Androida API<=22 nie potrzebujemy żadnych uprawnień, natomiast w nowszym Androidzie musimy uzyskać uprawnienia, aby aplikacja mogła „rysować” widoki nad innymi aplikacjami. W pliku manifestu dodajemy:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
W kodzie aplikacji (na przykład w głównej aktywności) dodajemy coś takiego:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
checkPermission();
} else {
initBtn();
}
....
private void initBtn() {
Button startFloatingWindow = findViewById(R.id.startFloatingWindow);
startFloatingWindow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(new Intent(MainActivity.this, FloatWindowService.class));
}
});
}
@TargetApi(Build.VERSION_CODES.M)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (resultCode == RESULT_OK)
initBtn();
else {
Toast.makeText(this,"Draw over other app permission not available.", Toast.LENGTH_SHORT).show();
}
}
}
public void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
}
Musisz także zarejestrować usługę w manifeście:
<service android:name=".FloatWindowService" />
Przygotuj serwis
Teraz musisz stworzyć klasę FloatWindowService, która będzie pracowała w tle. Rozszerz ją o klasę Service. Metoda onCreate() może wyglądać tak:
@Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
else
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.x = 0;
params.y = 0;
params.gravity = Gravity.CENTER;
floatingWindow = getXML();
windowManager.addView(floatingWindow, params);
floatingWindow.setOnTouchListener( new View.OnTouchListener() {
WindowManager.LayoutParams updatedParams = params;
int x,y;
float touchX,touchY;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
//remember the initial position.
x= updatedParams.x;
y=updatedParams.y;
//get the touch location
touchX = motionEvent.getRawX();
touchY = motionEvent.getRawY();
break;
case MotionEvent.ACTION_MOVE:
//Calculate the X and Y coordinates of the view.
updatedParams.x = (int)(x+(motionEvent.getRawX() - touchX));
updatedParams.y = (int)(y+(motionEvent.getRawY() - touchY));
//Update the layout with new X & Y coordinate
windowManager.updateViewLayout(view,updatedParams);
default:break;
}
return false;
}
});
}W pierwszej kolejności tworzymy menadżer okna wraz z parametrami, który ma się pojawić. Następnie dodajemy widok do menadżera (zmienna floatingWindow).
Metoda setOnTouchListener() pozwala na przesuwanie elementu na ekranie. Za każdym razem, gdy użytkownik dotknie widoku, zarejestrujemy początkowe współrzędne X i Y, a kiedy użytkownik poruszy element, aplikacja obliczy nowe współrzędne X i Y i przeniesie widok w nowe miejsce.
Tworzenie widoku
Tworząc pływające okna w Androidzie, masz dwie opcję:
- Stworzyć za pomocą pliku xml jak każdy inny layout.
- Stworzyć programowo.
Poniżej przedstawiam dwie metody przykładowe. Za pomocą XML:
public View getXML() {
View myview = LayoutInflater.from(this).inflate(R.layout.window, null);
Button button = myview.findViewById(R.id.stopWindow);
button.setOnClickListener(btnListener);
return myview;
}lub programowo:
public View getLayout() {
LinearLayout linearLayout = new LinearLayout(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
linearLayout.setLayoutParams(layoutParams);
linearLayout.setBackgroundResource(R.color.transparent);
linearLayout.setOrientation(LinearLayout.VERTICAL);
TextView textView = new TextView(this);
textView.setText("This is a floating window");
textView.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams layoutParamsText = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
textView.setLayoutParams(layoutParamsText);
linearLayout.addView(textView);
Button button = new Button(this);
button.setText("Stop floating window");
ViewGroup.LayoutParams btnparms = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
button.setLayoutParams(btnparms);
button.setGravity(Gravity.CENTER_HORIZONTAL);
button.setOnClickListener(btnListener);
linearLayout.addView(button);
return linearLayout;
}Nie zapomnij też o obsłudze przycisku, który zamknie okno i wyłączy usługę.
View.OnClickListener btnListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
windowManager.removeView(floatingWindow);
stopSelf();
}
};Efekt:
Podsumowanie
To wszystkie kroki, które musisz wykonać, aby wyświetlić pływające okno w Androidzie. Powyższy przykład jest prosty i pokazuje kwadraz z guzikiem. Nic nie stoi, na przeszkodzi, aby widok zmienić na kółko, trójkąt czy inny wygląd 🙂 Teraz stwórz własny projekt. Efekt fajny, ale pamiętaj, że ma swoje ograniczenia. Musisz zapytać użytkownika o uprawnienia. Warto przed ustawieniem uprawnień wyjaśnić użytkownikowi czemu potrzebujesz takich uprawnień.

