简体   繁体   English

自定义 ActionBar 溢出菜单

[英]Custom ActionBar Overflow Menu

I'm trying to make an ActionBar Menu OverFlow.我正在尝试制作一个 ActionBar 菜单 OverFlow。 The type twitter does.推特的类型。 Where The Name and The UserName shows on the first Item on the OverFlow.名称和用户名显示在 OverFlow 的第一个项目上。 So, I did this, but it's not taking any effect, any help would be appreciated.所以,我这样做了,但没有任何效果,任何帮助将不胜感激。 There is my code:有我的代码:

MyActivity.java我的活动.java

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    MenuItem menuItem = menu.findItem(R.id.username);
    View usname = getLayoutInflater().inflate(R.layout.action_menu_overflow, null);
    TextView uName = (TextView) usname.findViewById(R.id.profileName);
    TextView slug = (TextView) usname.findViewById(R.id.slugName);
    uName.setText("Users");
    slug.setText("Tracer");
    menuItem.setActionView(usname);
    //MenuItemCompat.setActionView(menuItem, usname);

    //menuItem.setTitle("Users");
    return super.onPrepareOptionsMenu(menu);
}

Menu.xml菜单文件

<menu 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"
    tools:context=".MainActivity">

    <item
        android:id="@+id/username"
        android:title="@string/username"
        app:showAsAction="never" />

    <item
        android:id="@+id/logout"
        android:title="@string/logout"
        app:showAsAction="never" />
</menu>

action_menu_overflow.xml action_menu_overflow.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/slugLayout">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:text="New Text"
        android:id="@+id/profileName" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginLeft="15dp"
        android:text="New Text"
        android:id="@+id/slugName" />
</LinearLayout>

Twitter 菜单溢出

This cannot be achieved by use of PopUpMenu, which the normal android overflow menu uses since it is constrained to not easily be used with complex custom layout/adapter . 这无法通过使用PopUpMenu来实现,因为它被限制为不易与复杂的自定义布局/适配器一起使用,因此无法正常使用android溢出菜单。 However, this twitter-like overflow menu can easily be achieved by use of ListPopupWindow, which is made to be easily used with more complex layouts/adapters. 但是,可以通过使用ListPopupWindow轻松实现此类似Twitter的溢出菜单,该菜单可轻松用于更复杂的布局/适配器。

To make this simple ,you can have a function in your activity/fragment to setup the ListPopupWindow . 为了简单起见,您可以在活动/片段中具有一个函数来设置ListPopupWindow。 This is an example: 这是一个例子:

public void onListPopUp(View anchor)
    {
        // This a sample dat to fill our ListView
        ArrayList<Person> personItem = new ArrayList<Person>();
        personItem.add(new Person(R.drawable.remove_placeholder_userpic, "Mamluki", "@DigitalSurgeonR"));
        personItem.add(new Person(0, "Lists", "@Lists"));
        personItem.add(new Person(0, "Drafts", "@Drafts"));
        personItem.add(new Person(0, "Accounts", "@Accounts"));
        // Initialise our adapter
        ListPopupWindowAdapter mListPopUpAdapter = new ListPopupWindowAdapter(this, personItem);

        //Initialise our ListPopupWindow instance
        final ListPopupWindow pop = new ListPopupWindow(this);
        // Configure ListPopupWindow properties
        pop.setAdapter(mListPopUpAdapter);
        // Set the view below/above which ListPopupWindow dropdowns
        pop.setAnchorView(anchor);
        // Setting this enables window to be dismissed by click outside ListPopupWindow
        pop.setModal(true);
        // Sets the width of the ListPopupWindow
        pop.setContentWidth(150);
        // Sets the Height of the ListPopupWindow
        pop.setHeight(ListPopupWindow.WRAP_CONTENT);
        // Set up a click listener for the ListView items
        pop.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                // Dismiss the LisPopupWindow when a list item is clicked
                pop.dismiss();
                Toast.makeText(MainActivity.this, "Clicked ListPopUp item " + ((Person) adapterView.getItemAtPosition(position)).getName(), Toast.LENGTH_LONG).show();
            }
        });
        pop.show();
    } 

This function can be called from the method override below -: 可以从下面的方法重写中调用此函数-:

  @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case R.id.action_overflow:
                // Works as long as list item is always visible and does not go into the menu overflow
                final View menuItemView = findViewById(R.id.action_overflow);
                onListPopUp(menuItemView);
                Log.w(LOG_TAG, "You called me OverFlow");

                return true;
            default:
            {
                return super.onOptionsItemSelected(item);
            }
        }
    }

