app/src/main/java/jp/aosystem/whichisbettervalue/MainActivity.kt
package jp.aosystem.whichisbettervalue
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Shader
import android.os.Build
import android.os.Bundle
import android.os.LocaleList
import android.text.Editable
import android.text.TextWatcher
import android.util.DisplayMetrics
import android.view.View
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.view.inputmethod.InputMethodManager
import android.widget.Chronometer
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
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 jp.aosystem.whichisbettervalue.databinding.ActivityMainBinding
import java.util.*
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: ConstraintLayout
private var inputMethodManager: InputMethodManager? = null
//
private val resourceImgCat: List<Int> = listOf(
R.drawable.ic_cat1,
R.drawable.ic_cat2,
R.drawable.ic_cat3,
R.drawable.ic_cat4,
R.drawable.ic_cat5,
R.drawable.ic_cat6,
R.drawable.ic_cat7,
)
private lateinit var textResult: TextView
private var baseWidth: Int = 0
private var baseHeight: Int = 0
private var boxSize: Int = 0
private var marginLeft: Int = 0
private var marginTop: Int = 0
private var destroyFlag: Boolean = false //Activity破棄された場合など
private var busyFlag: Boolean = false //回転中
private var themeNumber: Int = 0
private var localeLanguage: String = ""
private lateinit var chronometer: Chronometer //経過時間tick
private var chronometerSecond: Int = 0 //経過時間秒
//adMob
private lateinit var adView: AdView //adMob
private val adSize: AdSize
get() {
val display = windowManager.defaultDisplay
val outMetrics = DisplayMetrics()
display.getMetrics(outMetrics)
val density = outMetrics.density
var adWidthPixels = this.binding.adContainer.width.toFloat()
if (adWidthPixels == 0f) {
adWidthPixels = outMetrics.widthPixels.toFloat()
}
val adWidth = (adWidthPixels / density).toInt()
return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(this, adWidth)
}
companion object {
//private const val AD_UNIT_ID: String = "ca-app-pub-3940256099942544/6300978111" //adMob Test
private const val AD_UNIT_ID: String = "ca-app-pub-0000000000000000/0000000000" //adMob
internal const val RESULT_ERASE: Int = 9
private const val RESULT_SETTING_ACTIVITY: Int = 1
internal const val SETTINGS: String = "settings"
internal const val THEME_NUMBER: String = "themeNumber"
internal const val LOCALE_LANGUAGE: String = "localeLanguage"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
this.binding = ActivityMainBinding.inflate(layoutInflater)
this.viewModel = this.binding.root
setContentView(this.viewModel)
//タイトルバー非表示
supportActionBar?.hide()
//テーマ読み込みと設定
this.loadThemeNumber()
this.setTheme()
//adMob
MobileAds.initialize(this) {}
this.adView = AdView(this)
this.binding.adContainer.addView(this.adView)
this.loadBanner()
//背景画像
val d = ContextCompat.getDrawable(this, R.drawable.ic_back)
this.binding.imageBack.setImageDrawable(d?.let { TileDrawable(it, Shader.TileMode.REPEAT) })
//背景タッチでテキストエリアからフォーカスを外してキーボードを隠す
this.setTouchListener()
}
override fun onResume() {
super.onResume()
//準備が出来たらwidth,heightを取得して次へ進む
this.binding.layoutBase.viewTreeObserver.addOnGlobalLayoutListener(object :
OnGlobalLayoutListener {
override fun onGlobalLayout() {
this@MainActivity.binding.layoutBase.viewTreeObserver.removeOnGlobalLayoutListener(
this
)
this@MainActivity.baseWidth = this@MainActivity.binding.layoutBase.width
this@MainActivity.baseHeight = this@MainActivity.binding.layoutBase.height
this@MainActivity.init()
}
})
}
override fun onDestroy() {
this.destroyFlag = true
super.onDestroy()
}
//adMob
private fun loadBanner() {
this.adView.adUnitId = AD_UNIT_ID
this.adView.adSize = adSize
val adRequest = AdRequest
.Builder()
//.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build()
this.adView.loadAd(adRequest)
}
//背景タッチでテキストエリアからフォーカスを外してキーボードを隠す
private fun setTouchListener() {
this.inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
this.binding.editNet1.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
this.inputMethodManager!!.hideSoftInputFromWindow( //キーボードを隠す
this.binding.editNet1.windowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}
}
this.binding.editNet2.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
this.inputMethodManager!!.hideSoftInputFromWindow( //キーボードを隠す
this.binding.editNet2.windowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}
}
this.binding.editPrice1.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
this.inputMethodManager!!.hideSoftInputFromWindow( //キーボードを隠す
this.binding.editPrice1.windowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}
}
this.binding.editPrice2.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
this.inputMethodManager!!.hideSoftInputFromWindow( //キーボードを隠す
this.binding.editPrice2.windowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}
}
}
private fun init() {
this.boxSize = minOf(this.baseWidth, this.baseHeight)
this.marginLeft = (this.baseWidth - this.boxSize).div(2)
this.marginTop = (this.baseHeight - this.boxSize).div(2)
//
this.chronometer = Chronometer(this)
this.chronometer.onChronometerTickListener = Chronometer.OnChronometerTickListener {
this.chronometerSecond += 1
if (this.chronometerSecond % 5 == 0) {
val num: Int = this.chronometerSecond % this.resourceImgCat.size
this.binding.imageCenter.setImageResource(this.resourceImgCat[num])
}
}
this.chronometer.setTextColor(Color.TRANSPARENT)
this.chronometer.textSize = 1F
this.binding.layoutBase.addView(this.chronometer) //addViewしないとonChronometerTickListenerが呼ばれない
this.chronometer.start()
//this.chronometer.stop()
//
this.setTextChangeListener()
this.calcUnitPrice()
}
private fun setTextChangeListener() {
this.binding.editNet1.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
this@MainActivity.calcUnitPrice()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
this.binding.editNet2.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
this@MainActivity.calcUnitPrice()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
this.binding.editPrice1.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
this@MainActivity.calcUnitPrice()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
this.binding.editPrice2.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
this@MainActivity.calcUnitPrice()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
}
private fun calcUnitPrice() {
val net1: Float = ("0" + this.binding.editNet1.text.toString()).toFloat()
val price1: Float = ("0" + this.binding.editPrice1.text.toString()).toFloat()
val net2: Float = ("0" + this.binding.editNet2.text.toString()).toFloat()
val price2: Float = ("0" + this.binding.editPrice2.text.toString()).toFloat()
var unitPrice1: Float = 0F
var unitPrice2: Float = 0F
if (net1 != 0F) {
unitPrice1 = price1.div(net1)
}
if (net2 != 0F) {
unitPrice2 = price2.div(net2)
}
this.binding.textUnitPrice1.text = if (unitPrice1 == 0F) "" else String.format("%.2f",unitPrice1)
this.binding.textUnitPrice2.text = if (unitPrice2 == 0F) "" else String.format("%.2f",unitPrice2)
if (unitPrice1 < unitPrice2 && unitPrice1 != 0F) {
this.binding.tableRowUnitPrice1.alpha = 1F
} else {
this.binding.tableRowUnitPrice1.alpha = 0.6F
}
if (unitPrice2 < unitPrice1 && unitPrice2 != 0F) {
this.binding.tableRowUnitPrice2.alpha = 1F
} else {
this.binding.tableRowUnitPrice2.alpha = 0.6F
}
}
//----------------------------------------------
fun onClickSetting(v: View) {
if (this.busyFlag) {
return
}
this.destroyFlag = true
val intent = Intent(applicationContext, SettingActivity::class.java)
intent.putExtra(THEME_NUMBER, this.themeNumber)
intent.putExtra(LOCALE_LANGUAGE, this.localeLanguage)
startActivityForResult(intent, RESULT_SETTING_ACTIVITY)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
if (resultCode == Activity.RESULT_OK && requestCode == RESULT_SETTING_ACTIVITY && intent != null) {
val lastThemeNumber = this.themeNumber
this.themeNumber = intent.getIntExtra(THEME_NUMBER, 0)
if (lastThemeNumber != this.themeNumber) {
this.saveThemeNumber()
}
val lastLocaleLanguage = this.localeLanguage
this.localeLanguage = intent.getStringExtra(LOCALE_LANGUAGE) ?: ""
if (this.localeLanguage != lastLocaleLanguage) {
this.saveLocaleLanguage()
}
} else if (resultCode == MainActivity.RESULT_ERASE && requestCode == RESULT_SETTING_ACTIVITY && intent != null) {
this.binding.editNet1.setText("")
this.binding.editPrice1.setText("")
this.binding.editNet2.setText("")
this.binding.editPrice2.setText("")
}
recreate()
}
//----------------------------------------------
//テーマを保存
private fun saveThemeNumber() {
getSharedPreferences(SETTINGS, Context.MODE_PRIVATE).edit().apply {
putInt(THEME_NUMBER, this@MainActivity.themeNumber)
apply()
}
}
//テーマを読み出し
private fun loadThemeNumber() {
val pref = getSharedPreferences(SETTINGS, Context.MODE_PRIVATE)
this.themeNumber = pref.getInt(THEME_NUMBER, 0)
}
//テーマを設定
private fun setTheme() {
when (this.themeNumber) {
0 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
1 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
//--------------------------------------------------------------------------------
//localeLanguageを保存
private fun saveLocaleLanguage() {
getSharedPreferences(SETTINGS, Context.MODE_PRIVATE).edit().apply {
putString(LOCALE_LANGUAGE, this@MainActivity.localeLanguage)
apply()
}
}
//言語設定
override fun attachBaseContext(base: Context) {
val pref = base.getSharedPreferences(SETTINGS, Context.MODE_PRIVATE)
this.localeLanguage = pref.getString(LOCALE_LANGUAGE, "") ?: ""
val loc: Locale? = if (this.localeLanguage != "") Locale(this.localeLanguage) else null
if (loc != null) {
val res = base.resources
val config = Configuration(res.configuration)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //minSdkVersion 24
val localeList = LocaleList(loc)
LocaleList.setDefault(localeList)
config.setLocales(localeList)
} else { //minSdkVersion 17 16はダメ
config.setLocale(loc)
}
super.attachBaseContext(base.createConfigurationContext(config))
} else {
super.attachBaseContext(base)
}
}
//----------------------------------------------
}
app/src/main/java/jp/aosystem/whichisbettervalue/SettingActivity.kt
package jp.aosystem.whichisbettervalue
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.os.LocaleList
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import jp.aosystem.whichisbettervalue.databinding.ActivitySettingBinding
import java.util.*
class SettingActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingBinding
private lateinit var viewModel: ConstraintLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
this.binding = ActivitySettingBinding.inflate(layoutInflater)
this.viewModel = this.binding.root
setContentView(this.viewModel)
//データ受け取り
val intent = this.intent
val themeNumber: Int = intent.getIntExtra(MainActivity.THEME_NUMBER,0)
this.binding.switchTheme.isChecked = themeNumber != 0
val localeLanguage: String = intent.getStringExtra(MainActivity.LOCALE_LANGUAGE) ?: ""
when (localeLanguage) {
"en" -> this.binding.radioLanguageEn.isChecked = true
"ja" -> this.binding.radioLanguageJa.isChecked = true
else -> this.binding.radioLanguageSystem.isChecked = true
}
//
supportActionBar?.hide() //タイトルバー非表示
}
fun onClickApply(v: View) {
val themeNumber = if (this.binding.switchTheme.isChecked) 1 else 0
var localeLanguage: String = ""
if (this.binding.radioLanguageEn.isChecked) {
localeLanguage = "en"
} else if (this.binding.radioLanguageJa.isChecked) {
localeLanguage = "ja"
}
val intent = Intent()
intent.putExtra(MainActivity.THEME_NUMBER, themeNumber)
intent.putExtra(MainActivity.LOCALE_LANGUAGE, localeLanguage)
setResult(Activity.RESULT_OK, intent)
finish()
}
fun onClickCancel(v: View) {
val intent = Intent()
setResult(Activity.RESULT_CANCELED, intent)
finish()
}
fun onClickErase(v: View) {
val intent = Intent()
setResult(MainActivity.RESULT_ERASE, intent)
finish()
}
//--------------------------------------------------------------------------------
//言語設定
override fun attachBaseContext(base: Context) {
val pref = base.getSharedPreferences(MainActivity.SETTINGS, Context.MODE_PRIVATE)
val localeLanguage: String = pref.getString(MainActivity.LOCALE_LANGUAGE, "") ?: ""
val loc: Locale? = if (localeLanguage != "") Locale(localeLanguage) else null
if (loc != null) {
val res = base.resources
val config = Configuration(res.configuration)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //minSdkVersion 24
val localeList = LocaleList(loc)
LocaleList.setDefault(localeList)
config.setLocales(localeList)
} else { //minSdkVersion 17 16はダメ
config.setLocale(loc)
}
super.attachBaseContext(base.createConfigurationContext(config))
} else {
super.attachBaseContext(base)
}
}
//--------------------------------------------------------------------------------
}
app/src/main/java/jp/aosystem/whichisbettervalue/TileDrawable.kt
package jp.aosystem.whichisbettervalue
import android.graphics.Bitmap
import android.graphics.BitmapShader
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Shader
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
class TileDrawable(drawable: Drawable, tileMode: Shader.TileMode) : Drawable() {
private val paint: Paint
init {
paint = Paint().apply {
shader = BitmapShader(getBitmap(drawable), tileMode, tileMode)
}
}
override fun draw(canvas: Canvas) {
canvas.drawPaint(paint)
}
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
}
override fun getOpacity() = PixelFormat.TRANSLUCENT
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
}
private fun getBitmap(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable) {
return drawable.bitmap
}
val bmp = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight,
Bitmap.Config.ARGB_8888)
val c = Canvas(bmp)
drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
drawable.draw(c)
return bmp
}
}