add basic widget selection list

This commit is contained in:
Josia Pietsch 2025-04-16 15:31:45 +02:00
parent 49ae7e130f
commit f025ac12c1
Signed by: jrpie
GPG key ID: E70B571D66986A2D
8 changed files with 237 additions and 4 deletions

View file

@ -106,6 +106,7 @@ dependencies {
implementation 'com.google.android.material:material:1.12.0'
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
implementation "eu.jonahbauer:android-preference-annotations:1.1.2"
implementation 'androidx.activity:activity:1.10.1'
annotationProcessor "eu.jonahbauer:android-preference-annotations:1.1.2"
annotationProcessor "com.android.databinding:compiler:$android_plugin_version"
testImplementation 'junit:junit:4.13.2'

View file

@ -8,7 +8,6 @@
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.ACCESS_HIDDEN_PROFILES" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<!--<uses-permission android:name="android.permission.BIND_APPWIDGET" />-->
<application
android:name=".Application"
@ -20,6 +19,9 @@
android:supportsRtl="true"
android:theme="@style/launcherBaseTheme"
tools:ignore="UnusedAttribute">
<activity
android:name=".ui.widgets.SelectWidgetActivity"
android:exported="false" />
<activity
android:name=".ui.PinShortcutActivity"
android:autoRemoveFromRecents="true"
@ -98,4 +100,4 @@
</service>
</application>
</manifest>
</manifest>

View file

@ -21,6 +21,8 @@ import de.jrpie.android.launcher.apps.togglePrivateSpaceLock
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.list.ListActivity
import de.jrpie.android.launcher.ui.settings.SettingsActivity
import de.jrpie.android.launcher.ui.tutorial.TutorialActivity
import de.jrpie.android.launcher.ui.widgets.SelectWidgetActivity
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -61,7 +63,10 @@ enum class LauncherAction(
"choose_from_favorites",
R.string.list_other_list_favorites,
R.drawable.baseline_favorite_24,
{ context -> openAppsList(context, favorite = true) },
{ context ->
context.startActivity(Intent(context.applicationContext, SelectWidgetActivity::class.java))
},
//openAppsList(context, favorite = true) },
true
),
CHOOSE_FROM_PRIVATE_SPACE(

View file

@ -83,7 +83,7 @@ class HomeActivity : UIObject, AppCompatActivity() {
LauncherAction.SETTINGS.invoke(this)
}
deleteAllWidgets(this)
// deleteAllWidgets(this)
LauncherPreferences.internal().widgets().forEach { widget ->
createAppWidgetView(this, widget)?.let {

View file

@ -0,0 +1,105 @@
package de.jrpie.android.launcher.ui.widgets
import android.app.Activity
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.actions.Action
import de.jrpie.android.launcher.actions.Gesture
import de.jrpie.android.launcher.actions.LauncherAction
import de.jrpie.android.launcher.databinding.ActivitySelectWidgetBinding
import de.jrpie.android.launcher.databinding.HomeBinding
import de.jrpie.android.launcher.ui.list.ListActivity
import de.jrpie.android.launcher.ui.list.other.OtherRecyclerAdapter
import de.jrpie.android.launcher.widgets.bindAppWidget
import de.jrpie.android.launcher.widgets.getAppWidgetProviders
class SelectWidgetActivity : AppCompatActivity() {
lateinit var binding: ActivitySelectWidgetBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
// Initialise layout
binding = ActivitySelectWidgetBinding.inflate(layoutInflater)
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val viewManager = LinearLayoutManager(this)
val viewAdapter = SelectWidgetRecyclerAdapter(this)
binding.selectWidgetRecycler.apply {
// improve performance (since content changes don't change the layout size)
setHasFixedSize(true)
layoutManager = viewManager
adapter = viewAdapter
}
}
}
class SelectWidgetRecyclerAdapter(val activity: Activity) :
RecyclerView.Adapter<SelectWidgetRecyclerAdapter.ViewHolder>() {
private val widgets = getAppWidgetProviders(activity).toTypedArray()
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
View.OnClickListener {
var textView: TextView = itemView.findViewById(R.id.list_widgets_row_name)
var iconView: ImageView = itemView.findViewById(R.id.list_widgets_row_icon)
var previewView: ImageView = itemView.findViewById(R.id.list_widgets_row_preview)
override fun onClick(v: View) {
val pos = bindingAdapterPosition
val content = widgets[pos]
bindAppWidget(activity, content)
activity.finish()
}
init {
itemView.setOnClickListener(this)
}
}
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
val label = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
"${widgets[i].activityInfo.loadLabel(activity.packageManager)} ${widgets[i].loadDescription(activity)}"
} else {
widgets[i].label
}
val preview = widgets[i].loadPreviewImage(activity, 100)
val icon = widgets[i].loadIcon(activity, 100)
viewHolder.textView.text = label
viewHolder.iconView.setImageDrawable(icon)
viewHolder.previewView.setImageDrawable(preview)
}
override fun getItemCount(): Int {
return widgets.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view: View = inflater.inflate(R.layout.list_widgets_row, parent, false)
return ViewHolder(view)
}
}

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.widgets.SelectWidgetActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/select_widget_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@null"
app:elevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/select_widget_heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="?actionBarSize"
android:padding="@dimen/appbar_padding"
android:text="@string/select_widget_title"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:textSize="30sp"
app:layout_constraintEnd_toStartOf="@id/select_widget_close"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/select_widget_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"
android:paddingRight="16sp"
android:src="@drawable/baseline_close_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/select_widget_recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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/list_apps_row_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15sp">
<ImageView
android:id="@+id/list_widgets_row_preview"
android:layout_width="0dp"
android:maxWidth="500dp"
android:maxHeight="200dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@mipmap/ic_launcher_round"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/list_widgets_row_icon"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constraintBottom_toBottomOf="@id/list_widgets_row_preview"
app:layout_constraintStart_toStartOf="@id/list_widgets_row_preview"
tools:src="@mipmap/ic_launcher_round"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/list_widgets_row_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20sp"
android:gravity="start"
android:text=""
android:textSize="20sp"
tools:text="some widget"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/list_widgets_row_preview"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -388,5 +388,6 @@
<string name="legal_info_title">Open Source Licenses</string>
<string name="toast_activity_not_found_search_web">No app found to handle search.</string>
<string name="toast_activity_not_found_browser">Can\'t open URL: no browser found.</string>
<string name="select_widget_title">Choose Widget</string>
</resources>