app/src/main/java/jp/aosystem/roulettewheel/MainActivity.kt
package jp.aosystem.roulettewheel
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.os.Handler
import android.os.LocaleList
import android.os.Looper
import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
import android.util.DisplayMetrics
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.res.ResourcesCompat
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.MobileAds
import java.util.*
import kotlin.math.cos
import kotlin.math.sin
class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {
private lateinit var vTextStart: TextView
private lateinit var vTextSetting: TextView
private lateinit var vLayoutBase: FrameLayout
private lateinit var vImageWheelBase: ImageView
private lateinit var vLinearlayoutWheelTop: LinearLayout
private lateinit var vImageWheelTop: ImageView
private lateinit var vLinearlayoutBall: LinearLayout
private lateinit var vImageBall: ImageView
private lateinit var vImageTextThree: ImageView
private lateinit var vImageTextTwo: ImageView
private lateinit var vImageTextOne: ImageView
private lateinit var vImageTextNoMoreBets: ImageView
private lateinit var vTextResult: TextView
private lateinit var vAdContainer: LinearLayout
//
private lateinit var bgGreen: Drawable
private lateinit var bgBlack: Drawable
private lateinit var bgRed: Drawable
//
private lateinit var textToSpeech: TextToSpeech
private var speechVoices: ArrayList<String> = arrayListOf()
//
private var baseWidth: Int = 0
private var baseHeight: Int = 0
private var boxSize: Int = 0
private var busyFlag: Boolean = false //回転中
private var speechNumber: Int = 0 //数字を読み上げるか否か 0 or 1
private var speechVoice: String = "en-US-language" //voice e.g. "ja-jp-x-jad-local"
private var shortNumber: Int = 0 //短く回転 0 to 9
private var themeNumber: Int = 0 //0:light 1:dark
private var localeLanguage: String = "" //en or ja or else
private var wheelAngle: Float = 360F
private var ballAngle: Float = 0F
private var wheelAngleStart: Float = 0F
private var ballRotateFlag: Boolean = false //ball回転中はTrue
private var ballTick: Int = 0 //回転をこの数値の減算で制御
private var adjustAngle: Float = 0F //最終の確度調整用
private var ballDistanceRatio: Float = 0F //BALL_DISTANCE_START to BALL_DISTANCE_END
private val mainHandler: Handler = Handler(Looper.getMainLooper())
private var wheelRunnable: Runnable? = null
private var wheelRunnerAlready: Boolean = false //wheel回転開始済み。アプリ退避からの復帰で2重処理を防ぐ
//adMob
private lateinit var adView: AdView //adMob
private val adSize: AdSize
get() {
val density = resources.displayMetrics.density
var adWidthPixels = this.vAdContainer.width.toFloat()
if (adWidthPixels == 0f) {
adWidthPixels = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
// APIレベル30以上
val windowMetrics = windowManager.currentWindowMetrics
windowMetrics.bounds.width().toFloat()
} else {
// APIレベル30未満
val display = windowManager.defaultDisplay
val outMetrics = DisplayMetrics()
display.getMetrics(outMetrics)
outMetrics.widthPixels.toFloat()
}
}
val adWidth = (adWidthPixels / density).toInt()
return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(this, adWidth)
}
private var isAdLoaded: Boolean = false
companion object {
private const val BALL_SIZE_RATIO: Float = 0.04F
private const val BALL_DISTANCE_START: Float = 0.89F
private const val BALL_DISTANCE_END: Float = 0.535F
private val LIST_NUMBER: List<String> = listOf("0","28","9","26","30","11","7","20","32","17","5","22","34","15","3","24","36","13","1","00","27","10","25","29","12","8","19","31","18","6","21","33","16","4","23","35","14","2")
private val LIST_COLOR: List<String> = listOf("g","k","r","k","r","k","r","k","r","k","r","k","r","k","r","k","r","k","r","g","r","k","r","k","r","k","r","k","r","k","r","k","r","k","r","k","r","k")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide() //タイトルバー非表示
//
this.vTextStart = findViewById(R.id.textStart)
this.vTextSetting = findViewById(R.id.textSetting)
this.vLayoutBase = findViewById(R.id.layoutBase)
this.vImageWheelBase = findViewById(R.id.imageWheelBase)
this.vLinearlayoutWheelTop = findViewById(R.id.linearLayoutWheelTop)
this.vImageWheelTop = findViewById(R.id.imageWheelTop)
this.vLinearlayoutBall = findViewById(R.id.linearLayoutBall)
this.vImageBall = findViewById(R.id.imageBall)
this.vImageTextThree = findViewById(R.id.imageTextThree)
this.vImageTextTwo = findViewById(R.id.imageTextTwo)
this.vImageTextOne = findViewById(R.id.imageTextOne)
this.vImageTextNoMoreBets = findViewById(R.id.imageTextNoMoreBets)
this.vTextResult = findViewById(R.id.textResult)
this.vAdContainer = findViewById(R.id.adContainer)
this.vTextStart.setOnClickListener {
this.onClickStart()
}
this.vTextSetting.setOnClickListener {
this.onClickSetting()
}
//resource
this.bgGreen = ResourcesCompat.getDrawable(this.resources,R.drawable.bg_green_border,null)!!
this.bgBlack = ResourcesCompat.getDrawable(this.resources,R.drawable.bg_black_border,null)!!
this.bgRed = ResourcesCompat.getDrawable(this.resources,R.drawable.bg_red_border,null)!!
//設定
this.loadThemeNumber()
this.setTheme()
this.loadSpeechNumber()
this.loadSpeechVoice()
this.loadShortNumber()
this.loadLocaleLanguage()
//読み上げ
this.textToSpeech = TextToSpeech(this, this)
this.textToSpeech.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
override fun onDone(utteranceId: String) {
}
override fun onError(p0: String?) {
}
override fun onStart(utteranceId: String) {
}
})
//adMob
MobileAds.initialize(this) {}
}
override fun onResume() {
super.onResume()
//レイアウトの幅と高さが確定するまで待つ。準備が出来たらwidth,heightを取得して次へ進む
this.vLayoutBase.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
this@MainActivity.vLayoutBase.viewTreeObserver.removeOnGlobalLayoutListener(this)
this@MainActivity.baseWidth = this@MainActivity.vLayoutBase.width
this@MainActivity.baseHeight = this@MainActivity.vLayoutBase.height
this@MainActivity.init()
if (isAdLoaded == false) {
this@MainActivity.loadAd()
isAdLoaded = true
}
}
})
}
private fun loadAd() {
if (!::adView.isInitialized) {
adView = AdView(this).apply {
adUnitId = ConstValue.AD_UNIT_ID
setAdSize(this@MainActivity.adSize)
}
vAdContainer.addView(adView)
}
val adRequest = AdRequest.Builder().build()
if (!adView.isLoading) {
adView.loadAd(adRequest)
}
}
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
this.speechVoices = arrayListOf()
val vs = textToSpeech.voices
vs.forEach{v ->
this.speechVoices += v.locale.toString() + " " + v.name
}
this.speechVoices.sort()
this.setSpeechVoiceName()
}
}
override fun onPause() {
super.onPause()
if (::adView.isInitialized) {
adView.pause()
}
}
override fun onDestroy() {
if (::textToSpeech.isInitialized) {
this.textToSpeech.shutdown()
}
if (::adView.isInitialized) {
adView.destroy()
}
super.onDestroy()
}
private fun init() {
this.boxSize = minOf(this.baseWidth, this.baseHeight)
val topPadding: Int = (this.boxSize * 0.14).toInt()
this.vLinearlayoutWheelTop.setPadding(topPadding,topPadding,topPadding,topPadding)
this.wheelRunnable = object: Runnable {
override fun run() {
this@MainActivity.wheelAngle -= 0.5F
if (this@MainActivity.wheelAngle < 0F) {
this@MainActivity.wheelAngle = 359.5F
}
this@MainActivity.vImageWheelTop.rotation = this@MainActivity.wheelAngle
if (this@MainActivity.ballRotateFlag) {
this@MainActivity.adjustAngle += 0.5F //wheelAngleと同じ数値にする
this@MainActivity.ballAngle += 5F
if (this@MainActivity.ballAngle >= 360F) {
this@MainActivity.ballAngle = 0F
}
if (this@MainActivity.ballTick > 0) {
this@MainActivity.ballTick -= 1
if (this@MainActivity.ballTick == 500) {
this@MainActivity.vImageTextThree.animate().alpha(0.8F).setDuration(500).start()
this@MainActivity.speakText("3")
}
if (this@MainActivity.ballTick == 450) {
this@MainActivity.vImageTextThree.animate().alpha(0F).setDuration(500).start()
this@MainActivity.vImageTextTwo.animate().alpha(0.8F).setDuration(500).start()
this@MainActivity.speakText("2")
}
if (this@MainActivity.ballTick == 400) {
this@MainActivity.vImageTextTwo.animate().alpha(0F).setDuration(500).start()
this@MainActivity.vImageTextOne.animate().alpha(0.8F).setDuration(500).start()
this@MainActivity.speakText("1")
}
if (this@MainActivity.ballTick == 350) {
this@MainActivity.vImageTextOne.animate().alpha(0F).setDuration(500).start()
this@MainActivity.vImageTextNoMoreBets.animate().alpha(0.8F).setDuration(500).start()
this@MainActivity.speakText(resources.getString(R.string.nomorebets))
}
if (this@MainActivity.ballTick == 250) {
this@MainActivity.vImageTextNoMoreBets.animate().alpha(0F).setDuration(1000).start()
this@MainActivity.ballTick -= (Math.random() * 100).toInt()
}
if (this@MainActivity.ballTick < 5) {
this@MainActivity.ballDistanceRatio = (BALL_DISTANCE_START + BALL_DISTANCE_END) / 2
}
if (this@MainActivity.ballTick < 1) {
this@MainActivity.ballDistanceRatio = BALL_DISTANCE_END
}
if (this@MainActivity.ballTick <= 0) {
this@MainActivity.ballRotateFlag = false
this@MainActivity.startButtonColor(true)
this@MainActivity.resultNumber()
this@MainActivity.busyFlag = false
}
}
}
ballPosition()
this@MainActivity.mainHandler.postDelayed(this,25)
}
}
if (!wheelRunnerAlready) { //アプリ退避からの復帰で2重処理を防ぐ
mainHandler.post(this.wheelRunnable as Runnable)
wheelRunnerAlready = true
}
this.startButtonColor(true)
//
val vImageBallLayout: ViewGroup.LayoutParams = this.vImageBall.layoutParams
vImageBallLayout.width = (this.boxSize * BALL_SIZE_RATIO).toInt()
vImageBallLayout.height = (this.boxSize * BALL_SIZE_RATIO).toInt()
this.vImageBall.alpha = 0F
this.vImageTextThree.alpha = 0F
this.vImageTextTwo.alpha = 0F
this.vImageTextOne.alpha = 0F
this.vImageTextNoMoreBets.alpha = 0F
this.vTextResult.alpha = 0F
}
private fun onClickStart() {
if (this.busyFlag) {
return
}
this.busyFlag = true
this.vTextResult.animate().alpha(0F).setDuration(300).start()
this.startButtonColor(false)
this.ballAngle = 0F
this.vImageBall.alpha = 1F
this.ballDistanceRatio = BALL_DISTANCE_START
this.wheelAngleStart = this.wheelAngle
this.ballTick = (10 - this.shortNumber) * 100 + 260 //1260 to 360
this.adjustAngle = 0F
this.ballRotateFlag = true
}
private fun ballPosition() {
val ballSize: Float = this.boxSize * BALL_SIZE_RATIO
var angle: Float = this.ballAngle
if (this.ballRotateFlag == false) {
angle = ((angle - this.wheelAngleStart + this.adjustAngle) / (360 / 38F)).toInt() * (360 / 38F) + (180 / 38F)
angle += this.wheelAngle
}
var x: Double = (-sin(angle * (Math.PI / 180)) * (this.boxSize / 2)) //回転
var y: Double = (cos(angle * (Math.PI / 180)) * (this.boxSize / 2)) //回転
x *= this.ballDistanceRatio //内側の距離
y *= this.ballDistanceRatio //内側の距離
x += this.boxSize / 2.0 * 0.89 //中心位置
y += this.boxSize / 2.0 * 0.89 //中心位置
x += ballSize * 0.9 //微調整
y += ballSize * 0.9 //微調整
this.vLinearlayoutBall.setPadding(x.toInt(),y.toInt(),0,0)
}
private fun resultNumber() {
var angle: Float = this.ballAngle
angle = ((angle - this.wheelAngleStart + this.adjustAngle) / (360 / 38F)).toInt() * (360 / 38F) + (180 / 38F)
angle = 180F - angle
angle += 3600F
angle %= 360F
var num: Int = 38 - (angle / (360 / 38F)).toInt() - 1
num %= 38
val resultNumber: String = LIST_NUMBER[num]
val resultColor: String = LIST_COLOR[num]
this.vTextResult.text = resultNumber
val greenBlackRed: Drawable? = when (resultColor) {
"g" -> bgGreen
"k" -> bgBlack
"r" -> bgRed
else -> null
}
this.vTextResult.background = greenBlackRed
this.vTextResult.animate().alpha(1F).setDuration(500).start()
this.speakText(resultNumber)
}
//start,settingのボタン色
private fun startButtonColor(onOff: Boolean) {
val targetAlpha = if (onOff) 1F else 0F
val duration = 300L // アニメーションの時間(ミリ秒)
// アニメーション処理
vTextStart.animate()
.alpha(targetAlpha)
.setDuration(duration)
.start()
vTextSetting.animate()
.alpha(targetAlpha)
.setDuration(duration)
.start()
}
private fun speakText(text: String) {
if (speechNumber == 1) {
this.textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, "utteranceId")
}
}
//-------------------------------------------------
private fun onClickSetting() {
if (this.busyFlag) {
return
}
val intent = Intent(applicationContext, SettingActivity::class.java)
intent.putExtra(ConstValue.SPEECH_NUMBER, this.speechNumber)
intent.putExtra(ConstValue.SPEECH_VOICE, this.speechVoice)
intent.putStringArrayListExtra(ConstValue.SPEECH_VOICES, this.speechVoices)
intent.putExtra(ConstValue.SHORT_NUMBER, this.shortNumber)
intent.putExtra(ConstValue.THEME_NUMBER, this.themeNumber)
intent.putExtra(ConstValue.LOCALE_LANGUAGE, this.localeLanguage)
this.settingStartForResult.launch(intent)
}
private val settingStartForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK && result.data != null) {
val intent: Intent = result.data!!
val lastSpeechNumber: Int = this.speechNumber
this.speechNumber = intent.getIntExtra(ConstValue.SPEECH_NUMBER, 1)
if (lastSpeechNumber != this.speechNumber) {
this.saveSpeechNumber()
}
val lastSpeechVoice: String = this.speechVoice
this.speechVoice = intent.getStringExtra(ConstValue.SPEECH_VOICE) ?: ""
if (lastSpeechVoice != this.speechVoice) {
this.saveSpeechVoice()
this.setSpeechVoiceName()
}
val lastShortNumber: Int = this.shortNumber
this.shortNumber = intent.getIntExtra(ConstValue.SHORT_NUMBER, 1)
if (lastShortNumber != this.shortNumber) {
this.saveShortNumber()
}
val lastThemeNumber: Int = this.themeNumber
this.themeNumber = intent.getIntExtra(ConstValue.THEME_NUMBER, 0)
if (lastThemeNumber != this.themeNumber) {
this.saveThemeNumber()
}
val lastLocaleLanguage = this.localeLanguage
this.localeLanguage = intent.getStringExtra(ConstValue.LOCALE_LANGUAGE) ?: ""
if (this.localeLanguage != lastLocaleLanguage) {
this.saveLocaleLanguage()
}
}
recreate()
}
//-------------------------------------------------
//数字読み上げを保存
private fun saveSpeechNumber() {
getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE).edit().apply {
putInt(ConstValue.SPEECH_NUMBER, this@MainActivity.speechNumber)
apply()
}
}
//数字読み上げを読み出し
private fun loadSpeechNumber() {
val pref = getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE)
this.speechNumber = pref.getInt(ConstValue.SPEECH_NUMBER, 1)
}
//-------------------------------------------------
//声を保存
private fun saveSpeechVoice() {
getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE).edit().apply {
putString(ConstValue.SPEECH_VOICE, this@MainActivity.speechVoice)
apply()
}
}
//声を読み出し
private fun loadSpeechVoice() {
val pref = getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE)
this.speechVoice = pref.getString(ConstValue.SPEECH_VOICE,"en-US-language").toString()
}
//-------------------------------------------------
//回転早くを保存
private fun saveShortNumber() {
getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE).edit().apply {
putInt(ConstValue.SHORT_NUMBER, this@MainActivity.shortNumber)
apply()
}
}
//回転早くを読み出し
private fun loadShortNumber() {
val pref = getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE)
this.shortNumber = pref.getInt(ConstValue.SHORT_NUMBER, 0)
}
//-------------------------------------------------
//テーマを保存
private fun saveThemeNumber() {
getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE).edit().apply {
putInt(ConstValue.THEME_NUMBER, this@MainActivity.themeNumber)
apply()
}
}
//テーマを読み出し
private fun loadThemeNumber() {
val pref = getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE)
this.themeNumber = pref.getInt(ConstValue.THEME_NUMBER, 0)
}
//テーマを設定
private fun setTheme() {
when (this.themeNumber) {
0 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
1 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
//-------------------------------------------------
//音声設定
private fun setSpeechVoiceName() {
this.textToSpeech.voice = this.textToSpeech.voices.find { it.name == this.speechVoice } ?: this.textToSpeech.defaultVoice
}
//----------------------------------------------
//localeLanguageを保存
private fun saveLocaleLanguage() {
getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE).edit().apply {
putString(ConstValue.LOCALE_LANGUAGE, this@MainActivity.localeLanguage)
apply()
}
}
//localeLanguageを読み出し
private fun loadLocaleLanguage() {
val pref = getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE)
this.localeLanguage = pref.getString(ConstValue.LOCALE_LANGUAGE, "") ?: ""
}
//言語設定
override fun attachBaseContext(base: Context) {
val pref = base.getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE)
val localeLanguage = pref.getString(ConstValue.LOCALE_LANGUAGE, "").orEmpty()
if (localeLanguage.isNotEmpty() && this.isValidLocale(localeLanguage)) {
val locale = Locale(localeLanguage)
val config = Configuration(base.resources.configuration)
val localeList = LocaleList(locale)
LocaleList.setDefault(localeList)
config.setLocales(localeList)
super.attachBaseContext(base.createConfigurationContext(config))
} else {
super.attachBaseContext(base)
}
}
private fun isValidLocale(languageCode: String): Boolean {
return Locale.getAvailableLocales().any { it.language == languageCode }
}
//----------------------------------------------
}
app/src/main/java/jp/aosystem/roulettewheel/SettingActivity.kt
package jp.aosystem.roulettewheel
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import android.os.LocaleList
import android.view.View
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat
import java.util.*
class SettingActivity : AppCompatActivity() {
private lateinit var vTextCancel: TextView
private lateinit var vTextApply: TextView
private lateinit var vSwitchSpeechNumber: SwitchCompat
private lateinit var vSpinnerVoice: Spinner
private lateinit var vSeekBarShortNumber: SeekBar
private lateinit var vSwitchTheme: SwitchCompat
private lateinit var vRadioGroupLanguage: RadioGroup
private var spinnerSelectVoice: String = ""
private val languageRadioMap: Map<String, Int> = mapOf(
"en" to R.id.radioLanguageEn,
"bg" to R.id.radioLanguageBg,
"cs" to R.id.radioLanguageCs,
"da" to R.id.radioLanguageDa,
"de" to R.id.radioLanguageDe,
"el" to R.id.radioLanguageEl,
"es" to R.id.radioLanguageEs,
"et" to R.id.radioLanguageEt,
"fi" to R.id.radioLanguageFi,
"fr" to R.id.radioLanguageFr,
"hu" to R.id.radioLanguageHu,
"it" to R.id.radioLanguageIt,
"ja" to R.id.radioLanguageJa,
"ko" to R.id.radioLanguageKo,
"lt" to R.id.radioLanguageLt,
"lv" to R.id.radioLanguageLv,
"nl" to R.id.radioLanguageNl,
"pl" to R.id.radioLanguagePl,
"pt" to R.id.radioLanguagePt,
"ro" to R.id.radioLanguageRo,
"ru" to R.id.radioLanguageRu,
"sk" to R.id.radioLanguageSk,
"sv" to R.id.radioLanguageSv,
"th" to R.id.radioLanguageTh,
"zh" to R.id.radioLanguageZh,
"" to R.id.radioLanguageSystem
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_setting)
supportActionBar?.hide()
// ビューの初期化
vTextCancel = findViewById(R.id.textCancel)
vTextApply = findViewById(R.id.textApply)
vSwitchSpeechNumber = findViewById(R.id.switchSpeechNumber)
vSpinnerVoice = findViewById(R.id.spinnerVoice)
vSeekBarShortNumber = findViewById(R.id.seekBarShortNumber)
vSwitchTheme = findViewById(R.id.switchTheme)
vRadioGroupLanguage = findViewById(R.id.radioGroupLanguage)
// データ受け取りとUIの初期化
this.setupUIFromIntent()
// イベントリスナー
vTextCancel.setOnClickListener { this.onClickCancel() }
vTextApply.setOnClickListener { this.onClickApply() }
}
private fun setupUIFromIntent() {
val intent = this.intent
vSwitchSpeechNumber.isChecked = intent.getIntExtra(ConstValue.SPEECH_NUMBER, 0) != 0
vSeekBarShortNumber.progress = intent.getIntExtra(ConstValue.SHORT_NUMBER, 0)
vSwitchTheme.isChecked = intent.getIntExtra(ConstValue.THEME_NUMBER, 0) != 0
val localeLanguage = intent.getStringExtra(ConstValue.LOCALE_LANGUAGE).orEmpty()
languageRadioMap[localeLanguage]?.let { radioId ->
findViewById<RadioButton>(radioId).isChecked = true
}
val speechVoice = intent.getStringExtra(ConstValue.SPEECH_VOICE).orEmpty()
val speechVoices = intent.getStringArrayListExtra(ConstValue.SPEECH_VOICES) ?: arrayListOf()
this.setupSpinnerVoice(speechVoice, speechVoices)
}
private fun setupSpinnerVoice(speechVoice: String, speechVoices: ArrayList<String>) {
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, speechVoices)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
vSpinnerVoice.adapter = adapter
// スピナー選択イベント
vSpinnerVoice.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val selectedValue = parent?.getItemAtPosition(position) as String
spinnerSelectVoice = selectedValue.split(" ").getOrNull(1).orEmpty()
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
// 初期選択を設定
val initialIndex = speechVoices.indexOfFirst { it.contains(speechVoice) }
if (initialIndex >= 0) {
vSpinnerVoice.setSelection(initialIndex)
}
}
private fun onClickApply() {
val speechNumber = if (vSwitchSpeechNumber.isChecked) 1 else 0
val shortNumber = vSeekBarShortNumber.progress
val themeNumber = if (vSwitchTheme.isChecked) 1 else 0
val localeLanguage = languageRadioMap.entries.find {
findViewById<RadioButton>(it.value).isChecked
}?.key.orEmpty()
val intent = Intent().apply {
putExtra(ConstValue.SPEECH_NUMBER, speechNumber)
putExtra(ConstValue.SPEECH_VOICE, spinnerSelectVoice)
putExtra(ConstValue.SHORT_NUMBER, shortNumber)
putExtra(ConstValue.THEME_NUMBER, themeNumber)
putExtra(ConstValue.LOCALE_LANGUAGE, localeLanguage)
}
setResult(Activity.RESULT_OK, intent)
finish()
}
private fun onClickCancel() {
setResult(Activity.RESULT_CANCELED)
finish()
}
// 言語設定
override fun attachBaseContext(base: Context) {
val pref = base.getSharedPreferences(ConstValue.SETTINGS, Context.MODE_PRIVATE)
val localeLanguage = pref.getString(ConstValue.LOCALE_LANGUAGE, "").orEmpty()
if (localeLanguage.isNotEmpty() && this.isValidLocale(localeLanguage)) {
val locale = Locale(localeLanguage)
val config = Configuration(base.resources.configuration)
val localeList = LocaleList(locale)
LocaleList.setDefault(localeList)
config.setLocales(localeList)
super.attachBaseContext(base.createConfigurationContext(config))
} else {
super.attachBaseContext(base)
}
}
private fun isValidLocale(languageCode: String): Boolean {
return Locale.getAvailableLocales().any { it.language == languageCode }
}
}
app/src/main/java/jp/aosystem/roulettewheel/ConstValue.kt
package jp.aosystem.roulettewheel
object ConstValue {
internal const val AD_UNIT_ID: String = "ca-app-pub-0000000000000000/0000000000"
internal const val SETTINGS: String = "settings"
internal const val SPEECH_NUMBER: String = "speechNumber"
internal const val SPEECH_VOICE: String = "speechVoice"
internal const val SPEECH_VOICES: String = "speechVoices"
internal const val SHORT_NUMBER: String = "shortNumber"
internal const val THEME_NUMBER: String = "themeNumber"
internal const val LOCALE_LANGUAGE: String = "localeLanguage"
}