android仿360加速球?qū)崿F(xiàn)內(nèi)存釋放
現(xiàn)在手機(jī)上的懸浮窗應(yīng)用越來越多,對用戶來說,最常見的懸浮窗應(yīng)用就是安全軟件的懸浮小控件,拿360衛(wèi)士來說,當(dāng)開啟懸浮窗時(shí),它是一個(gè)小球,小球可以拖動(dòng),當(dāng)點(diǎn)擊小球出現(xiàn)大窗體控件,可以進(jìn)行進(jìn)一步的操作如:釋放手機(jī)內(nèi)存等等。于是借著慕課網(wǎng)的視頻,仿著實(shí)現(xiàn)了360加速球,增加了點(diǎn)擊小球進(jìn)行釋放內(nèi)存的功能。
由于是手機(jī)只有頻幕截圖:實(shí)現(xiàn)后如下圖所示:點(diǎn)擊開啟按鈕,出現(xiàn)懸浮窗小球控件上面顯示手機(jī)的可用內(nèi)存百分比;當(dāng)拖動(dòng)小球時(shí),小球變?yōu)锳ndroid圖標(biāo);松開小球,小球依附在頻幕兩側(cè);點(diǎn)擊小球,手機(jī)底部出現(xiàn)大窗體控件,點(diǎn)擊里面的小球,進(jìn)行手機(jī)內(nèi)存的釋放;點(diǎn)擊手機(jī)屏幕的其他區(qū)域,大窗體消失,小球重新出現(xiàn)。
效果如下:


接下來就是實(shí)現(xiàn)的一些重要步驟:
1.FloatCircleView的實(shí)現(xiàn)(自定義view)
實(shí)現(xiàn)FloatCircleView的過程就是自定義view的過程。1、自定義View的屬性 2、在View的構(gòu)造方法中獲得我們自定義的屬性 3、重寫onMesure 4、重寫onDraw。我們沒有自定義其他屬性所以省了好多步驟。
各種變量的初始化,設(shè)置拖動(dòng)小球時(shí)要顯示的圖標(biāo),已經(jīng)計(jì)算各種內(nèi)存。(用于顯示在小球上)
public int width=100;
public int heigth=100;
private Paint circlePaint;//畫圓
private Paint textPaint; //畫字
private float availMemory; //已用內(nèi)存
private float totalMemory; //總內(nèi)存
private String text; //顯示的已用內(nèi)存百分比
private boolean isDraging=false; //是否在拖動(dòng)狀態(tài)。
private Bitmap src;
private Bitmap scaledBitmap; //縮放后的圖片。
/**
* 初始化畫筆以及計(jì)算可用內(nèi)存,總內(nèi)存,和可用內(nèi)存百分比。
*/
public void initPatints() {
circlePaint = new Paint();
circlePaint.setColor(Color.CYAN);
circlePaint.setAntiAlias(true);
textPaint = new Paint();
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(25);
textPaint.setFakeBoldText(true);
textPaint.setAntiAlias(true);
//設(shè)置圖片
src = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
//縮放后的圖片(將圖標(biāo)設(shè)置的和懸浮小球一樣大小。)
scaledBitmap = Bitmap.createScaledBitmap(src, width, heigth, true);
//計(jì)算已用內(nèi)存,總內(nèi)存,已用內(nèi)存百分比,
availMemory= (float) getAvailMemory(getContext());
totalMemory= (float) getTotalMemory(getContext());
text=(int)((availMemory/totalMemory)*100)+"%";
}
onMeasure();就是將固定的寬高寫死,通過 setMeasuredDimension(width, heigth);傳入。
onDraw();進(jìn)行懸浮小球繪制。定義一個(gè)boolean變量判斷當(dāng)前狀態(tài)是否為拖動(dòng)小球狀態(tài),如果是拖動(dòng)小球狀態(tài),就在該位置繪制android圖標(biāo),如果不是拖動(dòng)狀態(tài),就進(jìn)行小球繪制。畫小球沒有難度,關(guān)鍵是畫字。下面的2個(gè)圖可以加深對畫字時(shí)的理解。

1.畫字時(shí)的x坐標(biāo)(1.textPaint.measureText(text);得到字的寬度2.小球的寬度/2-字的寬度/2。)
2.畫字時(shí)的y坐標(biāo)(1.Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();得到字體屬性測量類。2.(fontMetrics.ascent + fontMetrics.descent) / 2 得到字的高度。3.小球的高度/2-字體的高度/2)
畫個(gè)圖就很好理解了:

/**
* 畫小球及文字。如果小球是在拖動(dòng)狀態(tài)就顯示android圖標(biāo),如果不是拖動(dòng)狀態(tài)就顯示小球。
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
if (isDraging){
canvas.drawBitmap(scaledBitmap,0,0,null);
}else {
//1.畫圓
canvas.drawCircle(width / 2, heigth / 2, width / 2, circlePaint);
//2.畫text
float textwidth = textPaint.measureText(text);//文本寬度
float x = width / 2 - textwidth / 2;
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float dy = -(fontMetrics.ascent + fontMetrics.descent) / 2;
float y = heigth / 2 + dy;
canvas.drawText(text, x, y, textPaint);
}
}
獲得手機(jī)已用內(nèi)存及總內(nèi)存的方法:
public long getAvailMemory(Context context)
{
// 獲取android當(dāng)前可用內(nèi)存大小
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
am.getMemoryInfo(mi);
//mi.availMem; 當(dāng)前系統(tǒng)的可用內(nèi)存
//return Formatter.formatFileSize(context, mi.availMem);// 將獲取的內(nèi)存大小規(guī)格化
return mi.availMem/(1024*1024);
}
public long getTotalMemory(Context context)
{
String str1 = "/proc/meminfo";// 系統(tǒng)內(nèi)存信息文件
String str2;
String[] arrayOfString;
long initial_memory = 0;
try
{
FileReader localFileReader = new FileReader(str1);
BufferedReader localBufferedReader = new BufferedReader(
localFileReader, 8192);
str2 = localBufferedReader.readLine();// 讀取meminfo第一行,系統(tǒng)總內(nèi)存大小
arrayOfString = str2.split("\\s+");
for (String num : arrayOfString) {
Log.i(str2, num + "\t");
}
initial_memory = Integer.valueOf(arrayOfString[1]).intValue() * 1024;// 獲得系統(tǒng)總內(nèi)存,單位是KB,乘以1024轉(zhuǎn)換為Byte
localBufferedReader.close();
} catch (IOException e) {
}
//return Formatter.formatFileSize(context, initial_memory);// Byte轉(zhuǎn)換為KB或者M(jìn)B,內(nèi)存大小規(guī)格化
return initial_memory/(1024*1024);
}
2.創(chuàng)建WindowManager窗體管理類,管理懸浮小球和底部大窗體。
WindowManager類。用來管理整個(gè)懸浮小球和手機(jī)底部大窗體的顯示和隱藏。
必須在Manifest文件中增加<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />權(quán)限。
通過 WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);獲取窗體管理類;
利用wm.addView(view, params);將view增加到窗體中。
利用wm.remove(view,params);將view從窗體中移除。
利用wm.updateViewLayout(view,params);來更新view.
WindowManager.LayoutParams用來設(shè)置view的各種屬性。
1.創(chuàng)建FloatViewManager實(shí)例。
//單例模式創(chuàng)建
public static FloatViewManager getInstance(Context context){
if (inStance==null){
synchronized(FloatViewManager.class){
if (inStance==null){
inStance=new FloatViewManager(context);
}
}
}
return inStance;
}
2.展示懸浮小球和展示底部窗體的方法。(展示窗體的方法同展示懸浮小球類似。)
/**
* 展示浮窗
*/
public void showFloatCircleView(){
//參數(shù)設(shè)置
if (params==null){
params = new WindowManager.LayoutParams();
//寬高
params.width=circleView.width;
params.height=circleView.heigth;
//對齊方式
params.gravity= Gravity.TOP|Gravity.LEFT;
//偏移量
params.x=0;
params.y=0;
//類型
params.type=WindowManager.LayoutParams.TYPE_TOAST;
//設(shè)置該window屬性。
params.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
//像素格式
params.format= PixelFormat.RGBA_8888;
}
//將小球加入窗體中。
wm.addView(circleView, params);
}
public void showFloatCircleView(){
......
}
3.當(dāng)啟動(dòng)程序,首先創(chuàng)建懸浮小球,小球可以拖拽,點(diǎn)擊小球,手機(jī)底部窗體顯示(FloatMenuView),小球隱藏。所以,對小球(circleView)要對其進(jìn)行setOnTouchListener和setOnClickListener事件監(jiān)聽。
分析小球的事件分發(fā); 對于小球:
當(dāng)ACTION_DOWN時(shí),記錄小球的downX,downY,以及startX,startY,
當(dāng)ACTION_MOVE時(shí),將circleView是否拖拽狀態(tài)置為true,記錄小球的moveX,moveY,計(jì)算小球移動(dòng)的距離(dx,dy),然后根據(jù) wm.updateViewLayout(circleView,params);更新小球位置。最后將最后move的坐標(biāo)賦值給startX,startY。
當(dāng)ACTION_UP時(shí),將circleView是否拖拽置為false,記錄抬起時(shí)的坐標(biāo),upx,根據(jù)upx和手機(jī)屏幕寬度/2,進(jìn)行判斷,來覺得最終小球是貼在屏幕左側(cè),還是右側(cè)。后面為小球拖拽的誤差。當(dāng)小球拖拽的距離小于10個(gè)像素時(shí),可以觸發(fā)小球的點(diǎn)擊事件。(小球的Touch事件,優(yōu)先于小球的點(diǎn)擊事件,當(dāng)Touch事件返回true時(shí),此事件被消費(fèi),不再向下傳遞事件。當(dāng)Touch事件返回false時(shí),此事件繼續(xù)向下傳遞,從而觸發(fā)小球的點(diǎn)擊事件。)
小球的點(diǎn)擊事件:點(diǎn)擊小球,懸浮小球隱藏,手機(jī)底部窗體出現(xiàn)。并設(shè)置有底部窗體出現(xiàn)時(shí)的過渡動(dòng)畫。
//給circleView設(shè)置touch監(jiān)聽。
private View.OnTouchListener circleViewOnTouchListener=new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//最后按下時(shí)的坐標(biāo),根據(jù)ACTION_MOVE理解。
startX = event.getRawX();
startY = event.getRawY();
//按下時(shí)的坐標(biāo)。
downX = event.getRawX();
downY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
circleView.setDrageState(true);
moveX = event.getRawX();
moveY=event.getRawY();
float dx = moveX -startX;
float dy=moveY-startY;
params.x+=dx;
params.y+=dy;
wm.updateViewLayout(circleView,params);
startX= moveX;
startY=moveY;
break;
case MotionEvent.ACTION_UP:
float upx=event.getRawX();
if (upx>getScreenWidth()/2){
params.x=getScreenWidth()-circleView.width;
}else {
params.x=0;
}
circleView.setDrageState(false);
wm.updateViewLayout(circleView,params);
if (Math.abs(moveX-downX)>10){
return true;
}else {
return false;
}
default:
break;
}
return false;
}
};
circleView.setOnTouchListener(circleViewOnTouchListener);
circleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Toast.makeText(, "onclick", Toast.LENGTH_SHORT).show();
//隱藏circleView,顯示菜單欄。
wm.removeView(circleView);
showFloatMenuView();
floatMenuView.startAnimation();
}
});
3.MyProgreeView(手機(jī)底部窗體中小球的實(shí)現(xiàn))。
1.初始化畫筆,對view進(jìn)行手勢監(jiān)聽。監(jiān)聽單擊和雙擊事件。(必須設(shè)置view是可以點(diǎn)擊的)
private void initPaint() {
//畫圓畫筆
circlepaint = new Paint();
circlepaint.setColor(Color.argb(0xff, 0x3a, 0x8c, 0x6c));
circlepaint.setAntiAlias(true);
//畫進(jìn)度條畫筆
progerssPaint = new Paint();
progerssPaint.setAntiAlias(true);
progerssPaint.setColor(Color.argb(0xff, 0x4e, 0xcc, 0x66));
progerssPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//繪制重疊部分
//畫進(jìn)度畫筆
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(25);
//畫布
bitmap = Bitmap.createBitmap(width, heigth, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
//手勢監(jiān)聽。
gestureDetector = new GestureDetector(new MyGertureDetectorListener());
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
//設(shè)置view可以點(diǎn)擊。
setClickable(true);
}
class MyGertureDetectorListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onDoubleTap(MotionEvent e) {
......
//雙擊事件的邏輯
return super.onDoubleTap(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
......
//單擊事件的邏輯
return super.onSingleTapConfirmed(e);
}
}
2.用handler交互進(jìn)行單擊和雙擊事件的狀態(tài)更新。單擊時(shí),利用貝塞爾曲線,實(shí)現(xiàn)波紋蕩漾效果。雙擊時(shí),波紋不斷下降,進(jìn)行內(nèi)存釋放,最后顯示內(nèi)存釋放后的已用內(nèi)存百分比。handler發(fā)送周期消息,讓單擊事件和雙擊事件的小球不斷進(jìn)行重繪。(重繪在下一小節(jié)講)。
//單擊事件發(fā)送周期handler.
private void startSingleTapAnimation() {
handler.postDelayed(singleTapRunnable,200);
}
private SingleTapRunnable singleTapRunnable=new SingleTapRunnable();
class SingleTapRunnable implements Runnable{
@Override
public void run() {
count--;
if (count>=0) {
invalidate();//不斷進(jìn)行重繪。
handler.postDelayed(singleTapRunnable,200);
}else {
handler.removeCallbacks(singleTapRunnable);
count=50;
}
}
}
//雙擊事件發(fā)送周期handler。
private void startDoubleTapAnimation() {
handler.postDelayed(runnbale,50);
}
private DoubleTapRunnable runnbale=new DoubleTapRunnable();
class DoubleTapRunnable implements Runnable{
@Override
public void run() {
num--;
if (num>=0){
invalidate();//不斷進(jìn)行重繪。
handler.postDelayed(runnbale,50);
}else {
handler.removeCallbacks(runnbale);
//釋放內(nèi)存。
killprocess();
//計(jì)算釋放后的已用內(nèi)存百分比。
num=(int)(((float)currentProgress/max)*100);
}
}
}
3.單擊事件和雙擊事件的重繪。
首先是小球的繪制,和波紋路徑的繪制。
//繪制小球
bitmapCanvas.drawCircle(width / 2, heigth / 2, width / 2, circlepaint);
//根據(jù)path,繪制波紋路徑。每次繪制前將上次的path,reset.
path.reset();
float y =(1-(float)num/100)*heigth;
path.moveTo(width, y);
path.lineTo(width, heigth);
path.lineTo(0, heigth);
path.lineTo(0, y);
接著利用貝塞爾曲線將波紋路徑繪制。
Android-貝塞爾曲線
貝塞爾曲線在android中的應(yīng)用
這里有詳細(xì)的講解貝塞爾曲線。其實(shí)不需要深入的理解。只要知道能用它來實(shí)現(xiàn)水波紋效果就行了(貝塞爾曲線用處很多,翻書效果也可以用它實(shí)現(xiàn)。)主要利用 path.rQuadTo(x1,y1,x2,y2); 終點(diǎn)(x2,y2),輔助控制點(diǎn)(x1,y1)的貝塞爾曲線。因此,通過不斷改變y1的位置,我們可以繪制出水波紋的效果。
首先判斷它是否為雙擊擊事件:
若是雙擊:設(shè)置一個(gè)變量d,通過不斷改變d的值(d的值的改變由num引起,而num實(shí)在handler中不斷減小的。num–;),來繪制貝塞爾曲線。實(shí)現(xiàn)水波紋的下降效果。
若是單擊:設(shè)置一個(gè)count值,通過不斷改變count值(count值的改變是在handler中實(shí)現(xiàn)的。count–;),首先判斷count是否能被2整除,交替繪制這兩條貝塞爾曲線。(這兩條貝塞爾曲線正好相反),從而實(shí)現(xiàn)水波蕩漾的效果。
(用for循環(huán)是實(shí)現(xiàn)水波的波數(shù),一對path.rQuadTo();只能實(shí)現(xiàn)一次波紋??梢宰约喝ヲ?yàn)證)
if (!isSingleTap){
float d=(1-(float)num/(100/2))*10;
for (int i=0;i<3;i++){
path.rQuadTo(10,-d,20,0);
path.rQuadTo(10,d,20,0);
}
}else {
float d=(float)count/50*10;
if (count%2==0){
for (int i=0;i<=3;i++){
path.rQuadTo(10,-d,30,0);
path.rQuadTo(10,d,30,0);
}
}else {
for (int i=0;i<=3;i++){
path.rQuadTo(10,d,30,0);
path.rQuadTo(10,-d,30,0);
}
}
}
最后是釋放內(nèi)存的方法。記得要在Manifest文件中增加<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>權(quán)限。
public void killprocess(){
ActivityManager activityManger=(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> list=activityManger.getRunningAppProcesses();
if(list!=null)
for(int i=0;i<list.size();i++)
{
ActivityManager.RunningAppProcessInfo apinfo=list.get(i);
String[] pkgList=apinfo.pkgList;
if(apinfo.importance>ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE)
{
// Process.killProcess(apinfo.pid);
for(int j=0;j<pkgList.length;j++) {
boolean flag=pkgList[j].contains("com.example.yyh.animation360");//這里要判斷是否為當(dāng)前應(yīng)用,要不然也可能會(huì)結(jié)束當(dāng)前應(yīng)用。
if(!flag){
activityManger.killBackgroundProcesses(pkgList[j]);
}
}
}
}
4.FloatMenuView的實(shí)現(xiàn)。
1.創(chuàng)建一個(gè)float_menuview.xml;其中包括一個(gè)ImageView+TextView+自定義的MyProgreeView。
底部窗體要被設(shè)置能被點(diǎn)擊。android:clickable="true";
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#33000000"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#F02F3942"
android:layout_alignParentBottom="true"
android:id="@+id/ll"
android:clickable="true"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/ic_launcher"
android:layout_gravity="center_vertical"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:textColor="#c93944"
android:text="360加速球"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
<com.example.yyh.animation360.view.MyProgreeView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
/>
</LinearLayout>
</RelativeLayout>
2.將FloatMenuView 根據(jù)條件,利用(wm.addView(view, params);將view增加到窗體中。
利用wm.remove(view,params);將view從窗體中移除。)方法,進(jìn)行底部窗體view的顯示和隱藏
TranslateAnimation類用來設(shè)置底部窗體進(jìn)入時(shí)的動(dòng)畫效果。TranslateAnimation(int fromXType,float fromXValue,int toXType,float toXValue,int fromYType,float fromYValue,int toYType,float toYValue)
int fromXType:x軸方向起始的參照值有3個(gè)選項(xiàng)。(1.Animation.ABSOLUTE:具體的坐標(biāo)值,指絕對的屏幕像素單位。
2.Animation.RELATIVE_TO_SELF:相對自己的坐標(biāo)值。3.Animation.RELATIVE_TO_PARENT:相對父容器的坐標(biāo)值。)
float fromXValue 第二個(gè)參數(shù)是第一個(gè)參數(shù)類型的起始值(例如若第一個(gè)參數(shù)設(shè)置為Animation.RELATIVE_TO_SELF,第二個(gè)參數(shù)為0.1f,就表示為自己的坐標(biāo)值乘以0.1);
int toXType:x軸方向終點(diǎn)的參照值有3個(gè)選項(xiàng)同第一個(gè)參數(shù)。
float toValue:第四個(gè)參數(shù)是第三個(gè)參數(shù)類型的起始值。
Y軸方向的參數(shù)同理。起點(diǎn)+終點(diǎn);(每個(gè)參數(shù)后一個(gè)參數(shù)為前一個(gè)參數(shù)的起始值。)
并對此view設(shè)置OnTouchListener,OnTouch事件最后必須返回false,表示此事件仍然需要向下傳遞。從而實(shí)現(xiàn)點(diǎn)擊手機(jī)其他區(qū)域時(shí),手機(jī)底部窗體隱藏,懸浮小球顯示,點(diǎn)擊底部窗體時(shí)無變化,點(diǎn)擊底部窗體中的小球時(shí),觸發(fā)其單擊和雙擊事件。
View view =View.inflate(getContext(), R.layout.float_menuview,null);
LinearLayout linearLayout= (LinearLayout) view.findViewById(R.id.ll);
translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,1.0f,Animation.RELATIVE_TO_SELF,0);
translateAnimation.setDuration(500);
translateAnimation.setFillAfter(true);
linearLayout.setAnimation(translateAnimation);
view.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
FloatViewManager manager=FloatViewManager.getInstance(getContext());
manager.hideFloatMenuView();
manager.showFloatCircleView();
return false;
}
});
addView(view);
5.MyFloatService
用來創(chuàng)建FloatVIewManager單例,管理懸浮小球+手機(jī)底部窗體的創(chuàng)建和移除。
public class MyFloatService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
//用來開啟FloatViewManager
FloatViewManager manager=FloatViewManager.getInstance(this);
manager.showFloatCircleView();
super.onCreate();
}
}
6.MainActivity的實(shí)現(xiàn)
定義一個(gè)intent,開啟服務(wù)(在服務(wù)中創(chuàng)建WindowManager單例對象,進(jìn)行懸浮小球和手機(jī)底部窗體的管理。),關(guān)閉當(dāng)前的activity。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view){
Intent intent=new Intent(this, MyFloatService.class);
startService(intent);
finish();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android實(shí)現(xiàn)手機(jī)定位的案例代碼
今天小編就為大家分享一篇關(guān)于Android實(shí)現(xiàn)手機(jī)定位的案例代碼,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
Android實(shí)現(xiàn)隨意拖動(dòng)View效果的實(shí)例代碼
這篇文章主要介紹了Android實(shí)現(xiàn)隨意拖動(dòng)View效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07
Flutter網(wǎng)絡(luò)請求Dio庫的使用及封裝詳解
本文主要介紹了Flutter網(wǎng)絡(luò)請求Dio庫的使用及封裝詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
Android自定義View原理(實(shí)戰(zhàn))
這篇文章主要介紹了Android自定義View原理,由于Android系統(tǒng)內(nèi)置的View不滿足我們的業(yè)務(wù)需求,變產(chǎn)生了需要自定義View的原因,關(guān)于自定義詳情,需要的小伙伴可以參考下面文章具體詳情2022-05-05
Android10 App 啟動(dòng)分析進(jìn)程創(chuàng)建源碼解析
這篇文章主要為大家介紹了Android10 App啟動(dòng)分析進(jìn)程創(chuàng)建源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Android 實(shí)現(xiàn)截屏功能的實(shí)例
這篇文章主要介紹了Android 實(shí)現(xiàn)截屏功能的實(shí)例的相關(guān)資料,這里實(shí)現(xiàn)截屏的實(shí)例在代碼中注釋非常清楚,希望能幫助到大家,需要的朋友可以參考下2017-08-08
Android RecyclerView詳解之實(shí)現(xiàn) ListView GridView瀑布流效果
RecyclerView 是Android L版本中新添加的一個(gè)用來取代ListView的SDK,它的靈活性與可替代性比listview更好2016-07-07

