使用Kotlin的Android菜单

时间:2020-02-23 14:29:04  来源:igfitidea点击:

在本教程中,我们将使用Kotlin在我们的android应用程序中讨论和实现Android Menu类。
我们将看到菜单在屏幕上显示的不同方式。

Android菜单

菜单是一个UI组件,用于显示选项列表以执行快速操作。
Android中的菜单大致分为三种类型:

  • 选项菜单–这些是最常见的菜单形式。
    它们通常显示在工具列中。

  • 上下文菜单–这些是浮动菜单,当用户长按应显示菜单的小部件时会显示这些菜单

  • 弹出菜单–这些显示在单击的小部件上方或者下方的锚点上。

可以在resources文件夹内定义Android菜单。
每个菜单都与一个图标和一个标题以及一个属性" showAsAction"相关联。
android:orderInCategory属性用于设置菜单中菜单项的顺序。
最高顺序占据最左侧的位置。
它接受一个整数值。

在下一节中,我们将使用Kotlin创建一个Android应用程序,其中将涵盖所有这些菜单类型。

项目结构

在res文件夹中,创建一个新的资源目录来保存菜单。
在创建的新菜单文件夹中,创建菜单资源布局文件:

代码

menu_main.xml菜单文件的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">

  <item
      android:id="@+id/agenda"
      android:icon="@android:drawable/ic_menu_agenda"
      android:orderInCategory="100"
      android:title="Agenda"
      app:showAsAction="never" 

  <item
      android:id="@+id/call"
      android:icon="@android:drawable/ic_menu_call"
      android:orderInCategory="100"
      android:title="Call"
      app:showAsAction="always" 

  <item
      android:id="@+id/add"
      android:icon="@android:drawable/ic_menu_add"
      android:orderInCategory="100"
      android:title="Add"
      app:showAsAction="ifRoom" 

  <item
      android:id="@+id/compass"
      android:icon="@android:drawable/ic_menu_compass"
      android:orderInCategory="100"
      android:title="Compass"
      app:showAsAction="always" 

  <item
      android:id="@+id/day"
      android:orderInCategory="100"
      android:title="Day"
      app:showAsAction="always|withText" 

</menu>

ifRoom值指示仅在有空间时显示菜单图标。
此优先级是第二低的。
从不值表示菜单图标在工具列/菜单布局中根本不会显示。
它位于溢出菜单中。
始终表示菜单图标。
withText表示将显示菜单文本。

我们可以合并以上两个值中的任何一个(不合并绝对值没有意义!)

菜单文件" popup_menu.xml"的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

  <item
      android:id="@+id/one"
      android:title="One" 

  <item
      android:id="@+id/two"
      android:title="Two" 

  <item
      android:id="@+id/three"
      android:title="Three" 

</menu>

菜单项也可以分组。
我们可以在组上添加可检查的行为:popup_menu_group.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

  <group
      android:id="@+id/my_move"
      android:checkableBehavior="single">
      <item
          android:id="@+id/one"
          android:title="One" 

      <item
          android:id="@+id/two"
          android:title="Two" 

      <item
          android:id="@+id/three"
          android:title="Three" 
  </group>

  <group
      android:id="@+id/second"
      android:checkableBehavior="all">
      <item
          android:id="@+id/four"
          android:checked="true"
          android:title="Four" 

      <item
          android:id="@+id/five"
          android:title="Five" 

      <item
          android:id="@+id/six"
          android:title="Six" 
  </group>

</menu>

下面给出了" activity_main.xml"布局文件的代码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">

  <Button
      android:id="@+id/btnContextMenu"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Context Menu"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toTopOf="parent" 

  <Button
      android:id="@+id/btnPopUpMenu"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginTop="16dp"
      android:text="Popup Menu"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/btnContextMenu" 

  <Button
      android:id="@+id/btnPopUpMenuGroup"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginTop="16dp"
      android:text="Popup Menu Group"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/btnPopUpMenu" 

</android.support.constraint.ConstraintLayout>

对于选项菜单,需要重写两个方法:onCreateOptionsMenu和onOptionsItemSelected。
在" onCreateOptionsMenu"中,我们使用MenuInflater类为XML菜单充气。

ContextMenu在特定视图上触发。
我们需要在该视图上调用registerForContextMenu
这会触发onCreateContextMenu,在此我们在菜单列表中添加MenuItems。
选择任何文本菜单时onContextItemSelected被触发。

单击任何视图时将创建PopupMenu。
PopMenu本身通过使用menuInflater扩展菜单资源文件进行初始化。
为了显示PopupMenu,我们在其实例上调用show函数。

MainActivity.kt类的代码如下:

package com.theitroad.androidlymenus

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import android.support.v7.widget.PopupMenu

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      registerForContextMenu(btnContextMenu)

      btnContextMenu.setOnLongClickListener {
          openContextMenu(btnContextMenu)
          true
      }

      btnPopUpMenu.setOnClickListener {

          val popup = PopupMenu(this@MainActivity, btnPopUpMenu)
          //Inflating the Popup using xml file
          popup.menuInflater.inflate(R.menu.popup_menu, popup.menu)

          popup.setOnMenuItemClickListener({
              if (it.itemId == R.id.one) {
                  Toast.makeText(applicationContext, "One", Toast.LENGTH_SHORT).show()
              } else {
                  Toast.makeText(applicationContext, "None", Toast.LENGTH_SHORT).show()
              }
              true
          })

          popup.show()//showing popup menu

      }

      btnPopUpMenuGroup.setOnClickListener {

          val popup = PopupMenu(this@MainActivity, btnPopUpMenu)
          //Inflating the Popup using xml file
          popup.menuInflater.inflate(R.menu.popup_menu_group, popup.menu)

          popup.setOnMenuItemClickListener({
              if (it.itemId == R.id.four && it.isChecked) {
                  Toast.makeText(applicationContext, "Four. Was Checked", Toast.LENGTH_SHORT).show()
              } else {
                  Toast.makeText(applicationContext, it.title, Toast.LENGTH_SHORT).show()
              }
              true
          })
          popup.show()

      }
  }

  override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
      super.onCreateContextMenu(menu, v, menuInfo)
      menu?.setHeaderTitle("Context Menu")
      menu?.add(0, v?.id!!, 0, "Call")
      menu?.add(0, v?.id!!, 1, "SMS")
      menu?.add(1, v?.id!!, 0, "Search")

  }

  override fun onCreateOptionsMenu(menu: Menu): Boolean {
      val inflater = menuInflater
      inflater.inflate(R.menu.menu_main, menu)
      return true
  }

  override fun onContextItemSelected(item: MenuItem?): Boolean {

      when {
          item?.title == "Call" -> {
              Toast.makeText(applicationContext, "Call", Toast.LENGTH_LONG).show()
              return true
          }
          item?.title == "SMS" -> {
              Toast.makeText(applicationContext, "SMS", Toast.LENGTH_LONG).show()
              return true
          }
          item?.title == "Search" -> {
              Toast.makeText(applicationContext, "Search", Toast.LENGTH_LONG).show()
              return true
          }
          else -> return super.onContextItemSelected(item)
      }
  }

  override fun onOptionsItemSelected(item: MenuItem): Boolean {
      when (item.itemId) {
          R.id.add -> {
              Log.d("API123", "done")
              return true
          }
          R.id.call -> {
              Log.d("API123", "done")
              return true
          }
          R.id.day -> {
              Log.d("API123", "done")
              return true
          }
          R.id.compass -> {
              Log.d("API123", "done")
              return true
          }

          R.id.agenda -> {
              Log.d("API123", "done")
              return true
          }

          else -> return super.onOptionsItemSelected(item)
      }

  }
}

onCreateContextMenu中:menu?.add(1,v?.id !!,0," Search")用于在上下文菜单中添加新菜单。
第一个参数是groupId。
因此,我们可以在菜单中拥有不同的菜单组。
第二个是菜单项ID。
第三个是优先级,第四个是标题。