Android如何自定义Menu

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android如何自定义Menu相关的知识,希望对你有一定的参考价值。

最近想做 个一排6个操作的menu但是默认的menu会换行查了下资料和论坛,很多人说使用PopupWindow,但是这个感觉和menu有很大的区别,因为显示Popupwindow后,界面其他部分不能点击了,他也不会被点击隐藏还有人使用布局的显示隐藏实现,但是这种显示的前后会改变布局的样式不知道坛友还有什么更好的方法没有谢谢

新建自定义Menu————>TabMenu.java如下:

package com.ncw;

 

import android.content.Context;

import android.graphics.Color;

import android.graphics.drawable.ColorDrawable;

import android.view.Gravity;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.GridView;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.PopupWindow;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.LinearLayout.LayoutParams;

 

public class TabMenu extends PopupWindow

    private GridView gridView;

    private LinearLayout mLayout;

 

    public TabMenu(Context context, OnItemClickListener bodyClick, int colorBgTabMenu)

        super(context);

 

        mLayout = new LinearLayout(context);

        mLayout.setOrientation(LinearLayout.VERTICAL);

 

        gridView = new GridView(context);

        gridView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,

                LayoutParams.WRAP_CONTENT));

        gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));// 选中的时候为透明色

        gridView.setNumColumns(4);

        gridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);

        gridView.setVerticalSpacing(0);

        gridView.setHorizontalSpacing(0);

        gridView.setPadding(0, 0, 0, 0);

        gridView.setGravity(Gravity.CENTER);

        gridView.setOnItemClickListener(bodyClick);

        mLayout.addView(gridView);

 

        // 设置默认项

        this.setContentView(mLayout);

        this.setWidth(LayoutParams.FILL_PARENT);

        this.setHeight(LayoutParams.WRAP_CONTENT);

        this.setBackgroundDrawable(new ColorDrawable(colorBgTabMenu));// 设置TabMenu菜单背景

        this.setFocusable(true);// menu菜单获得焦点 如果没有获得焦点menu菜单中的控件事件无法响应

    

 

    public void SetBodySelect(int index, int colorSelBody)

        int count = gridView.getChildCount();

        for (int i = 0; i < count; i++)

            if (i != index)

                ((LinearLayout) gridView.getChildAt(i))

                        .setBackgroundColor(Color.TRANSPARENT);

        

        ((LinearLayout) gridView.getChildAt(index))

                .setBackgroundColor(colorSelBody);

    

 

    public void SetBodyAdapter(MenuBodyAdapter bodyAdapter)

        gridView.setAdapter(bodyAdapter);

    

 

    /**

     * 自定义Adapter,TabMenu的每个分页的主体

     *

     */

    static public class MenuBodyAdapter extends BaseAdapter

        private Context mContext;

        private int[] resID;

 

        /**

         * 设置TabMenu的分页主体

         *

         * @param context

         *            调用方的上下文

         * @param resID

         */

        public MenuBodyAdapter(Context context, int[] resID)

            this.mContext = context;

            this.resID = resID;

        

 

        @Override

        public int getCount()

            return resID.length;

        

 

        public Object getItem(int position)

 

            return makeMenyBody(position);

        

 

        public long getItemId(int position)

            return position;

        

 

        private LinearLayout makeMenyBody(int position)

            LinearLayout result = new LinearLayout(this.mContext);

            result.setOrientation(LinearLayout.VERTICAL);

            result.setGravity(Gravity.CENTER_HORIZONTAL

                    | Gravity.CENTER_VERTICAL);

            result.setPadding(0, 0, 0, 0);

 

            ImageView img = new ImageView(this.mContext);

            img.setBackgroundResource(resID[position]);

            result.addView(img, new LinearLayout.LayoutParams(new LayoutParams(

                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)));

            return result;

        

 

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

            return makeMenyBody(position);

        

 

    

   

?

1

   

使用自定义Menu————>testTabMenu.java

package com.ncw;

 

import android.app.Activity;

import android.graphics.Color;

import android.os.Bundle;

import android.util.Log;

import android.view.Gravity;

import android.view.Menu;

import android.view.View;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

 

public class testTabMenu extends Activity

    TabMenu.MenuBodyAdapter bodyAdapter = new TabMenu.MenuBodyAdapter(this,

            new int[] R.drawable.menu_01, R.drawable.menu_02,

                    R.drawable.menu_03, R.drawable.menu_04 );

    TabMenu tabMenu;

 

    @Override

    public void onCreate(Bundle savedInstanceState)

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        tabMenu = new TabMenu(this, new BodyClickEvent(), R.drawable.menu_bg);// 出现与消失的动画

        tabMenu.update();

        tabMenu.SetBodyAdapter(bodyAdapter);

    

 

    class BodyClickEvent implements OnItemClickListener

        @Override

        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,

                long arg3)

            tabMenu.SetBodySelect(arg2, Color.GRAY);

            Log.i("Log", " BodyClickEvent implements OnItemClickListener "

                    + arg2);

        

 

    

 

    @Override

    /**

     * 创建MENU

     */

    public boolean onCreateOptionsMenu(Menu menu)

        menu.add("menu");// 必须创建一项

        return super.onCreateOptionsMenu(menu);

    

 

    @Override

    /**

     * 拦截MENU

     */

    public boolean onMenuOpened(int featureId, Menu menu)

        if (tabMenu != null)

            if (tabMenu.isShowing())

                tabMenu.dismiss();

            else

                tabMenu.showAtLocation(findViewById(R.id.LinearLayout01),

                        Gravity.BOTTOM, 0, 0);

            

        

        return false;// 返回为true 则显示系统menu

    


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/LinearLayout01"

    android:layout_

    android:layout_ >

 

    <TextView

        android:id="@+id/TextView01"

        android:layout_

        android:layout_

        android:text="自定义Menu————张亚龙" >

    </TextView>

 

</LinearLayout> 

   

运行效果图:

参考技术A 重载Activity的 onCreatePanelView将你要实现的一排6个item的view传给系统就可以了,不过这样会改变系统默认Menu的事件执行次序:只要onCreatePanelView方法返回值不为null,系统将不会调用默认处理的部分Menu事件,如像onCreateOptionsMenu等,只会调用OnCreatePanelView和onMenuOpen两个事件,其他细节楼主自己去实现吧 参考技术B 做一个LinearLayout放你要放的button(bg="@drawab/selector")这个控制几种状态,然后让这个view的visibility 为gone,捕获onkeydown中的menu,然后处理隐藏和show,事件自己加上,我的想法。LZ有好的想法,欢迎交流 参考技术C PopWindow可以实现。捕获onkeydown中的menu事件 Popwendow 不会导致 下层的view不能点击啊系统默认的Menu 每行3个最多两行。 超过6个item 还会隐藏到 更多里面。 很恶心。貌似menu不能重写哦。 而且外观丑陋。。。

自定义ActionMode Menu

参考技术A

ActionMode 是啥?

这是来自官方的解释。简单来说,其实就是在用户界面提供一个action的菜单,辅助ui完成操作。
最常见ActionMode是这个样子的:

好看的ActionMode是这个样子的:

这样在6.0以前是ok的。但是6.0以后WebView的ActionMode menu样式终于做成和ios一样的悬浮菜单了,亲测上面的方法是没有显示我们自定义的callback的。
不得不另寻它法,最后发现一个规律是:调用View.startActionMode(callback) 都会走Activity的onActionModeStarted (ActionMode mode) 方法,所以我们可以来这里自定义:

记得在 onActionModeFinished****(ActionMode mode)清理掉我们自己的ActionMode

这样就可以替换掉WebView自带的ActionMode Menu,改成我们自己的。

昨晚俺在 知乎专栏 撸的,搬运到。

以上是关于Android如何自定义Menu的主要内容,如果未能解决你的问题,请参考以下文章

安卓编程怎样自定义menu中的字体大小

如何在 django 管理面板中完全自定义 sidebar_menu?

自定义控件

Android MenuItem 自定义布局

自定义ActionProvider ToolBar 自定义Menu小红点

如何在 WordPress 中使用 wp_get_nav_menu_items 生成自定义菜单/子菜单系统?