Add downloadable fonts
This commit is contained in:
parent
b7bc93e174
commit
6ab8e40d45
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
@ -122,4 +122,7 @@ dependencies {
|
||||
|
||||
// Permissions
|
||||
implementation 'com.karumi:dexter:6.1.0'
|
||||
|
||||
// Fonts
|
||||
implementation 'com.github.firatkarababa:downloadable-font-list-library:1.0.2'
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.CustomFontActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
|
@ -8,6 +8,9 @@ object Constants {
|
||||
const val RESULT_APP_PACKAGE = "RESULT_APP_PACKAGE"
|
||||
|
||||
const val CUSTOM_FONT_GOOGLE_SANS = 1
|
||||
const val CUSTOM_FONT_DOWNLOADED = 2
|
||||
const val CUSTOM_FONT_DOWNLOAD_NEW = 3
|
||||
|
||||
enum class ClockBottomMargin(val value: Int) {
|
||||
NONE(0),
|
||||
SMALL(1),
|
||||
|
@ -92,7 +92,8 @@ object Preferences : KotprefModel() {
|
||||
var showOnlyBusyEvents by booleanPref(default = false)
|
||||
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 0)
|
||||
var customFont by intPref(key = "PREF_CUSTOM_FONT", default = Constants.CUSTOM_FONT_GOOGLE_SANS)
|
||||
var customFontFile by stringPref(key = "PREF_CUSTOM_FONT_FILE")
|
||||
var customFontFile by stringPref(default = "")
|
||||
var customFontName by stringPref(default = "")
|
||||
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
||||
|
||||
var showDividers by booleanPref(default = true)
|
||||
|
@ -54,11 +54,12 @@ object SettingsStringHelper {
|
||||
}
|
||||
}
|
||||
|
||||
fun getCustomFontLabel(shadow: Int): Int {
|
||||
return when (shadow) {
|
||||
0 -> R.string.custom_font_subtitle_0
|
||||
1 -> R.string.custom_font_subtitle_1
|
||||
else -> R.string.custom_font_subtitle_1
|
||||
fun getCustomFontLabel(context: Context, font: Int): String {
|
||||
return when (font) {
|
||||
0 -> context.getString(R.string.custom_font_subtitle_0)
|
||||
Constants.CUSTOM_FONT_GOOGLE_SANS -> context.getString(R.string.custom_font_subtitle_1)
|
||||
Constants.CUSTOM_FONT_DOWNLOADED -> Preferences.customFontName
|
||||
else -> context.getString(R.string.custom_font_subtitle_1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,20 @@ package com.tommasoberlose.anotherwidget.helpers
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
||||
import android.graphics.Typeface
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.core.provider.FontRequest
|
||||
import androidx.core.provider.FontsContractCompat
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import kotlin.math.min
|
||||
|
||||
object WidgetHelper {
|
||||
class WidgetSizeProvider(
|
||||
@ -44,4 +54,37 @@ object WidgetHelper {
|
||||
width to second * factor
|
||||
}
|
||||
}
|
||||
|
||||
fun runWithCustomTypeface(context: Context, function: (typeface: Typeface?) -> Unit) {
|
||||
if (Preferences.customFontFile != "") {
|
||||
val request = FontRequest(
|
||||
"com.google.android.gms.fonts",
|
||||
"com.google.android.gms",
|
||||
Preferences.customFontFile,
|
||||
R.array.com_google_android_gms_fonts_certs
|
||||
)
|
||||
|
||||
val callback = object : FontsContractCompat.FontRequestCallback() {
|
||||
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||
function.invoke(typeface)
|
||||
}
|
||||
|
||||
override fun onTypefaceRequestFailed(reason: Int) {
|
||||
function.invoke(null)
|
||||
}
|
||||
}
|
||||
|
||||
val handlerThread = HandlerThread("generateView")
|
||||
handlerThread.start()
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare()
|
||||
}
|
||||
|
||||
Handler(handlerThread.looper).run {
|
||||
FontsContractCompat.requestFont(context, request, callback, this)
|
||||
}
|
||||
} else {
|
||||
function.invoke(null)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.provider.FontRequest
|
||||
import androidx.core.provider.FontsContractCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.chibatching.kotpref.blockingBulk
|
||||
import com.koolio.library.Font
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomFontBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomFontViewModel
|
||||
import kotlinx.android.synthetic.main.activity_choose_application.*
|
||||
import kotlinx.coroutines.*
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
import net.idik.lib.slimadapter.diff.DefaultDiffCallback
|
||||
|
||||
|
||||
class CustomFontActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var adapter: SlimAdapter
|
||||
private lateinit var viewModel: CustomFontViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java)
|
||||
val binding = DataBindingUtil.setContentView<ActivityCustomFontBinding>(
|
||||
this,
|
||||
R.layout.activity_custom_font
|
||||
)
|
||||
|
||||
list_view.setHasFixedSize(true)
|
||||
val mLayoutManager = LinearLayoutManager(this)
|
||||
list_view.layoutManager = mLayoutManager
|
||||
|
||||
adapter = SlimAdapter.create()
|
||||
adapter.enableDiff(object: DefaultDiffCallback() {
|
||||
override fun areItemsTheSame(oldItem: Any?, newItem: Any?): Boolean {
|
||||
return oldItem is Font && newItem is Font && oldItem.fontFamily == newItem.fontFamily
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: Any?, newItem: Any?): Boolean {
|
||||
return oldItem is Font && newItem is Font && oldItem.fontFamily == newItem.fontFamily
|
||||
}
|
||||
})
|
||||
adapter
|
||||
.register<Font>(R.layout.list_item) { item, injector ->
|
||||
injector
|
||||
.text(R.id.text, item.fontFamily)
|
||||
.with<TextView>(R.id.text) {
|
||||
val request = FontRequest(
|
||||
"com.google.android.gms.fonts",
|
||||
"com.google.android.gms",
|
||||
item.queryString,
|
||||
R.array.com_google_android_gms_fonts_certs
|
||||
)
|
||||
|
||||
|
||||
val callback = object : FontsContractCompat.FontRequestCallback() {
|
||||
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||
it.typeface = typeface
|
||||
it.isVisible = true
|
||||
|
||||
it.measure(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
}
|
||||
|
||||
override fun onTypefaceRequestFailed(reason: Int) {
|
||||
it.isVisible = false
|
||||
it.layoutParams = it.layoutParams.apply {
|
||||
height = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val handlerThread = HandlerThread(item.fontFamily)
|
||||
handlerThread.start()
|
||||
val mHandler = Handler(handlerThread.looper)
|
||||
FontsContractCompat.requestFont(this, request, callback, mHandler)
|
||||
}
|
||||
|
||||
injector.clicked(R.id.text) {
|
||||
saveFont(item)
|
||||
}
|
||||
}
|
||||
.attachTo(list_view)
|
||||
|
||||
setupListener()
|
||||
subscribeUi(binding, viewModel)
|
||||
|
||||
search.requestFocus()
|
||||
}
|
||||
|
||||
private var filterJob: Job? = null
|
||||
|
||||
private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) {
|
||||
binding.viewModel = viewModel
|
||||
|
||||
viewModel.fontList.observe(this, Observer {
|
||||
updateList(list = it)
|
||||
loader.visibility = View.INVISIBLE
|
||||
})
|
||||
|
||||
viewModel.searchInput.observe(this, Observer { search ->
|
||||
updateList(search = search)
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateList(
|
||||
list: ArrayList<Font>? = viewModel.fontList.value,
|
||||
search: String? = viewModel.searchInput.value
|
||||
) {
|
||||
loader.visibility = View.VISIBLE
|
||||
filterJob?.cancel()
|
||||
filterJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
if (list != null && list.isNotEmpty()) {
|
||||
delay(200)
|
||||
val filteredList: List<Font> = if (search == null || search == "") {
|
||||
list
|
||||
} else {
|
||||
list.filter {
|
||||
it.fontFamily.contains(search, true)
|
||||
}
|
||||
}.distinctBy { it.fontFamily }
|
||||
withContext(Dispatchers.Main) {
|
||||
adapter.updateData(filteredList)
|
||||
loader.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_back.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveFont(font: Font) {
|
||||
val resultIntent = Intent()
|
||||
Preferences.blockingBulk {
|
||||
customFont = Constants.CUSTOM_FONT_DOWNLOADED
|
||||
customFontName = font.fontFamily
|
||||
customFontFile = font.queryString
|
||||
}
|
||||
setResult(Activity.RESULT_OK, resultIntent)
|
||||
finish()
|
||||
}
|
||||
}
|
@ -3,16 +3,24 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.provider.FontRequest
|
||||
import androidx.core.provider.FontsContractCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.chibatching.kotpref.blockingBulk
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
@ -25,9 +33,13 @@ import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.CustomFontActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_general_settings.*
|
||||
@ -271,7 +283,15 @@ class GeneralTabFragment : Fragment() {
|
||||
|
||||
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
custom_font_label?.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
||||
custom_font_label?.text = SettingsStringHelper.getCustomFontLabel(requireContext(), it)
|
||||
MainWidget.updateWidget(requireContext())
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.customFontFile.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
custom_font_label?.text = SettingsStringHelper.getCustomFontLabel(requireContext(), Preferences.customFont)
|
||||
MainWidget.updateWidget(requireContext())
|
||||
}
|
||||
})
|
||||
|
||||
@ -455,10 +475,25 @@ class GeneralTabFragment : Fragment() {
|
||||
action_custom_font.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_custom_font_title)).setSelectedValue(Preferences.customFont)
|
||||
(0..1).forEach {
|
||||
dialog.addItem(getString(SettingsStringHelper.getCustomFontLabel(it)), it)
|
||||
dialog.addItem(SettingsStringHelper.getCustomFontLabel(requireContext(), it), it)
|
||||
}
|
||||
if (Preferences.customFontFile != "") {
|
||||
dialog.addItem(Preferences.customFontName, Constants.CUSTOM_FONT_DOWNLOADED)
|
||||
}
|
||||
dialog.addItem(getString(R.string.action_custom_font_to_search), Constants.CUSTOM_FONT_DOWNLOAD_NEW)
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
Preferences.customFont = value
|
||||
if (value == Constants.CUSTOM_FONT_DOWNLOAD_NEW) {
|
||||
startActivityForResult(
|
||||
Intent(requireContext(), CustomFontActivity::class.java),
|
||||
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code
|
||||
)
|
||||
} else if (value != Constants.CUSTOM_FONT_DOWNLOADED) {
|
||||
Preferences.bulk {
|
||||
customFont = value
|
||||
customFontFile = ""
|
||||
customFontName = ""
|
||||
}
|
||||
}
|
||||
}.show()
|
||||
|
||||
/*
|
||||
@ -487,15 +522,7 @@ class GeneralTabFragment : Fragment() {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
when (requestCode) {
|
||||
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code -> {
|
||||
/*val uri = data.data
|
||||
Log.d("AW", "File Uri: " + uri.toString())
|
||||
val path = Util.getPath(this, uri)
|
||||
Log.d("AW", "File Path: " + path)
|
||||
SP.edit()
|
||||
.putString(Constants.PREF_CUSTOM_FONT_FILE, path)
|
||||
.commit()
|
||||
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
|
||||
updateSettings()*/
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
@ -147,133 +148,136 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
ColorHelper.getBackgroundColor(activity?.isDarkTheme() == true)
|
||||
)
|
||||
)
|
||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
val generatedView = MainWidget.generateWidgetView(requireContext())
|
||||
WidgetHelper.runWithCustomTypeface(requireContext()) { typeface ->
|
||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
val generatedView = MainWidget.generateWidgetView(requireContext(), typeface)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
generatedView.measure(0, 0)
|
||||
preview?.measure(0, 0)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
generatedView.measure(0, 0)
|
||||
preview?.measure(0, 0)
|
||||
}
|
||||
|
||||
val bitmap = if (preview != null) {
|
||||
BitmapHelper.getBitmapFromView(
|
||||
generatedView,
|
||||
if (preview.width > 0) preview.width else generatedView.measuredWidth,
|
||||
generatedView.measuredHeight
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
// Clock
|
||||
time?.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||
time_am_pm?.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||
time?.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext())
|
||||
)
|
||||
time_am_pm?.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
||||
)
|
||||
time_am_pm?.isVisible = Preferences.showAMPMIndicator
|
||||
val bitmap = if (preview != null) {
|
||||
BitmapHelper.getBitmapFromView(
|
||||
generatedView,
|
||||
if (preview.width > 0) preview.width else generatedView.measuredWidth,
|
||||
generatedView.measuredHeight
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
// Clock
|
||||
time?.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||
time_am_pm?.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||
time?.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext())
|
||||
)
|
||||
time_am_pm?.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
||||
)
|
||||
time_am_pm?.isVisible = Preferences.showAMPMIndicator
|
||||
|
||||
// Clock bottom margin
|
||||
clock_bottom_margin_none?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
|
||||
clock_bottom_margin_small?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
|
||||
clock_bottom_margin_medium?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
|
||||
clock_bottom_margin_large?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
|
||||
// Clock bottom margin
|
||||
clock_bottom_margin_none?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
|
||||
clock_bottom_margin_small?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
|
||||
clock_bottom_margin_medium?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
|
||||
clock_bottom_margin_large?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
|
||||
|
||||
if ((Preferences.showClock && (time?.alpha ?: 1f < 1f)) || (!Preferences.showClock && (time?.alpha ?: 0f > 0f))) {
|
||||
if (Preferences.showClock) {
|
||||
if ((Preferences.showClock && (time?.alpha ?: 1f < 1f)) || (!Preferences.showClock && (time?.alpha ?: 0f > 0f))) {
|
||||
if (Preferences.showClock) {
|
||||
time_container?.layoutParams = time_container.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
time_container?.measure(0, 0)
|
||||
}
|
||||
val initialHeight = time_container?.measuredHeight ?: 0
|
||||
ValueAnimator.ofFloat(
|
||||
if (Preferences.showClock) 0f else 1f,
|
||||
if (Preferences.showClock) 1f else 0f
|
||||
).apply {
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Float
|
||||
time_container?.layoutParams =
|
||||
time_container.layoutParams.apply {
|
||||
height = (initialHeight * animatedValue).toInt()
|
||||
}
|
||||
time?.alpha = animatedValue
|
||||
}
|
||||
addListener(
|
||||
onStart = {
|
||||
if (Preferences.showClock) {
|
||||
time_container?.isVisible = true
|
||||
}
|
||||
},
|
||||
onEnd = {
|
||||
if (!Preferences.showClock) {
|
||||
time_container?.isVisible = false
|
||||
}
|
||||
}
|
||||
)
|
||||
}.start()
|
||||
|
||||
if (preview != null) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
if (preview != null) {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
} else {
|
||||
time_container?.layoutParams = time_container.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
time_container?.measure(0, 0)
|
||||
}
|
||||
val initialHeight = time_container?.measuredHeight ?: 0
|
||||
ValueAnimator.ofFloat(
|
||||
if (Preferences.showClock) 0f else 1f,
|
||||
if (Preferences.showClock) 1f else 0f
|
||||
).apply {
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Float
|
||||
time_container?.layoutParams =
|
||||
time_container.layoutParams.apply {
|
||||
height = (initialHeight * animatedValue).toInt()
|
||||
}
|
||||
time?.alpha = animatedValue
|
||||
}
|
||||
addListener(
|
||||
onStart = {
|
||||
if (Preferences.showClock) {
|
||||
time_container?.isVisible = true
|
||||
}
|
||||
},
|
||||
onEnd = {
|
||||
if (!Preferences.showClock) {
|
||||
time_container?.isVisible = false
|
||||
}
|
||||
}
|
||||
)
|
||||
}.start()
|
||||
|
||||
if (preview != null) {
|
||||
if (preview != null && preview.height == 0) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
duration = 500L
|
||||
duration = 300L
|
||||
addUpdateListener {
|
||||
if (preview != null) {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
preview?.layoutParams = layoutParams
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
} else {
|
||||
time_container?.layoutParams = time_container.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
|
||||
widget_loader?.animate()?.scaleX(0f)?.scaleY(0f)?.alpha(0f)
|
||||
?.setDuration(200L)?.start()
|
||||
bitmap_container?.apply {
|
||||
setImageBitmap(bitmap)
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
}
|
||||
time_container?.measure(0, 0)
|
||||
widget?.animate()?.alpha(1f)?.start()
|
||||
}
|
||||
|
||||
if (preview != null && preview.height == 0) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
duration = 300L
|
||||
addUpdateListener {
|
||||
if (preview != null) {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview?.layoutParams = layoutParams
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
widget_loader?.animate()?.scaleX(0f)?.scaleY(0f)?.alpha(0f)?.setDuration(200L)?.start()
|
||||
bitmap_container?.apply {
|
||||
setImageBitmap(bitmap)
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
}
|
||||
widget?.animate()?.alpha(1f)?.start()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -0,0 +1,39 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.content.pm.ResolveInfo
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.koolio.library.DownloadableFontList
|
||||
import com.koolio.library.Font
|
||||
import com.koolio.library.FontList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class CustomFontViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
val fontList: MutableLiveData<ArrayList<Font>> = MutableLiveData()
|
||||
val searchInput: MutableLiveData<String> = MutableLiveData("")
|
||||
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
|
||||
|
||||
val fontListCallback: DownloadableFontList.FontListCallback =
|
||||
object : DownloadableFontList.FontListCallback {
|
||||
override fun onFontListRetrieved(downloadedList: FontList?) {
|
||||
fontList.postValue(downloadedList?.fontArrayList)
|
||||
}
|
||||
|
||||
override fun onTypefaceRequestFailed(reason: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DownloadableFontList.requestDownloadableFontList(fontListCallback, "AIzaSyCT_v2Qw1zCWfmc_ywsovj_4poSXr7k5f0")
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ class MainViewModel : ViewModel() {
|
||||
val textShadow = Preferences.asLiveData(Preferences::textShadow)
|
||||
val textShadowDark = Preferences.asLiveData(Preferences::textShadowDark)
|
||||
val customFont = Preferences.asLiveData(Preferences::customFont)
|
||||
val customFontFile = Preferences.asLiveData(Preferences::customFontFile)
|
||||
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
|
||||
val showDividers = Preferences.asLiveData(Preferences::showDividers)
|
||||
val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin)
|
||||
|
@ -11,12 +11,18 @@ import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.Looper
|
||||
import android.text.format.DateUtils
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.provider.FontRequest
|
||||
import androidx.core.provider.FontsContractCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
@ -90,10 +96,14 @@ class MainWidget : AppWidgetProvider() {
|
||||
val height = displayMetrics.heightPixels
|
||||
|
||||
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)))
|
||||
|
||||
WidgetHelper.runWithCustomTypeface(context) {
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
|
||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int, typeface: Typeface? = null) {
|
||||
|
||||
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
|
||||
|
||||
try {
|
||||
@ -125,7 +135,8 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
// Setup listener
|
||||
try {
|
||||
val generatedView = generateWidgetView(context)
|
||||
|
||||
val generatedView = generateWidgetView(context, typeface)
|
||||
views.setImageViewBitmap(
|
||||
R.id.bitmap_container,
|
||||
BitmapHelper.getBitmapFromView(generatedView, width = w)
|
||||
@ -492,7 +503,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
|
||||
// Generates the widget bitmap from the view
|
||||
fun generateWidgetView(context: Context): View {
|
||||
fun generateWidgetView(context: Context, typeface: Typeface? = null): View {
|
||||
val eventRepository = EventRepository(context)
|
||||
val v = View.inflate(context, R.layout.the_widget, null)
|
||||
|
||||
@ -514,8 +525,10 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||
// Multiple counter
|
||||
v.action_next.isVisible = Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||
v.action_previous.isVisible = Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||
v.action_next.isVisible =
|
||||
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||
v.action_previous.isVisible =
|
||||
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||
|
||||
v.next_event.text = nextEvent.title
|
||||
|
||||
@ -528,7 +541,11 @@ class MainWidget : AppWidgetProvider() {
|
||||
)
|
||||
.toLowerCase(Locale.getDefault())
|
||||
} else {
|
||||
SettingsStringHelper.getAllDayEventDifferenceText(context, now.timeInMillis, nextEvent.startDate).toLowerCase(Locale.getDefault())
|
||||
SettingsStringHelper.getAllDayEventDifferenceText(
|
||||
context,
|
||||
now.timeInMillis,
|
||||
nextEvent.startDate
|
||||
).toLowerCase(Locale.getDefault())
|
||||
}
|
||||
v.next_event_difference_time.visibility = View.VISIBLE
|
||||
} else {
|
||||
@ -536,15 +553,30 @@ class MainWidget : AppWidgetProvider() {
|
||||
}
|
||||
|
||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
||||
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.round_place))
|
||||
v.second_row_icon.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.round_place
|
||||
)
|
||||
)
|
||||
v.next_event_date.text = nextEvent.address
|
||||
} else {
|
||||
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.round_today))
|
||||
v.second_row_icon.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.round_today
|
||||
)
|
||||
)
|
||||
if (!nextEvent.allDay) {
|
||||
val startHour = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(nextEvent.startDate)
|
||||
val endHour = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(nextEvent.endDate)
|
||||
val startHour =
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
|
||||
.format(nextEvent.startDate)
|
||||
val endHour =
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
|
||||
.format(nextEvent.endDate)
|
||||
|
||||
var dayDiff = TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
|
||||
var dayDiff =
|
||||
TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
|
||||
|
||||
val startCal = Calendar.getInstance()
|
||||
startCal.timeInMillis = nextEvent.startDate
|
||||
@ -554,31 +586,46 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
|
||||
dayDiff++
|
||||
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(Calendar.MINUTE) >= endCal.get(Calendar.MINUTE)) {
|
||||
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
|
||||
Calendar.MINUTE
|
||||
) >= endCal.get(Calendar.MINUTE)
|
||||
) {
|
||||
dayDiff++
|
||||
}
|
||||
var multipleDay = ""
|
||||
if (dayDiff > 0) {
|
||||
multipleDay = String.format(" (+%s%s)", dayDiff, context.getString(R.string.day_char))
|
||||
multipleDay = String.format(
|
||||
" (+%s%s)",
|
||||
dayDiff,
|
||||
context.getString(R.string.day_char)
|
||||
)
|
||||
}
|
||||
v.next_event_date.text = String.format("%s - %s%s", startHour, endHour, multipleDay)
|
||||
v.next_event_date.text =
|
||||
String.format("%s - %s%s", startHour, endHour, multipleDay)
|
||||
|
||||
} else {
|
||||
val flags: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
v.next_event_date.text = DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
||||
val flags: Int =
|
||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
v.next_event_date.text =
|
||||
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
||||
}
|
||||
}
|
||||
|
||||
v.empty_layout.visibility = View.GONE
|
||||
v.calendar_layout.visibility = View.VISIBLE
|
||||
|
||||
v.second_row_top_margin_small.visibility = if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_medium.visibility = if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_large.visibility = if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_small.visibility =
|
||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_medium.visibility =
|
||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_large.visibility =
|
||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||
v.second_row_icon.isVisible = true
|
||||
var showSomething = false
|
||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
||||
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(
|
||||
context
|
||||
)) {
|
||||
when (provider) {
|
||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||
@ -613,9 +660,13 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.second_row_icon.isVisible = false
|
||||
val batteryLevel = BatteryHelper.getBatteryLevel(context)
|
||||
if (batteryLevel == 100) {
|
||||
v.next_event_date.text = "%s - %d%%".format(context.getString(R.string.charging), batteryLevel)
|
||||
v.next_event_date.text = "%s - %d%%".format(
|
||||
context.getString(R.string.charging),
|
||||
batteryLevel
|
||||
)
|
||||
} else {
|
||||
v.next_event_date.text = context.getString(R.string.charging)
|
||||
v.next_event_date.text =
|
||||
context.getString(R.string.charging)
|
||||
}
|
||||
showSomething = true
|
||||
break@loop
|
||||
@ -641,7 +692,9 @@ class MainWidget : AppWidgetProvider() {
|
||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
||||
v.second_row_icon.isVisible = false
|
||||
v.next_event_date.text = context.getString(R.string.daily_steps_counter).format(Preferences.googleFitSteps)
|
||||
v.next_event_date.text =
|
||||
context.getString(R.string.daily_steps_counter)
|
||||
.format(Preferences.googleFitSteps)
|
||||
showSomething = true
|
||||
break@loop
|
||||
}
|
||||
@ -654,9 +707,12 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.empty_layout.visibility = View.GONE
|
||||
v.calendar_layout.visibility = View.VISIBLE
|
||||
|
||||
v.second_row_top_margin_small.visibility = if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_medium.visibility = if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_large.visibility = if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_small.visibility =
|
||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_medium.visibility =
|
||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||
v.second_row_top_margin_large.visibility =
|
||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||
} else {
|
||||
v.second_row_icon.isVisible = false
|
||||
}
|
||||
@ -664,17 +720,33 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
|
||||
// Color
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.divider3, v.special_temp).forEach {
|
||||
listOf<TextView>(
|
||||
v.empty_date,
|
||||
v.divider1,
|
||||
v.temp,
|
||||
v.next_event,
|
||||
v.next_event_difference_time,
|
||||
v.divider3,
|
||||
v.special_temp
|
||||
).forEach {
|
||||
it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme()))
|
||||
}
|
||||
|
||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) {
|
||||
listOf<ImageView>(v.action_next, v.action_previous)
|
||||
} else {
|
||||
listOf<ImageView>(v.action_next, v.action_previous, v.empty_weather_icon, v.special_weather_icon)
|
||||
listOf<ImageView>(
|
||||
v.action_next,
|
||||
v.action_previous,
|
||||
v.empty_weather_icon,
|
||||
v.special_weather_icon
|
||||
)
|
||||
}.forEach {
|
||||
it.setColorFilter(ColorHelper.getFontColorRgb(context.applicationContext.isDarkTheme()))
|
||||
it.alpha = (if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue().toFloat() else Preferences.textGlobalAlpha.toIntValue().toFloat()) / 100
|
||||
it.alpha =
|
||||
(if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue()
|
||||
.toFloat() else Preferences.textGlobalAlpha.toIntValue()
|
||||
.toFloat()) / 100
|
||||
}
|
||||
|
||||
listOf<TextView>(v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
||||
@ -687,7 +759,10 @@ class MainWidget : AppWidgetProvider() {
|
||||
listOf<ImageView>(v.second_row_icon, v.weather_icon)
|
||||
}.forEach {
|
||||
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
|
||||
it.alpha = (if (context.isDarkTheme()) Preferences.textSecondaryAlphaDark.toIntValue().toFloat() else Preferences.textSecondaryAlpha.toIntValue().toFloat()) / 100
|
||||
it.alpha =
|
||||
(if (context.isDarkTheme()) Preferences.textSecondaryAlphaDark.toIntValue()
|
||||
.toFloat() else Preferences.textSecondaryAlpha.toIntValue()
|
||||
.toFloat()) / 100
|
||||
}
|
||||
|
||||
// Text Size
|
||||
@ -727,35 +802,76 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
|
||||
// Shadows
|
||||
val shadowRadius = when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||
0 -> 0f
|
||||
1 -> 5f
|
||||
2 -> 5f
|
||||
else -> 5f
|
||||
}
|
||||
val shadowColor = when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||
0 -> Color.TRANSPARENT
|
||||
1 -> R.color.black_50
|
||||
2 -> Color.BLACK
|
||||
else -> R.color.black_50
|
||||
}
|
||||
val shadowDy = when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||
0 -> 0f
|
||||
1 -> 0f
|
||||
2 -> 1f
|
||||
else -> 0f
|
||||
}
|
||||
val shadowRadius =
|
||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||
0 -> 0f
|
||||
1 -> 5f
|
||||
2 -> 5f
|
||||
else -> 5f
|
||||
}
|
||||
val shadowColor =
|
||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||
0 -> Color.TRANSPARENT
|
||||
1 -> R.color.black_50
|
||||
2 -> Color.BLACK
|
||||
else -> R.color.black_50
|
||||
}
|
||||
val shadowDy =
|
||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||
0 -> 0f
|
||||
1 -> 0f
|
||||
2 -> 1f
|
||||
else -> 0f
|
||||
}
|
||||
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp, v.divider3, v.special_temp).forEach {
|
||||
listOf<TextView>(
|
||||
v.empty_date,
|
||||
v.divider1,
|
||||
v.temp,
|
||||
v.next_event,
|
||||
v.next_event_difference_time,
|
||||
v.next_event_date,
|
||||
v.divider2,
|
||||
v.calendar_temp,
|
||||
v.divider3,
|
||||
v.special_temp
|
||||
).forEach {
|
||||
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
|
||||
}
|
||||
|
||||
// Custom Font
|
||||
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
|
||||
val googleSans: Typeface = Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf")
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp, v.divider3, v.special_temp).forEach {
|
||||
val googleSans: Typeface =
|
||||
Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf")
|
||||
listOf<TextView>(
|
||||
v.empty_date,
|
||||
v.divider1,
|
||||
v.temp,
|
||||
v.next_event,
|
||||
v.next_event_difference_time,
|
||||
v.next_event_date,
|
||||
v.divider2,
|
||||
v.calendar_temp,
|
||||
v.divider3,
|
||||
v.special_temp
|
||||
).forEach {
|
||||
it.typeface = googleSans
|
||||
}
|
||||
} else if (Preferences.customFont == Constants.CUSTOM_FONT_DOWNLOADED && typeface != null) {
|
||||
listOf<TextView>(
|
||||
v.empty_date,
|
||||
v.divider1,
|
||||
v.temp,
|
||||
v.next_event,
|
||||
v.next_event_difference_time,
|
||||
v.next_event_date,
|
||||
v.divider2,
|
||||
v.calendar_temp,
|
||||
v.divider3,
|
||||
v.special_temp
|
||||
).forEach {
|
||||
it.typeface = typeface
|
||||
}
|
||||
}
|
||||
|
||||
// Weather
|
||||
@ -763,7 +879,12 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.weather.visibility = View.VISIBLE
|
||||
v.calendar_weather.visibility = View.VISIBLE
|
||||
v.special_weather.visibility = View.VISIBLE
|
||||
val currentTemp = String.format(Locale.getDefault(), "%d °%s", Preferences.weatherTemp.roundToInt(), Preferences.weatherRealTempUnit)
|
||||
val currentTemp = String.format(
|
||||
Locale.getDefault(),
|
||||
"%d °%s",
|
||||
Preferences.weatherTemp.roundToInt(),
|
||||
Preferences.weatherRealTempUnit
|
||||
)
|
||||
|
||||
val icon: String = Preferences.weatherIcon
|
||||
if (icon == "") {
|
||||
@ -772,8 +893,16 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.special_weather_icon.visibility = View.GONE
|
||||
} else {
|
||||
v.weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.empty_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.special_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.empty_weather_icon.setImageResource(
|
||||
WeatherHelper.getWeatherIconResource(
|
||||
icon
|
||||
)
|
||||
)
|
||||
v.special_weather_icon.setImageResource(
|
||||
WeatherHelper.getWeatherIconResource(
|
||||
icon
|
||||
)
|
||||
)
|
||||
v.weather_icon.visibility = View.VISIBLE
|
||||
v.empty_weather_icon.visibility = View.VISIBLE
|
||||
v.special_weather_icon.visibility = View.VISIBLE
|
||||
|
113
app/src/main/res/layout/activity_custom_font.xml
Normal file
113
app/src/main/res/layout/activity_custom_font.xml
Normal file
@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout>
|
||||
<data>
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.tommasoberlose.anotherwidget.ui.viewmodels.CustomFontViewModel" />
|
||||
</data>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/colorPrimaryDark"
|
||||
tools:context="com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity">
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
android:id="@+id/toolbar"
|
||||
app:cardBackgroundColor="@color/colorPrimary">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="10dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_centerVertical="true"
|
||||
android:id="@+id/action_back"
|
||||
android:layout_alignParentLeft="true"
|
||||
app:tint="@color/colorPrimaryText"
|
||||
android:src="@drawable/round_arrow_back" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="@string/action_choose_application"
|
||||
android:gravity="center"
|
||||
style="@style/AnotherWidget.Main.Title"/>
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="10dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_centerVertical="true"
|
||||
android:id="@+id/action_filter"
|
||||
android:layout_alignParentRight="true"
|
||||
android:visibility="gone"
|
||||
app:tint="@color/colorPrimaryText"
|
||||
android:src="@drawable/round_filter_list" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:cardBackgroundColor="@color/colorPrimary">
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="@color/colorPrimaryDark"
|
||||
app:cardCornerRadius="9dp"
|
||||
app:cardElevation="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="16dp">
|
||||
<EditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="@color/colorPrimaryDark"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:inputType="textCapWords"
|
||||
android:textColor="@color/colorPrimaryText"
|
||||
android:textColorHint="@color/colorSecondaryText"
|
||||
android:textAlignment="viewStart"
|
||||
android:id="@+id/search"
|
||||
android:fontFamily="@font/google_sans"
|
||||
android:gravity="center_vertical|start"
|
||||
android:hint="@string/search"
|
||||
android:text="@={viewModel.searchInput}"
|
||||
android:autofillHints="" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateTint="@color/colorAccent"
|
||||
android:layout_marginTop="-7dp"
|
||||
android:id="@+id/loader"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/list_view" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</layout>
|
16
app/src/main/res/layout/list_item.xml
Normal file
16
app/src/main/res/layout/list_item.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingEnd="32dp"
|
||||
android:paddingStart="32dp"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:textColor="@color/colorPrimaryText"
|
||||
style="@style/AnotherWidget.Settings.Title"/>
|
@ -27,6 +27,7 @@
|
||||
<string name="settings_date_format_title">Formato data</string>
|
||||
<string name="header_widget_background">Sfondo widget</string>
|
||||
<string name="settings_secondary_row_top_margin_title">Margine</string>
|
||||
<string name="action_custom_font_to_search">Cerca font...</string>
|
||||
|
||||
<!-- Calendar -->
|
||||
<string name="settings_calendar_title">Calendario</string>
|
||||
|
29
app/src/main/res/values/font_certs.xml
Normal file
29
app/src/main/res/values/font_certs.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017 The Android Open Source Project
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<array name="com_google_android_gms_fonts_certs">
|
||||
<item>@array/com_google_android_gms_fonts_certs_dev</item>
|
||||
<item>@array/com_google_android_gms_fonts_certs_prod</item>
|
||||
</array>
|
||||
<string-array name="com_google_android_gms_fonts_certs_dev">
|
||||
<item>
|
||||
MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
|
||||
</item>
|
||||
</string-array>
|
||||
<string-array name="com_google_android_gms_fonts_certs_prod">
|
||||
<item>
|
||||
MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK
|
||||
</item>
|
||||
</string-array>
|
||||
</resources>
|
@ -29,6 +29,7 @@
|
||||
<string name="settings_date_format_title">Date format</string>
|
||||
<string name="header_widget_background">Widget background</string>
|
||||
<string name="settings_secondary_row_top_margin_title">Margin</string>
|
||||
<string name="action_custom_font_to_search">Custom font...</string>
|
||||
|
||||
<!-- Calendar -->
|
||||
<string name="settings_calendar_title">Calendar</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user