Android實現(xiàn)全局懸浮框
本文實例為大家分享了Android實現(xiàn)全局懸浮框的具體代碼,供大家參考,具體內(nèi)容如下
效果圖:

代碼實現(xiàn):
Androidmanifest.xml添加彈框權(quán)限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
自定義懸浮窗類FloatWindow.java
public class FloatWindow implements View.OnTouchListener {
private Context mContext;
private WindowManager.LayoutParams mWindowParams;
private WindowManager mWindowManager;
private View mFloatLayout;
private float mInViewX;
private float mInViewY;
private float mDownInScreenX;
private float mDownInScreenY;
private float mInScreenX;
private float mInScreenY;
private TextView infoText;
public FloatWindow(Context context) {
this.mContext = context;
initFloatWindow();
}
private void initFloatWindow() {
LayoutInflater inflater = LayoutInflater.from(mContext);
if(inflater == null)
return;
mFloatLayout = (View) inflater.inflate(R.layout.layout_float, null);
infoText = mFloatLayout.findViewById(R.id.textView);
mFloatLayout.setOnTouchListener(this);
mWindowParams = new WindowManager.LayoutParams();
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= 26) {//8.0新特性
mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}else{
mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
mWindowParams.format = PixelFormat.RGBA_8888;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowParams.gravity = Gravity.START | Gravity.TOP;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return floatLayoutTouch(motionEvent);
}
private boolean floatLayoutTouch(MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
// 獲取相對View的坐標(biāo),即以此View左上角為原點
mInViewX = motionEvent.getX();
mInViewY = motionEvent.getY();
// 獲取相對屏幕的坐標(biāo),即以屏幕左上角為原點
mDownInScreenX = motionEvent.getRawX();
mDownInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);
mInScreenX = motionEvent.getRawX();
mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);
break;
case MotionEvent.ACTION_MOVE:
// 更新浮動窗口位置參數(shù)
mInScreenX = motionEvent.getRawX();
mInScreenY = motionEvent.getRawY() - getSysBarHeight(mContext);
mWindowParams.x = (int) (mInScreenX- mInViewX);
mWindowParams.y = (int) (mInScreenY - mInViewY);
// 手指移動的時候更新小懸浮窗的位置
mWindowManager.updateViewLayout(mFloatLayout, mWindowParams);
break;
case MotionEvent.ACTION_UP:
// 如果手指離開屏幕時,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,則視為觸發(fā)了單擊事件。
if (mDownInScreenX == mInScreenX && mDownInScreenY == mInScreenY){
}
break;
}
return true;
}
public void showFloatWindow(){
if (mFloatLayout.getParent() == null){
DisplayMetrics metrics = new DisplayMetrics();
// 默認(rèn)固定位置,靠屏幕右邊緣的中間
mWindowManager.getDefaultDisplay().getMetrics(metrics);
mWindowParams.x = metrics.widthPixels;
mWindowParams.y = metrics.heightPixels/2 - getSysBarHeight(mContext);
mWindowManager.addView(mFloatLayout, mWindowParams);
}
}
public void updateText(final String s) {
infoText.setText(s);
}
public void hideFloatWindow(){
if (mFloatLayout.getParent() != null)
mWindowManager.removeView(mFloatLayout);
}
public void setFloatLayoutAlpha(boolean alpha){
if (alpha)
mFloatLayout.setAlpha((float) 0.5);
else
mFloatLayout.setAlpha(1);
}
// 獲取系統(tǒng)狀態(tài)欄高度
public static int getSysBarHeight(Context contex) {
Class<?> c;
Object obj;
Field field;
int x;
int sbar = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
sbar = contex.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
return sbar;
}
}
自定義懸浮窗界面布局文件layout_float.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/float_win" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00ffffff" android:text="hello" android:textSize="12sp" app:layout_constraintLeft_toLeftOf="@id/imageView" app:layout_constraintRight_toRightOf="@id/imageView" app:layout_constraintTop_toBottomOf="@id/imageView"/> </android.support.constraint.ConstraintLayout>
在Activity中使用懸浮窗。
public class MainActivity extends AppCompatActivity {
private Button btnShow;
FloatWindow floatWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 權(quán)限判斷
if (Build.VERSION.SDK_INT >= 23) {
if(!Settings.canDrawOverlays(getApplicationContext())) {
// 啟動Activity讓用戶授權(quán)
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName()));
startActivityForResult(intent,10);
} else {
// 執(zhí)行6.0以上繪制代碼
initView();
}
} else {
// 執(zhí)行6.0以下繪制代碼
initView();
}
}
@Override
protected void onResume() {
super.onResume();
// 權(quán)限判斷
if (Build.VERSION.SDK_INT >= 23) {
if(Settings.canDrawOverlays(getApplicationContext())) {
initView();
}
} else {
//執(zhí)行6.0以下繪制代碼
initView();
}
}
private void initView() {
setContentView(R.layout.activity_main);
floatWindow = new FloatWindow(getApplicationContext());
btnShow = findViewById(R.id.btn_show);
btnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (null != floatWindow) {
floatWindow.showFloatWindow();
}
}
});
Button btnrefresh = findViewById(R.id.btn_refresh);
btnrefresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int random = (int) (Math.random() * 10);
if (null != floatWindow) {
floatWindow.updateText(String.valueOf(random));
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (null != floatWindow) {
floatWindow.hideFloatWindow();
}
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Studio 中aidl的自定義類的使用詳解
這篇文章主要介紹了Android Studio 中aidl的自定義類的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android如何實現(xiàn)一個DocumentProvider示例詳解
這篇文章主要為大家介紹了Android如何實現(xiàn)一個DocumentProvider示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Flutter搞定寬高不統(tǒng)一布局開發(fā)的方法詳解
我們在開發(fā)移動端界面的時候,經(jīng)常會遇到一組尺寸不一的組件需要作為同一組展示,所以本文就將利用Wrap組件搞定寬高不統(tǒng)一布局開發(fā),需要的可以參考一下2023-06-06
Android仿銀行客戶簽名并且保存簽名的截圖文件并命名為本地時間
本文通過實例代碼給大家介紹了Android仿銀行客戶簽名并且保存簽名的截圖文件并命名為本地時間,需要的朋友可以參考下2017-07-07
Android apk 項目一鍵打包并上傳到蒲公英的實現(xiàn)方法
這篇文章主要介紹了Android apk 項目一鍵打包并上傳到蒲公英,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
android listview實現(xiàn)新聞列表展示效果
這篇文章主要為大家詳細(xì)介紹了android listview實現(xiàn)新聞列表展示效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03

