Android開發(fā)全局音量調整的實現(xiàn)方式詳解
引言
之前參與過一個項目,開發(fā)的是一個系統(tǒng)級別的軟件,安裝在定制的設備上,設備沒有控制音量的按鍵,因此軟件需要實現(xiàn)一個在任意頁面都能控制音量的功能。
實現(xiàn)方案是在所有頁面的頂部加上一個觸發(fā)音量控制彈窗的按鈕,用戶點擊該按鈕后顯示音量控制彈窗。
全局添加按鈕
參與項目時,已經(jīng)出了第一版了,包含的頁面很多,因此一個個頁面去加肯定不合適。項目中所有Activity都繼承了一個自定義的BaseActivity,所以只能在這個BaseActivity中做文章。
Android中,每個Activity都包含一個DecorView,DecorView內(nèi)部包含一個FrameLayout,可以通過android.R.id.content來獲取,我們的布局包含在這個FrameLayout中。
因此如果需要在所有的頁面都添加View,那么在BaseActivity中實現(xiàn)向android.R.id.content對應的FrameLayout添加View的邏輯,然后所有的Activity就都可以自動添加View了。
實現(xiàn)代碼如下:
object DensityUtil {
@JvmStatic
fun dp2Px(dpValue: Int): Int {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue.toFloat(), Resources.getSystem().displayMetrics).toInt()
}
@JvmStatic
fun px2Dp(pxValue: Int): Int {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, pxValue.toFloat(), Resources.getSystem().displayMetrics).toInt()
}
}
// Base類
open class BaseActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
// 在onResume中添加,確保在主布局添加完成后添加,避免被遮擋。
initVolumeControllerView()
}
private fun initVolumeControllerView() {
val controllerView = AppCompatImageView(this)
controllerView.layoutParams = FrameLayout.LayoutParams(DensityUtil.dp2Px(80), DensityUtil.dp2Px(12)).apply {
gravity = Gravity.START
marginStart = DensityUtil.dp2Px(20)
topMargin = DensityUtil.dp2Px(10)
}
controllerView.setImageResource(R.drawable.shape_vollume_controller)
controllerView.setOnClickListener {
runOnUiThread { Toast.makeText(this, "點擊了全局按鈕", Toast.LENGTH_SHORT).show() }
}
val rootView = findViewById<FrameLayout>(android.R.id.content)
rootView.addView(controllerView)
}
}
效果如圖:

音量控制
AudioManager類提供了控制音量的方法。
實現(xiàn)音量控制代碼如下:
class VolumeControllerDialog : DialogFragment() {
private var binding: LayoutVolumeContollerDialogBinding? = null
private var currentVolume = 0
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
dialog?.window?.run {
setBackgroundDrawable(ContextCompat.getDrawable(requireContext(), android.R.color.transparent))
decorView.setBackgroundResource(android.R.color.transparent)
val layoutParams = attributes
layoutParams.width = DensityUtil.dp2Px(360)
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
layoutParams.gravity = Gravity.CENTER
attributes = layoutParams
}
binding = DataBindingUtil.inflate(inflater, R.layout.layout_volume_contoller_dialog, container, false)
return binding?.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
val step = 1
binding?.run {
btnMute.text = getMuteButtonString(audioManager.isStreamMute(AudioManager.STREAM_MUSIC))
btnIncreaseVolume.setOnClickListener {
// 增加音量
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume + step, AudioManager.FLAG_SHOW_UI or AudioManager.FLAG_PLAY_SOUND)
btnMute.text = getMuteButtonString(audioManager.isStreamMute(AudioManager.STREAM_MUSIC))
}
btnReduceVolume.setOnClickListener {
//減少音量
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, if (currentVolume - step < 0) 0 else currentVolume - step, AudioManager.FLAG_SHOW_UI or AudioManager.FLAG_PLAY_SOUND)
btnMute.text = getMuteButtonString(audioManager.isStreamMute(AudioManager.STREAM_MUSIC))
}
btnMute.setOnClickListener {
// 靜音或取消靜音
val currentMute = audioManager.isStreamMute(AudioManager.STREAM_MUSIC)
if (currentVolume == 0) {
btnMute.text = getMuteButtonString(true)
} else {
btnMute.text = getMuteButtonString(!currentMute)
}
val setVolume = if (currentMute) {
currentVolume
} else {
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
0
}
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, setVolume, AudioManager.FLAG_SHOW_UI or AudioManager.FLAG_PLAY_SOUND)
}
}
}
private fun getMuteButtonString(mute: Boolean): String {
return if (mute) "UnMute" else "Mute"
}
}
open class BaseActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
// 在onResume中添加,確保在主布局添加完成后添加,避免被遮擋。
initVolumeControllerView()
}
private fun initVolumeControllerView() {
val controllerView = AppCompatImageView(this)
controllerView.layoutParams = FrameLayout.LayoutParams(DensityUtil.dp2Px(80), DensityUtil.dp2Px(12)).apply {
gravity = Gravity.START
marginStart = DensityUtil.dp2Px(20)
topMargin = DensityUtil.dp2Px(10)
}
controllerView.setImageResource(R.drawable.shape_vollume_controller)
controllerView.setOnClickListener {
VolumeControllerDialog().show(supportFragmentManager, null)
}
val rootView = findViewById<FrameLayout>(android.R.id.content)
rootView.addView(controllerView)
}
}
效果如圖:

以上就是Android開發(fā)全局音量調整的實現(xiàn)方式詳解的詳細內(nèi)容,更多關于Android 全局音量調整的資料請關注腳本之家其它相關文章!
相關文章
Android實現(xiàn)點擊Button產(chǎn)生水波紋效果
這篇文章主要介紹了Android實現(xiàn)點擊Button產(chǎn)生水波紋效果,需要的朋友可以參考下2016-01-01
Android數(shù)據(jù)庫增刪改查實戰(zhàn)案例
我們在編程中經(jīng)常會遇到數(shù)據(jù)庫的操作,這篇文章主要給大家介紹了關于Android數(shù)據(jù)庫增刪改查的相關資料,文中通過圖文以及實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04
Android 操作系統(tǒng)獲取Root權限 原理詳細解析
許多機友新購來的Android機器沒有破解過Root權限,無法使用一些需要高權限的軟件,以及進行一些高權限的操作,其實破解手機Root權限是比較簡單及安全的,破解Root權限的原理就是在手機的/system/bin/或/system/xbin/目錄下放置一個可執(zhí)行文件“su”2013-10-10
Android實現(xiàn)socket通信統(tǒng)一接口的方法
這篇文章主要介紹了Android實現(xiàn)socket通信統(tǒng)一接口?,實現(xiàn)了統(tǒng)一接口之后確實可以使后續(xù)修改實現(xiàn)更加方便,程序結構也更加工程化,需要的朋友可以參考下2021-12-12
android 仿微信demo——微信通訊錄界面功能實現(xiàn)(移動端,服務端)
本系列文章主要介紹了微信小程序-閱讀小程序實例(demo),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望能給你們提供幫助2021-06-06

