Android實(shí)戰(zhàn)教程第十篇仿騰訊手機(jī)助手小火箭發(fā)射效果
之前對(duì)系統(tǒng)自帶的土司的源碼做了簡(jiǎn)要分析,見(jiàn)博客:點(diǎn)擊打開(kāi)鏈接
這一篇給一個(gè)小案例,自定義土司,模擬騰訊衛(wèi)士的小火箭發(fā)射。如果想要迅速看懂代碼,建議先去看一下上篇介紹點(diǎn)擊打開(kāi)鏈接
首先,定義一個(gè)服務(wù),在這個(gè)服務(wù)里面,完成土司的創(chuàng)建(小火箭布局創(chuàng)建),煙的效果屬于動(dòng)畫(huà)播放,而且要依托一個(gè)activity。(這個(gè)activity要定義為透明狀態(tài))
定義煙的activity的布局文件
<?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" > <ImageView android:id="@+id/smoke_m" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:src="@drawable/desktop_smoke_m" /> <ImageView android:layout_above="@id/smoke_m" android:id="@+id/smoke_t" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/desktop_smoke_t"/> </RelativeLayout>
在對(duì)應(yīng)的Smokeactivity里面加入“煙”的動(dòng)畫(huà)
package com.itydl.rockets;
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.ImageView;
public class SmokeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.smoke);
//底部煙圖片
ImageView iv_m = (ImageView) findViewById(R.id.smoke_m);
//煙柱子
ImageView iv_t = (ImageView) findViewById(R.id.smoke_t);
//漸變動(dòng)畫(huà)
AlphaAnimation aa = new AlphaAnimation(0.0f,1.0f);
aa.setDuration(1000);
//比例動(dòng)畫(huà) 設(shè)置錨點(diǎn)。x軸一半,y軸圖片最低端y值最大處
ScaleAnimation sa = new ScaleAnimation(1.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 1f);
sa.setDuration(1000);
//動(dòng)畫(huà)集添加動(dòng)畫(huà)
iv_m.startAnimation(aa);//給下面這張圖片實(shí)現(xiàn)漸變動(dòng)畫(huà)
AnimationSet as = new AnimationSet(true);
as.addAnimation(aa);
as.addAnimation(sa);
//給上邊圖片(煙柱子)設(shè)置漸變動(dòng)畫(huà)和比例動(dòng)畫(huà)
iv_t.startAnimation(as);
//1秒后關(guān)閉Activity,正好動(dòng)畫(huà)播完,關(guān)閉這個(gè)activity。這里也是那樣,主線程動(dòng)畫(huà)的同時(shí),子線程也在執(zhí)行耗時(shí)操作
new Thread(){
public void run() {
//1秒后關(guān)閉當(dāng)前Activity
SystemClock.sleep(1000);
runOnUiThread(new Runnable() {//activity類中的方法
@Override
public void run() {
// TODO Auto-generated method stub
finish();//關(guān)閉自己也屬于更新界面操作,因此要在主線程執(zhí)行。
}
});
};
}.start();
}
}
定義Service,用于自定義土司布局,加入火箭圖片的動(dòng)畫(huà)、參數(shù)初始化、觸摸事件等
package com.itydl.rockets;
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.ImageView;
public class RocketService extends Service {
private WindowManager.LayoutParams params;
private View view;
private WindowManager wm;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
//初始化params(土司參數(shù))
initToastParams();
showRocket();//打開(kāi)小火箭
super.onCreate();
}
/**
* 初始化土司的參數(shù)
*/
private void initToastParams() {
// TODO Auto-generated method stub
// XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
params = new WindowManager.LayoutParams();
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
//對(duì)齊方式左上角
params.gravity = Gravity.LEFT | Gravity.TOP;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
/* | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE */
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.format = PixelFormat.TRANSLUCENT;
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;// 土司天生不響應(yīng)事件,改變類型。TYPE_SYSTEM_ALERT系統(tǒng)彈窗
params.setTitle("Toast");
}
private void closeRocket(){
if (view != null) {
wm.removeView(view);//移除小火箭
}
}
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
wm.updateViewLayout(view, params);//更新小火箭在屏幕中的位置,刷新位置。屬于更新ui。在主線程執(zhí)行(更新土司的位置)
};
};
private void showRocket(){
//小火箭的布局
view = View.inflate(getApplicationContext(), R.layout.rocket, null);
ImageView iv_rocket = (ImageView) view.findViewById(R.id.iv_rocket);
//獲取小火箭的動(dòng)畫(huà)背景
AnimationDrawable ad = (AnimationDrawable) iv_rocket.getBackground();
//開(kāi)始小火箭動(dòng)畫(huà)(小火箭動(dòng)畫(huà),兩張圖片切換)
ad.start();
//給小火箭加觸摸事件(給自定義土司加觸摸事件),按住拖動(dòng)小火箭到屏幕正下方,松開(kāi)發(fā)射火箭
view.setOnTouchListener(new OnTouchListener() {
private float startX;
private float startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println(event.getX() + ":" + event.getRawX());
// 拖動(dòng)土司
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:// 按下
startX = event.getRawX();
startY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:// 按下移動(dòng),拖動(dòng)
//新的 x y坐標(biāo)
float moveX = event.getRawX();//移動(dòng)后的x坐標(biāo)
float moveY = event.getRawY();//移動(dòng)后的y坐標(biāo)
//dx x方向的位置變化值 dy y方向的位置變化值
float dx = moveX - startX;
float dy = moveY - startY;
//改變土司的坐標(biāo)
params.x += dx;
params.y += dy;
//重新獲取新的x y坐標(biāo)
startX = moveX;
startY = moveY;
//更新土司的位置
wm.updateViewLayout(view, params);
break;
case MotionEvent.ACTION_UP:// 松開(kāi),接下來(lái)要發(fā)射小火箭
//判斷位置 發(fā)射
//x軸方向 離兩邊框超過(guò)100,y軸方向大于200 就可以發(fā)射火箭
if (params.x > 100 && params.x + view.getWidth()< wm.getDefaultDisplay().getWidth() - 100 &&
params.y > 200){
//發(fā)射火箭
//1,火箭往上跑
//火箭在中心線上發(fā)射(自定義土司左上角為基準(zhǔn))
params.x = (wm.getDefaultDisplay().getWidth() - view.getWidth()) / 2;
new Thread(){//發(fā)射火箭改變y軸屬于耗時(shí)操作,更新火箭位置是更新UI操作
public void run() {
for (int j = 0; j < view.getHeight(); ) {
SystemClock.sleep(50);//休眠50毫秒
params.y -= j;
j += 5;
handler.obtainMessage().sendToTarget();//參數(shù)y的值改變一次,發(fā)消息通知更新一次ui,更新一次土司的位置
}
//,發(fā)射完畢,關(guān)閉小火箭
stopSelf();//關(guān)閉服務(wù),關(guān)閉當(dāng)前自己服務(wù)。這個(gè)方法用在關(guān)閉自己服務(wù)里。觸發(fā)onDestroy方法,從而觸發(fā)這個(gè)方法里面的關(guān)閉小火箭
};
}.start();
//2,煙的效果。因?yàn)楦禄鸺吓苁窃谧泳€程執(zhí)行的,因此在小火箭往上跑的同時(shí),煙的效果也同時(shí)開(kāi)始播放(子線程不影響主線程執(zhí)行。兩個(gè)線程可以同時(shí)進(jìn)行)
//煙的效果,是一個(gè)動(dòng)畫(huà),在activity完成,這個(gè)activity需要定義為透明
Intent intent = new Intent(RocketService.this,SmokeActivity.class);
//在服務(wù)中打開(kāi)activity,需要設(shè)置任務(wù)棧:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//任務(wù)棧
startActivity(intent);//啟動(dòng)煙的Activity
}
//冒煙的Activity
default:
break;
}
return false;//默認(rèn)返回值。
}
});
wm.addView(view, params);//把小火箭加到窗體管理器
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
closeRocket();//關(guān)閉小火箭
super.onDestroy();
}
}
對(duì)于主動(dòng)人任務(wù)只是加入個(gè)按鈕,打開(kāi)這個(gè)服務(wù)就行了。
package com.itydl.rockets;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 通過(guò)點(diǎn)擊按鈕打開(kāi)小火箭
* @param v
*/
public void openRocket(View v){
//RocketService service = new RocketService();
Intent service = new Intent(this,RocketService.class);
startService(service);//啟動(dòng)小火箭服務(wù)
finish();//關(guān)閉當(dāng)前界面。因?yàn)橐@示火箭發(fā)射,不能在這個(gè)activity里面演示
}
}
最后清單文件配置上兩個(gè)活動(dòng)和一個(gè)服務(wù),還有一個(gè)彈出窗體的權(quán)限
<activity
android:name="com.itheima62.rockets.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 配置該活動(dòng)的主題,為透明、無(wú)標(biāo)題、全屏 -->
<activity android:name="com.itheima62.rockets.SmokeActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"></activity>
<service android:name="com.itheima62.rockets.RocketService"></service>
好了主要代碼和功能都介紹完了,看一下運(yùn)行效果截圖:


完整代碼請(qǐng)查看文末的原文鏈接。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android-wheel控件實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了android-wheel控件實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)效果的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
android編程判斷應(yīng)用是否具有某個(gè)權(quán)限的方法
這篇文章主要介紹了android編程判斷應(yīng)用是否具有某個(gè)權(quán)限的方法,涉及Android進(jìn)程操作及權(quán)限控制的相關(guān)使用技巧,需要的朋友可以參考下2015-10-10
Android持久化技術(shù)之文件的讀取與寫入實(shí)例詳解
這篇文章主要介紹了Android持久化技術(shù)之文件的讀取與寫入操作,結(jié)合實(shí)例形式較為詳細(xì)的分析講述了Android持久化操作的相關(guān)技巧與具體實(shí)現(xiàn)方法,需要的朋友可以參考下2016-01-01
android中Glide實(shí)現(xiàn)加載圖片保存至本地并加載回調(diào)監(jiān)聽(tīng)
本篇文章主要介紹了android中Glide實(shí)現(xiàn)加載圖片保存至本地并加載回調(diào)監(jiān)聽(tīng),具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09
Android用PopupWindow實(shí)現(xiàn)自定義overflow
這篇文章主要介紹了Android用PopupWindow實(shí)現(xiàn)自定義overflow的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11

