简体   繁体   English

单击片段中的工具栏菜单项 (Kotlin)

[英]ToolBar menu item click in a fragment (Kotlin)

In my app, i have an Activity, which has a FrameLayout in it.在我的应用程序中,我有一个 Activity,其中有一个 FrameLayout。 In this FrameLayout, there is a fragment, containing a ToolBar and a RecyclerView.在这个 FrameLayout 中,有一个片段,包含一个 ToolBar 和一个 RecyclerView。

In this toolbar, i have a search button, which should start an Activity on item click.在这个工具栏中,我有一个搜索按钮,它应该在项目点击时启动一个活动。 However, when i try to use onOptionsItemSelected, the apps gets built and installed succesfully, but when i try to tap that button in question, nothing happens.但是,当我尝试使用 onOptionsItemSelected 时,应用程序已成功构建和安装,但是当我尝试点击有问题的按钮时,没有任何反应。 The Logcat, doesnt say anything either. Logcat,也没有说什么。

Can some points me what im doing wrong?可以指出我做错了什么吗? Are there simpler or other easy ways to manage on ToolBar item clicks?是否有更简单或其他简单的方法来管理工具栏项目的点击?

Fragment.kt

class FragmentTrack : Fragment() {
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = inflater.inflate(R.layout.fragment_track, container, false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        ...

        topToolbar.setNavigationOnClickListener {
            val dialog = FragmentBottomSheetDrawer()
            dialog.show(childFragmentManager, dialog.tag)

        }
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.menu_toolbar, menu)
        super.onCreateOptionsMenu(menu, inflater)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId) {
            R.id.fsvSearch -> Toast.makeText(context, "Clicked search button", Toast.LENGTH_SHORT).show()
        }
        return true
    }
}

fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:theme="@style/Theme.Design.NoActionBar">

        <androidx.appcompat.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/topToolbar"
            android:background="@color/colorPrimaryDark"
            app:navigationIcon="@drawable/ic_outline_menu_24"
            app:popupTheme="@style/popupMenuThemeDark"
            app:titleTextColor="@android:color/white"
            app:title="Revo"
            app:menu="@menu/menu_toolbar"
            app:layout_scrollFlags="scroll|enterAlways" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvTracks"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

toolbar_menu.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/fsvSearch"
            android:icon="@drawable/ic_search_24px"
            android:title="@string/search"
            app:showAsAction="always"/>
 
        <item
            android:id="@+id/fsvOrder"
            android:icon="@drawable/ic_sort_24px"
            android:title="@string/sort"
            app:showAsAction="ifRoom">
                <menu>
                        <group android:id="@+id/sortMenu" android:checkableBehavior="single">
                                <item
                                    android:id="@+id/sortIncrease"
                                    android:title="@string/increasing"/>
 
                                <item
                                    android:id="@+id/sortDecrease"
                                    android:title="@string/decreasing"/>
 
                                <item
                                    android:id="@+id/sortMArtist"
                                    android:title="@string/artist"/>
 
                                <item
                                    android:id="@+id/sortAlbum"
                                    android:title="@string/albums"/>
 
                                <item
                                    android:id="@+id/sortYear"
                                    android:title="@string/year"/>
 
                                <item
                                    android:id="@+id/sortDate"
                                    android:title="@string/date"/>
 
                        </group>
                </menu>
        </item>
 
        <item
            android:id="@+id/fsvGrid"
            android:icon="@drawable/ic_grid_on_24px"
            android:title="@string/grid"
            app:showAsAction="ifRoom">
                <menu>
                        <group android:id="@+id/gridMenu" android:checkableBehavior="single">
                                <item
                                    android:id="@+id/gridOne"
                                    android:title="1"/>
 
                                <item
                                    android:id="@+id/gridTwo"
                                    android:title="2"/>
 
                                <item
                                    android:id="@+id/gridThree"
                                    android:title="3"/>
 
                                <item
                                    android:id="@+id/gridFour"
                                    android:title="4"/>
                        </group>
                </menu>
        </item>
