【移動(dòng)應(yīng)用開發(fā)技術(shù)】如何使用Android實(shí)現(xiàn)QQ手機(jī)管家懸浮小火箭效果_第1頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】如何使用Android實(shí)現(xiàn)QQ手機(jī)管家懸浮小火箭效果_第2頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】如何使用Android實(shí)現(xiàn)QQ手機(jī)管家懸浮小火箭效果_第3頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】如何使用Android實(shí)現(xiàn)QQ手機(jī)管家懸浮小火箭效果_第4頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】如何使用Android實(shí)現(xiàn)QQ手機(jī)管家懸浮小火箭效果_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】如何使用Android實(shí)現(xiàn)QQ手機(jī)管家懸浮小火箭效果

這篇文章主要介紹了如何使用Android實(shí)現(xiàn)QQ手機(jī)管家懸浮小火箭效果,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓在下帶著大家一起了解一下。首先創(chuàng)建launcher.xml作為火箭發(fā)射臺(tái)的布局文件如下所示:<?xml

version="1.0"

encoding="UTF-8"?>

<LinearLayout

xmlns:android="/apk/res/android"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="vertical"

>

<ImageView

android:id="@+id/launcher_img"

android:layout_width="200dp"

android:layout_height="88dp"

android:src="@drawable/launcher_bg_hold"

/>

</LinearLayout>可以看到,這里的ImageView是用于顯示當(dāng)前火箭發(fā)射臺(tái)狀態(tài)的。我事先準(zhǔn)備好了兩張圖片,一張是當(dāng)小火箭未拖動(dòng)到火箭發(fā)射臺(tái)時(shí)顯示的,一張是當(dāng)小火箭拖動(dòng)到火箭發(fā)射臺(tái)上時(shí)顯示的。

接下來創(chuàng)建RocketLauncher類,作為火箭發(fā)射臺(tái)的View代碼如下所示:public

class

RocketLauncher

extends

LinearLayout

{

/**

*

記錄火箭發(fā)射臺(tái)的寬度

*/

public

static

int

width;

/**

*

記錄火箭發(fā)射臺(tái)的高度

*/

public

static

int

height;

/**

*

火箭發(fā)射臺(tái)的背景圖片

*/

private

ImageView

launcherImg;

public

RocketLauncher(Context

context)

{

super(context);

LayoutInflater.from(context).inflate(R.layout.launcher,

this);

launcherImg

=

(ImageView)

findViewById(R.id.launcher_img);

width

=

launcherImg.getLayoutParams().width;

height

=

launcherImg.getLayoutParams().height;

}

/**

*

更新火箭發(fā)射臺(tái)的顯示狀態(tài)。如果小火箭被拖到火箭發(fā)射臺(tái)上,就顯示發(fā)射。

*/

public

void

updateLauncherStatus(boolean

isReadyToLaunch)

{

if

(isReadyToLaunch)

{

launcherImg.setImageResource(R.drawable.launcher_bg_fire);

}

else

{

launcherImg.setImageResource(R.drawable.launcher_bg_hold);

}

}

}RocketLauncher中的代碼還是非常簡單的,在構(gòu)建方法中調(diào)用了LayoutInflater的inflate()方法來將launcher.xml這個(gè)布局文件加載進(jìn)來,并獲取到了當(dāng)前View的寬度和高度。在updateLauncherStatus()方法中會(huì)進(jìn)行判斷,如果傳入的參數(shù)是true,就顯示小火箭即將發(fā)射的圖片,如果傳入的是false,就顯示將小火箭拖動(dòng)到發(fā)射臺(tái)的圖片。新增的文件只有這兩個(gè),剩下的就是要修改之前的代碼了。首先修改MyWindowManager中的代碼,如下所示:public

class

MyWindowManager