Our adapter will extend the BaseAdapter and will have the following code snippet . 我们的适配器将扩展BaseAdapter并将具有以下代码片段。

public class ListPopupWindowAdapter extends BaseAdapter {

    // ----------------------------------------
    // Variables
    // ----------------------------------------
    private Context context;
    private ArrayList<Person> personItem;
    // ----------------------------------------
    // Methods
    // ----------------------------------------

    public ListPopupWindowAdapter(Context context, ArrayList<Person> personItem)
    {
        this.context = context;
        this.personItem = personItem;
    }

    // ----------------------------------------

    public View getView(int position, View convertView, ViewGroup parent) {

        ImageView profilePic;
        TextView name;
        TextView userName;
        boolean isWithPicture = (personItem.get(position).getProfilePic() != 0);

            // Small List View , no need to recycle views
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            // Is this the row with the p.picture
            if(isWithPicture)
            {
                //Layout for the top row with profile picture /Avatar
                convertView = inflater.inflate(R.layout.toolbar_overflow_item_row, parent, false);

                profilePic = (ImageView) convertView .findViewById(R.id.imageProfilePic);
                profilePic.setImageResource(personItem.get(position).getProfilePic());

                userName = (TextView) convertView .findViewById(R.id.textUsername);
                userName.setText(personItem.get(position).getUserName());
            }
            else
            {
                //Layout for the other layout without an images
                convertView = inflater.inflate(R.layout.toolbar_overflow_item_row_text, parent, false);
            }


        name = (TextView) convertView .findViewById(R.id.textViewName);
        name.setText(personItem.get(position).getName());


        return convertView ;
    }


    // ----------------------------------------
    //  Implemented
    // ----------------------------------------
    @Override
    public Object getItem(int index)
    {
        return personItem.get(index);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public int getCount()
    {
        return personItem.size();
    }

}

We have two layouts . 我们有两种布局。 One for the listView top row item and another for the other rows. 一个用于listView顶部行项目,另一个用于其他行。

toolbar_overfow_row_item.xml -top row item toolbar_overfow_row_item.xml-顶行项目

<?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="match_parent"
    android:orientation="horizontal"
    android:padding="6dp">

    <ImageView
        android:id="@+id/imageProfilePic"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:visibility="visible"
        android:src="@color/apptheme_accent_teal" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingLeft="16dp"
        >

        <TextView
            android:id="@+id/textViewName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Mamluki"
            android:textColor="@android:color/black"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/textUsername"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="visible"
            android:paddingTop="6dp"

            android:text="\@DigitalSurgeonR"
            android:textColor="?android:attr/textColorSecondary"
            android:textSize="13sp" />

    </LinearLayout> </LinearLayout>

toolbar_overfow_row_item_text.xml -other row items 工具栏_overfow_row_item_text.xml-其他行项目

<?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="match_parent"
    android:orientation="horizontal"
    android:padding="14dp">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <TextView
            android:id="@+id/textViewName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Mamluki"
            android:textColor="@android:color/black"
            android:textSize="16sp" />


    </LinearLayout>
</LinearLayout>

Additionally , to set the position of the ListPopupWindow 另外,设置ListPopupWindow的位置

we can use methods:- 我们可以使用以下方法:

 setVerticalOffset(int offset)
 setHorizontalOffset(int offset)

The Horizontal & Vertical offset are 0 by default . 默认情况下,水平和垂直偏移为0。 Setting the vertical offset to setVerticalOffset(-36) makes the ListPopupWindow overlay the actionbar/toolbar . 将垂直偏移设置为setVerticalOffset(-36)可使ListPopupWindow覆盖actionbar / toolbar。 The more negative value pushes it further up . 负值越大,则将其推高。 Alternatively you can set it as a Style in your styles.xml like below 另外,您可以在styles.xml中将其设置为样式,如下所示

    <style name="AppThemeToolBar" parent="AppBaseThemeNoActionBar.Dark" >
            <!-- Customize your theme here. -->
    <!-- ListPopUpWindow styles -->
            <item name="listPopupWindowStyle">@style/Widget.App.ListPopupWindow</item>
        </style>

<!-- Widget styles -->
    <style name="Widget" />

    <style name="Widget.App" parent="Widget" />
    <!-- Widget ListPopUpWindow Style-->
        <style name="Widget.App.ListPopupWindow" parent="Widget.AppCompat.Light.ListPopupWindow">
            <item name="android:dropDownVerticalOffset">-36px</item>
        </style>

It's not working because you are setting an actionView to the menu item but this item will never be shown as action : app:showAsAction="never" so unfortunately you can't go that way (if you set this to ifRoom you will have your custom layout displayed in the action bar). 它不起作用,因为您正在将actionView设置为菜单项,但是此项目将永远不会显示为action: app:showAsAction="never"因此很遗憾,您不能那样做(如果将其设置为ifRoom您将拥有自定义布局显示在操作栏中)。

To display profile name you can use setTitle but you will not have your custom layout. 要显示配置文件名称,您可以使用setTitle,但是您将没有自定义布局。

I haven't find yet how to customize ActionBar dropdown menu items without creating a custom view for the ActionBar and a PopupMenu for the dropdown menu... 我还没有找到如何在不为ActionBar创建自定义视图和为下拉菜单创建PopupMenu的情况下自定义ActionBar下拉菜单项的方法...

With the help of @Otieno Rowland answer above, I was able to achieve this in Kotlin.在上面@Otieno Rowland 回答的帮助下,我能够在 Kotlin 中实现这一点。 result MainActivity class结果MainActivity 类

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        bottomNavigationView.background = null
        bottomNavigationView.menu.getItem(2).isEnabled = false
        toolbar.title = "Home"
        toolbar.setLogo(R.drawable.downloadresized_modified)
        toolbar.inflateMenu(R.menu.toolbar_menu)
        toolbar.logoDescription = "Company Logo"
        toolbar.setOnMenuItemClickListener { p0 ->
            val menuItemView = findViewById<View>(R.id.notifications)
            when (p0!!.itemId) {
                R.id.about_us -> Toast.makeText(this, "About Us", Toast.LENGTH_SHORT).show()
                R.id.shop -> Toast.makeText(this, p0.title, Toast.LENGTH_SHORT).show()
                R.id.notifications -> Toast.makeText(this, p0.title, Toast.LENGTH_SHORT).show()
                R.id.app_bar_search -> Toast.makeText(this, p0.title, Toast.LENGTH_SHORT).show()
                R.id.profile -> onListPopup(menuItemView)
            }
            true
        }
    }

    private fun onListPopup(anchor: View){
        val menuItems: ArrayList<Menu> = ArrayList()
        menuItems.add(Menu(R.drawable.logo_2, "Mohammed Trouble", "Mdee@gmail.com"))
        menuItems.add( Menu(0, "About Us", "@About_Us"))
        menuItems.add( Menu(0, "Contact Us", "@Contact_Us"))
        menuItems.add( Menu(0, "Settings", "@Settings"))
        menuItems.add( Menu(0, "DONATE", "@Donate"))

        val listPopupAdapter = ListPopupWindowAdapter(this,menuItems)
        val pop = ListPopupWindow(this)
        pop.setAdapter(listPopupAdapter)
        pop.anchorView = anchor
        pop.isModal = true
        pop.width = ListPopupWindow.WRAP_CONTENT
        pop.setContentWidth(450)
        pop.horizontalOffset = -5
        pop.setOnItemClickListener { adapterView, view, position, l -> // Dismiss the LisPopupWindow when a list item is clicked
            pop.dismiss()
            Log.w("MainActivityTAG","Item clicked")
            Toast.makeText(
                this@MainActivity,
                "Clicked ListPopUp item " + (adapterView.getItemAtPosition(position) as Menu).name,
                Toast.LENGTH_LONG
            ).show()
        }
        pop.show()
    }

ListPopupWindowAdapter class ListPopupWindowAdapter 类

class ListPopupWindowAdapter(private val context: Context, private val menuItems:ArrayList<Menu>): BaseAdapter() {
    override fun getCount(): Int {
        return menuItems.size
    }

    override fun getItem(p0: Int): Any {
        return menuItems[p0]
    }

    override fun getItemId(p0: Int): Long {
        return p0.toLong()
    }

     override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
        val convertView: View
        val profilePic: ImageView?
         val userName:TextView?
        val isWithPicture: Boolean = menuItems[p0].getProfilePic()!= 0
        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        if(isWithPicture){
            convertView =  inflater.inflate(R.layout.toolbar_overflow_top_row,p2,false)
            profilePic = convertView.findViewById(R.id.imageProfilePic)
            profilePic.setImageResource(menuItems[p0].getProfilePic())

            userName =  convertView.findViewById(R.id.textUsername)
            userName.text = (menuItems[p0].getUserName())
        }else{
            convertView =  inflater.inflate(R.layout.toolbar_overflow_bottom_row,p2,false)
        }
         val name: TextView? = convertView.findViewById(R.id.textViewName)
         name!!.text = (menuItems[p0].getName())
         return convertView
    }

Menu class菜单类

data class Menu(val profilePic: Int, val name:String, val userName:String){
    @JvmName("getProfilePic1")
    fun getProfilePic(): Int {
        return profilePic
    }

    @JvmName("getUserName1")
    fun getUserName(): String {
        return userName
    }

    fun getName(): CharSequence {
        return name
    }
}

activity_main.xml活动_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    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">

    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bottomAppBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:fabCradleMargin="10dp"
        app:fabCradleRoundedCornerRadius="10dp"
        app:fabCradleVerticalOffset="10dp">

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottomNavigationView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginEnd="16dp"
            android:background="@android:color/transparent"
            app:menu="@menu/bottom_nav_menu" />

    </com.google.android.material.bottomappbar.BottomAppBar>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/app_name"
        android:src="@drawable/ic_baseline_chat_24"
        app:layout_anchor="@id/bottomAppBar" />

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme" />

<!--    <include-->
<!--        layout="@layout/activity_content_page"-->
<!--        android:layout_width="wrap_content"-->
<!--        android:layout_height="wrap_content" />-->

</androidx.coordinatorlayout.widget.CoordinatorLayout>

toolbar_overflow_bottom_row.xml toolbar_overflow_bottom_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="@drawable/_1609"
    android:orientation="horizontal"
    android:padding="14dp">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:divider="@drawable/_1609"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textViewName"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="Mamluki"
            android:textColor="@android:color/black"
            android:textSize="16sp"
            app:drawableBottomCompat="@color/purple_200" />


    </LinearLayout>
</LinearLayout>

toolbar_overflow_top_row.xml toolbar_overflow_top_row.xml

<?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="match_parent"
    android:orientation="horizontal"
    android:padding="6dp">

    <ImageView
        android:id="@+id/imageProfilePic"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:visibility="visible"
        android:src="@drawable/logo_2" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingLeft="16dp">

        <TextView
            android:id="@+id/textViewName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Mohammed Trouble"
            android:textColor="@android:color/black"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/textUsername"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="6dp"
            android:text="\@DigitalSurgeonR"

            android:textColor="?android:attr/textColorSecondary"
            android:textSize="13sp"
            android:visibility="visible" />

    </LinearLayout> </LinearLayout>

bottom_nav_menu.xml bottom_nav_menu.xml

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

    <item
        android:id="@+id/home"
        android:icon="@drawable/ic_baseline_home_24"
        android:title="@string/home" />

    <item
        android:id="@+id/Wizkid"
        android:icon="@drawable/_1_star_boy_modified"
        android:title="@string/wizkid" />

    <item
        android:id="@+id/placeholder"
        android:title="" />

    <item
        android:id="@+id/shop"
        android:icon="@drawable/ic_baseline_shopping_cart_24"
        android:title="@string/shop" />

    <item
        android:id="@+id/Projects"
        android:icon="@drawable/ic_baseline_event_note_24"
        android:title="@string/projects" />

</menu>

toolbar_menu.xml toolbar_menu.xml

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

    <item
        android:id="@+id/shop"
        android:icon="@drawable/ic_baseline_shopping_cart_24"
        android:title="@string/shop"
        app:showAsAction="always" />
    <item
        android:id="@+id/notifications"
        android:icon="@drawable/ic_baseline_notifications_24"
        android:title="@string/notifications"
        app:showAsAction="always" />
    <item
        android:id="@+id/app_bar_search"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="@string/search"
        app:actionViewClass="android.widget.SearchView"
        app:showAsAction="always" />
    <item
        android:id="@+id/profile"
        android:icon="@drawable/ic_baseline_account_circle_24"
        android:title="@string/notifications"
        app:showAsAction="always" />

</menu>

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

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