赞
踩
在台式电脑上,我们可以很轻松的最小化窗口,在后台做一些事情,并在任何时候都可以最大化窗口。但我们在android应用程序中看不到这一功能。如今,我们可以看到android提供了分屏功能,但这是操作系统提供的功能,而不是应用程序的单独功能。让我们制作一个应用程序,只需单击一个按钮即可将其最小化和最大化。该功能可以在很多方面帮助用户。假设你正在阅读一些带有数学计算的文档,那么最小化计算器将非常有用。
1.1要在Android Studio中创建新项目。请注意,先选择Emply Activity,再选择选择Java作为编程语言。
2.1为应用程序添加新颜色:
转到values->Colors.xml。可以在此处添加任何自定义颜色。我们添加了这两种颜色。
代码如下(示例):
- <color name="gfgTheme">#FF2F8D46</color>
- <color name="gfgThemeTwo">#FF098043</color>
2.2移除操作栏:
在Android Studio 4.1中,转到values->themes。有两个主题XML文件,一个用于亮模式,另一个用于暗模式。在这两个XML中,在样式块中将父属性更改为Theme.MaterialComponents.DayNight.NoActionBar。
- <resources xmlns:tools="http://schemas.android.com/tools">
- <!-- Base application theme. -->
- <style name="Theme.FloatingWindow" parent="Theme.MaterialComponents.DayNight.NoActionBar">
- <!-- Primary brand color. -->
- <item name="colorPrimary">@color/purple_500</item>
- <item name="colorPrimaryVariant">@color/purple_700</item>
- <item name="colorOnPrimary">@color/white</item>
- <!-- Secondary brand color. -->
- <item name="colorSecondary">@color/teal_200</item>
- <item name="colorSecondaryVariant">@color/teal_700</item>
- <item name="colorOnSecondary">@color/black</item>
- <!-- Status bar color. -->
- <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
- <!-- Customize your theme here. -->
- </style>
- </resources>
2.3更改应用程序的主主题颜色:
更改应用程序的主要主题颜色:在同一文件中,第一个项目块必须与应用程序的主要颜色有关。在这里添加了新添加的颜色。在项目块中添加@color/gfgTheme 或 @color/gfgThemeTwo.
3.1制作activity_main.xml文件
此 XML 文件制作应用程序的主要活动的布局。布局没有那么复杂。在约束布局中只有一个Button、TextView、EditText和ConstraintLayout中的一个又一个按钮。下面是 XML 代码。
- <?xml version="1.0" encoding="utf-8"?>
- <androidx.constraintlayout.widget.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/white"
- tools:context=".MainActivity">
-
- <Button
- android:id="@+id/buttonMinimize"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="20dp"
- android:text="Wink"
- android:textColor="@android:color/white"
- android:textSize="25sp"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
- <TextView
- android:id="@+id/titleText"
- android:layout_width="match_parent"
- android:layout_height="70dp"
- android:gravity="center"
- android:text="浮动窗口"
- android:textColor="@color/gfgTheme"
- android:textSize="30sp"
- android:textStyle="bold"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/buttonMinimize" />
-
- <EditText
- android:id="@+id/descEditText"
- android:layout_width="match_parent"
- android:layout_height="330dp"
- android:layout_marginTop="10dp"
- android:gravity="start"
- android:hint="这里写下内容"
- android:paddingLeft="20dp"
- android:paddingTop="10dp"
- android:paddingRight="20dp"
- android:paddingBottom="10dp"
- android:textColor="@android:color/black"
- android:textSize="22sp"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/titleText" />
-
- <Button
- android:id="@+id/saveBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="20dp"
- android:text="保存"
- android:textColor="@android:color/white"
- android:textSize="25sp"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/descEditText" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
3.2制作floating_layout.xml文件
转到 res -> layout。右键单击layout -> New -> Layout Resource File。添加布局的名称(此处floating_layout)。此 XML 文件创建浮动窗口的布局。它具有与主布局相同的组件,但大小限制略有不同。下面是 XML 代码。
- <?xml version="1.0" encoding="utf-8"?>
- <androidx.constraintlayout.widget.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/white">
-
- <Button
- android:id="@+id/buttonMaximize"
- android:layout_width="match_parent"
- android:layout_height="40dp"
- android:layout_marginTop="20dp"
- android:background="@color/gfgThemeTwo"
- android:text="Wink"
- android:textColor="@android:color/white"
- android:textSize="15sp"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
- <TextView
- android:id="@+id/titleText"
- android:layout_width="match_parent"
- android:layout_height="30dp"
- android:layout_marginTop="10dp"
- android:gravity="center"
- android:text="浮动窗口"
- android:textColor="@color/gfgThemeTwo"
- android:textSize="18sp"
- android:textStyle="bold"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/buttonMaximize" />
-
- <EditText
- android:id="@+id/descEditText"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="10dp"
- android:gravity="start"
- android:hint="在这里写下"
- android:paddingLeft="20dp"
- android:paddingTop="10dp"
- android:paddingRight="20dp"
- android:paddingBottom="10dp"
- android:textColor="@android:color/black"
- android:textSize="16sp"
- app:layout_constraintBottom_toTopOf="@+id/saveBtn"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/titleText" />
-
- <Button
- android:id="@+id/saveBtn"
- android:layout_width="wrap_content"
- android:layout_height="40dp"
- android:layout_marginBottom="10dp"
- android:background="@color/gfgThemeTwo"
- android:text="保存"
- android:textColor="@android:color/white"
- android:textSize="12sp"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
4.1为公共变量创建类:
首先,让我们先创建一个名为 Common 的包。右键单击项目包路径 -> new -> Package.
将弹出一个窗口。编写预期的包名称。将创建一个新包。
右键单击New Package -> 新建 -> Java 类。编写预期的类名。
创建两个公共字符串变量,一个是currentDesc,另一个是savedDesc。两者都使用空字符串启动。
下面是 Common.java 类的代码。
- package com.example.floatingwindow.Common;
-
- public class Common {
-
- public static String currentDesc = "";
-
-
- public static String savedDesc = "";
- }
4.2更改MainActivity.java文件
首先,创建组件类的引用。将创建两个Buttons、一个AlertDialog和一个EditText 引用。
在到onCreate()之前,先创建了一些其他方法。
isMyServiceRunning():此方法有助于查找此应用程序的浮动窗口服务是否正在运行。当打开同一应用程序时,浮动窗口已经可见,因此需要此功能,然后需要停止浮动窗口服务。这是java代码:
- private boolean isMyServiceRunning() {
- ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
- for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
- if (FloatingWindowGFG.class.getName().equals(service.service.getClassName())) {
- return true;
- }
- }
- return false;
- }
requestOverlayDisplayPermission():该方法有助于将应用程序重定向到设置以启用“在其他应用程序上显示”。虽然为此需要向AndroidManifest.xml文件添加额外的行。
为此,请转到app ->manifests-> AndroidManifest.xml。在application程序块之前添加此行:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
java代码如下:
- private void requestOverlayDisplayPermission() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setCancelable(true);
- builder.setTitle("Screen Overlay Permission Needed");
- builder.setMessage("Enable 'Display over other apps' from System Settings.");
- builder.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
- startActivityForResult(intent, RESULT_OK);
- }
- });
- dialog = builder.create();
- dialog.show();
- }
checkOverlayDisplayPermission():此方法实际上检查如果 API 级别超过 23,则是否在设置中启用了“在其他应用程序上显示”。下面是此函数的代码:
- private boolean checkOverlayDisplayPermission() {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
- if (!Settings.canDrawOverlays(this)) {
- return false;
- } else {
- return true;
- }
- } else {
- return true;
- }
- }
- }
现在这里是 MainActivity.java 文件的完整代码:
- package com.example.floatingwindow;
-
- import android.app.ActivityManager;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.net.Uri;
- import android.os.Build;
- import android.os.Bundle;
- import android.provider.Settings;
- import android.text.Editable;
- import android.text.TextWatcher;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
-
- import androidx.appcompat.app.AlertDialog;
- import androidx.appcompat.app.AppCompatActivity;
-
- import com.example.floatingwindow.Common.Common;
-
- public class MainActivity extends AppCompatActivity {
-
- private Button minimizeBtn;
- private AlertDialog dialog;
- private EditText descEditArea;
- private Button save;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- minimizeBtn = findViewById(R.id.buttonMinimize);
- descEditArea = findViewById(R.id.descEditText);
- save = findViewById(R.id.saveBtn);
- if (isMyServiceRunning()) {
- stopService(new Intent(MainActivity.this, FloatingWindowGFG.class));
- }
- descEditArea.setText(Common.currentDesc);
- descEditArea.setSelection(descEditArea.getText().toString().length());
- descEditArea.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
- }
-
- @Override
- public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
- Common.currentDesc = descEditArea.getText().toString();
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
- }
- });
- save.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Common.savedDesc = descEditArea.getText().toString();
- descEditArea.setCursorVisible(false);
- descEditArea.clearFocus();
- Toast.makeText(MainActivity.this, "Text Saved!!!", Toast.LENGTH_SHORT).show();
- }
- });
-
- minimizeBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (checkOverlayDisplayPermission()) {
- startService(new Intent(MainActivity.this, FloatingWindowGFG.class));
- finish();
- } else {
- requestOverlayDisplayPermission();
- }
- }
- });
- }
-
- private boolean isMyServiceRunning() {
- ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
- for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
- if (FloatingWindowGFG.class.getName().equals(service.service.getClassName())) {
- return true;
- }
- }
- return false;
- }
-
- private void requestOverlayDisplayPermission() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setCancelable(true);
- builder.setTitle("Screen Overlay Permission Needed");
- builder.setMessage("Enable 'Display over other apps' from System Settings.");
- builder.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
- startActivityForResult(intent, RESULT_OK);
- }
- });
- dialog = builder.create();
- dialog.show();
- }
-
- private boolean checkOverlayDisplayPermission() {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
- if (!Settings.canDrawOverlays(this)) {
- return false;
- } else {
- return true;
- }
- } else {
- return true;
- }
- }
- }
4.3:制作FloatingWindowGFG.java文件
创建另一个名为 FloatingWindowGFG 的类。转到项目包路径-> New -> Java 类
此类继承服务类。
现在,由于此类继承自 Service 类,因此此类可以用作清单文件中的服务。因此,在 AndroidManifest.xml在activity之后和application结束之前添加此行。
- <service android:name=".FloatingWindowGFG"
- tools:ignore="Instantiatable" />
FloatingWindowGFG.java代码:
- package com.example.floatingwindow;
-
- import android.app.Service;
- import android.content.Context;
- import android.content.Intent;
- import android.graphics.PixelFormat;
- import android.os.Build;
- import android.os.IBinder;
- import android.text.Editable;
- import android.text.TextWatcher;
- import android.util.DisplayMetrics;
- import android.view.Gravity;
- import android.view.LayoutInflater;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.WindowManager;
- import android.view.inputmethod.InputMethodManager;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
-
- import androidx.annotation.Nullable;
-
- import com.example.floatingwindow.Common.Common;
-
- public class FloatingWindowGFG extends Service {
- private ViewGroup floatView;
- private int LAYOUT_TYPE;
- private WindowManager.LayoutParams floatWindowLayoutParam;
- private WindowManager windowManager;
- private Button maximizeBtn;
- private EditText descEditArea;
- private Button saveBtn;
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
- @Override
- public void onCreate() {
- super.onCreate();
- DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics();
- int width = metrics.widthPixels;
- int height = metrics.heightPixels;
- windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
- LayoutInflater inflater = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
- floatView = (ViewGroup) inflater.inflate(R.layout.floating_layout, null);
- maximizeBtn = floatView.findViewById(R.id.buttonMaximize);
- descEditArea = floatView.findViewById(R.id.descEditText);
- saveBtn = floatView.findViewById(R.id.saveBtn);
-
-
- descEditArea.setText(Common.currentDesc);
- descEditArea.setSelection(descEditArea.getText().toString().length());
- descEditArea.setCursorVisible(false);
-
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-
- LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- } else {
-
- LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_TOAST;
- }
-
- floatWindowLayoutParam = new WindowManager.LayoutParams(
- (int) (width * (0.55f)),
- (int) (height * (0.58f)),
- LAYOUT_TYPE,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT
- );
-
- floatWindowLayoutParam.gravity = Gravity.CENTER;
-
- floatWindowLayoutParam.x = 0;
- floatWindowLayoutParam.y = 0;
-
- windowManager.addView(floatView, floatWindowLayoutParam);
-
- maximizeBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- stopSelf();
- windowManager.removeView(floatView);
- Intent backToHome = new Intent(FloatingWindowGFG.this, MainActivity.class);
- backToHome.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- startActivity(backToHome);
- }
- });
- descEditArea.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
- }
-
- @Override
- public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
- Common.currentDesc = descEditArea.getText().toString();
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
- }
- });
- floatView.setOnTouchListener(new View.OnTouchListener() {
- final WindowManager.LayoutParams floatWindowLayoutUpdateParam = floatWindowLayoutParam;
- double x;
- double y;
- double px;
- double py;
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- x = floatWindowLayoutUpdateParam.x;
- y = floatWindowLayoutUpdateParam.y;
- px = event.getRawX();
- py = event.getRawY();
- break;
- case MotionEvent.ACTION_MOVE:
- floatWindowLayoutUpdateParam.x = (int) ((x + event.getRawX()) - px);
- floatWindowLayoutUpdateParam.y = (int) ((y + event.getRawY()) - py);
- windowManager.updateViewLayout(floatView, floatWindowLayoutUpdateParam);
- break;
- }
- return false;
- }
- });
- descEditArea.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- descEditArea.setCursorVisible(true);
- WindowManager.LayoutParams floatWindowLayoutParamUpdateFlag = floatWindowLayoutParam;
- floatWindowLayoutParamUpdateFlag.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
- windowManager.updateViewLayout(floatView, floatWindowLayoutParamUpdateFlag);
- return false;
- }
- });
-
-
- saveBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
-
- Common.savedDesc = descEditArea.getText().toString();
- descEditArea.setCursorVisible(false);
- WindowManager.LayoutParams floatWindowLayoutParamUpdateFlag = floatWindowLayoutParam;
- floatWindowLayoutParamUpdateFlag.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- windowManager.updateViewLayout(floatView, floatWindowLayoutParamUpdateFlag);
- InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodManager.hideSoftInputFromWindow(floatView.getApplicationWindowToken(), 0);
- Toast.makeText(FloatingWindowGFG.this, "Text Saved!!!", Toast.LENGTH_SHORT).show();
- }
- });
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- stopSelf();
-
- windowManager.removeView(floatView);
- }
- }
悬浮窗
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。