{

/**

*

小懸浮窗View的實(shí)例

*/

private

static

FloatWindowSmallView

smallWindow;

/**

*

大懸浮窗View的實(shí)例

*/

private

static

FloatWindowBigView

bigWindow;

/**

*

火箭發(fā)射臺(tái)的實(shí)例

*/

private

static

RocketLauncher

rocketLauncher;

/**

*

小懸浮窗View的參數(shù)

*/

private

static

LayoutParams

smallWindowParams;

/**

*

大懸浮窗View的參數(shù)

*/

private

static

LayoutParams

bigWindowParams;

/**

*

火箭發(fā)射臺(tái)的參數(shù)

*/

private

static

LayoutParams

launcherParams;

/**

*

用于控制在屏幕上添加或移除懸浮窗

*/

private

static

WindowManager

mWindowManager;

/**

*

用于獲取手機(jī)可用內(nèi)存

*/

private

static

ActivityManager

mActivityManager;

/**

*

創(chuàng)建一個(gè)小懸浮窗。初始位置為屏幕的右部中間位置。

*/

public

static

void

createSmallWindow(Context

context)

{

WindowManager

windowManager

=

getWindowManager(context);

int

screenWidth

=

windowManager.getDefaultDisplay().getWidth();

int

screenHeight

=

windowManager.getDefaultDisplay().getHeight();

if

(smallWindow

==

null)

{

smallWindow

=

new

FloatWindowSmallView(context);

if

(smallWindowParams

==

null)

{

smallWindowParams

=

new

LayoutParams();

smallWindowParams.type

=

LayoutParams.TYPE_SYSTEM_ALERT;

smallWindowParams.format

=

PixelFormat.RGBA_8888;

smallWindowParams.flags

=

LayoutParams.FLAG_NOT_TOUCH_MODAL

|

LayoutParams.FLAG_NOT_FOCUSABLE;

smallWindowParams.gravity

=

Gravity.LEFT

|

Gravity.TOP;

smallWindowParams.width

=

FloatWindowSmallView.windowViewWidth;

smallWindowParams.height

=

FloatWindowSmallView.windowViewHeight;

smallWindowParams.x

=

screenWidth;

smallWindowParams.y

=

screenHeight

/

2;

}

smallWindow.setParams(smallWindowParams);

windowManager.addView(smallWindow,

smallWindowParams);

}

}

/**

*

將小懸浮窗從屏幕上移除。

*/

public

static

void

removeSmallWindow(Context

context)

{

if

(smallWindow

!=

null)

{

WindowManager

windowManager

=

getWindowManager(context);

windowManager.removeView(smallWindow);

smallWindow

=

null;

}

}

/**

*

創(chuàng)建一個(gè)大懸浮窗。位置為屏幕正中間。

*/

public

static

void

createBigWindow(Context

context)

{

WindowManager

windowManager

=

getWindowManager(context);

int

screenWidth

=

windowManager.getDefaultDisplay().getWidth();

int

screenHeight

=

windowManager.getDefaultDisplay().getHeight();

if

(bigWindow

==

null)

{

bigWindow

=

new

FloatWindowBigView(context);

if

(bigWindowParams

==

null)

{

bigWindowParams

=

new

LayoutParams();

bigWindowParams.x

=

screenWidth

/

2

-

FloatWindowBigView.viewWidth

/

2;

bigWindowParams.y

=

screenHeight

/

2

-

FloatWindowBigView.viewHeight

/

2;

bigWindowParams.type

=

LayoutParams.TYPE_PHONE;

bigWindowParams.format

=

PixelFormat.RGBA_8888;

bigWindowParams.gravity

=

Gravity.LEFT

|

Gravity.TOP;

bigWindowParams.width

=

FloatWindowBigView.viewWidth;

bigWindowParams.height

=

FloatWindowBigView.viewHeight;

}

windowManager.addView(bigWindow,

bigWindowParams);

}

}

/**

*

將大懸浮窗從屏幕上移除。

*/

public

static

void

removeBigWindow(Context

context)

{

if

(bigWindow

!=

null)

{

WindowManager

windowManager

=

getWindowManager(context);

windowManager.removeView(bigWindow);

bigWindow

=

null;

}

}

/**

*

創(chuàng)建一個(gè)火箭發(fā)射臺(tái),位置為屏幕底部。

*/

public

static

void

createLauncher(Context

context)

{

WindowManager

windowManager

=

getWindowManager(context);

int

screenWidth

=

windowManager.getDefaultDisplay().getWidth();

int

screenHeight

=

windowManager.getDefaultDisplay().getHeight();

if

(rocketLauncher

==

null)

{

rocketLauncher

=

new

RocketLauncher(context);

if

(launcherParams

==

null)

{

launcherParams

=

new

LayoutParams();

launcherParams.x

=

screenWidth

/

2

-

RocketLauncher.width

/

2;

launcherParams.y

=

screenHeight

-

RocketLauncher.height;

launcherParams.type

=

LayoutParams.TYPE_PHONE;

launcherParams.format

=

PixelFormat.RGBA_8888;

launcherParams.gravity

=

Gravity.LEFT

|

Gravity.TOP;

launcherParams.width

=

RocketLauncher.width;

launcherParams.height

=

RocketLauncher.height;

}

windowManager.addView(rocketLauncher,

launcherParams);

}

}

/**

*

將火箭發(fā)射臺(tái)從屏幕上移除。

*/

public

static

void

removeLauncher(Context

context)

{

if

(rocketLauncher

!=

null)

{

WindowManager

windowManager

=

getWindowManager(context);

windowManager.removeView(rocketLauncher);

rocketLauncher

=

null;

}

}

/**

*

更新火箭發(fā)射臺(tái)的顯示狀態(tài)。

*/

public

static

void

updateLauncher()

{

if

(rocketLauncher

!=

null)

{

rocketLauncher.updateLauncherStatus(isReadyToLaunch());

}

}

/**

*

更新小懸浮窗的TextView上的數(shù)據(jù),顯示內(nèi)存使用的百分比。

*

*

@param

context

*

可傳入應(yīng)用程序上下文。

*/

public

static

void

updateUsedPercent(Context

context)

{

if

(smallWindow

!=

null)

{

TextView

percentView

=

(TextView)

smallWindow

.findViewById(R.id.percent);

percentView.setText(getUsedPercentValue(context));

}

}

/**

*

是否有懸浮窗(包括小懸浮窗和大懸浮窗)顯示在屏幕上。

*

*

@return

有懸浮窗顯示在桌面上返回true,沒有的話返回false。

*/

public

static

boolean

isWindowShowing()

{

return

smallWindow

!=

null

||

bigWindow

!=

null;

}

/**

*

判斷小火箭是否準(zhǔn)備好發(fā)射了。

*

*

@return

當(dāng)火箭被發(fā)到發(fā)射臺(tái)上返回true,否則返回false。

*/

public

static

boolean

isReadyToLaunch()

{

if

((smallWindowParams.x

>

launcherParams.x

&&

smallWindowParams.x

+

smallWindowParams.width

<

launcherParams.x

+

launcherParams.width)

&&

(smallWindowParams.y

+

smallWindowParams.height

>

launcherParams.y))

{

return

true;

}

return

false;

}

/**

*

如果WindowManager還未創(chuàng)建,則創(chuàng)建一個(gè)新的WindowManager返回。否則返回當(dāng)前已創(chuàng)建的WindowManager。

*

*

@param

context

*

必須為應(yīng)用程序的Context.

*

@return

WindowManager的實(shí)例,用于控制在屏幕上添加或移除懸浮窗。

*/

private

static

WindowManager

getWindowManager(Context

context)

{

if

(mWindowManager

==

null)

{

mWindowManager

=

(WindowManager)

context

.getSystemService(Context.WINDOW_SERVICE);

}

return

mWindowManager;

}

/**

*

如果ActivityManager還未創(chuàng)建,則創(chuàng)建一個(gè)新的ActivityManager返回。否則返回當(dāng)前已創(chuàng)建的ActivityManager。

*

*

@param

context

*

可傳入應(yīng)用程序上下文。

*

@return

ActivityManager的實(shí)例,用于獲取手機(jī)可用內(nèi)存。

*/

private

static

ActivityManager

getActivityManager(Context

context)

{

if

(mActivityManager

==

null)

{

mActivityManager

=

(ActivityManager)

context

.getSystemService(Context.ACTIVITY_SERVICE);

}

return

mActivityManager;

}

/**

*

計(jì)算已使用內(nèi)存的百分比,并返回。

*

*

@param

context

*

可傳入應(yīng)用程序上下文。

*

@return

已使用內(nèi)存的百分比,以字符串形式返回。

*/

public

static

String

getUsedPercentValue(Context

context)

{

String

dir

=

"/proc/meminfo";

try

{

FileReader

fr

=

new

FileReader(dir);

BufferedReader

br

=

new

BufferedReader(fr,

2048);

String

memoryLine

=

br.readLine();

String

subMemoryLine

=

memoryLine.substring(memoryLine

.indexOf("MemTotal:"));

br.close();

long

totalMemorySize

=

Integer.parseInt(subMemoryLine.replaceAll(

"\\D+",

""));

long

availableSize

=

getAvailableMemory(context)

/

1024;

int

percent

=

(int)

((totalMemorySize

-

availableSize)

/

(float)

totalMemorySize

*

100);

return

percent

+

"%";

}

catch

(IOException

e)

{

e.printStackTrace();

}

return

"懸浮窗";

}

/**

*

獲取當(dāng)前可用內(nèi)存,返回?cái)?shù)據(jù)以字節(jié)為單位。

*

*

@param

context

*

可傳入應(yīng)用程序上下文。

*

@return

當(dāng)前可用內(nèi)存。

*/

private

static

long

getAvailableMemory(Context

context)

{

ActivityManager.MemoryInfo

mi

=

new

ActivityManager.MemoryInfo();

getActivityManager(context).getMemoryInfo(mi);

return

mi.availMem;

}

}MyWindowManager是所有桌面懸浮窗的管理器,這里我們主要添加了createLauncher()、removeLauncher()和updateLauncher()這幾個(gè)方法,分別用于創(chuàng)建、移除、以及更新火箭發(fā)射臺(tái)懸浮窗。另外還添加了isReadyToLaunch()這個(gè)方法,它是用于判斷小火箭是否已經(jīng)拖動(dòng)到火箭發(fā)射臺(tái)上了。判斷的方式當(dāng)然也很簡單,只需要對(duì)小火箭的邊界和火箭發(fā)射臺(tái)的邊界進(jìn)行檢測,判斷它們是否相交就行了。接下來還需要修改FloatWindowSmallView中的代碼,當(dāng)手指拖動(dòng)懸浮窗的時(shí)候要將它變成小火箭,如下所示:public

class

FloatWindowSmallView

extends

LinearLayout

{

/**

*

記錄小懸浮窗的寬度

*/

public

static

int

windowViewWidth;

/**

*

記錄小懸浮窗的高度

*/

public

static

int

windowViewHeight;

/**

*

記錄系統(tǒng)狀態(tài)欄的高度

*/

private

static

int

statusBarHeight;

/**

*

用于更新小懸浮窗的位置

*/

private

WindowManager

windowManager;

/**

*

小懸浮窗的布局

*/

private

LinearLayout

smallWindowLayout;

/**

*

小火箭控件

*/

private

ImageView

rocketImg;

/**

*

小懸浮窗的參數(shù)

*/

private

WindowManager.LayoutParams

mParams;

/**

*

記錄當(dāng)前手指位置在屏幕上的橫坐標(biāo)值

*/

private

float

xInScreen;

/**

*

記錄當(dāng)前手指位置在屏幕上的縱坐標(biāo)值

*/

private

float

yInScreen;

/**

*

記錄手指按下時(shí)在屏幕上的橫坐標(biāo)的值

*/

private

float

xDownInScreen;

/**

*

記錄手指按下時(shí)在屏幕上的縱坐標(biāo)的值

*/

private

float

yDownInScreen;

/**

*

記錄手指按下時(shí)在小懸浮窗的View上的橫坐標(biāo)的值

*/

private

float

xInView;

/**

*

記錄手指按下時(shí)在小懸浮窗的View上的縱坐標(biāo)的值

*/

private

float

yInView;

/**

*

記錄小火箭的寬度

*/

private

int

rocketWidth;

/**

*

記錄小火箭的高度

*/

private

int

rocketHeight;

/**

*

記錄當(dāng)前手指是否按下

*/

private

boolean

isPressed;

public

FloatWindowSmallView(Context

context)

{

super(context);

windowManager

=

(WindowManager)

context

.getSystemService(Context.WINDOW_SERVICE);

LayoutInflater.from(context).inflate(R.layout.float_window_small,

this);

smallWindowLayout

=

(LinearLayout)

findViewById(R.id.small_window_layout);

windowViewWidth

=

smallWindowLayout.getLayoutParams().width;

windowViewHeight

=

smallWindowLayout.getLayoutParams().height;

rocketImg

=

(ImageView)

findViewById(R.id.rocket_img);

rocketWidth

=

rocketImg.getLayoutParams().width;

rocketHeight

=

rocketImg.getLayoutParams().height;

TextView

percentView

=

(TextView)

findViewById(R.id.percent);

percentView.setText(MyWindowManager.getUsedPercentValue(context));

}

@Override

public

boolean

onTouchEvent(MotionEvent

event)

{

switch

(event.getAction())

{

case

MotionEvent.ACTION_DOWN:

isPressed

=

true;

//

手指按下時(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í)候更新小懸浮窗的狀態(tài)和位置

updateViewStatus();

updateViewPosition();

break;

case

MotionEvent.ACTION_UP:

isPressed

=

false;

if

(MyWindowManager.isReadyToLaunch())

{

launchRocket();

}

else

{

updateViewStatus();

//

如果手指離開屏幕時(shí),xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,則視為觸發(fā)了單擊事件。

if

(xDownInScreen

==

xInScreen

&&

yDownInScreen

==

yInScreen)

{

openBigWindow();

}

}

break;

default:

break;

}

return

true;

}

/**

*

將小懸浮窗的參數(shù)傳入,用于更新小懸浮窗的位置。

*

*

@param

params

*

小懸浮窗的參數(shù)

*/

public

void

setParams(WindowManager.LayoutParams

params)

{

mParams

=

params;

}

/**

*

用于發(fā)射小火箭。

*/

private

void

launchRocket()

{

MyWindowManager.removeLauncher(getContext());

new

LaunchTask().execute();

}

/**

*

更新小懸浮窗在屏幕中的位置。

*/

private

void

updateViewPosition()

{

mParams.x

=

(int)

(xInScreen

-

xInView);

mParams.y

=

(int)

(yInScreen

-

yInView);

windowManager.updateViewLayout(this,

mParams);

MyWindowManager.updateLauncher();

}

/**

*

更新View的顯示狀態(tài),判斷是顯示懸浮窗還是小火箭。

*/

private

void

updateViewStatus()

{

if

(isPressed

&&

rocketImg.getVisibility()

!=

View.VISIBLE)

{

mParams.width

=

rocketWidth;

mParams.height

=

rocketHeight;

windowManager.updateViewLayout(this,

mParams);

smallWindowLayout.setVisibility(View.GONE);

rocketImg.setVisibility(View.VISIBLE);

MyWindowManager.createLauncher(getContext());

}

else

if

(!isPressed)

{

mParams.width

=

windowViewWidth;

mParams.height

=

windowViewHeight;

windowManager.updateViewLayout(this,

mParams);

smallWindowLayout.setVisibility(View.VISIBLE);

rocketImg.setVisibility(View.GONE);

MyWindowManager.removeLauncher(getContext());

}

}

/**

*

打開大懸浮窗,同時(shí)關(guān)閉小懸浮窗。

*/

private

void

openBigWindow()

{

MyWindowManager.createBigWindow(getContext());

MyWindowManager.removeSmallWindow(getContext());

}

/**

*

用于獲取狀態(tài)欄的高度。

*

*

@return

返回狀態(tài)欄高度的像素值。

*/

private

int

getStatusBarHeight()

{

if

(statusBarHeight

==

0)

{

try

{

Class<?>

c

=

Class.forName("ernal.R$dimen");

Object

o

=

c.newInstance();

Field

field

=

c.getField("status_bar_height");

int

x

=

(Integer)

field.get(o);

statusBarHeight

=

getResources().getDimensionPixelSize(x);

}

catch

(Exception

e)

{

e.printStackTrace();

}

}

return

statusBarHeight;

}

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論