Clean and Refractor code.

Split up the `SettingsActivity` into the smaller Fragments, Rename many 
ids... overall cleaner code.

It is 03:56 am and I did not sleep yet... I won't today ^^
This commit is contained in:
Finn M Glas 2020-05-24 03:59:25 +02:00
parent ff72364983
commit 0eecdff99f
No known key found for this signature in database
GPG key ID: 25037A2E81AB459C
21 changed files with 530 additions and 406 deletions

View file

@ -10,6 +10,7 @@ import android.view.WindowManager
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.finnmglas.launcher.extern.*
import kotlinx.android.synthetic.main.activity_choose.* import kotlinx.android.synthetic.main.activity_choose.*
@ -33,19 +34,18 @@ class ChooseActivity : AppCompatActivity() {
setContentView(R.layout.activity_choose) setContentView(R.layout.activity_choose)
// As older APIs somehow do not recognize the xml defined onClick // As older APIs somehow do not recognize the xml defined onClick
close_chooser.setOnClickListener() { finish() } activity_choose_close.setOnClickListener() { finish() }
val bundle = intent.extras val bundle = intent.extras
val action = bundle!!.getString("action") // why choose an app val action = bundle!!.getString("action") // why choose an app
val forApp = bundle.getString("forApp") // which app we choose val forApp = bundle.getString("forApp") // which app we choose
if (action == "launch") if (action == "launch")
heading.text = getString(R.string.choose_title_launch) activity_choose_heading.text = getString(R.string.choose_title_launch)
else if (action == "pick") { else if (action == "pick")
heading.text = getString(R.string.choose_title) activity_choose_heading.text = getString(R.string.choose_title)
}
else if (action == "uninstall") else if (action == "uninstall")
heading.text = getString(R.string.choose_title_remove) activity_choose_heading.text = getString(R.string.choose_title_remove)
/* Build Layout */ /* Build Layout */
@ -78,10 +78,12 @@ class ChooseActivity : AppCompatActivity() {
val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE)
intent.data = Uri.parse("package:" + app.packageName) intent.data = Uri.parse("package:" + app.packageName)
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) intent.putExtra(Intent.EXTRA_RETURN_RESULT, true)
startActivityForResult(intent, REQUEST_UNINSTALL) startActivityForResult(intent,
REQUEST_UNINSTALL
)
} }
} }
apps_list.addView(tvdynamic) activity_choose_apps_list.addView(tvdynamic)
} }
} }

View file

@ -5,9 +5,10 @@ import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue import android.util.TypedValue
import android.view.* import android.view.*
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.finnmglas.launcher.extern.blink
import com.finnmglas.launcher.extern.getSavedTheme
import com.finnmglas.launcher.extern.resetSettings
import kotlinx.android.synthetic.main.activity_firststartup.* import kotlinx.android.synthetic.main.activity_firststartup.*
@ -40,7 +41,7 @@ class FirstStartupActivity : AppCompatActivity(){
) )
setContentView(R.layout.activity_firststartup) setContentView(R.layout.activity_firststartup)
hintText.blink() // animate activity_firststartup_hint_text.blink() // animate
loadMenu(this) loadMenu(this)
val sharedPref = this.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE) val sharedPref = this.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE)
@ -50,10 +51,10 @@ class FirstStartupActivity : AppCompatActivity(){
if (isFirstTime) if (isFirstTime)
defaultApps = resetSettings(sharedPref, this) // UP, DOWN, RIGHT, LEFT, VOLUME_UP, VOLUME_DOWN defaultApps = resetSettings(sharedPref, this) // UP, DOWN, RIGHT, LEFT, VOLUME_UP, VOLUME_DOWN
else else
app_bar.visibility = View.VISIBLE activity_firststartup_app_bar.visibility = View.VISIBLE
// As older APIs somehow do not recognize the xml defined onClick // As older APIs somehow do not recognize the xml defined onClick
close_tutorial.setOnClickListener() { finish() } activity_firststartup_close.setOnClickListener() { finish() }
} }
/** Touch- and Key-related functions to navigate */ /** Touch- and Key-related functions to navigate */
@ -92,14 +93,16 @@ class FirstStartupActivity : AppCompatActivity(){
if (menuNumber < intro.size){ if (menuNumber < intro.size){
val entry = intro[menuNumber].split("|").toTypedArray() //heading|infoText|hintText|size val entry = intro[menuNumber].split("|").toTypedArray() //heading|infoText|hintText|size
heading.text = entry[0] activity_firststartup_section_heading.text = entry[0]
if (entry[4] == "1" && isFirstTime)infoText.text = String.format(entry[1], if (entry[4] == "1" && isFirstTime)
activity_firststartup_descriptive_text.text = String.format(entry[1],
defaultApps[0], defaultApps[1], defaultApps[2], defaultApps[3], defaultApps[4], defaultApps[5]) defaultApps[0], defaultApps[1], defaultApps[2], defaultApps[3], defaultApps[4], defaultApps[5])
else if (entry[4] == "1" && !isFirstTime)infoText.text = String.format(entry[1], else if (entry[4] == "1" && !isFirstTime)
activity_firststartup_descriptive_text.text = String.format(entry[1],
"-", "-", "-", "-", "-", "-") "-", "-", "-", "-", "-", "-")
else infoText.text = entry[1] else activity_firststartup_descriptive_text.text = entry[1]
hintText.text = entry[2] activity_firststartup_hint_text.text = entry[2]
infoText.setTextSize(TypedValue.COMPLEX_UNIT_SP, entry[3].toFloat()) activity_firststartup_descriptive_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, entry[3].toFloat())
} else { // End intro } else { // End intro
if (isFirstTime){ if (isFirstTime){

View file

@ -8,6 +8,7 @@ import android.util.DisplayMetrics
import android.view.* import android.view.*
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
import com.finnmglas.launcher.extern.*
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -66,7 +67,7 @@ class MainActivity : AppCompatActivity(),
showSettingsIcon() showSettingsIcon()
// As older APIs somehow do not recognize the xml defined onClick // As older APIs somehow do not recognize the xml defined onClick
settingstooltip.setOnClickListener() { openSettings() } activity_main_settings_icon.setOnClickListener() { openSettings() }
// First Startup // First Startup
if (!sharedPref.getBoolean("startedBefore", false)){ if (!sharedPref.getBoolean("startedBefore", false)){
@ -95,8 +96,8 @@ class MainActivity : AppCompatActivity(),
// TODO: do this immediately after changing preferences // TODO: do this immediately after changing preferences
if (currentTheme != getSavedTheme(this)) recreate() if (currentTheme != getSavedTheme(this)) recreate()
if (background_image != null && getSavedTheme(this) == "custom") if (activity_main_background_image != null && getSavedTheme(this) == "custom")
background_image.setImageBitmap(background) activity_main_background_image.setImageBitmap(background)
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault()) val timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
@ -104,9 +105,12 @@ class MainActivity : AppCompatActivity(),
clockTimer = fixedRateTimer("clockTimer", true, 0L, 100) { clockTimer = fixedRateTimer("clockTimer", true, 0L, 100) {
this@MainActivity.runOnUiThread { this@MainActivity.runOnUiThread {
val t = timeFormat.format(Date()) val t = timeFormat.format(Date())
if (timeView.text != t) timeView.text = t if (activity_main_time_view.text != t)
activity_main_time_view.text = t
val d = dateFormat.format(Date()) val d = dateFormat.format(Date())
if (dateView.text != d) dateView.text = d if (activity_main_date_view.text != d)
activity_main_date_view.text = d
} }
} }
@ -173,8 +177,8 @@ class MainActivity : AppCompatActivity(),
} }
private fun showSettingsIcon(){ private fun showSettingsIcon(){
settingstooltip.fadeRotateIn() activity_main_settings_icon.fadeRotateIn()
settingstooltip.visibility = View.VISIBLE activity_main_settings_icon.visibility = View.VISIBLE
settingsIconShown = true settingsIconShown = true
tooltipTimer = fixedRateTimer("tooltipTimer", true, 10000, 1000) { tooltipTimer = fixedRateTimer("tooltipTimer", true, 10000, 1000) {
@ -184,8 +188,8 @@ class MainActivity : AppCompatActivity(),
private fun hideSettingsIcon(){ private fun hideSettingsIcon(){
tooltipTimer.cancel() tooltipTimer.cancel()
settingstooltip.fadeRotateOut() activity_main_settings_icon.fadeRotateOut()
settingstooltip.visibility = View.INVISIBLE activity_main_settings_icon.visibility = View.INVISIBLE
settingsIconShown = false settingsIconShown = false
} }

View file

@ -15,10 +15,11 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.finnmglas.launcher.ui.main.SectionsPagerAdapter import com.finnmglas.launcher.extern.*
import com.finnmglas.launcher.settings.SectionsPagerAdapter
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import kotlinx.android.synthetic.main.activity_settings.* import kotlinx.android.synthetic.main.activity_settings.*
import kotlinx.android.synthetic.main.activity_settings.container import kotlinx.android.synthetic.main.fragment_settings_apps.*
import kotlinx.android.synthetic.main.fragment_settings_theme.* import kotlinx.android.synthetic.main.fragment_settings_theme.*
@ -43,224 +44,18 @@ class SettingsActivity : AppCompatActivity() {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager) val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
val viewPager: ViewPager = findViewById(R.id.view_pager) val viewPager: ViewPager = findViewById(R.id.activity_settings_view_pager)
viewPager.adapter = sectionsPagerAdapter viewPager.adapter = sectionsPagerAdapter
val tabs: TabLayout = findViewById(R.id.tabs) val tabs: TabLayout = findViewById(R.id.activity_settings_tabs)
tabs.setupWithViewPager(viewPager) tabs.setupWithViewPager(viewPager)
// Hide 'select' button for the selected theme
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
if (tab == tabs.getTabAt(1 )) {
when (getSavedTheme(container!!.context)) {
"dark" -> select_theme_dark.visibility = View.INVISIBLE
"finn" -> select_theme_finn.visibility = View.INVISIBLE
"custom" -> {
select_theme_custom.text = getString(R.string.settings_select_image)
}
}
}
}
override fun onTabUnselected(tab: TabLayout.Tab) {}
override fun onTabReselected(tab: TabLayout.Tab) {}
})
// As older APIs somehow do not recognize the xml defined onClick // As older APIs somehow do not recognize the xml defined onClick
close_settings.setOnClickListener() { finish() } activity_settings_close.setOnClickListener() { finish() }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_CHOOSE_APP -> {
val value = data?.getStringExtra("value")
val forApp = data?.getStringExtra("forApp") ?: return
// Save the new App to Preferences
val sharedPref = this.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE)
val editor :SharedPreferences.Editor = sharedPref.edit()
editor.putString("action_$forApp", value.toString())
editor.apply()
loadSettings(sharedPref)
}
REQUEST_PERMISSION_STORAGE -> letUserPickImage()
REQUEST_PICK_IMAGE -> handlePickedImage(resultCode, data)
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
/** onClick functions for Settings */
fun chooseDownApp(view: View) {chooseApp("downApp")}
fun chooseUpApp(view: View) {chooseApp("upApp")}
fun chooseLeftApp(view: View) {chooseApp("leftApp")}
fun chooseRightApp(view: View) {chooseApp("rightApp")}
fun chooseVolumeDownApp(view: View) {chooseApp("volumeDownApp")}
fun chooseVolumeUpApp(view: View) {chooseApp("volumeUpApp")}
fun chooseApp(forAction :String) {
val intent = Intent(this, ChooseActivity::class.java)
intent.putExtra("action", "pick")
intent.putExtra("forApp", forAction) // for which action we choose the app
startActivityForResult(intent, REQUEST_CHOOSE_APP)
}
fun chooseUninstallApp(view: View) {
val intent = Intent(this, ChooseActivity::class.java)
intent.putExtra("action", "uninstall")
startActivity(intent)
}
fun chooseLaunchApp(view: View) {
val intent = Intent(this, ChooseActivity::class.java)
intent.putExtra("action", "launch")
startActivity(intent)
}
fun chooseInstallApp(view : View) {
try {
val rateIntent = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/"))
startActivity(rateIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(this,getString(R.string.settings_toast_store_not_found), Toast.LENGTH_SHORT)
.show()
}
}
fun openFinnWebsite(view: View) { openNewTabWindow(getString(R.string.settings_footer_web), this) }
fun openGithubRepo(view: View) { openNewTabWindow(getString(R.string.settings_footer_repo), this) }
// Rate App
// Just copied code from https://stackoverflow.com/q/10816757/12787264
// that is how we write good software ^
fun rateApp(view: View) {
try {
val rateIntent = rateIntentForUrl("market://details")
startActivity(rateIntent)
} catch (e: ActivityNotFoundException) {
val rateIntent = rateIntentForUrl("https://play.google.com/store/apps/details")
startActivity(rateIntent)
}
}
private fun rateIntentForUrl(url: String): Intent {
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse(String.format("%s?id=%s", url, packageName))
)
var flags = Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
flags = if (Build.VERSION.SDK_INT >= 21) {
flags or Intent.FLAG_ACTIVITY_NEW_DOCUMENT
} else {
flags or Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
}
intent.addFlags(flags)
return intent
} }
fun backHome(view: View) { finish() } fun backHome(view: View) { finish() }
fun setLauncher(view: View) {
// on newer sdk: choose launcher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val callHomeSettingIntent = Intent(Settings.ACTION_HOME_SETTINGS)
startActivity(callHomeSettingIntent)
}
// on older sdk: manage app details
else {
AlertDialog.Builder(this, R.style.AlertDialogCustom)
.setTitle(getString(R.string.alert_cant_choose_launcher))
.setMessage(getString(R.string.alert_cant_choose_launcher_message))
.setPositiveButton(android.R.string.yes,
DialogInterface.OnClickListener { dialog, which ->
try {
openAppSettings(packageName, this)
} catch ( e : ActivityNotFoundException) {
val intent = Intent(android.provider.Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)
startActivity(intent)
}
})
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_info)
.show()
}
}
fun viewTutorial (view: View){
startActivity(Intent(this, FirstStartupActivity::class.java))
}
// Show a dialog prompting for confirmation
fun resetSettingsClick(view: View) {
AlertDialog.Builder(this, R.style.AlertDialogCustom)
.setTitle(getString(R.string.settings_reset))
.setMessage(getString(R.string.settings_reset_message))
.setPositiveButton(android.R.string.yes,
DialogInterface.OnClickListener { dialog, which ->
resetSettings(this.getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE), this)
finish()
})
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
/** Theme - related */ /** Theme - related */
fun chooseDarkTheme(view: View) {
saveTheme(this, "dark")
recreate()
}
fun chooseFinnTheme(view: View) {
saveTheme(this, "finn")
recreate()
}
fun chooseCustomTheme(view: View) {
// Request permission (on newer APIs)
if (Build.VERSION.SDK_INT >= 23) {
when {
ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
-> letUserPickImage()
shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
-> {}
else
-> requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_PERMISSION_STORAGE)
}
}
else letUserPickImage()
}
private fun letUserPickImage() {
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_PICK // other option: Intent.ACTION_GET_CONTENT
//intent.putExtra("crop", "true")
//intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString())
startActivityForResult(intent, REQUEST_PICK_IMAGE)
}
private fun handlePickedImage(resultCode: Int, data: Intent?) {
if (resultCode == RESULT_OK) {
if (data == null) return
//BitmapFactory.(data.data)
val imageUri = data.data
background = MediaStore.Images.Media.getBitmap(this.contentResolver, imageUri)
saveTheme(this, "custom")
recreate()
}
}
} }

View file

@ -1,20 +0,0 @@
package com.finnmglas.launcher
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
/** The 'Apps' Tab associated Fragment in Settings */
class SettingsFragmentApps : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_settings_apps, container, false)
}
}

View file

@ -1,20 +0,0 @@
package com.finnmglas.launcher
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
/** The 'Launcher' Tab associated Fragment in Settings */
class SettingsFragmentLauncher : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_settings_launcher, container, false)
}
}

View file

@ -1,20 +0,0 @@
package com.finnmglas.launcher
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
/** The 'Theme' Tab associated Fragment in Settings */
class SettingsFragmentTheme : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_settings_theme, container, false)
}
}

View file

@ -1,4 +1,4 @@
package com.finnmglas.launcher // replace with your package package com.finnmglas.launcher.extern // replace with your package
// On GitHub: https://github.com/finnmglas/fontawesome-android // On GitHub: https://github.com/finnmglas/fontawesome-android
@ -6,6 +6,7 @@ import android.content.Context
import android.graphics.Typeface import android.graphics.Typeface
import android.util.AttributeSet import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import com.finnmglas.launcher.R
/** [FontAwesome] is just a type of TextView with special functions: /** [FontAwesome] is just a type of TextView with special functions:
* *
@ -28,7 +29,9 @@ class FontAwesome : AppCompatTextView {
private fun init(attrs: AttributeSet?) { private fun init(attrs: AttributeSet?) {
if (attrs != null) { if (attrs != null) {
val a = context!!.obtainStyledAttributes(attrs, R.styleable.FontAwesome) val a = context!!.obtainStyledAttributes(attrs,
R.styleable.FontAwesome
)
if (a.hasValue(R.styleable.FontAwesome_type)) if (a.hasValue(R.styleable.FontAwesome_type))
type = a.getString(R.styleable.FontAwesome_type)!! type = a.getString(R.styleable.FontAwesome_type)!!
a.recycle() a.recycle()

View file

@ -1,4 +1,4 @@
package com.finnmglas.launcher package com.finnmglas.launcher.extern
import android.app.Activity import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
@ -9,12 +9,18 @@ import android.content.SharedPreferences
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.ResolveInfo import android.content.pm.ResolveInfo
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BlendMode
import android.graphics.BlendModeColorFilter
import android.graphics.PorterDuff
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Settings import android.provider.Settings
import android.view.View import android.view.View
import android.view.animation.* import android.view.animation.*
import android.widget.Button
import android.widget.Toast import android.widget.Toast
import com.finnmglas.launcher.R
/** Variables for all of the app */ /** Variables for all of the app */
var upApp = "" var upApp = ""
@ -134,7 +140,8 @@ private fun getIntent(packageName: String, context: Context): Intent? {
} }
fun launchApp(packageName: String, context: Context) { fun launchApp(packageName: String, context: Context) {
val intent = getIntent(packageName, context) val intent =
getIntent(packageName, context)
if (intent != null) { if (intent != null) {
context.startActivity(intent) context.startActivity(intent)
@ -145,12 +152,17 @@ fun launchApp(packageName: String, context: Context) {
} else { } else {
if (isInstalled(packageName, context)){ if (isInstalled(packageName, context)){
AlertDialog.Builder(context, R.style.AlertDialogCustom) AlertDialog.Builder(context,
R.style.AlertDialogCustom
)
.setTitle(context.getString(R.string.alert_cant_open_title)) .setTitle(context.getString(R.string.alert_cant_open_title))
.setMessage(context.getString(R.string.alert_cant_open_message)) .setMessage(context.getString(R.string.alert_cant_open_message))
.setPositiveButton(android.R.string.yes, .setPositiveButton(android.R.string.yes,
DialogInterface.OnClickListener { dialog, which -> DialogInterface.OnClickListener { dialog, which ->
openAppSettings(packageName, context) openAppSettings(
packageName,
context
)
}) })
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_info) .setIcon(android.R.drawable.ic_dialog_info)
@ -217,32 +229,53 @@ fun resetSettings(sharedPref : SharedPreferences, context: Context) : MutableLis
val editor: SharedPreferences.Editor = sharedPref.edit() val editor: SharedPreferences.Editor = sharedPref.edit()
val (chosenUpName, chosenUpPackage) = pickDefaultApp("action_upApp", context) val (chosenUpName, chosenUpPackage) = pickDefaultApp(
"action_upApp",
context
)
editor.putString("action_upApp", chosenUpPackage) editor.putString("action_upApp", chosenUpPackage)
defaultList.add(chosenUpName) defaultList.add(chosenUpName)
val (chosenDownName, chosenDownPackage) = pickDefaultApp("action_downApp", context) val (chosenDownName, chosenDownPackage) = pickDefaultApp(
"action_downApp",
context
)
editor.putString("action_downApp", chosenDownPackage) editor.putString("action_downApp", chosenDownPackage)
defaultList.add(chosenDownName) defaultList.add(chosenDownName)
val (chosenRightName, chosenRightPackage) = pickDefaultApp("action_rightApp", context) val (chosenRightName, chosenRightPackage) = pickDefaultApp(
"action_rightApp",
context
)
editor.putString("action_rightApp", chosenRightPackage) editor.putString("action_rightApp", chosenRightPackage)
defaultList.add(chosenRightName) defaultList.add(chosenRightName)
val (chosenLeftName, chosenLeftPackage) = pickDefaultApp("action_leftApp", context) val (chosenLeftName, chosenLeftPackage) = pickDefaultApp(
"action_leftApp",
context
)
editor.putString("action_leftApp", chosenLeftPackage) editor.putString("action_leftApp", chosenLeftPackage)
editor.putString("action_calendarApp", chosenLeftPackage) editor.putString("action_calendarApp", chosenLeftPackage)
defaultList.add(chosenLeftName) defaultList.add(chosenLeftName)
val (chosenVolumeUpName, chosenVolumeUpPackage) = pickDefaultApp("action_volumeUpApp", context) val (chosenVolumeUpName, chosenVolumeUpPackage) = pickDefaultApp(
"action_volumeUpApp",
context
)
editor.putString("action_volumeUpApp", chosenVolumeUpPackage) editor.putString("action_volumeUpApp", chosenVolumeUpPackage)
defaultList.add(chosenVolumeUpName) defaultList.add(chosenVolumeUpName)
val (chosenVolumeDownName, chosenVolumeDownPackage) = pickDefaultApp("action_volumeDownApp", context) val (chosenVolumeDownName, chosenVolumeDownPackage) = pickDefaultApp(
"action_volumeDownApp",
context
)
editor.putString("action_volumeDownApp", chosenVolumeDownPackage) editor.putString("action_volumeDownApp", chosenVolumeDownPackage)
defaultList.add(chosenVolumeDownName) defaultList.add(chosenVolumeDownName)
val (_, chosenClockPackage) = pickDefaultApp("action_clockApp", context) val (_, chosenClockPackage) = pickDefaultApp(
"action_clockApp",
context
)
editor.putString("action_clockApp", chosenClockPackage) editor.putString("action_clockApp", chosenClockPackage)
editor.apply() editor.apply()
@ -264,7 +297,7 @@ fun pickDefaultApp(action: String, context: Context) : Pair<String, String>{
// Related question: https://stackoverflow.com/q/3013655/12787264 (Adjusted) // Related question: https://stackoverflow.com/q/3013655/12787264 (Adjusted)
val list = context.resources.getStringArray(arrayResource) val list = context.resources.getStringArray(arrayResource)
for (entry in list!!){ for (entry in list){
val splitResult = entry.split("|").toTypedArray() val splitResult = entry.split("|").toTypedArray()
val pkgname = splitResult[0] val pkgname = splitResult[0]
val name = splitResult[1] val name = splitResult[1]
@ -273,3 +306,19 @@ fun pickDefaultApp(action: String, context: Context) : Pair<String, String>{
} }
return Pair(context.getString(R.string.none_found), "") return Pair(context.getString(R.string.none_found), "")
} }
/** Bitmaps */
fun getDominantColor(bitmap: Bitmap?): Int {
val newBitmap = Bitmap.createScaledBitmap(bitmap!!, 1, 1, true)
val color = newBitmap.getPixel(0, 0)
newBitmap.recycle()
return color
}
fun setButtonColor(btn: Button, color: Int) {
if (Build.VERSION.SDK_INT >= 29)
btn.background.colorFilter = BlendModeColorFilter(color, BlendMode.DST_OVER)
else
btn.background.setColorFilter(color, PorterDuff.Mode.MULTIPLY)
}

View file

@ -1,10 +1,9 @@
package com.finnmglas.launcher.ui.main package com.finnmglas.launcher.settings
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class PageViewModel : ViewModel() { class PageViewModel : ViewModel() {

View file

@ -1,4 +1,4 @@
package com.finnmglas.launcher.ui.main package com.finnmglas.launcher.settings
import android.content.Context import android.content.Context
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -14,13 +14,13 @@ private val TAB_TITLES = arrayOf(
/** Returns the fragment corresponding to the selected tab.*/ /** Returns the fragment corresponding to the selected tab.*/
class SectionsPagerAdapter(private val context: Context, fm: FragmentManager) class SectionsPagerAdapter(private val context: Context, fm: FragmentManager)
: FragmentPagerAdapter(fm) { : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment { override fun getItem(position: Int): Fragment {
return when (position){ return when (position){
0 -> SettingsFragmentApps() 0 -> SettingsFragmentApps()
1 -> SettingsFragmentTheme() 1 -> SettingsFragmentTheme()
2 -> SettingsFragmentLauncher() 2 -> SettingsFragmentMeta()
else -> Fragment() else -> Fragment()
} }
} }
@ -29,7 +29,5 @@ class SectionsPagerAdapter(private val context: Context, fm: FragmentManager)
return context.resources.getString(TAB_TITLES[position]) return context.resources.getString(TAB_TITLES[position])
} }
override fun getCount(): Int { override fun getCount(): Int { return 3 }
return 3
}
} }

View file

@ -0,0 +1,98 @@
package com.finnmglas.launcher.settings
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.finnmglas.launcher.ChooseActivity
import com.finnmglas.launcher.R
import com.finnmglas.launcher.extern.REQUEST_CHOOSE_APP
import com.finnmglas.launcher.extern.loadSettings
import kotlinx.android.synthetic.main.fragment_settings_apps.*
/** The 'Apps' Tab associated Fragment in Settings */
class SettingsFragmentApps : Fragment() {
/** Lifecycle functions */
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_settings_apps, container, false)
}
override fun onStart() {
// Action - selecting buttons
fragment_settings_apps_choose_up_btn.setOnClickListener{ chooseApp("upApp") }
fragment_settings_apps_choose_down_btn.setOnClickListener{ chooseApp("downApp") }
fragment_settings_apps_choose_left_btn.setOnClickListener{ chooseApp("leftApp") }
fragment_settings_apps_choose_right_btn.setOnClickListener{ chooseApp("rightApp") }
fragment_settings_apps_choose_vol_up_btn.setOnClickListener{ chooseApp("volumeUpApp")}
fragment_settings_apps_choose_vol_down_btn.setOnClickListener{ chooseApp("volumeDownApp")}
// App management buttons
fragment_settings_apps_launch_btn.setOnClickListener{
val intent = Intent(this.context, ChooseActivity::class.java)
intent.putExtra("action", "launch")
startActivity(intent)
}
fragment_settings_apps_install_btn.setOnClickListener{
try {
val rateIntent = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/"))
startActivity(rateIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(this.context, getString(R.string.settings_toast_store_not_found), Toast.LENGTH_SHORT)
.show()
}
}
fragment_settings_apps_remove_btn.setOnClickListener{
val intent = Intent(this.context, ChooseActivity::class.java)
intent.putExtra("action", "uninstall")
startActivity(intent)
}
super.onStart()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_CHOOSE_APP -> {
val value = data?.getStringExtra("value")
val forApp = data?.getStringExtra("forApp") ?: return
// Save the new App to Preferences
val sharedPref = this.context!!.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE)
val editor : SharedPreferences.Editor = sharedPref.edit()
editor.putString("action_$forApp", value.toString())
editor.apply()
loadSettings(sharedPref)
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
/** Extra functions */
private fun chooseApp(forAction: String) {
val intent = Intent(this.context, ChooseActivity::class.java)
intent.putExtra("action", "pick")
intent.putExtra("forApp", forAction) // for which action we choose the app
startActivityForResult(intent, REQUEST_CHOOSE_APP)
}
}

View file

@ -0,0 +1,127 @@
package com.finnmglas.launcher.settings
import android.app.AlertDialog
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.finnmglas.launcher.FirstStartupActivity
import com.finnmglas.launcher.R
import com.finnmglas.launcher.extern.openAppSettings
import com.finnmglas.launcher.extern.openNewTabWindow
import com.finnmglas.launcher.extern.resetSettings
import kotlinx.android.synthetic.main.fragment_settings_meta.*
/** The 'Meta' Tab associated Fragment in Settings */
class SettingsFragmentMeta : Fragment() {
/** Lifecycle functions */
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_settings_meta, container, false)
}
override fun onStart() {
// Button onClicks
fragment_settings_meta_select_launcher_btn.setOnClickListener {
// on newer sdk: choose launcher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val callHomeSettingIntent = Intent(Settings.ACTION_HOME_SETTINGS)
startActivity(callHomeSettingIntent)
}
// on older sdk: manage app details
else {
AlertDialog.Builder(this.context!!, R.style.AlertDialogCustom)
.setTitle(getString(R.string.alert_cant_choose_launcher))
.setMessage(getString(R.string.alert_cant_choose_launcher_message))
.setPositiveButton(android.R.string.yes,
DialogInterface.OnClickListener { _, _ ->
try {
openAppSettings(this.context!!.packageName, this.context!!)
} catch ( e : ActivityNotFoundException) {
val intent = Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)
startActivity(intent)
}
})
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_info)
.show()
}
}
fragment_settings_meta_view_tutorial_btn.setOnClickListener {
startActivity(Intent(this.context, FirstStartupActivity::class.java))
}
// prompting for settings-reset confirmation
fragment_settings_meta_reset_settings_btn.setOnClickListener {
AlertDialog.Builder(this.context!!, R.style.AlertDialogCustom)
.setTitle(getString(R.string.settings_reset))
.setMessage(getString(R.string.settings_reset_message))
.setPositiveButton(android.R.string.yes,
DialogInterface.OnClickListener { _, _ ->
resetSettings(this.context!!.getSharedPreferences(getString(R.string.preference_file_key),
Context.MODE_PRIVATE), this.context!!)
activity!!.finish()
})
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
// rate app
fragment_settings_meta_rate_app_btn.setOnClickListener {
try {
val rateIntent = rateIntentForUrl("market://details")
startActivity(rateIntent)
} catch (e: ActivityNotFoundException) {
val rateIntent = rateIntentForUrl("https://play.google.com/store/apps/details")
startActivity(rateIntent)
}
}
// Footer onClicks
fragment_settings_meta_footer_github_link.setOnClickListener {
openNewTabWindow(getString(R.string.settings_footer_repo), this.context!!)
}
fragment_settings_meta_footer_website_link.setOnClickListener {
openNewTabWindow(getString(R.string.settings_footer_web), this.context!!)
}
super.onStart()
}
/** Extra functions */
// Rate App
// Just copied code from https://stackoverflow.com/q/10816757/12787264
// that is how we write good software ^^
private fun rateIntentForUrl(url: String): Intent {
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse(String.format("%s?id=%s", url, this.context!!.packageName))
)
var flags = Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
flags = if (Build.VERSION.SDK_INT >= 21) {
flags or Intent.FLAG_ACTIVITY_NEW_DOCUMENT
} else {
flags or Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
}
intent.addFlags(flags)
return intent
}
}

View file

@ -0,0 +1,101 @@
package com.finnmglas.launcher.settings
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.finnmglas.launcher.R
import com.finnmglas.launcher.extern.*
import kotlinx.android.synthetic.main.fragment_settings_theme.*
/** The 'Theme' Tab associated Fragment in Settings */
class SettingsFragmentTheme : Fragment() {
/** Lifecycle functions */
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_settings_theme, container, false)
}
override fun onStart(){
// Hide 'select' button for the selected theme or allow customisation
when (getSavedTheme(this.context!!)) {
"dark" -> fragment_settings_theme_select_dark_btn.visibility = View.INVISIBLE
"finn" -> fragment_settings_theme_select_finn_btn.visibility = View.INVISIBLE
"custom" -> {
fragment_settings_theme_select_custom_btn.text = getString(R.string.settings_select_image)
}
}
// Theme changing buttons
fragment_settings_theme_select_dark_btn.setOnClickListener {
saveTheme(this.context!!, "dark")
activity!!.recreate()
}
fragment_settings_theme_select_finn_btn.setOnClickListener {
saveTheme(this.context!!, "finn")
activity!!.recreate()
}
fragment_settings_theme_select_custom_btn.setOnClickListener {
// Request permission (on newer APIs)
if (Build.VERSION.SDK_INT >= 23) {
when {
ContextCompat.checkSelfPermission(this.context!!,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
-> letUserPickImage()
shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
-> {}
else
-> requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_PERMISSION_STORAGE)
}
}
else letUserPickImage()
}
super.onStart()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_PERMISSION_STORAGE -> letUserPickImage()
REQUEST_PICK_IMAGE -> handlePickedImage(resultCode, data)
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
/** Extra functions */
private fun letUserPickImage(crop: Boolean = false) {
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_PICK // other option: Intent.ACTION_GET_CONTENT
if (crop) intent.putExtra("crop", "true")
startActivityForResult(intent, REQUEST_PICK_IMAGE)
}
private fun handlePickedImage(resultCode: Int, data: Intent?) {
if (resultCode == AppCompatActivity.RESULT_OK) {
if (data == null) return
val imageUri = data.data
background = MediaStore.Images.Media.getBitmap(this.context!!.contentResolver, imageUri)
saveTheme(this.context!!, "custom")
activity!!.recreate()
}
}
}

View file

@ -1,15 +1,16 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto" xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container" android:id="@+id/activity_choose_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
tools:context=".ChooseActivity"> tools:context=".ChooseActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar" android:id="@+id/activity_choose_app_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -22,7 +23,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <TextView
android:id="@+id/heading" android:id="@+id/activity_choose_heading"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -35,8 +36,8 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<com.finnmglas.launcher.FontAwesome <com.finnmglas.launcher.extern.FontAwesome
android:id="@+id/close_chooser" android:id="@+id/activity_choose_close"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
@ -69,10 +70,10 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/app_bar"> app:layout_constraintTop_toBottomOf="@id/activity_choose_app_bar">
<LinearLayout <LinearLayout
android:id="@+id/apps_list" android:id="@+id/activity_choose_apps_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" /> android:orientation="vertical" />

View file

@ -1,17 +1,17 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto" xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container" android:id="@+id/activity_firststartup_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
android:longClickable="false"
android:onClick="clickAnywhere" android:onClick="clickAnywhere"
tools:context=".FirstStartupActivity"> tools:context=".FirstStartupActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar" android:id="@+id/activity_firststartup_app_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -25,6 +25,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <TextView
android:id="@+id/activity_firststartup_heading"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -36,8 +37,8 @@
custom:layout_constraintStart_toStartOf="parent" custom:layout_constraintStart_toStartOf="parent"
custom:layout_constraintTop_toTopOf="parent" /> custom:layout_constraintTop_toTopOf="parent" />
<com.finnmglas.launcher.FontAwesome <com.finnmglas.launcher.extern.FontAwesome
android:id="@+id/close_tutorial" android:id="@+id/activity_firststartup_close"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
@ -59,7 +60,7 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<TextView <TextView
android:id="@+id/heading" android:id="@+id/activity_firststartup_section_heading"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -73,7 +74,7 @@
app:layout_constraintVertical_bias="0.100000024" /> app:layout_constraintVertical_bias="0.100000024" />
<TextView <TextView
android:id="@+id/infoText" android:id="@+id/activity_firststartup_descriptive_text"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginStart="32dp" android:layout_marginStart="32dp"
@ -89,10 +90,10 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.6" app:layout_constraintHorizontal_bias="0.6"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/heading" /> app:layout_constraintTop_toBottomOf="@id/activity_firststartup_section_heading" />
<TextView <TextView
android:id="@+id/hintText" android:id="@+id/activity_firststartup_hint_text"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginStart="32dp" android:layout_marginStart="32dp"
@ -109,6 +110,6 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.6" app:layout_constraintHorizontal_bias="0.6"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/infoText" /> app:layout_constraintTop_toBottomOf="@id/activity_firststartup_descriptive_text" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,8 +1,9 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto" xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container" android:id="@+id/activity_main_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
@ -10,18 +11,19 @@
tools:context=".MainActivity"> tools:context=".MainActivity">
<ImageView <ImageView
android:id="@+id/background_image" android:id="@+id/activity_main_background_image"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:orientation="vertical" android:orientation="vertical"
android:scaleType="centerCrop" /> android:scaleType="centerCrop"
tools:ignore="ContentDescription" />
<TextView <TextView
android:id="@+id/dateView" android:id="@+id/activity_main_date_view"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="left|center_vertical" android:gravity="start|center_vertical"
android:onClick="dateViewOnTouch" android:onClick="dateViewOnTouch"
android:textSize="30sp" android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -31,10 +33,10 @@
app:layout_constraintVertical_bias="0.45" /> app:layout_constraintVertical_bias="0.45" />
<TextView <TextView
android:id="@+id/timeView" android:id="@+id/activity_main_time_view"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="left|center_vertical" android:gravity="start|center_vertical"
android:onClick="timeViewOnTouch" android:onClick="timeViewOnTouch"
android:textSize="18sp" android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -43,8 +45,8 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<com.finnmglas.launcher.FontAwesome <com.finnmglas.launcher.extern.FontAwesome
android:id="@+id/settingstooltip" android:id="@+id/activity_main_settings_icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="settingsIconOnTouch" android:onClick="settingsIconOnTouch"

View file

@ -1,14 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto" xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container" android:id="@+id/activity_settings_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".SettingsActivity"> tools:context=".SettingsActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/activity_settings_app_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -17,7 +19,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <TextView
android:id="@+id/heading" android:id="@+id/activity_settings_heading"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
@ -26,11 +28,13 @@
android:text="@string/settings_title" android:text="@string/settings_title"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:textSize="30sp" android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.finnmglas.launcher.FontAwesome <com.finnmglas.launcher.extern.FontAwesome
android:id="@+id/close_settings" android:id="@+id/activity_settings_close"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
@ -50,7 +54,7 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout
android:id="@+id/tabs" android:id="@+id/activity_settings_tabs"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:tabTextColor="?attr/android:textColor" /> app:tabTextColor="?attr/android:textColor" />
@ -58,7 +62,7 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager <androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager" android:id="@+id/activity_settings_view_pager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> app:layout_behavior="@string/appbar_scrolling_view_behavior" />

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container" android:id="@+id/fragment_settings_apps_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
@ -11,10 +12,9 @@
android:paddingTop="16sp" android:paddingTop="16sp"
android:paddingLeft="32sp" android:paddingLeft="32sp"
android:paddingRight="32sp" android:paddingRight="32sp"
tools:context=".SettingsActivity"> tools:context=".settings.SettingsFragmentApps">
<TableLayout <TableLayout
android:id="@+id/actionschooser"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="32sp" android:paddingBottom="32sp"
@ -29,7 +29,7 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
android:id="@+id/text_up" android:id="@+id/fragment_settings_apps_text_up"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10sp" android:paddingLeft="10sp"
@ -38,10 +38,9 @@
android:textSize="20sp" /> android:textSize="20sp" />
<Button <Button
android:id="@+id/btn_choose_up" android:id="@+id/fragment_settings_apps_choose_up_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseUpApp"
android:text="@string/settings_choose_btn" android:text="@string/settings_choose_btn"
android:textAllCaps="false" /> android:textAllCaps="false" />
</TableRow> </TableRow>
@ -52,7 +51,7 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
android:id="@+id/text_down" android:id="@+id/fragment_settings_apps_choose_down_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10sp" android:paddingLeft="10sp"
@ -61,10 +60,9 @@
android:textSize="20sp" /> android:textSize="20sp" />
<Button <Button
android:id="@+id/btn_choose_down" android:id="@+id/fragment_settings_apps_choose_down_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseDownApp"
android:text="@string/settings_choose_btn" android:text="@string/settings_choose_btn"
android:textAllCaps="false" /> android:textAllCaps="false" />
@ -76,7 +74,7 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
android:id="@+id/text_left" android:id="@+id/fragment_settings_apps_choose_left_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10sp" android:paddingLeft="10sp"
@ -85,10 +83,9 @@
android:textSize="20sp" /> android:textSize="20sp" />
<Button <Button
android:id="@+id/btn_choose_left" android:id="@+id/fragment_settings_apps_choose_left_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseLeftApp"
android:text="@string/settings_choose_btn" android:text="@string/settings_choose_btn"
android:textAllCaps="false" /> android:textAllCaps="false" />
</TableRow> </TableRow>
@ -99,7 +96,7 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
android:id="@+id/text_right" android:id="@+id/fragment_settings_apps_choose_right_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10sp" android:paddingLeft="10sp"
@ -108,10 +105,9 @@
android:textSize="20sp" /> android:textSize="20sp" />
<Button <Button
android:id="@+id/btn_choose_right" android:id="@+id/fragment_settings_apps_choose_right_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseRightApp"
android:text="@string/settings_choose_btn" android:text="@string/settings_choose_btn"
android:textAllCaps="false" /> android:textAllCaps="false" />
@ -123,7 +119,7 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
android:id="@+id/text_vol_up" android:id="@+id/fragment_settings_apps_choose_vol_up_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10sp" android:paddingLeft="10sp"
@ -132,10 +128,9 @@
android:textSize="20sp" /> android:textSize="20sp" />
<Button <Button
android:id="@+id/btn_choose_volume_up" android:id="@+id/fragment_settings_apps_choose_vol_up_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseVolumeUpApp"
android:text="@string/settings_choose_btn" android:text="@string/settings_choose_btn"
android:textAllCaps="false" /> android:textAllCaps="false" />
</TableRow> </TableRow>
@ -146,7 +141,7 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
android:id="@+id/text_vol_down" android:id="@+id/fragment_settings_apps_choose_vol_down_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="10sp" android:paddingLeft="10sp"
@ -155,10 +150,9 @@
android:textSize="20sp" /> android:textSize="20sp" />
<Button <Button
android:id="@+id/btn_choose_volume_down" android:id="@+id/fragment_settings_apps_choose_vol_down_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseVolumeDownApp"
android:text="@string/settings_choose_btn" android:text="@string/settings_choose_btn"
android:textAllCaps="false" /> android:textAllCaps="false" />
@ -167,23 +161,23 @@
</TableLayout> </TableLayout>
<Button <Button
android:id="@+id/fragment_settings_apps_launch_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseLaunchApp"
android:text="@string/settings_launch" android:text="@string/settings_launch"
android:textAllCaps="false" /> android:textAllCaps="false" />
<Button <Button
android:id="@+id/fragment_settings_apps_install_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseInstallApp"
android:text="@string/settings_install" android:text="@string/settings_install"
android:textAllCaps="false" /> android:textAllCaps="false" />
<Button <Button
android:id="@+id/fragment_settings_apps_remove_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseUninstallApp"
android:text="@string/settings_uninstall" android:text="@string/settings_uninstall"
android:textAllCaps="false" /> android:textAllCaps="false" />
</LinearLayout> </LinearLayout>

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container" android:id="@+id/fragment_settings_meta_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
@ -11,34 +12,34 @@
android:paddingTop="16sp" android:paddingTop="16sp"
android:paddingLeft="32sp" android:paddingLeft="32sp"
android:paddingRight="32sp" android:paddingRight="32sp"
tools:context=".SettingsActivity"> tools:context=".settings.SettingsFragmentMeta">
<Button <Button
android:id="@+id/fragment_settings_meta_select_launcher_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="setLauncher"
android:text="@string/settings_select_launcher" android:text="@string/settings_select_launcher"
android:textAllCaps="false" /> android:textAllCaps="false" />
<Button <Button
android:id="@+id/fragment_settings_meta_view_tutorial_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="viewTutorial"
android:text="@string/settings_show_tutorial" android:text="@string/settings_show_tutorial"
android:textAllCaps="false" /> android:textAllCaps="false" />
<Button <Button
android:id="@+id/fragment_settings_meta_reset_settings_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="32sp" android:layout_marginBottom="32sp"
android:onClick="resetSettingsClick"
android:text="@string/settings_reset" android:text="@string/settings_reset"
android:textAllCaps="false" /> android:textAllCaps="false" />
<Button <Button
android:id="@+id/fragment_settings_meta_rate_app_btn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="rateApp"
android:text="@string/settings_feedback" android:text="@string/settings_feedback"
android:textAllCaps="false" /> android:textAllCaps="false" />
@ -49,21 +50,23 @@
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:id="@+id/fragment_settings_meta_footer_by_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/settings_footer_by" android:text="@string/settings_footer_by"
android:textSize="18sp" /> android:textSize="18sp" />
<TextView <TextView
android:id="@+id/fragment_settings_meta_footer_website_link"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="openFinnWebsite"
android:text=" Finn M Glas" android:text=" Finn M Glas"
android:textColor="?attr/colorAccent" android:textColor="?attr/colorAccent"
android:textSize="18sp" android:textSize="18sp"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/fragment_settings_meta_footer_pipe_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text=" | " android:text=" | "
@ -71,9 +74,9 @@
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
android:id="@+id/fragment_settings_meta_footer_github_link"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="openGithubRepo"
android:text="Open Source" android:text="Open Source"
android:textColor="?attr/colorAccent" android:textColor="?attr/colorAccent"
android:textSize="18sp" android:textSize="18sp"

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container" android:id="@+id/fragment_settings_theme_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
@ -11,7 +12,7 @@
android:paddingLeft="32sp" android:paddingLeft="32sp"
android:paddingTop="16sp" android:paddingTop="16sp"
android:paddingRight="32sp" android:paddingRight="32sp"
tools:context=".SettingsActivity"> tools:context=".settings.SettingsFragmentMeta">
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -30,21 +31,20 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:background="?attr/colorAccent">
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:scaleType="fitXY" android:scaleType="fitXY"
app:srcCompat="@drawable/finnmglas_theme" /> app:srcCompat="@drawable/finnmglas_theme"
tools:ignore="ContentDescription" />
<Button <Button
android:id="@+id/select_theme_finn" android:id="@+id/fragment_settings_theme_select_finn_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseFinnTheme"
android:text="@string/settings_select_theme" android:text="@string/settings_select_theme"
android:textAllCaps="false" android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -69,13 +69,13 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:scaleType="fitXY" android:scaleType="fitXY"
app:srcCompat="@drawable/dark_theme" /> app:srcCompat="@drawable/dark_theme"
tools:ignore="ContentDescription" />
<Button <Button
android:id="@+id/select_theme_dark" android:id="@+id/fragment_settings_theme_select_dark_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseDarkTheme"
android:text="@string/settings_select_theme" android:text="@string/settings_select_theme"
android:textAllCaps="false" android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -99,13 +99,13 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:scaleType="fitXY" android:scaleType="fitXY"
app:srcCompat="@drawable/custom_theme" /> app:srcCompat="@drawable/custom_theme"
tools:ignore="ContentDescription" />
<Button <Button
android:id="@+id/select_theme_custom" android:id="@+id/fragment_settings_theme_select_custom_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="chooseCustomTheme"
android:text="@string/settings_select_theme" android:text="@string/settings_select_theme"
android:textAllCaps="false" android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"