This code demonstrates how to create a popup menu with icons in an Android application written in Kotlin. The code utilizes functionalities from the AppCompat library and offers solutions for different Android API levels.
Key functionalities explained:
- The
MainActivity.kt
file handles the core logic. It displays a text view with a click listener that triggers theshowPopupMenu()
function. - The
showPopupMenu()
function inflates a popup menu from a resource file (popup_menu.xml
). It sets a listener to handle user selections on the menu items. - There are two approaches for displaying icons on the menu items:
- For API level 29 (Android Q) and above, a direct method (
setForceShowIcon(true)
) is available. - For lower API levels, reflection is used to access a hidden method and achieve the same result.
- For API level 29 (Android Q) and above, a direct method (
Summary
This code provides a well-structured and informative example for implementing a popup menu with icons in an Android Kotlin application. It showcases handling different API levels and offers flexibility for developers targeting various Android versions.
MainActivity.kt
package com.example.jetpack
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.widget.PopupMenu
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.reflect.Method
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// show sdk version in text view
textView.append("\nAPI " + Build.VERSION.SDK_INT)
// text view click listener
textView.setOnClickListener {
showPopupMenu()
}
}
// method to show popup menu
private fun showPopupMenu(){
val popup = PopupMenu(this,textView)
popup.apply {
// inflate the popup menu
menuInflater.inflate(R.menu.popup_menu,menu)
// popup menu item click listener
setOnMenuItemClickListener {
when(it.itemId){
R.id.red->{
textView.setTextColor(Color.RED)
}R.id.green->{
textView.setTextColor(Color.GREEN)
}R.id.yellow->{
textView.setTextColor(Color.YELLOW)
}R.id.gray->{
textView.setTextColor(Color.GRAY)
}
}
false
}
}
// show icons on popup menu
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
popup.setForceShowIcon(true)
}else{
try {
val fields = popup.javaClass.declaredFields
for (field in fields) {
if ("mPopup" == field.name) {
field.isAccessible = true
val menuPopupHelper = field[popup]
val classPopupHelper =
Class.forName(menuPopupHelper.javaClass.name)
val setForceIcons: Method = classPopupHelper.getMethod(
"setForceShowIcon",
Boolean::class.javaPrimitiveType
)
setForceIcons.invoke(menuPopupHelper, true)
break
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
// finally, show the popup menu
popup.show()
}
}
activity_main.xml
<?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/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/textView"
style="@style/TextAppearance.MaterialComponents.Headline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="11dp"
android:text="Show Popup Menu"
android:background="#F6F6F2"
android:padding="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
res/menu/popup_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/red"
android:title="Red"
android:icon="@drawable/ic_camera"
android:iconTint="#F44336"
android:iconTintMode="src_in"
/>
<item
android:id="@+id/green"
android:title="Green"
android:icon="@drawable/ic_donut_large"
android:iconTint="#4CAF50"
android:iconTintMode="src_in"
/>
<item
android:id="@+id/yellow"
android:title="Yellow"
android:icon="@drawable/ic_dock"
android:iconTint="#FFEB3B"
android:iconTintMode="src_in"
/>
<item
android:id="@+id/gray"
android:title="Gray"
android:icon="@drawable/ic_add_circle"
android:iconTint="#707070"
android:iconTintMode="src_in"
/>
</menu>