您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Android中怎么實(shí)現(xiàn)一個(gè)可移動(dòng)的懸浮窗,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
首先我們先建一個(gè)windowmangerdemo的項(xiàng)目
在activity_main里面增加一個(gè)button的按鈕
然后在布局Layout里面增加window_small.xml和window_big.xml兩個(gè)布局文件,用于點(diǎn)擊小窗口后展開(kāi)大窗口
window_small.xml
我們?cè)诰€性布局管理囂中直接加上一個(gè)相對(duì)布局管理囂.然后設(shè)上背景圖片即可
FloatWindowSmallView
我們的floatWindowSmallView繼承自LinearLayout
重寫(xiě)onTouchEvent事件,我們用于可以隨時(shí)點(diǎn)擊移動(dòng)和展開(kāi)我們的懸浮框
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 手指按下時(shí)記錄必要數(shù)據(jù),縱坐標(biāo)的值都需要減去狀態(tài)欄高度
xInView = event.getX();
yInView = event.getY();
xDownInScreen = event.getRawX();
yDownInScreen = event.getRawY() - getStatusBarHeight();
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
break;
case MotionEvent.ACTION_MOVE:
xInScreen = event.getRawX();
yInScreen = event.getRawY() - getStatusBarHeight();
// 手指移動(dòng)的時(shí)候更新小懸浮窗的位置
updateViewPosition();
break;
case MotionEvent.ACTION_UP:
// 如果手指離開(kāi)屏幕時(shí),xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,則視為觸發(fā)了單擊事件。
if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {
openBigWindow();
}
break;
default:
break;
}
return true;
}
window_big.xml
我們?cè)O(shè)了三個(gè)垂直的ImageButton,代表點(diǎn)擊小窗體后展開(kāi)的大的窗體
FloatWindowBigView
代碼比較簡(jiǎn)單,直接寫(xiě)對(duì)應(yīng)的事件即可
public class FloatWindowBigView extends LinearLayout {
public static int viewWidth;
public static int viewHeight;
public FloatWindowBigView(final Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.window_big, this);
View view = findViewById(R.id.big_window_layout);
// viewWidth = view.getLayoutParams().width;
// viewHeight = view.getLayoutParams().height;
viewWidth= 120;
viewHeight = 370;
ImageButton imgbig = (ImageButton) findViewById(R.id.imgbig);
ImageButton imgcamera = findViewById(R.id.imgcamera);
ImageButton imgvoice = findViewById(R.id.imgvoice);
imgcamera.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "點(diǎn)擊了照相機(jī)", Toast.LENGTH_SHORT).show();
}
});
imgvoice.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "點(diǎn)擊了語(yǔ)音識(shí)別", Toast.LENGTH_SHORT).show();
}
});
imgbig.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 點(diǎn)擊返回的時(shí)候,移除大懸浮窗,創(chuàng)建小懸浮窗
MyWindowManager.removeBigWindow(context);
MyWindowManager.createSmallWindow(context);
}
});
}
}
MyWindowManager
這個(gè)類(lèi)是我們管理大小懸浮框的事件類(lèi),包括關(guān)閉小懸浮窗,展開(kāi)大懸浮窗等
我們把大小懸浮穿的參數(shù)分別對(duì)應(yīng)不同的LayoutParams,都在這里處理
FloatWindow
做一個(gè)floatWindow繼承自Service
通過(guò)Handler和Time控件來(lái)刷新懸浮窗是否一直存在
/**
* 判斷當(dāng)前界面是否是掃碼界面
*/
private boolean isForeground(String[] classNames) {
if (classNames.length <= 0) {
return false;
}
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
//判斷當(dāng)前進(jìn)程
List<ActivityManager.RunningAppProcessInfo> appProcesses = am
.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(getPackageName())) {
//判斷程序是否處于前臺(tái),如果是后臺(tái)則不顯示懸浮框
if (appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
Log.i(getPackageName(), "處于后臺(tái)"
+ appProcess.processName);
return false;
}
}
}
//判斷頂層Activity
List<ActivityManager.RunningTaskInfo> list = am.getRunningTasks(1);
if (list != null && list.size() > 0) {
ComponentName cpn = list.get(0).topActivity;
for (String className : classNames) {
if (className.equals(cpn.getClassName())) {
return true;
}
}
}
return false;
}
class RefreshTask extends TimerTask {
@Override
public void run() {
// 當(dāng)前界面是要顯示的界面,且沒(méi)有懸浮窗顯示,則創(chuàng)建懸浮窗。
if (isForeground(activityname) && !MyWindowManager.isWindowShowing()) {
handler.post(new Runnable() {
@Override
public void run() {
MyWindowManager.createSmallWindow(getApplicationContext());
}
});
}
// 當(dāng)前界面要顯示的界面,且有懸浮窗顯示,則移除懸浮窗。
else if (!isForeground(activityname) && MyWindowManager.isWindowShowing()) {
handler.post(new Runnable() {
@Override
public void run() {
MyWindowManager.removeSmallWindow(getApplicationContext());
MyWindowManager.removeBigWindow(getApplicationContext());
}
});
}
// 當(dāng)前界面是要顯示的界面,且有懸浮窗顯示,則更新內(nèi)存數(shù)據(jù)。
else if (isForeground(activityname) && MyWindowManager.isWindowShowing()) {
handler.post(new Runnable() {
@Override
public void run() {
MyWindowManager.updateUsedPercent(getApplicationContext());
}
});
}
}
}
上述就是小編為大家分享的Android中怎么實(shí)現(xiàn)一個(gè)可移動(dòng)的懸浮窗了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。