</menu>

I found a solution thanks to some external help.由于一些外部帮助,我找到了解决方案。 Its possible to work on the Toolbars item in an easier way.可以更轻松地处理工具栏项目。

In the onViewCreated method, we must add:onViewCreated方法中,我们必须添加:

    topToolbar.inflateMenu(R.menu.menu_toolbar)

    topToolbar.setOnMenuItemClickListener {
            when(it.itemId) {
                R.id.fsvSearch -> //your code
            }
            true
        }

Also, if the menu gets duplicated, remove the app:menu tag in the Toolbars xml此外,如果菜单重复,请删除工具栏 xml 中的app:menu标记

thanks Meltix for this, I've done a lot of research but most of the posts in SO are about Java and old fashioned ActionBar.感谢 Meltix 为此,我做了很多研究,但 SO 中的大部分帖子都是关于 Java 和老式的 ActionBar。 There is not much info about material ToolBar and kotlin examples.关于材料工具栏和kotlin示例的信息不多。 In my case I'm working on an old app developed mostly in Java but now developing new functionalities in Kotlin. In my fragment, I wasn't able to change the ActionBar's icons and behaviour (I wanted a particular ActionBar for my fragment).在我的例子中,我正在开发一个主要在 Java 中开发的旧应用程序,但现在在 Kotlin 中开发新功能。在我的片段中,我无法更改 ActionBar 的图标和行为(我想要一个特定的 ActionBar 作为我的片段)。 The solution I found is to hide the ActionBar and create a Toolbar inflating a custom menu inside.我找到的解决方案是隐藏 ActionBar 并创建一个工具栏以在其中扩展自定义菜单。 Also I added a back arrow button (thanks to John: here ).我还添加了一个后退箭头按钮(感谢 John: here )。 I've came to the conclusion (maybe I'm wrong) that you can't manage ActionBars from kotlin fragments, that's why you have to use toolbars.我得出的结论(也许我错了)您无法管理来自 kotlin 个片段的 ActionBar,这就是您必须使用工具栏的原因。 Here is my code in case it can help someone.这是我的代码,以防它可以帮助某人。

MyFragment.kt我的片段.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    // hide the old actionBar
    (activity as AppCompatActivity).supportActionBar!!.hide()
    
    // create the toolbar
    val toolbar = binding?.myToolbar
    
    // add the back arrow button, see function below
    val resId = getResIdFromAttribute(toolbar.context, android.R.attr.homeAsUpIndicator)
    toolbar.navigationIcon = ContextCompat.getDrawable(toolbar.context, resId)
    // tapping on the arrow will pop the current fragment
    toolbar.setNavigationOnClickListener { parentFragmentManager?.popBackStackImmediate() }

    // change toolbar title
    toolbar.title = "Some title"
    
    // inflate a custom menu, see code below
    toolbar.inflateMenu(R.menu.my_custom_menu)
    toolbar.setOnMenuItemClickListener {
        when (it.itemId) {
            R.id.infoButton -> someAction()
        }
        true
    }
}

// get back arrow icon
@AnyRes
fun getResIdFromAttribute(context: Context, @AttrRes attr: Int): Int {
    if (attr == 0) return 0
    val typedValueAttr = TypedValue()
    context.theme.resolveAttribute(attr, typedValueAttr, true)
    return typedValueAttr.resourceId
}

my_fragment.xml我的片段.xml

...
<androidx.appcompat.widget.Toolbar
    android:id="@+id/myToolBar"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:visibility="visible"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:background="@color/azulOscuro"
    >
</androidx.appcompat.widget.Toolbar>

my_custom_menu.xml my_custom_menu.xml

<?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:jsmovil="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <item
        android:id="@+id/infoButton"
        android:icon="@drawable/ic_info_blanco"
        android:title="@string/tutorial"
        android:textColor="@color/blanco"
        jsmovil:showAsAction="always"
        />
</menu>

Result结果

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM