Rewriting the app into a single activity is in progress

This commit is contained in:
ottoptj 2024-05-22 00:35:28 +03:00
commit 1f0a91e2df
5 changed files with 542 additions and 163 deletions

View file

@ -17,6 +17,7 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatButton
import eu.ottop.yamlauncher.databinding.ActivityAppMenuBinding
import eu.ottop.yamlauncher.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -26,9 +27,9 @@ class AppActionMenu {
private val appUtils = AppUtils()
fun setActionListeners(
activity: AppMenuActivity,
activity: MainActivity,
uiScope: CoroutineScope,
binding: ActivityAppMenuBinding,
binding: ActivityMainBinding,
textView: TextView,
editLayout: LinearLayout,
actionMenu: View,

View file

@ -15,26 +15,24 @@ import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import eu.ottop.yamlauncher.databinding.ActivityAppMenuBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, AppMenuAdapter.OnShortcutListener, AppMenuAdapter.OnItemLongClickListener {
/*
private lateinit var binding: ActivityAppMenuBinding
private lateinit var recyclerView: RecyclerView
private lateinit var searchView: EditText
private lateinit var adapter: AppMenuAdapter
private lateinit var filteredApps: MutableList<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
private var job: Job? = null
private var appActionMenu = AppActionMenu()
private lateinit var launcherApps: LauncherApps
@ -79,14 +77,19 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
recyclerView = findViewById(R.id.recycler_view)
recyclerView.scrollToPosition(0)
installedApps = currentApps
filteredApps = mutableListOf()
filteredApps.addAll(installedApps)
val newApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
newApps.addAll(installedApps)
adapter = AppMenuAdapter(this@AppMenuActivity, newApps, this, this,this, menuMode)
recyclerView.adapter = adapter
setupSearch()
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
finish()
}
})
}
override fun onItemClick(appInfo: LauncherActivityInfo, userHandle: UserHandle) {
@ -218,7 +221,6 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
private fun startTask() {
job = CoroutineScope(Dispatchers.Default).launch {
while (true) {
ensureActive()
manualRefresh()
delay(5000)
}
@ -317,5 +319,32 @@ class AppMenuActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener,
data class Change(val type: ChangeType, val position: Int, val newPosition: Int = 0)
enum class ChangeType {
INSERT, REMOVE, UPDATE
INSERT, REMOVE, UPDATE*/
override fun onItemClick(appInfo: LauncherActivityInfo, userHandle: UserHandle) {
TODO("Not yet implemented")
}
override fun onItemLongClick(
appInfo: LauncherActivityInfo,
userHandle: UserHandle,
userProfile: Int,
textView: TextView,
actionMenuLayout: LinearLayout,
editView: LinearLayout,
position: Int
) {
TODO("Not yet implemented")
}
override fun onShortcut(
appInfo: LauncherActivityInfo,
userHandle: UserHandle,
textView: TextView,
userProfile: Int,
shortcutView: TextView
) {
TODO("Not yet implemented")
}
}

View file

@ -14,15 +14,17 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatButton
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
class AppMenuAdapter(
private val activity: AppMenuActivity,
private val activity: FragmentActivity,
var apps: MutableList<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>,
private val itemClickListener: OnItemClickListener,
private val shortcutListener: OnShortcutListener,
private val itemLongClickListener: OnItemLongClickListener,
private val menuMode: String
private val menuMode: String = "app",
private val shortcutTextView: TextView? = null
) :
RecyclerView.Adapter<AppMenuAdapter.AppViewHolder>() {
@ -33,7 +35,7 @@ class AppMenuAdapter(
}
interface OnShortcutListener {
fun onShortcut(appInfo: LauncherActivityInfo, userHandle: UserHandle, textView: TextView, userProfile: Int)
fun onShortcut(appInfo: LauncherActivityInfo, userHandle: UserHandle, textView: TextView, userProfile: Int, shortcutView: TextView)
}
interface OnItemLongClickListener {
@ -62,7 +64,7 @@ class AppMenuAdapter(
val position = bindingAdapterPosition
val app = apps[position].first
if (menuMode == "shortcut") {
shortcutListener.onShortcut(app, apps[position].second.first, textView, apps[position].second.second)
shortcutListener.onShortcut(app, apps[position].second.first, textView, apps[position].second.second, shortcutTextView!!)
}
else if (menuMode == "app") {
itemClickListener.onItemClick(app, apps[position].second.first)

View file

@ -5,27 +5,43 @@ import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.os.Bundle
import android.os.UserHandle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import eu.ottop.yamlauncher.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.math.abs
class MainActivity : AppCompatActivity() {
class MainActivity : AppCompatActivity(), AppMenuAdapter.OnItemClickListener, AppMenuAdapter.OnShortcutListener, AppMenuAdapter.OnItemLongClickListener {
private lateinit var binding: ActivityMainBinding
private lateinit var gestureDetector: GestureDetector
private lateinit var launcherApps: LauncherApps
private lateinit var installedApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
private lateinit var recyclerView: RecyclerView
private lateinit var searchView: EditText
private lateinit var adapter: AppMenuAdapter
private var job: Job? = null
private var appActionMenu = AppActionMenu()
private val sharedPreferenceManager = SharedPreferenceManager()
private val appUtils = AppUtils()
@ -36,9 +52,6 @@ class MainActivity : AppCompatActivity() {
setSupportActionBar(null)
launcherApps = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
CoroutineScope(Dispatchers.Default).launch {
installedApps = appUtils.getInstalledApps(this@MainActivity)
}
for (i in findViewById<LinearLayout>(R.id.shortcuts).children) {
@ -74,35 +87,122 @@ class MainActivity : AppCompatActivity() {
}
i.setOnLongClickListener {
AppMenuActivity.start(this@MainActivity, installedApps, "shortcut") { newText ->
binding.homeView.visibility = View.GONE
if (newText.first.second != 0) {
textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_work_app, null),null,null,null)
}
else {
textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_empty, null),null,null,null)
}
textView.text = newText.first.first
i.setOnClickListener {
val mainActivity = launcherApps.getActivityList(newText.second.first.applicationInfo.packageName, newText.second.second).firstOrNull()
if (mainActivity != null) {
launcherApps.startMainActivity(mainActivity.componentName, newText.second.second, null, null)
} else {
Toast.makeText(this, "Cannot launch app", Toast.LENGTH_SHORT).show()
}
}
sharedPreferenceManager.setShortcut(this, textView, newText.second.first.applicationInfo.packageName, newText.first.second)
}
val newApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
newApps.addAll(installedApps)
adapter = AppMenuAdapter(this@MainActivity, newApps, this@MainActivity, this@MainActivity, this@MainActivity, "shortcut", i)
recyclerView.adapter = adapter
binding.appView.visibility = View.VISIBLE
return@setOnLongClickListener true
}
}
}}
gestureDetector = GestureDetector(this, GestureListener())
//Experimental
CoroutineScope(Dispatchers.Default).launch {
installedApps = appUtils.getInstalledApps(this@MainActivity)
recyclerView = findViewById(R.id.recycler_view)
recyclerView.scrollToPosition(0)
searchView = findViewById(R.id.searchView)
setupSearch()
}
}
private fun setupSearch() {
binding.root.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom ->
if (bottom - top > oldBottom - oldTop) {
searchView.clearFocus()
if (searchView.text.isNullOrEmpty()) {
job?.cancel()
startTask()
}
}
else {
job?.cancel()
}
}
searchView.addTextChangedListener(object :
TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
filterItems(searchView.text.toString())
}
override fun afterTextChanged(s: Editable?) {
}
})
}
private fun filterItems(query: String?) {
CoroutineScope(Dispatchers.Default).launch {
val cleanQuery = query?.clean()
val newFilteredApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
val updatedApps = appUtils.getInstalledApps(this@MainActivity)
if (cleanQuery.isNullOrEmpty()) {
manualRefresh()
newFilteredApps.addAll(installedApps)
} else {
updatedApps.forEach {
val cleanItemText = sharedPreferenceManager.getAppName(this@MainActivity, it.first.applicationInfo.packageName, it.second.second, it.first.applicationInfo.loadLabel(packageManager)).toString().clean()
if (cleanItemText.contains(cleanQuery, ignoreCase = true)) {
newFilteredApps.add(it)
}
}
}
val changes = detectChanges(installedApps, newFilteredApps)
installedApps = newFilteredApps
withContext(Dispatchers.Main) {
applyChanges(changes, installedApps)
}
}
}
private fun String.clean(): String {
return this.replace("[^a-zA-Z0-9]".toRegex(), "")
}
override fun onStop() {
super.onStop()
job?.cancel()
}
override fun onDestroy() {
super.onDestroy()
job?.cancel()
}
override fun onStart() {
super.onStart()
startTask()
// Keyboard is sometimes open when going back to the app, so close it.
val imm =
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.root.windowToken, 0)
}
private fun startTask() {
job = CoroutineScope(Dispatchers.Default).launch {
while (true) {
manualRefresh()
delay(5000)
}
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
gestureDetector.onTouchEvent(event)
@ -134,9 +234,178 @@ class MainActivity : AppCompatActivity() {
}
fun openAppMenuActivity() {
AppMenuActivity.start(this, installedApps) {
//AppMenuActivity.start(this, installedApps) {
//}
binding.homeView.visibility = View.GONE
val newApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
newApps.addAll(installedApps)
adapter = AppMenuAdapter(this@MainActivity, newApps, this@MainActivity, this@MainActivity, this@MainActivity, "app")
recyclerView.adapter = adapter
binding.appView.visibility = View.VISIBLE
}
override fun onItemClick(appInfo: LauncherActivityInfo, userHandle: UserHandle) {
val mainActivity = launcherApps.getActivityList(appInfo.applicationInfo.packageName, userHandle).firstOrNull()
if (mainActivity != null) {
launcherApps.startMainActivity(mainActivity.componentName, userHandle, null, null)
} else {
Toast.makeText(this, "Cannot launch app", Toast.LENGTH_SHORT).show()
}
}
override fun onShortcut(
appInfo: LauncherActivityInfo,
userHandle: UserHandle,
textView: TextView,
userProfile: Int,
shortcutView: TextView
) {
if (userProfile != 0) {
shortcutView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_work_app, null),null,null,null)
}
else {
shortcutView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_empty, null),null,null,null)
}
shortcutView.text = textView.text.toString()
shortcutView.setOnClickListener {
val mainActivity = launcherApps.getActivityList(appInfo.applicationInfo.packageName, userHandle).firstOrNull()
if (mainActivity != null) {
launcherApps.startMainActivity(mainActivity.componentName, userHandle, null, null)
} else {
Toast.makeText(this, "Cannot launch app", Toast.LENGTH_SHORT).show()
}
}
sharedPreferenceManager.setShortcut(this, shortcutView, appInfo.applicationInfo.packageName, userProfile)
binding.appView.visibility = View.GONE
binding.homeView.visibility = View.VISIBLE
}
override fun onItemLongClick(
appInfo: LauncherActivityInfo,
userHandle: UserHandle,
userProfile: Int,
textView: TextView,
actionMenuLayout: LinearLayout,
editView: LinearLayout,
position: Int
) {
textView.visibility = View.INVISIBLE
actionMenuLayout.visibility = View.VISIBLE
val mainActivity =
launcherApps.getActivityList(appInfo.applicationInfo.packageName, userHandle)
.firstOrNull()
appActionMenu.setActionListeners(
this@MainActivity,
CoroutineScope(Dispatchers.Main),
binding,
textView,
editView,
actionMenuLayout,
searchView,
appInfo.applicationInfo,
userHandle,
userProfile,
launcherApps,
mainActivity,
position
)
}
fun manualRefresh() {
CoroutineScope(Dispatchers.Default).launch {
try {
val updatedApps = appUtils.getInstalledApps(this@MainActivity)
val changes = detectChanges(installedApps, updatedApps)
installedApps = updatedApps
withContext(Dispatchers.Main) {
applyChanges(changes, installedApps)
}
}
catch (_: UninitializedPropertyAccessException) {
}
}
}
private fun detectChanges(oldList: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>, newList: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>): List<Change> {
val changes = mutableListOf<Change>()
val removalChanges = mutableListOf<Change>()
val oldSet = oldList.map { Pair(it.first.applicationInfo.packageName, it.second.second) }.toSet()
val newSet = newList.map { Pair(it.first.applicationInfo.packageName, it.second.second) }.toSet()
//Detect updates
oldList.forEachIndexed { index, oldItem ->
if (newSet.contains(Pair(oldItem.first.applicationInfo.packageName, oldItem.second.second))) {
val newIndex = newList.indexOfFirst { it.first.applicationInfo.packageName == oldItem.first.applicationInfo.packageName && it.second.second == oldItem.second.second }
if (oldItem.first.componentName != newList[newIndex].first.componentName) {
changes.add(Change(ChangeType.UPDATE, index))
}
}
}
// Detect insertions
newList.forEachIndexed { index, newItem ->
if (!oldSet.contains(Pair(newItem.first.applicationInfo.packageName, newItem.second.second))) {
changes.add(Change(ChangeType.INSERT, index))
}
}
// Detect removals
oldList.forEachIndexed { index, oldItem ->
if (!newSet.contains(Pair(oldItem.first.applicationInfo.packageName, oldItem.second.second))) {
removalChanges.add(Change(ChangeType.REMOVE, index))
}
}
changes.addAll(removalChanges.reversed())
return changes
}
private fun applyChanges(changes: List<Change>, updatedApps: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>) {
changes.forEach { change ->
when (change.type) {
ChangeType.INSERT -> {
insertItem(change.position, updatedApps[change.position])
}
ChangeType.REMOVE -> {
try {
removeItem(change.position)
}
catch (_: IndexOutOfBoundsException) {
}
}
ChangeType.UPDATE -> {
updateItem(change.position, updatedApps[change.position])
}
}
}
}
private fun insertItem(position: Int, app: Pair<LauncherActivityInfo, Pair<UserHandle, Int>>) {
adapter.addApp(position, app)
adapter.notifyItemInserted(position)
}
private fun removeItem(position: Int) {
adapter.removeApp(position)
adapter.notifyItemRemoved(position)
}
fun updateItem(position: Int, app: Pair<LauncherActivityInfo, Pair<UserHandle, Int>>) {
adapter.updateApp(position, app)
adapter.notifyItemChanged(position)
}
fun moveItem(position: Int, newPosition: Int) {
Log.d("Movestatus","MOVED")
adapter.moveApp(position, newPosition)
adapter.notifyItemMoved(position, newPosition)
}
}
data class Change(val type: ChangeType, val position: Int, val newPosition: Int = 0)
enum class ChangeType {
INSERT, REMOVE, UPDATE
}

