1、最近在做视频通话功能,用到了悬浮窗。项目代码不能随便上,写一个简单的Demo记录下!更复杂的功能,自由发挥吧!!!
2、废话不说,上代码;
a、权限必须要;
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
b、主要业务代码;
import android.content.Context
import android.content.Intent
import android.graphics.PixelFormat
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main2.*
class Main2Activity : AppCompatActivity() {
private var mWindowManager: WindowManager? = null
private var mWindowParams: WindowManager.LayoutParams? = null
private lateinit var mWindowView: View
private val mMinWidht = dp2px(100F)
private val mMinHeight = dp2px(150F)
private val mMaxWidth = getMaxWidth()
private val mMaxHeight = getMaxHeight()
private val mStatusHeight = getStatusHeight()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
btn_1.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
startActivity(
Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:${packageName}")
)
)
} else {
openWindowView()
}
}
btn_2.setOnClickListener {
mWindowManager?.removeView(mWindowView)
}
}
/**
* 打开Window窗口
*/
private fun openWindowView() {
mWindowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
mWindowParams = WindowManager.LayoutParams()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mWindowParams!!.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
mWindowParams!!.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
}
mWindowParams?.flags = (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)
mWindowParams?.format = PixelFormat.TRANSLUCENT
mWindowParams?.width = mMinWidht
mWindowParams?.height = mMinHeight
mWindowParams?.gravity = Gravity.START or Gravity.TOP
mWindowParams?.x = mMaxWidth - mMinWidht
mWindowParams?.y = mStatusHeight
mWindowView = View.inflate(this, R.layout.view_layout_window, null)
mWindowView.findViewById<View>(R.id.v_event).setOnClickListener {
/*点击放大、缩小事件*/
mWindowParams?.width = if (mWindowParams?.width == mMinWidht) mMaxWidth else mMinWidht
mWindowParams?.height =
if (mWindowParams?.height == mMinHeight) mMaxHeight else mMinHeight
mWindowManager!!.updateViewLayout(mWindowView, mWindowParams)
}
mWindowView.setOnTouchListener(WindowOnTouchListener())
mWindowManager!!.addView(mWindowView, mWindowParams)
}
/**
* Window窗口触摸事件
*/
inner class WindowOnTouchListener : View.OnTouchListener {
private var mTouchStartX = 0
private var mTouchStartY = 0
private var mStartX = 0
private var mStartY = 0
override fun onTouch(v: View?, motionEvent: MotionEvent): Boolean {
val action = motionEvent.action
val x = motionEvent.x.toInt()
val y = motionEvent.y.toInt()
when (action) {
MotionEvent.ACTION_DOWN -> {
mTouchStartX = motionEvent.rawX.toInt()
mTouchStartY = motionEvent.rawY.toInt()
mStartX = x
mStartY = y
}
MotionEvent.ACTION_MOVE -> {
if (null != mWindowParams && null != mWindowManager) {
val mTouchCurrentX = motionEvent.rawX.toInt()
val mTouchCurrentY = motionEvent.rawY.toInt()
val tempX = mWindowParams!!.x + mTouchCurrentX - mTouchStartX
val tempY = mWindowParams!!.y + mTouchCurrentY - mTouchStartY
var newX: Int = -1
var newY: Int = -1
if (tempX >= 0 && tempX <= (mMaxWidth - mMinWidht)) {
newX = tempX
mTouchStartX = mTouchCurrentX
}
if (tempY >= mStatusHeight && tempY <= (mMaxHeight - mMinHeight)) {
newY = tempY
mTouchStartY = mTouchCurrentY
}
mWindowParams!!.x = if (newX == -1) mWindowParams!!.x else newX
mWindowParams!!.y = if (newY == -1) mWindowParams!!.y else newY
mWindowManager!!.updateViewLayout(mWindowView, mWindowParams)
}
}
}
return true
}
}
/**
* 屏幕宽度
*/
private fun getMaxWidth(): Int {
val windowManager = GitTestApplication.getApplication()
.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val outMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(outMetrics)
return outMetrics.widthPixels
}
/**
* 屏幕高度
*/
private fun getMaxHeight(): Int {
val windowManager =
GitTestApplication.getApplication()
.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val outMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(outMetrics)
return outMetrics.heightPixels
}
/**
* dp转换为px
*/
private fun dp2px(dpValue: Float): Int {
val scale: Float = GitTestApplication.getApplication().resources.displayMetrics.density
return (dpValue * scale + 0.5f).toInt()
}
/**
* 获取状态栏高度
*/
private fun getStatusHeight(): Int {
val resources = GitTestApplication.getApplication().resources
val resourceId: Int = resources.getIdentifier("status_bar_height", "dimen", "android")
return resources.getDimensionPixelSize(resourceId)
}}
c、view_layout_window.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"
android:background="@drawable/shape_radius_12_solid_000000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="显示内容"
android:textColor="#FFFFFFFF"
android:textSize="18sp"
android:textStyle="bold" />
<View
android:id="@+id/v_event"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_margin="20dp"
android:background="@drawable/shape_oval_solid_red_light" />
</RelativeLayout>
d、shape_oval_solid_red_light.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/holo_red_light" />
</shape>
e、shape_radius_12_solid_000000.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="12dp" />
<solid android:color="#FF000000" />
</shape>
f、activity_main2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="打开" />
<Button
android:id="@+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="关闭" />
</LinearLayout>