android實(shí)現(xiàn)桌面移動(dòng)懸浮窗口
現(xiàn)在很多應(yīng)用都有這樣的功能,比如360等安全衛(wèi)士,手機(jī)管家之內(nèi)的應(yīng)用。
效果圖:
一、實(shí)現(xiàn)原理及移動(dòng)思路
調(diào)用WindowManager,并設(shè)置WindowManager.LayoutParams的相關(guān)屬性,通過(guò)WindowManager的addView方法創(chuàng)建View,這樣產(chǎn)生出來(lái)的View根據(jù)WindowManager.LayoutParams屬性不同,效果也就不同了。比如創(chuàng)建系統(tǒng)頂級(jí)窗口,實(shí)現(xiàn)懸浮窗口效果!然后通過(guò)覆寫懸浮View中onTouchEvent方法來(lái)改變windowMananager.LayoutParams中x和y的值來(lái)實(shí)現(xiàn)自由移動(dòng)懸浮窗口。
二、示例代碼
先看看懸浮View的代碼把
package com.example.suspend; import android.content.Context; import android.util.Log; import android.view.MotionEvent; import android.view.WindowManager; import android.widget.ImageView; public class MyFloatView extends ImageView { private float mTouchStartX; private float mTouchStartY; private float x; private float y; private WindowManager wm = (WindowManager) getContext() .getApplicationContext().getSystemService("window"); // 此wmParams變量為獲取的全局變量,用以保存懸浮窗口的屬性 private WindowManager.LayoutParams wmParams = ((MyApplication) getContext() .getApplicationContext()).getMywmParams(); public MyFloatView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub // 獲取相對(duì)屏幕的坐標(biāo),即以屏幕左上角為原點(diǎn) x = event.getRawX(); y = event.getRawY() - 25; // 25是系統(tǒng)狀態(tài)欄的高度 Log.i("currP", "currX" + x + "====currY" + y); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 捕獲手指觸摸按下動(dòng)作 // 獲取相對(duì)View的坐標(biāo),即以此View左上角為原點(diǎn) mTouchStartX = event.getX(); mTouchStartY = event.getY(); Log.i("startP", "startX" + mTouchStartX + "====startY" + mTouchStartY); break; case MotionEvent.ACTION_MOVE://捕獲手指觸摸移動(dòng)動(dòng)作 updateViewPosition(); break; case MotionEvent.ACTION_UP://捕獲手指觸摸離開(kāi)動(dòng)作 updateViewPosition(); mTouchStartX=mTouchStartY=0; break; default: break; } return true; } private void updateViewPosition() { //更新浮動(dòng)窗口位置參數(shù) wmParams.x = (int)(x - mTouchStartX); wmParams.y = (int)(y - mTouchStartY); wm.updateViewLayout(this, wmParams);//刷新顯示 } }
上面的wmParams變量(即WindowManager.LayoutParams)的存儲(chǔ)采用了extends Application的方式來(lái)創(chuàng)建全局變量,
示例代碼如下:
package com.example.suspend; import android.app.Application; import android.view.WindowManager; public class MyApplication extends Application { private WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams(); @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); } public WindowManager.LayoutParams getMywmParams() { return wmParams; } }
再來(lái)看一看Activity中的代碼:
package com.example.suspend; import android.app.Activity; import android.graphics.PixelFormat; import android.os.Bundle; import android.view.Gravity; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; public class MainActivity extends Activity { private WindowManager wm; private WindowManager.LayoutParams wmParams; private MyFloatView myFV; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 創(chuàng)建懸浮窗口 createFloatView(); } private void createFloatView() { myFV = new MyFloatView(getApplicationContext()); myFV.setImageResource(R.drawable.ic_launcher); // 獲取WindowManager wm = (WindowManager) getApplicationContext().getSystemService("window"); // 設(shè)置LayoutParams(全局變量)相關(guān)參數(shù) wmParams = ((MyApplication) getApplication()).getMywmParams(); wmParams.type = LayoutParams.TYPE_PHONE;// 設(shè)置window type wmParams.format = PixelFormat.RGBA_8888;// 設(shè)置圖片格式,效果為背景透明 // 設(shè)置Window flag wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; /* * * 下面的flags屬性的效果形同“鎖定”。 * * 懸浮窗不可觸摸,不接受任何事件,同時(shí)不影響后面的事件響應(yīng)。 * * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL * * | LayoutParams.FLAG_NOT_FOCUSABLE * * | LayoutParams.FLAG_NOT_TOUCHABLE; */ wmParams.gravity = Gravity.LEFT | Gravity.TOP;// 調(diào)整懸浮窗口至左上角,便于調(diào)整坐標(biāo) // 以屏幕左上角為原點(diǎn),設(shè)置x、y初始值 wmParams.x = 0; wmParams.y = 0; // 設(shè)置懸浮窗口長(zhǎng)寬數(shù)據(jù) wmParams.width = 40; wmParams.height = 40; // 顯示myFloatView圖像 wm.addView(myFV, wmParams); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); // 在程序退出(Activity銷毀)時(shí)銷毀懸浮窗口 wm.removeView(myFV); } }
最后,別忘了在AndroidManifest.xml中添加權(quán)限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android多功能視頻播放器GSYVideoPlayer開(kāi)發(fā)流程
怎么在Android中實(shí)現(xiàn)GSYVideoPlayer視頻播放器?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲2022-11-11詳解Android控件之DatePicker、TimePicker探究
本篇文章主要介紹了Android控件之DatePicker、TimePicker探究,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12Android開(kāi)發(fā)實(shí)現(xiàn)保存圖片到手機(jī)相冊(cè)功能
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)保存圖片到手機(jī)相冊(cè)功能,涉及Android圖形及文件相關(guān)操作技巧,需要的朋友可以參考下2019-03-03Android獲取arrays.xml里的數(shù)組字段值實(shí)例詳解
這篇文章主要介紹了Android獲取arrays.xml里的數(shù)組字段值實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04Android實(shí)現(xiàn)動(dòng)態(tài)高斯模糊效果示例代碼
這篇文章主要介紹了Android快速實(shí)現(xiàn)動(dòng)態(tài)模糊效果示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01Android 中 MD5 的幾種生成方式(小結(jié))
這篇文章主要介紹了Android 中 MD5 的幾種生成方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Android中創(chuàng)建對(duì)話框(確定取消對(duì)話框、單選對(duì)話框、多選對(duì)話框)實(shí)例代碼
這篇文章主要介紹了詳解Android中創(chuàng)建對(duì)話框(確定取消對(duì)話框、單選對(duì)話框、多選對(duì)話框)的相關(guān)資料,需要的朋友可以參考下2016-04-04