View file

@ -1,37 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout 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:id="@+id/home_view"
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:fillViewport="true"
android:layout_gravity="fill_vertical"
android:fitsSystemWindows="true"
android:gravity="bottom"
android:orientation="vertical"
tools:context=".MainActivity">
<TextClock
android:id="@+id/text_clock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:fontFamily="@null"
android:textAlignment="center"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="70sp" />
<LinearLayout
android:id="@+id/shortcuts"
android:id="@+id/app_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical">
android:layout_height="match_parent"
android:gravity="bottom"
android:orientation="vertical"
android:visibility="gone">
<Space
android:layout_width="match_parent"
android:layout_height="60dp" />
<TextView
android:id="@+id/app1"
android:id="@+id/menutitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
@ -40,129 +32,215 @@
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:text="Select an app"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
android:textColor="#C1F3F3F3"
android:textSize="36sp"
android:visibility="gone" />
<TextView
android:id="@+id/app2"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:fadingEdgeLength="20dp"
android:padding="0dp"
android:requiresFadingEdge="vertical"
android:scrollbars="none"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:stackFromEnd="true">
<TextView
android:id="@+id/app3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
</androidx.recyclerview.widget.RecyclerView>
<TextView
android:id="@+id/app4"
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:layout_marginHorizontal="40dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="40dp"
android:layout_weight="0.1"
android:background="@android:color/transparent"
android:cursorVisible="true"
android:drawableLeft="@android:drawable/ic_menu_search"
android:drawablePadding="8dp"
android:editTextColor="#f3f3f3"
android:hint="Search..."
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
android:textSize="25sp" />
<TextView
android:id="@+id/app5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
<TextView
android:id="@+id/app6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
<TextView
android:id="@+id/app7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
<TextView
android:id="@+id/app8"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
</LinearLayout>
<Space
<LinearLayout
android:id="@+id/home_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:fitsSystemWindows="true"
android:gravity="fill_vertical"
android:orientation="vertical">
</LinearLayout>
<TextClock
android:id="@+id/text_clock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:fontFamily="@null"
android:textAlignment="center"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="70sp" />
<LinearLayout
android:id="@+id/shortcuts"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/app1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoSizeTextType="uniform"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
<TextView
android:id="@+id/app2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
<TextView
android:id="@+id/app3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
<TextView
android:id="@+id/app4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="visible" />
<TextView
android:id="@+id/app5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="gone" />
<TextView
android:id="@+id/app6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="gone" />
<TextView
android:id="@+id/app7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="gone" />
<TextView
android:id="@+id/app8"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="start"
android:paddingLeft="40dp"
android:paddingTop="20dp"
android:paddingRight="40dp"
android:paddingBottom="20dp"
android:text="App"
android:textAppearance="@android:style/TextAppearance.DeviceDefault"
android:textColor="#F3F3F3"
android:textSize="28sp"
android:visibility="gone" />
</LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.15" />
</LinearLayout>
</FrameLayout>