實(shí)用小工具--Android懸浮秒表

最近在轉(zhuǎn)型kotlin放钦,然后又對(duì)天貓的茅臺(tái)活動(dòng)有點(diǎn)興趣色徘,于是,腦子一熱操禀,抽了十幾分鐘褂策,寫了個(gè)簡易的秒表助手。如下圖:


image.png

分析如下:
首先颓屑,要做到懸浮窗口斤寂,那么久必須要依賴Window屬性,在window中揪惦,添加自定義的view遍搞。然后腦子浮現(xiàn)出了這一幅圖:


image.png

emu,感覺完成一大半了器腋,最關(guān)鍵的就是 windowManager.addView(floatingView, layoutParams)這個(gè)操作了吧尾抑。

然后分析點(diǎn)歇父,第二點(diǎn):如何讓該應(yīng)用處于后臺(tái)也能運(yùn)行呢?沒錯(cuò)再愈,那就是Service榜苫,開一個(gè)Service不就好了嗎,于是乎翎冲,就先創(chuàng)建了一個(gè)Servie垂睬,并在AndroidManifest中完成注冊(cè)。

   <service
            android:name=".FloatingWindowService"
            android:enabled="true" />

最后一個(gè)問題: 如何實(shí)時(shí)把系統(tǒng)時(shí)間拋給主線程抗悍? 這里我利用了kotlin的協(xié)程屬性

  GlobalScope.launch(Dispatchers.IO) {
                println("deal data===>");
                while (state) {
                    val format = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
                    val myDate: String = format.format(Date())
                    withContext(Dispatchers.Main) {
                        println("deal UI===>");
                        tvContent.setText(myDate.toString());
                    }
                }

            }

如上圖所示驹饺,然IO線程不斷處理日期數(shù)據(jù),處理完后缴渊,轉(zhuǎn)換為主線程赏壹,然后把控件數(shù)據(jù)更新,即完成功能衔沼。

ok蝌借,動(dòng)手操作一下吧。

import android.annotation.SuppressLint
import android.app.ActionBar
import android.app.Service
import android.content.Intent
import android.graphics.PixelFormat
import android.os.Build
import android.os.IBinder
import android.provider.Settings
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import androidx.annotation.RequiresApi
import kotlinx.coroutines.*
import java.text.SimpleDateFormat
import java.util.*

class FloatingWindowService : Service() {
    private lateinit var windowManager: WindowManager
    private lateinit var layoutParams: WindowManager.LayoutParams
    private lateinit var tvContent: TextView
    private var floatingView: View? = null
    private var state = true;

    // 用來判斷floatingView是否attached 到 window manager指蚁,防止二次removeView導(dǎo)致崩潰
    private var attached = false
    override fun onCreate() {
        super.onCreate()

        // 獲取windowManager并設(shè)置layoutParams
        windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        layoutParams = WindowManager.LayoutParams().apply {
            type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                WindowManager.LayoutParams.TYPE_PHONE
            }
            format = PixelFormat.RGBA_8888
//            format = PixelFormat.TRANSPARENT
            gravity = Gravity.START or Gravity.TOP
            flags =
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            width = ActionBar.LayoutParams.WRAP_CONTENT
            height = ActionBar.LayoutParams.WRAP_CONTENT
            x = 300
            y = 300
        }

    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    @RequiresApi(Build.VERSION_CODES.M)
    @SuppressLint("ClickableViewAccessibility")
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (Settings.canDrawOverlays(this)) {
            floatingView = LayoutInflater.from(this).inflate(R.layout.activity_main, null)
            tvContent = floatingView!!.findViewById<TextView>(R.id.tv_time);
            // 設(shè)置TextView滾動(dòng)
            windowManager.addView(floatingView, layoutParams)
            attached = true

            GlobalScope.launch(Dispatchers.IO) {
                println("deal data===>");
                while (state) {
                    val format = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
                    val myDate: String = format.format(Date())
                    withContext(Dispatchers.Main) {
                        println("deal UI===>");
                        tvContent.setText(myDate.toString());
                    }
                }

            }

        }
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {

        if (attached) {
            windowManager.removeView(floatingView)
            state = false
        }
    }


}

最后菩佑,注意要在一個(gè)activity里面 ,startService 哈凝化。

   if (Settings.canDrawOverlays(this)) {
                val service = Intent(this, FloatingWindowService::class.java);
                startService(service);
            } else {
                startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
            }

ok稍坯,完成。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末搓劫,一起剝皮案震驚了整個(gè)濱河市瞧哟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌枪向,老刑警劉巖绢涡,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異遣疯,居然都是意外死亡雄可,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門缠犀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來数苫,“玉大人,你說我怎么就攤上這事辨液∨凹保” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵滔迈,是天一觀的道長止吁。 經(jīng)常有香客問我被辑,道長,這世上最難降的妖魔是什么敬惦? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任盼理,我火速辦了婚禮,結(jié)果婚禮上俄删,老公的妹妹穿的比我還像新娘宏怔。我一直安慰自己,他們只是感情好畴椰,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布臊诊。 她就那樣靜靜地躺著,像睡著了一般斜脂。 火紅的嫁衣襯著肌膚如雪抓艳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天帚戳,我揣著相機(jī)與錄音玷或,去河邊找鬼。 笑死销斟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的椒舵。 我是一名探鬼主播蚂踊,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼笔宿!你這毒婦竟也來了犁钟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤泼橘,失蹤者是張志新(化名)和其女友劉穎涝动,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炬灭,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡醋粟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了重归。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片米愿。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鼻吮,靈堂內(nèi)的尸體忽然破棺而出育苟,到底是詐尸還是另有隱情,我是刑警寧澤椎木,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布违柏,位于F島的核電站博烂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏漱竖。R本人自食惡果不足惜禽篱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闲孤。 院中可真熱鬧谆级,春花似錦、人聲如沸讼积。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勤众。三九已至舆绎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間们颜,已是汗流浹背吕朵。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窥突,地道東北人努溃。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像阻问,于是被迫代替她去往敵國和親梧税。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容

  • 在調(diào)試時(shí)間敏感的程序時(shí)称近,實(shí)時(shí)在屏幕上打印當(dāng)前系統(tǒng)時(shí)間非常有用第队,下面就是利用Andorid懸浮窗口制作的一個(gè)小工具,...
    bely熊閱讀 894評(píng)論 0 0
  • 第一章 Android 系統(tǒng)架構(gòu) Android系統(tǒng)架構(gòu)分為五層刨秆,從上到下依次是: 應(yīng)用層 應(yīng)用框架層 系統(tǒng)運(yùn)行庫...
    縱橫Top閱讀 783評(píng)論 0 0
  • 前言 嗨凳谦,大家好,好久不見衡未。一個(gè)月沒寫過文章了尸执,這里跟大家侃侃這中間發(fā)生了什么。 一個(gè)月前呢缓醋,想準(zhǔn)備面試剔交,就網(wǎng)上隨...
    積木zz閱讀 6,179評(píng)論 1 36
  • 目錄 前言及消息機(jī)制簡述 Handler的日常使用 HandlerThread和IntentService中的Ha...
    真心czx閱讀 330評(píng)論 0 2
  • Activity中的幾種啟動(dòng)模式 activity的幾種啟動(dòng)模式是android中常考的知識(shí)點(diǎn)改衩,一般會(huì)考察有哪幾種...
    的一幕閱讀 1,306評(píng)論 0 5