mirror of
https://github.com/He4eT/yamf_launcher.git
synced 2026-05-05 01:47:24 +00:00
Added a long-press menu (info, delete, hide, rename). Rename not done. Others work.
This commit is contained in:
parent
57721ac89b
commit
71338fb9f1
10 changed files with 249 additions and 615 deletions
|
|
@ -46,6 +46,7 @@ dependencies {
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
||||||
|
implementation("com.google.code.gson:gson:2.10")
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES" />
|
<uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES" />
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,29 @@
|
||||||
package eu.ottop.yamlauncher
|
package eu.ottop.yamlauncher
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.LauncherActivityInfo
|
import android.content.pm.LauncherActivityInfo
|
||||||
import android.content.pm.LauncherApps
|
import android.content.pm.LauncherApps
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.Drawable
|
import android.net.Uri
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.util.Log
|
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.PopupWindow
|
||||||
import android.widget.SearchView
|
import android.widget.SearchView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
|
||||||
import com.google.android.material.tabs.TabLayout
|
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
|
||||||
import eu.ottop.yamlauncher.databinding.ActivityAppMenuBinding
|
import eu.ottop.yamlauncher.databinding.ActivityAppMenuBinding
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.SortedMap
|
|
||||||
|
|
||||||
class AppMenuActivity : AppCompatActivity() {
|
class AppMenuActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
|
@ -40,10 +35,11 @@ class AppMenuActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
binding = ActivityAppMenuBinding.inflate(layoutInflater)
|
binding = ActivityAppMenuBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setSupportActionBar(null)
|
setSupportActionBar(null)
|
||||||
shownApps = listOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
|
shownApps = listOf()
|
||||||
searchView = findViewById(R.id.searchView)
|
searchView = findViewById(R.id.searchView)
|
||||||
container = findViewById(R.id.container)
|
container = findViewById(R.id.container)
|
||||||
|
|
||||||
|
|
@ -62,7 +58,7 @@ class AppMenuActivity : AppCompatActivity() {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.root.addOnLayoutChangeListener { view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
|
binding.root.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom ->
|
||||||
if (bottom - top > oldBottom - oldTop) {
|
if (bottom - top > oldBottom - oldTop) {
|
||||||
searchView.clearFocus()
|
searchView.clearFocus()
|
||||||
}
|
}
|
||||||
|
|
@ -70,45 +66,6 @@ class AppMenuActivity : AppCompatActivity() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
super.onStop()
|
|
||||||
checkApps?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
startTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startTask() {
|
|
||||||
checkApps = GlobalScope.launch {
|
|
||||||
while (true) {
|
|
||||||
if (!listsEqual(shownApps, getInstalledPersonalApps())) {
|
|
||||||
Log.d("AHAHHAHAA","AHJAHAHA")
|
|
||||||
shownApps = getInstalledPersonalApps()
|
|
||||||
runOnUiThread {
|
|
||||||
deleteAppMenuContents()
|
|
||||||
createPersonalAppMenu()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
delay(1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun listsEqual(list1: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>, list2: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>): Boolean {
|
|
||||||
if (list1.size != list2.size) return false
|
|
||||||
|
|
||||||
for (i in list1.indices) {
|
|
||||||
if (list1[i].first.componentName != list2[i].first.componentName || list1[i].second.first != list2[i].second.first) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun filterItems(query: String?) {
|
private fun filterItems(query: String?) {
|
||||||
val cleanQuery = query?.replace("[^a-zA-Z0-9]".toRegex(), "")
|
val cleanQuery = query?.replace("[^a-zA-Z0-9]".toRegex(), "")
|
||||||
|
|
||||||
|
|
@ -128,30 +85,101 @@ class AppMenuActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
checkApps?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
startTask()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startTask() {
|
||||||
|
checkApps = GlobalScope.launch {
|
||||||
|
while (true) {
|
||||||
|
if (!listsEqual(shownApps, getInstalledApps())) {
|
||||||
|
shownApps = getInstalledApps()
|
||||||
|
runOnUiThread {
|
||||||
|
refreshAppMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun listsEqual(
|
||||||
|
list1: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>,
|
||||||
|
list2: List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>
|
||||||
|
): Boolean {
|
||||||
|
if (list1.size != list2.size) return false
|
||||||
|
|
||||||
|
for (i in list1.indices) {
|
||||||
|
if (list1[i].first.componentName != list2[i].first.componentName || list1[i].second.first != list2[i].second.first) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshAppMenu() {
|
||||||
|
deleteAppMenuContents()
|
||||||
|
createAppMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteAppMenuContents(): Boolean {
|
||||||
|
binding.container.removeAllViewsInLayout()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAppMenu(): Boolean {
|
||||||
|
val apps = getInstalledApps()
|
||||||
|
apps.forEach { appInfo ->
|
||||||
|
createAppText(appInfo.first, appInfo.second.first, appInfo.second.second)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
private fun getInstalledApps(): List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> {
|
private fun getInstalledApps(): List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> {
|
||||||
val allApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
|
val allApps = mutableListOf<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>>()
|
||||||
val launcherApps = this.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
val launcherApps = this.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
||||||
for (i in launcherApps.profiles.indices) {
|
for (i in launcherApps.profiles.indices) {
|
||||||
launcherApps.getActivityList(null, launcherApps.profiles[i]).forEach { app ->
|
launcherApps.getActivityList(null, launcherApps.profiles[i]).forEach { app ->
|
||||||
allApps.add(Pair(app, Pair(launcherApps.profiles[i], i)))
|
if (!isAppHidden(app.activityInfo.applicationInfo.packageName, i)) {
|
||||||
|
allApps.add(Pair(app, Pair(launcherApps.profiles[i], i)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return allApps.sortedBy { it.first.label.toString().lowercase() }
|
return allApps.sortedBy {
|
||||||
|
it.first.applicationInfo.loadLabel(packageManager).toString().lowercase()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInstalledPersonalApps(): List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> {
|
private fun createAppText(
|
||||||
return getInstalledApps()
|
appInfo: LauncherActivityInfo,
|
||||||
}
|
userHandle: UserHandle,
|
||||||
|
workProfile: Int
|
||||||
private fun getInstalledWorkApps(): List<Pair<LauncherActivityInfo, Pair<UserHandle, Int>>> {
|
): Boolean {
|
||||||
return getInstalledApps()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAppMenu(appInfo: LauncherActivityInfo, userHandle: UserHandle, workProfile: Int): Boolean {
|
|
||||||
val appInfo = appInfo.activityInfo.applicationInfo
|
val appInfo = appInfo.activityInfo.applicationInfo
|
||||||
val textView = TextView(this)
|
|
||||||
|
|
||||||
|
val textView = TextView(this)
|
||||||
|
val launcherApps = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
||||||
|
val mainActivity =
|
||||||
|
launcherApps.getActivityList(appInfo.packageName, userHandle).firstOrNull()
|
||||||
|
|
||||||
|
setupTextView(textView, appInfo, workProfile)
|
||||||
|
|
||||||
|
setupTextListeners(textView, appInfo, userHandle, workProfile, launcherApps, mainActivity)
|
||||||
|
|
||||||
|
binding.container.addView(textView)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupTextView(textView: TextView, appInfo: ApplicationInfo, workProfile: Int) {
|
||||||
val states = arrayOf(
|
val states = arrayOf(
|
||||||
intArrayOf(-android.R.attr.state_pressed),
|
intArrayOf(-android.R.attr.state_pressed),
|
||||||
intArrayOf(android.R.attr.state_pressed)
|
intArrayOf(android.R.attr.state_pressed)
|
||||||
|
|
@ -164,57 +192,136 @@ class AppMenuActivity : AppCompatActivity() {
|
||||||
|
|
||||||
with(textView) {
|
with(textView) {
|
||||||
textSize = 28f
|
textSize = 28f
|
||||||
setPadding(0,0,0,50)
|
setPadding(0, 10, 0, 80)
|
||||||
isClickable = true
|
isClickable = true
|
||||||
focusable = View.FOCUSABLE
|
focusable = View.FOCUSABLE
|
||||||
gravity = Gravity.START
|
gravity = Gravity.START
|
||||||
|
|
||||||
if (workProfile != 0) {
|
text = if (workProfile != 0) {
|
||||||
text = "*"+appInfo.loadLabel(packageManager)
|
"*" + appInfo.loadLabel(packageManager)
|
||||||
}
|
} else {
|
||||||
else {
|
appInfo.loadLabel(packageManager)
|
||||||
text = appInfo.loadLabel(packageManager)
|
|
||||||
}
|
}
|
||||||
setTextColor(ColorStateList(states, colors))
|
setTextColor(ColorStateList(states, colors))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupTextListeners(
|
||||||
|
textView: TextView,
|
||||||
|
appInfo: ApplicationInfo,
|
||||||
|
userHandle: UserHandle,
|
||||||
|
workProfile: Int,
|
||||||
|
launcherApps: LauncherApps,
|
||||||
|
mainActivity: LauncherActivityInfo?
|
||||||
|
) {
|
||||||
textView.setOnLongClickListener {
|
textView.setOnLongClickListener {
|
||||||
Toast.makeText(this, "Long press detected on ${appInfo.loadLabel(packageManager)}", Toast.LENGTH_SHORT).show()
|
appActionMenu(textView, appInfo, userHandle, workProfile, launcherApps, mainActivity)
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textView.setOnClickListener {
|
textView.setOnClickListener {
|
||||||
val launcherApps = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
|
||||||
val packageName = appInfo.packageName
|
|
||||||
|
|
||||||
val mainActivity = launcherApps.getActivityList(packageName, userHandle).firstOrNull()
|
|
||||||
|
|
||||||
if (mainActivity != null) {
|
if (mainActivity != null) {
|
||||||
launcherApps.startMainActivity(mainActivity.componentName, userHandle, null, null)
|
launcherApps.startMainActivity(mainActivity.componentName, userHandle, null, null)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "Unable to launch ${appInfo.loadLabel(packageManager)}", Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
"Unable to launch ${appInfo.loadLabel(packageManager)}",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun appActionMenu(
|
||||||
|
textView: TextView,
|
||||||
|
appInfo: ApplicationInfo,
|
||||||
|
userHandle: UserHandle,
|
||||||
|
workProfile: Int,
|
||||||
|
launcherApps: LauncherApps,
|
||||||
|
mainActivity: LauncherActivityInfo?
|
||||||
|
): Boolean {
|
||||||
|
val inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||||
|
val popupView = inflater.inflate(R.layout.app_action_menu, null)
|
||||||
|
|
||||||
|
val popupWindow = PopupWindow(
|
||||||
|
popupView,
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
|
||||||
|
popupWindow.isOutsideTouchable = true
|
||||||
|
popupWindow.isFocusable = true
|
||||||
|
|
||||||
|
popupWindow.animationStyle = android.R.style.Animation_Translucent
|
||||||
|
|
||||||
|
if (appInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) {
|
||||||
|
popupView.findViewById<TextView>(R.id.uninstall).visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.visibility = View.INVISIBLE
|
||||||
|
|
||||||
|
popupWindow.showAsDropDown(textView, 0, -textView.height)
|
||||||
|
|
||||||
|
popupWindow.setOnDismissListener {
|
||||||
|
textView.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
popupView.findViewById<TextView>(R.id.info).setOnClickListener {
|
||||||
|
if (mainActivity != null) {
|
||||||
|
launcherApps.startAppDetailsActivity(
|
||||||
|
mainActivity.componentName,
|
||||||
|
userHandle,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
popupWindow.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the button to the LinearLayout
|
popupView.findViewById<TextView>(R.id.uninstall).setOnClickListener {
|
||||||
binding.container.addView(textView)
|
val intent = Intent(Intent.ACTION_DELETE)
|
||||||
|
intent.data = Uri.parse("package:${appInfo.packageName}")
|
||||||
|
intent.putExtra(Intent.EXTRA_USER, userHandle)
|
||||||
|
startActivity(intent)
|
||||||
|
|
||||||
return true
|
popupWindow.dismiss()
|
||||||
}
|
|
||||||
|
|
||||||
private fun createPersonalAppMenu(): Boolean {
|
|
||||||
val pApps = getInstalledPersonalApps()
|
|
||||||
pApps.forEach { appInfo ->
|
|
||||||
createAppMenu(appInfo.first, appInfo.second.first, appInfo.second.second)
|
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
|
popupView.findViewById<TextView>(R.id.rename).setOnClickListener {
|
||||||
|
// Handle rename action
|
||||||
|
popupWindow.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
popupView.findViewById<TextView>(R.id.hide).setOnClickListener {
|
||||||
|
setAppHidden(appInfo.packageName, workProfile, true)
|
||||||
|
refreshAppMenu()
|
||||||
|
|
||||||
|
popupWindow.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true // Indicate that the long click event is consumed}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteAppMenuContents(): Boolean {
|
private fun setAppHidden(packageName: String, profile: Int, hidden: Boolean) {
|
||||||
binding.container.removeAllViewsInLayout()
|
// Get the shared preferences editor
|
||||||
return true
|
val editor = getSharedPreferences("app_data", MODE_PRIVATE).edit()
|
||||||
|
val key = "$packageName-${profile}"
|
||||||
|
editor.putBoolean(key, hidden)
|
||||||
|
editor.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isAppHidden(packageName: String, profile: Int): Boolean {
|
||||||
|
// Get the shared preferences object
|
||||||
|
val sharedPref = getSharedPreferences("app_data", MODE_PRIVATE)
|
||||||
|
val key = "$packageName-${profile}"
|
||||||
|
return sharedPref.getBoolean(key, false) // Default to false (visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setAppVisible(packageName: String, profile: Int) {
|
||||||
|
// Get the shared preferences editor
|
||||||
|
val editor = getSharedPreferences("app_data", MODE_PRIVATE).edit()
|
||||||
|
val key = "$packageName-${profile}"
|
||||||
|
editor.remove(key)
|
||||||
|
editor.apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,24 +1,9 @@
|
||||||
package eu.ottop.yamlauncher
|
package eu.ottop.yamlauncher
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.FOCUSABLE
|
|
||||||
import android.view.View.OnFocusChangeListener
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.SearchView
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.navigation.findNavController
|
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
|
||||||
import androidx.navigation.ui.navigateUp
|
|
||||||
import eu.ottop.yamlauncher.databinding.ActivityMainBinding
|
import eu.ottop.yamlauncher.databinding.ActivityMainBinding
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
|
||||||
|
|
@ -1,241 +0,0 @@
|
||||||
package eu.ottop.yamlauncher
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.pm.LauncherActivityInfo
|
|
||||||
import android.content.pm.LauncherApps
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.UserHandle
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.Gravity
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.SearchView
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.content.getSystemService
|
|
||||||
import com.google.android.material.tabs.TabLayout
|
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
|
||||||
import eu.ottop.yamlauncher.databinding.ActivityAppMenuBinding
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
// TODO: Rename parameter arguments, choose names that match
|
|
||||||
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
|
||||||
private const val ARG_PARAM1 = "param1"
|
|
||||||
private const val ARG_PARAM2 = "param2"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple [Fragment] subclass.
|
|
||||||
* Use the [PersonalAppsFragment.newInstance] factory method to
|
|
||||||
* create an instance of this fragment.
|
|
||||||
*/
|
|
||||||
class PersonalAppsFragment : Fragment() {
|
|
||||||
|
|
||||||
private lateinit var binding: ActivityAppMenuBinding
|
|
||||||
private lateinit var searchView: SearchView
|
|
||||||
private lateinit var container: LinearLayout
|
|
||||||
private lateinit var tabLayout: TabLayout
|
|
||||||
private var checkApps: Job? = null
|
|
||||||
private lateinit var shownApps: List<LauncherActivityInfo>
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, viewContainer: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
val view = inflater.inflate(R.layout.fragment_personal_apps, viewContainer, false)
|
|
||||||
|
|
||||||
// Initialize views from the fragment layout
|
|
||||||
container = view.findViewById(R.id.container)
|
|
||||||
searchView = requireActivity().findViewById(R.id.searchView)
|
|
||||||
|
|
||||||
shownApps = listOf<LauncherActivityInfo>()
|
|
||||||
|
|
||||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
|
||||||
searchView.clearFocus()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String?): Boolean {
|
|
||||||
// Filter items based on the search query
|
|
||||||
filterItems(newText)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
checkApps?.cancel()
|
|
||||||
searchView.setOnQueryTextListener(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
startTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun filterItems(query: String?) {
|
|
||||||
val cleanQuery = query?.replace("[^a-zA-Z0-9]".toRegex(), "")
|
|
||||||
|
|
||||||
for (i in 0 until container.childCount) {
|
|
||||||
val view = container.getChildAt(i)
|
|
||||||
|
|
||||||
if (view is TextView) {
|
|
||||||
val itemText = view.text.toString()
|
|
||||||
val cleanItemText = itemText.replace("[^a-zA-Z0-9]".toRegex(), "")
|
|
||||||
|
|
||||||
if (cleanItemText.contains(cleanQuery ?: "", ignoreCase = true)) {
|
|
||||||
view.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
view.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startTask() {
|
|
||||||
checkApps = GlobalScope.launch {
|
|
||||||
while (true) {
|
|
||||||
Log.d("APPSITUATION", "Ahahahaha")
|
|
||||||
if (!listsEqual(shownApps, getInstalledPersonalApps())) {
|
|
||||||
shownApps = getInstalledPersonalApps()
|
|
||||||
requireActivity().runOnUiThread {
|
|
||||||
deleteAppMenuContents()
|
|
||||||
createPersonalAppMenu()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
delay(1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun listsEqual(
|
|
||||||
list1: List<LauncherActivityInfo>,
|
|
||||||
list2: List<LauncherActivityInfo>
|
|
||||||
): Boolean {
|
|
||||||
if (list1.size != list2.size) return false
|
|
||||||
|
|
||||||
for (i in list1.indices) {
|
|
||||||
if (list1[i].label != list2[i].label) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getInstalledApps(profile: Int): List<LauncherActivityInfo> {
|
|
||||||
val allApps = mutableListOf<LauncherActivityInfo>()
|
|
||||||
val launcherApps =
|
|
||||||
requireActivity().getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
|
||||||
|
|
||||||
allApps.addAll(launcherApps.getActivityList(null, launcherApps.profiles[profile]))
|
|
||||||
|
|
||||||
return allApps.sortedWith(compareBy {
|
|
||||||
it.applicationInfo.loadLabel(requireActivity().packageManager).toString().lowercase()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getInstalledPersonalApps(): List<LauncherActivityInfo> {
|
|
||||||
return getInstalledApps(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAppMenu(
|
|
||||||
appInfo: LauncherActivityInfo,
|
|
||||||
userHandle: UserHandle,
|
|
||||||
workProfile: Boolean
|
|
||||||
): Boolean {
|
|
||||||
val appInfo = appInfo.activityInfo.applicationInfo
|
|
||||||
val textView = TextView(requireContext())
|
|
||||||
textView.textSize = 28f
|
|
||||||
textView.setPadding(0, 0, 0, 50)
|
|
||||||
|
|
||||||
val states = arrayOf(
|
|
||||||
intArrayOf(-android.R.attr.state_pressed),
|
|
||||||
intArrayOf(android.R.attr.state_pressed)
|
|
||||||
)
|
|
||||||
|
|
||||||
val colors = intArrayOf(
|
|
||||||
Color.parseColor("#f3f3f3"), // Default text color
|
|
||||||
Color.parseColor("#c3c3c3") // Text color when pressed
|
|
||||||
)
|
|
||||||
|
|
||||||
textView.setTextColor(ColorStateList(states, colors))
|
|
||||||
|
|
||||||
textView.isClickable = true
|
|
||||||
textView.focusable = View.FOCUSABLE
|
|
||||||
textView.gravity = Gravity.START
|
|
||||||
textView.text = appInfo.loadLabel(requireActivity().packageManager)
|
|
||||||
|
|
||||||
textView.setOnLongClickListener {
|
|
||||||
Toast.makeText(
|
|
||||||
requireContext(),
|
|
||||||
"Long press detected on ${appInfo.loadLabel(requireActivity().packageManager)}",
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
textView.setOnClickListener {
|
|
||||||
val launcherApps =
|
|
||||||
requireActivity().getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
|
||||||
val packageName = appInfo.packageName
|
|
||||||
|
|
||||||
val mainActivity = launcherApps.getActivityList(packageName, userHandle).firstOrNull()
|
|
||||||
|
|
||||||
if (mainActivity != null) {
|
|
||||||
launcherApps.startMainActivity(mainActivity.componentName, userHandle, null, null)
|
|
||||||
} else {
|
|
||||||
Toast.makeText(
|
|
||||||
requireContext(),
|
|
||||||
"Unable to launch ${appInfo.loadLabel(requireActivity().packageManager)}",
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the button to the LinearLayout
|
|
||||||
container.addView(textView)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createPersonalAppMenu(): Boolean {
|
|
||||||
val pApps = getInstalledPersonalApps()
|
|
||||||
pApps.forEach { appInfo ->
|
|
||||||
createAppMenu(appInfo, pApps.first().user, false)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deleteAppMenuContents(): Boolean {
|
|
||||||
binding.container.removeAllViewsInLayout()
|
|
||||||
return true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setActivityReferences(binding: ActivityAppMenuBinding) {
|
|
||||||
this.binding = binding
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newInstance(binding: ActivityAppMenuBinding) = PersonalAppsFragment().apply {
|
|
||||||
this.binding = binding
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,237 +0,0 @@
|
||||||
package eu.ottop.yamlauncher
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.pm.LauncherActivityInfo
|
|
||||||
import android.content.pm.LauncherApps
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.UserHandle
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.Gravity
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.SearchView
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
|
||||||
import com.google.android.material.tabs.TabLayout
|
|
||||||
import eu.ottop.yamlauncher.databinding.ActivityAppMenuBinding
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
// TODO: Rename parameter arguments, choose names that match
|
|
||||||
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
|
||||||
private const val ARG_PARAM1 = "param1"
|
|
||||||
private const val ARG_PARAM2 = "param2"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple [Fragment] subclass.
|
|
||||||
* Use the [WorkAppsFragment.newInstance] factory method to
|
|
||||||
* create an instance of this fragment.
|
|
||||||
*/
|
|
||||||
class WorkAppsFragment : Fragment() {
|
|
||||||
private lateinit var binding: ActivityAppMenuBinding
|
|
||||||
private lateinit var searchView: SearchView
|
|
||||||
private lateinit var container: LinearLayout
|
|
||||||
private lateinit var tabLayout: TabLayout
|
|
||||||
private var checkApps: Job? = null
|
|
||||||
private lateinit var shownApps: List<LauncherActivityInfo>
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, viewContainer: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
val view = inflater.inflate(R.layout.fragment_personal_apps, viewContainer, false)
|
|
||||||
|
|
||||||
// Initialize views from the fragment layout
|
|
||||||
container = view.findViewById(R.id.container)
|
|
||||||
searchView = requireActivity().findViewById(R.id.searchView)
|
|
||||||
|
|
||||||
shownApps = listOf<LauncherActivityInfo>()
|
|
||||||
|
|
||||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
|
||||||
searchView.clearFocus()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String?): Boolean {
|
|
||||||
|
|
||||||
filterItems(newText)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
checkApps?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
startTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun filterItems(query: String?) {
|
|
||||||
val cleanQuery = query?.replace("[^a-zA-Z0-9]".toRegex(), "")
|
|
||||||
|
|
||||||
for (i in 0 until container.childCount) {
|
|
||||||
val view = container.getChildAt(i)
|
|
||||||
|
|
||||||
if (view is TextView) {
|
|
||||||
val itemText = view.text.toString()
|
|
||||||
val cleanItemText = itemText.replace("[^a-zA-Z0-9]".toRegex(), "")
|
|
||||||
|
|
||||||
if (cleanItemText.contains(cleanQuery ?: "", ignoreCase = true)) {
|
|
||||||
view.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
view.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startTask() {
|
|
||||||
checkApps = GlobalScope.launch {
|
|
||||||
while (true) {
|
|
||||||
Log.d("APPSITUATION1234", "Ahahahaha")
|
|
||||||
if (!listsEqual(shownApps, getInstalledWorkApps())) {
|
|
||||||
shownApps = getInstalledWorkApps()
|
|
||||||
requireActivity().runOnUiThread {
|
|
||||||
deleteAppMenuContents()
|
|
||||||
createWorkAppMenu()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
delay(1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun listsEqual(
|
|
||||||
list1: List<LauncherActivityInfo>,
|
|
||||||
list2: List<LauncherActivityInfo>
|
|
||||||
): Boolean {
|
|
||||||
if (list1.size != list2.size) return false
|
|
||||||
|
|
||||||
for (i in list1.indices) {
|
|
||||||
if (list1[i].label != list2[i].label) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getInstalledApps(profile: Int): List<LauncherActivityInfo> {
|
|
||||||
val allApps = mutableListOf<LauncherActivityInfo>()
|
|
||||||
val launcherApps =
|
|
||||||
requireActivity().getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
|
||||||
|
|
||||||
allApps.addAll(launcherApps.getActivityList(null, launcherApps.profiles[profile]))
|
|
||||||
|
|
||||||
return allApps.sortedWith(compareBy {
|
|
||||||
it.applicationInfo.loadLabel(requireActivity().packageManager).toString().lowercase()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getInstalledWorkApps(): List<LauncherActivityInfo> {
|
|
||||||
return getInstalledApps(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAppMenu(
|
|
||||||
appInfo: LauncherActivityInfo,
|
|
||||||
userHandle: UserHandle,
|
|
||||||
workProfile: Boolean
|
|
||||||
): Boolean {
|
|
||||||
val appInfo = appInfo.activityInfo.applicationInfo
|
|
||||||
val textView = TextView(requireContext())
|
|
||||||
textView.textSize = 28f
|
|
||||||
textView.setPadding(0, 0, 0, 50)
|
|
||||||
|
|
||||||
val states = arrayOf(
|
|
||||||
intArrayOf(-android.R.attr.state_pressed),
|
|
||||||
intArrayOf(android.R.attr.state_pressed)
|
|
||||||
)
|
|
||||||
|
|
||||||
val colors = intArrayOf(
|
|
||||||
Color.parseColor("#f3f3f3"), // Default text color
|
|
||||||
Color.parseColor("#c3c3c3") // Text color when pressed
|
|
||||||
)
|
|
||||||
|
|
||||||
textView.setTextColor(ColorStateList(states, colors))
|
|
||||||
|
|
||||||
textView.isClickable = true
|
|
||||||
textView.focusable = View.FOCUSABLE
|
|
||||||
textView.gravity = Gravity.START
|
|
||||||
textView.text = appInfo.loadLabel(requireActivity().packageManager)
|
|
||||||
|
|
||||||
textView.setOnLongClickListener {
|
|
||||||
Toast.makeText(
|
|
||||||
requireContext(),
|
|
||||||
"Long press detected on ${appInfo.loadLabel(requireActivity().packageManager)}",
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
textView.setOnClickListener {
|
|
||||||
val launcherApps =
|
|
||||||
requireActivity().getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
|
||||||
val packageName = appInfo.packageName
|
|
||||||
|
|
||||||
val mainActivity = launcherApps.getActivityList(packageName, userHandle).firstOrNull()
|
|
||||||
|
|
||||||
if (mainActivity != null) {
|
|
||||||
launcherApps.startMainActivity(mainActivity.componentName, userHandle, null, null)
|
|
||||||
} else {
|
|
||||||
Toast.makeText(
|
|
||||||
requireContext(),
|
|
||||||
"Unable to launch ${appInfo.loadLabel(requireActivity().packageManager)}",
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the button to the LinearLayout
|
|
||||||
container.addView(textView)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createWorkAppMenu(): Boolean {
|
|
||||||
val pApps = getInstalledWorkApps()
|
|
||||||
pApps.forEach { appInfo ->
|
|
||||||
createAppMenu(appInfo, pApps.first().user, false)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deleteAppMenuContents(): Boolean {
|
|
||||||
binding.container.removeAllViewsInLayout()
|
|
||||||
return true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setActivityReferences(binding: ActivityAppMenuBinding) {
|
|
||||||
this.binding = binding
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newInstance(binding: ActivityAppMenuBinding) = WorkAppsFragment().apply {
|
|
||||||
this.binding = binding
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
app/src/main/res/drawable/app_action_foreground.xml
Normal file
15
app/src/main/res/drawable/app_action_foreground.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- Pressed state -->
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#0FFFFFFF"/> <!-- Change color to indicate pressed state -->
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<!-- Normal state -->
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#00FFFFFF"/> <!-- Change color to indicate normal state -->
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
51
app/src/main/res/layout/app_action_menu.xml
Normal file
51
app/src/main/res/layout/app_action_menu.xml
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="#6F000000">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/info"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:foreground="@drawable/app_action_foreground"
|
||||||
|
android:drawableTop="@android:drawable/ic_menu_info_details"
|
||||||
|
android:text="Info"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="#F3F3F3FF" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/uninstall"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:foreground="@drawable/app_action_foreground"
|
||||||
|
android:drawableTop="@android:drawable/ic_menu_delete"
|
||||||
|
android:text="Uninstall"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="#F3F3F3FF" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/rename"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:foreground="@drawable/app_action_foreground"
|
||||||
|
android:drawableTop="@android:drawable/ic_menu_edit"
|
||||||
|
android:text="Rename"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="#F3F3F3FF" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/hide"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:foreground="@drawable/app_action_foreground"
|
||||||
|
android:drawableTop="@android:drawable/ic_menu_view"
|
||||||
|
android:text="Hide"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="#F3F3F3FF" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/app_list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:layout_marginHorizontal="10dp"
|
|
||||||
android:layout_marginTop="25dp"
|
|
||||||
android:layout_weight="0.9"
|
|
||||||
android:fadingEdge="none"
|
|
||||||
android:fillViewport="true"
|
|
||||||
android:requiresFadingEdge="vertical"
|
|
||||||
android:scrollbars="none">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fadingEdge="none"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp"/>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/app_list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:layout_marginHorizontal="10dp"
|
|
||||||
android:layout_marginTop="25dp"
|
|
||||||
android:layout_weight="0.9"
|
|
||||||
android:fadingEdge="none"
|
|
||||||
android:fillViewport="true"
|
|
||||||
android:requiresFadingEdge="vertical"
|
|
||||||
android:scrollbars="none">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fadingEdge="none"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<!-- Buttons dynamically added here -->
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue