一、项目
项目背景
随着移动应用的普及,用户对APP界面的要求越来越高,悬浮窗作为一种新颖的交互方式,能够显著提升用户体验,本文将探讨如何在Android平台上实现仿新版支付宝的浮窗效果。
项目目标
实现一个悬浮窗口,支持动画效果
确保悬浮窗在各种设备上的兼容性
提供良好的用户体验和交互效果
二、准备工作
开发环境配置
1.1 Android Studio安装与配置
请确保已安装Android Studio,并创建一个新的Android项目,项目应设置支持的最低API级别为Android 5.0(API 21)。
1.2 相关依赖库
在项目的build.gradle
文件中添加必要的依赖库:
dependencies { implementation 'com.github.jungerrn:gridpasswordview:0.3' }
权限配置
2.1 悬浮窗权限申请
在AndroidManifest.xml
中申请悬浮窗权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
> 并在运行时请求权限:
if (!Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, REQUEST_CODE); }
三、布局文件设计
activity_main.xml
创建一个基本的布局文件,其中包含一个按钮用于触发悬浮窗显示:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/buttonShowFloatingWindow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="显示悬浮窗" android:layout_centerInParent="true"/> </RelativeLayout>
2. floating_window_layout.xml
悬浮窗的布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:background="#FFFFFF" android:padding="16dp" android:elevation="4dp"> <TextView android:id="@+id/textViewMessage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是一个悬浮窗" /> <Button android:id="@+id/buttonClose" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关闭"/> </LinearLayout>
四、关键代码实现
MainActivity.java
在主活动中实现按钮点击事件以显示悬浮窗:
package com.example.floatingwindowdemo; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.content.Intent; import android.provider.Settings; import android.net.Uri; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE = 1001; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button buttonShowFloatingWindow = findViewById(R.id.buttonShowFloatingWindow); buttonShowFloatingWindow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showFloatingWindow(); } }); } private void showFloatingWindow() { if (!Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, REQUEST_CODE); } else { startService(new Intent(MainActivity.this, FloatingWindowService.class)); } } }
2. FloatingWindowService.java
创建一个服务来管理悬浮窗:
package com.example.floatingwindowdemo; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.os.IBinder; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; import android.widget.LinearLayout; public class FloatingWindowService extends Service { private WindowManager windowManager; private View floatingView; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window_layout, null); windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); final WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); params.gravity = Gravity.TOP | Gravity.LEFT; params.x = 100; params.y = 300; floatingView.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(floatingView, params); return true; } return false; } }); windowManager.addView(floatingView, params); } @Override public void onDestroy() { super.onDestroy(); if (floatingView != null) windowManager.removeView(floatingView); } }
3. ItemViewTouchListener.java(可选)
如果需要更复杂的触摸事件处理,可以实现一个触摸监听器:
package com.example.floatingwindowdemo; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.Toast; import androidx.annotation.Nullable; public class ItemViewTouchListener implements View.OnTouchListener { private int initialX; private int initialY; private float initialTouchX; private float initialTouchY; private WindowManager windowManager; private WindowManager.LayoutParams layoutParam; public ItemViewTouchListener(WindowManager windowManager, WindowManager.LayoutParams layoutParam) { this.windowManager = windowManager; this.layoutParam = layoutParam; } @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: initialX = layoutParam.x; initialY = layoutParam.y; initialTouchX = motionEvent.getRawX(); initialTouchY = motionEvent.getRawY(); return true; case MotionEvent.ACTION_MOVE: int nowX = (int) (initialX + (motionEvent.getRawX() initialTouchX)); int nowY = (int) (initialY + (motionEvent.getRawY() initialTouchY)); layoutParam.x = nowX; layoutParam.y = nowY; windowManager.updateViewLayout(view, layoutParam); return true; default: return false; } } }
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1259946.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复