精华内容
下载资源
问答
  • 菜单

    千次阅读 2011-11-28 19:03:38
    1、在菜单项前添加标记 用到的函数  GetMenu() 作用 :获取菜单栏;GetSubMenu() 作用: 获取子菜单;  CheckMenuItem()作用:菜单标记;  函数功能:该函数取得与指定菜单项相联系的菜单标志。如果该...

    1、在菜单项前添加标记

    用到的函数 

    GetMenu()  作用 :获取菜单栏;GetSubMenu() 作用: 获取子菜单;

     CheckMenuItem()作用:菜单标记;

     函数功能:该函数取得与指定菜单项相联系的菜单标志。如果该菜单项打开了一个子菜单,该函数也返回子菜单里的菜单项数。

     函数原型:DWORD CheckMenuItem(HMENU hmenu, UINT uIDCheckItem, UINT uCheck); 
     参数:
      hmenu:含有其菜单项的标志将被提取得的菜单的句柄。一般为缺省值,可以省略。
      uIDCheckItem:指定要修改的菜单项。这个参数取决于第三个参数,若第三个参数为MF_BYCOMMAND,则该参数是所选菜单项的ID号,若为MF_BYPOSITION,则该参数是所选菜单的索引值。
      uCheck:表示标记的状态。此参数可取下列值之一:
      MF_BYCOMMAND:表示参数uId给出菜单项的标识符。如果MF_BYCOMMAND和MF_BYPOSITION都没被指定,则MF_BYCOMMAND是缺省值。
      MF_BYPOSITION:表示参数uId给出菜单项相对于零的位置。

          其中MF_BYCOMMAND和MF_BYPOSITION均可以与菜单项相关的菜单标志一起使用。
     

      返回值:如果指定的项不存在,返回值是OXFFFFFFFF;如果菜单项打开了一个子菜单,则返回值的低位含有与菜单相联系的菜单标志,高位含有子菜单的项数。否则,返回           值是莱单标志的掩码(布尔OR)。
      下面列出与菜单项相关的菜单标志。
      MF_CHECKED:放置选取标记于菜单项旁边(只用于下拉式菜单、子菜单或快捷菜单)。
      MF_DISABLED:使菜单项无效。MF_GRAYED:使菜单项无效并交灰。MF_HILITE:加亮菜单项。
      MF_MENUBARBREAK:对下拉式菜单、子菜单和快捷菜单,新列和旧列由垂直线隔开,其余功能同MF_MENUBREAK标志。
      MF_MENUBREAK:将菜单项放于新行(对菜单条)或无分隔列地放于新列(对下拉式菜单、子菜单或快捷菜单)。
      MF_SEPARATOR:创建一个水平分隔线(只用于下拉式菜单、子菜单或快捷菜单)。
      MF_UNCHECKED: 相当于MF_CHECKED 的反作用,取消放置于菜单项旁边的标记。

    例如:对文件-新建菜单前添加一个标记,可在CMainFrame类 oncreat()下添加如下代码:

          GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED);

    或GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMOND|MF_CHECKED);


    2、创建缺省菜单项

    用到的函数:

    SetDaultItem()

    函数原型:BOOL SetDefaultItem(UINT UItem,BOOL fByPos = FALSE

    第二个参数缺省值是FALSE,若第二个参数是FALSE,则第一个参数是菜单项的ID,若若第二个参数是TRUE,则第一个参数是菜单项的索引值;

    例如:将文件-打开设置为缺省菜单,可在CMainFrame类 oncreat()下添加如下代码:

    GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);

    GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN,FALSE);

    GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN);

    注意:在一个菜单项中只能有一个缺省菜单


    3、创建图形标记菜单

    用到的函数:SetMenuItemBitmaps

    函数原型:BOOL SetMenuItemBitmaps( UINT nPosition, UINT nFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked );

    第一个参数取决于第二个参数,若第二个参数是MF_BYPOSITION,第一个参数则为菜单项的索引,若第二个参数是MF_BYCOMMOND,第一个参数则为菜单项的ID.第三个参数是选择菜单项时菜单项前标记的位图,第四个参数是不选菜单项时它前边的位图标记。

    添加步骤

    a、新建一个bitmap

    b、在CMainFrame中添加成员变量 CBitmap bitmap;

    c、在oncreat中添加代码:

    bitmap.LoadBitmap(IDB_BITMAP1);
    GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&bitmap,&bitmap);

    注意:图形标记菜单位图bitma的大小,可以先获取bitmap大小,通过以下代码:

    GetSystemMetrics()是获取系统信息;参数是指想获取关于哪方面的信息

    可以先获取图形标记菜单位图的大小

    CString str;
    str.Format("x = %d,y = %d",GetSystemMetrics(SM_CXMENUCHECK),GetSystemMetrics(SM_CYMENUCHECK));

     MessageBox(str);

     其中GetSystemMetrics(SM_CXMENUCHECK))和GetSystemMetrics(SM_CYMENUCHECK))分别是获取图形标记菜单位图的宽度和高度;

     通过 MessageBox输出。


    4、使菜单不可用

    用到的函数:

    EnableMenuItem()

    函数原型:BOOL EnableMenuItem(UINT uIDEnableItem, UINT uEnable);

    作用:允许或禁止指定的菜单条目

    但是在用EnableMenuItem()禁止指定的菜单条目时,应先在构造函数中赋值 m_bAutoMenuEnable = FALSE;

    例如: 将文件-保存设为不可用

    CMainFrame::CMainFrame()
    {
    m_bAutoMenuEnable = FALSE;
    }

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {

    。。。

    GetMenu()->GetSubMenu(0)->EnableMenuItem(2,MF_BYPOSITION|MF_GRAYED);

    GetMenu()->GetSubMenu(0)->EnableMenuItem(ID_FILE_SAVE,MF_BYCOMMAND|MF_GRAYED);

    }

    (注意,若用索引,只能设置菜单的可用与不可用,而不能控制工具栏中图标的可用和不可用,但是,用ID号可以使控制菜单项状态与工具栏状态一致)

    5、取消和添加整个菜单

    取消菜单:

    在oncreat中添加代码 SetMenu(NULL);即可

    添加菜单:

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {

            。。。

    CMenu menu;                                                  //定义变量
    menu.LoadMenu(IDR_MAINFRAME);                 //加载菜单
    SetMenu(&menu);                                            //添加菜单
    menu.Detach();                                                //将菜单句柄和c++断开,必须有。

    }

    命令更新机制:

    菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,谁捕获了CN_UPDATE_COMMAND_UI消息,MFC就在其中创建了一个CCmdUI对象。可以通过类向导在消息映射中添加ON_UPDATE_COMMAND_UI宏来捕获CN_UPDATE_COMMAND_UI消息。

    在后台所作的工作是:操作系统发出WM_INITMEUPOPUP消息,然后由MFC基类如CFrameWnd接管。他创建一个CCmdUI对象,并与第一个菜单项相关联,调用对象的一个成员函数,DoUpdate()。这个函数发出CN_UPDATE_COMMAND_UI消息,这条消息带有指向CCmdUI对象的指针。同一个CCmdUI对象就设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。

    更新命令UI处理程序仅应用于弹出式菜单项的项目,不能应用于永久显示的顶级菜单项目。

    利用这样的更新机制使菜单项能或不能使用可以用一下的方法:

    1、查看——建立类向导

    2、在object ids 中选择ID_FILE_NEW 在message中选择ON_UPDATE_COMMAND_UI,点击Addfunction。点击Edit。在函数中输入代码:

    pCmdUI->Enable(FALSE);

    3、运行,可以看到菜单上新建已经禁用。

    为了保证菜单项和工具栏中的工具相一致,一般用ID进行索引。

    6、右键弹出菜单功能

    工程——增加到工程——组建和控件——visual c++ components——pop-up-menu——insert——确定——add pop-up-menu to 中选择cmainmenu——关闭;

    运行,右击鼠标,弹出菜单;

    用到的函数:

    trackpopupmenu()

    函数功能:该函数在指定位置显示快捷菜单,并跟踪菜单项的选择。快捷菜单可出现在屏幕上的任何位置。

      函数原型:BOOL TrackPopupMenu(HMENU hMenu,UINT uFlags,int x,int y,int nReserved,HWND hWnd,CONST RECT* prcRect);

      hMenu:被显示的快捷菜单的句柄。此句柄可为调用CreatePopupMenu创建的新快捷菜单的句柄,也可以为调用GetSubMenu取得的与一个已存在菜单项相联系的子菜单的句柄。

      uFlags:一种指定功能选项的位标志。用下列标志位之一来确定函数如何水平放置快捷菜单:

      TPM_CENTERALIGN:若设置此标志,函数将按参数x指定的坐标水平居中放置快捷菜单。

      TPM_LEFTALIGN:若设置此标志,函数使快捷菜单的左边界与由参数X指定的坐标对齐。

      TPM_RIGHTALIGN:若设置此标志,函数使快捷菜单的右边界与由参数X指定的坐标对齐。

      用下列标志位之一来确定函数如何垂直放置快捷菜单:

      TPM_BOTTOMALIGN:若设置此标志,函数使快捷菜单的下边界与由参数y指定的坐标对齐。

      TPM_TOPALIGN:若设置此标志,函数使快捷菜单的上边界与由参数y指定的坐标对齐。

      TPM_VCENTERALIGN;若设置此标志,函数将按参数y指定的坐标垂直居中放置快捷菜单

      用下列标志位之一来确定在菜单没有父窗口的情况下用户的选择:

      TPM_NONOTIFY:若设置此标志,当用户单击菜单项时函数不发送通知消息。

      TPM_RETURNCMD;若设置此标志;函数将用户所选菜单项的标识符返回到返回值里。

      (补充:当TrackPopupMenu的返回值大于0,就说明用户从弹出菜单中选择了一个菜单。以返回的ID号为参数wParam的值,程序给自己发送了一个WM_SYSCOMMAND消息)

      用下列标志位之一来确定在快捷菜单跟踪哪一个鼠标键:

      TPM_LEFTBUTTON:若设置此标志,用户只能用鼠标左键选择菜单项。

      TPM_RIGHTBUTTON:若设置此标志,用户能用鼠标左、右键选择菜单项。

      X:在屏幕坐标下,快捷菜单的水平位置。

      Y:在屏幕坐标下,快捷菜单的垂直位置。

      NReserved:保留值,必须为零。

      HWnd:拥有快捷菜单的窗口的句柄。此窗口接收来自菜单的所有消息。函数返回前,此窗口不接受来自菜单的WM_COMMAND消息。

      如果在参数uFlags里指定了TPM_NONOTIFY值,此函数不向hWnd标识的窗口发消息。 但必须给hWnd里传一个窗口句柄,可以是应用程序里的任一个窗口句柄。

      PrcRect:未用。

      返回值:如果在参数uFlags里指定了TPM_RETURNCMD值,则返回值是用户选择的菜单项的标识符。如果用户未作选择就取消了菜单或发生了错误,则退回值是零。如果没在参数uFlags里指定TPM_RETURNCMD值,若函数调用成功,返回非零值,若函数调用失败,返回零。若想获得更多的错误信息,清调用GetLastError

    手动添加弹出菜单方法:

    1、在menu中添加菜单

    2、在从view中添加句柄,在window消息句柄中选择WM_RBUTTONDOWN,添加句柄。

    3、在OnRButtonDown中添加代码如下:

    void CMenuView::OnRButtonDown(UINT nFlags, CPoint point)
    {
     // TODO: Add your message handler code here and/or call default
     CMenu menu;
     menu.LoadMenu(IDR_MENU1); //加载弹出菜单
     CMenu *pPopup = menu.GetSubMenu(0);
     ClientToScreen(&point); //将客户区窗口转为屏幕窗口
     pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
       GetParent());     //GetParent()是指向cmainframe的指针,这样可以响应在cmainframe中添加的消息响应函数。
     CView::OnRButtonDown(nFlags, point);
    }

    4、运行。

    动态添加、删除、操作菜单:

    用到的函数 AppendMenu(在现有菜单后添加菜单) creatpopupmenu(创建空的弹出菜单,将他和CMENU的一个对象关联起来)

     eg:添加一个弹出菜单:

    eg:插入一个弹出菜单:

    InsertMenu

    eg:删除一个菜单

    DeleteMenu

    手动添加响应函数:

    1、定义ID号

    在resource中的Header File下的Resource.h中添加 

    #define IDM_HELLO          111(定义ID号)

    2. 添加函数

    a、在头文件中写:afx_msg void OnHello()      //消息原型

    b、ON_COMMAND (IDM_HELLO,OnHello()       //添加消息响应

    c、添加函数

    void CMainFrame::OnHello()
    {
     MessageBox("hello!");
    }

    d、运行,就可以发现winsun下的hello是可用的

     

     

     

     

     

     

     










    展开全文
  • java从数据库读取菜单,递归生成菜单

    万次阅读 多人点赞 2016-10-29 13:44:34
    java从数据库读取菜单,递归生成菜单

    首先看一下菜单的样子

    这里写图片描述

    根据这个样子我们定义菜单类

    public class Menu {
    	// 菜单id
    	private String id;
    	// 菜单名称
    	private String name;
    	// 父菜单id
    	private String parentId;
    	// 菜单url
    	private String url;
    	// 菜单图标
    	private String icon;
    	// 菜单顺序
    	private int order;
    	// 子菜单
    	private List<Menu> childMenus;
    	// ... 省去getter和setter方法以及toString方法
    }
    

    我们根据这个类定义数据库,并插入菜单数据

    DROP TABLE IF EXISTS `jrbac_menu`;
    CREATE TABLE `jrbac_menu` (
      `id` varchar(32) NOT NULL COMMENT '主键id,uuid32位',
      `name` varchar(64) NOT NULL COMMENT '菜单名称',
      `parent_id` varchar(32) DEFAULT NULL COMMENT '父菜单id',
      `url` varchar(64) DEFAULT NULL COMMENT '访问地址',
      `icon` varchar(32) DEFAULT NULL COMMENT '菜单图标',
      `order` tinyint(4) DEFAULT '0' COMMENT '菜单顺序',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单表';
    
    -- ----------------------------
    -- Records of jrbac_menu
    -- ----------------------------
    INSERT INTO `jrbac_menu` VALUES ('1', 'Forms', null, 'forms.html', 'fa fa-edit', '0');
    INSERT INTO `jrbac_menu` VALUES ('2', 'UI Elements', null, '', 'fa fa-wrench', '1');
    INSERT INTO `jrbac_menu` VALUES ('3', 'Buttons', '2', 'buttons.html', '', '0');
    INSERT INTO `jrbac_menu` VALUES ('4', 'Icons', '2', 'icons.html', null, '1');
    INSERT INTO `jrbac_menu` VALUES ('5', 'Multi-Level Dropdown', '', '', 'fa fa-sitemap', '2');
    INSERT INTO `jrbac_menu` VALUES ('6', 'Second Level Item', '5', 'second.html', null, '0');
    INSERT INTO `jrbac_menu` VALUES ('7', 'Third Level', '5', null, '', '1');
    INSERT INTO `jrbac_menu` VALUES ('8', 'Third Level Item', '7', 'third.html', null, '0');
    

    为了演示,我们把可展开的没有做完,仅仅插入几条数据能出效果就可以了。

    meuDao

    package com.jrbac.dao;
    
    import java.util.List;
    
    import com.jrbac.entity.LoginUser;
    import com.jrbac.entity.Menu;
    
    public interface MenuDao {
    
    	/**
    	 * 查找用户的菜单
    	 * @param loginUser
    	 * @return
    	 */
    	public List<Menu> queryMenuList(LoginUser loginUser);
    }
    
    

    mybatis

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.jrbac.dao.MenuDao">
    	<select id="queryMenuList" resultType="Menu">
    		SELECT 
    			id,`name`,parent_id,url,icon,`order`
    		FROM 
    			jrbac_menu ORDER BY `order` ASC
    	</select>
    </mapper>
    

    测试方法与递归方法

    
    @Test
    public void testQueryMenuList() {
    	// 原始的数据一条一条的
    	List<Menu> rootMenu = menuDao.queryMenuList(null);
    	// 构建好的菜单树,第一层菜单的pid是null
    	List<Menu> menuTree = buildMenuTree(rootMenu, null);
        System.out.println(menuTree);
    }
    
    /**
     * 构建菜单树
     *
     * @param menuList
     * @param pid
     * @return
     */
    private List<Menu> buildMenuTree(List<Menu> menuList, String pid) {
        List<Menu> treeList = new ArrayList<>();
        menuList.forEach(menu -> {
            if (StringUtils.equals(pid, menu.getParentId())) {
                menu.setChildMenus(buildMenuTree(menuList, menu.getId()));
                treeList.add(menu);
            }
        });
        return treeList;
    }
    

    menuDao.queryMenuList(null);查找的结果是一条一条的数据

    这里写图片描述
    测试程序的运行结果,对输出的json进行个格式化后的对比

    这里写图片描述

    最终效果

    这里写图片描述

    如果你也使用sbadmin后台模版的话,它只做到了二级菜单,三级的没有做展开控制。

    要做到三级将sb-admin-2.js的最后一个替换成下面的。

    if (element.is('li')) {
        element.addClass('active');
        element.parent().addClass('in');
    }
    

    再奉上前端jsp页面输出菜单的代码

    <c:forEach items="${userMenuList }" var="menu" varStatus="status">
                      	<!-- 一级子菜单没有parentId,有url -->
                      	<c:if test="${empty menu.parentId and not empty menu.url}">
    		<li>
    			<a href="<c:url value='${menu.url }'/>">
    				<i class="${menu.icon } fa-fw"></i> ${menu.name }
    			</a>
    		</li>
    	</c:if>
    	<!-- 可展开的一级菜单,没有parentId,有url -->
    	<c:if test="${empty menu.parentId and empty menu.url}">
    		<li>
    			<a href="#">
    				<i class="${menu.icon } fa-fw"></i> ${menu.name }<span class="fa arrow"></span>
    			</a>
    			<ul class="nav nav-second-level">
    				<!-- 没有url的是三级菜单,有url的直接输出到li中 -->
    				<c:forEach items="${menu.childMenus}" var="secondChild" varStatus="status">
    					<c:if test="${not empty secondChild.url }">
    						<li>
                                     <a href="<c:url value='${secondChild.url }'/>">${secondChild.name }</a>
                                  </li>
    					</c:if>
    					<!-- 二级菜单url为空,表示还有三级菜单 -->
    					<c:if test="${empty secondChild.url }">
    						<li>
                                     <a href="#">${secondChild.name }<span class="fa arrow"></span></a>
                                     <ul class="nav nav-third-level">
                                     		<c:forEach items="${secondChild.childMenus}" var="thirdChild" varStatus="status">
                                      		<li>
                                               <a href="<c:url value='${thirdChild.url }'/>">${thirdChild.name }</a>
                                           </li>
                                          </c:forEach>
                                     </ul>
                                  </li>
    					</c:if>
    				</c:forEach>
    			</ul>
    		</li>
    	</c:if>
    </c:forEach>
    

    参考文献

    https://blog.csdn.net/ldllovegyh/article/details/102692948

    展开全文
  • Java菜单菜单条、菜单菜单项)

    万次阅读 多人点赞 2018-08-15 14:03:23
    有两种类型的菜单:下拉式菜单和弹出式菜单。本章只讨论下拉式菜单编程方法。菜单与JComboBox和JCheckBox不同,它们在界面中是一直可见的。菜单与JComboBox的相同之处是每次只可选择一个项目。在下拉式菜单或弹出式...

    有两种类型的菜单:下拉式菜单和弹出式菜单。本章只讨论下拉式菜单编程方法。菜单与JComboBox和JCheckBox不同,它们在界面中是一直可见的。菜单与JComboBox的相同之处是每次只可选择一个项目。

    在下拉式菜单或弹出式菜单中选择一个选项就产生一个ActionEvent事件。该事件被发送给那个选项的监视器,事件的意义由监视器解释。

    菜单条、菜单和菜单项

    下拉式菜单通过出现在菜单条上的名字可视化表示,菜单条(JMenuBar)通常出现在JFrame的顶部,一个菜单条显示多个下拉式菜单的名字。可以用两种方式来激活下拉式菜单。一种是按下鼠标的按钮,并保持按下状态,移动鼠标,直至释放鼠标完成选择,高亮度显示的菜单项即为所选择的。另一种方式是当光标位于菜单条中的菜单名上时,点击鼠标,在这种情况下,菜单会展开,且高亮度显示菜单项。

    一个菜单条可以放多个菜单(JMenu),每个菜单又可以有许多菜单项(JMenuItem)。例如,Eclipse环境的菜单条有File、Edit、Source、Refactor等菜单,每个菜单又有许多菜单项。例如,File菜单有New、Open File、Close 、Close All等菜单项。

    向窗口增设菜单的方法是:先创建一个菜单条对象,然后再创建若干菜单对象,把这些菜单对象放在菜单条里,再按要求为每个菜单对象添加菜单项。
    菜单中的菜单项也可以是一个完整的菜单。由于菜单项又可以是另一个完整菜单,因此可以构造一个层次状菜单结构。

    1.菜单条
    类JMenuBar的实例就是菜单条。例如,以下代码创建菜单条对象menubar:
        JMenuBar menubar = new JMenuBar();
    在窗口中增设菜单条,必须使用JFrame类中的setJMenuBar()方法。例如,代码:
        setJMenuBar(menubar);

    类JMenuBar的常用方法有:

    1. add(JMenu m):将菜单m加入到菜单条中。
    2. countJMenus():获得菜单条中菜单条数。
    3. getJMenu(int p):取得菜单条中的菜单。
    4. remove(JMenu m):删除菜单条中的菜单m。


    2. 菜单
    由类JMenu创建的对象就是菜单。类JMenu的常用方法如下:

    1. JMenu():建立一个空标题的菜单。
    2. JMenu(String s):建立一个标题为s的菜单。
    3. add(JMenuItem item):向菜单增加由参数item指定的菜单选项。
    4. add(JMenu menu):向菜单增加由参数menu指定的菜单。实现在菜单嵌入子菜单。
    5. addSeparator():在菜单选项之间画一条分隔线。
    6. getItem(int n):得到指定索引处的菜单项。
    7. getItemCount():得到菜单项数目。
    8. insert(JMenuItem item,int n):在菜单的位置n插入菜单项item.
    9. remove(int n):删除菜单位置n的菜单项
    10. removeAll():删除菜单的所有菜单项。


    3.菜单项
    类JMenuItem 的实例就是菜单项。类JMenuItem的常用方法如下:

    1. JMenuItem():构造无标题的菜单项。
    2. JMenuItem(String s):构造有标题的菜单项。
    3. setEnabled(boolean b):设置当前单项是否可被选择。
    4. isEnabled():返回当前菜单项是否可被用户选择。
    5. getLabel():得到菜单项的名称。
    6. setLabel():设置菜单选项的名称。
    7. addActionListener(ActionListener e):为菜单项设置监视器。监视器接受点击某个菜单的动作事件。


    4. 处理菜单事件
    菜单的事件源是用鼠标点击某个菜单项。处理该事件的接口是ActionListener,要实现的接口方法是actionPerformed(ActionEvent e),获得事件源的方法getSource(). 

    【例 11-15】小应用程序示意窗口有菜单条的实现方法。设有一个按钮,当按钮处于打开窗口状态时,单击按钮将打开一个窗口,窗口设有一个菜单条,有两个菜单,每个菜单又各有三个菜单项。当一个菜单项被选中时,菜单项监视方法在文本框中显示相应菜单项被选中字样(查看源文件)。

    5. 嵌入子菜单
    创建了一个菜单,并创建多个菜单项,其中某个菜单项又是一个(含其他菜单项的)菜单,这就构成菜单嵌套。例如,将上述程序中的有关代码改成如下:
        Menu menu1,menu2,item4;
        MenuItem item3,item5,item6,item41,item42;
    另插入以下代码创建item41和item42菜单项,并把它们加入到item4菜单中:
        item41= new MenuItem(“东方红”);
        item42 = new MenuItem(“牡丹”);
        item4.add(item41);
        item4.add(item42);
    则点击item4菜单时,又会打开两个菜单项供选择。

    6. 向菜单增加退出项
    增设一个新的菜单项,对该菜单项加入监视,对应的监视方法中使用System.exit()方法,就能实现单击该菜单项时退出Java运行环境。例如,以下示意代码:

    item7 = new MenuItem(“退出”);
    item7.addActionListener(this);

    public void actionPerformed(ActionEvent e){
        if(e.getSource()==item7){
            System.exit(0);
        }
    }

    7.设置菜单项的快捷键
    用MenuShortcut类为菜单项设置快捷键。构造方法是MenuShortcut(int key)。其中key可以取值KeyEvent.VK_A至KenEvent.VK_Z,也可以取 ‘a’到 ‘z’键码值。菜单项使用setShortcut(MenuShortcut k)方法来设置快捷键。例如,以下代码设置字母e为快捷键。
    class Herwindow extends Frame implements ActionListener{
        MenuBar menbar;
        Menu menu;
        MenuItem item;
        MenuShortcut shortcut = new MenuShortcut(KeyEvent.VK_E);
        …
        item.setShortcut(shortcut);
        …
    }

    选择框菜单项

    菜单也可以包含具有持久的选择状态的选项,这种特殊的菜单可由JCheckBoxMenuItem类来定义。JCheckBoxMenuItem对象像选择框一样,能表示一个选项被选中与否,也可以作为一个菜单项加到下拉菜单中。点击JCheckBoxMenuItem菜单时,就会在它的左边出现打勾符号或清除打勾符号。例如,在例6.5程序的类MenuWindow中,将代码
        addItem(menu1,“跑步”,this);addItem(menu1,”跳绳”,this);
    改写成以下代码,就将两个普通菜单项“跑步“和“跳绳”改成两个选择框菜单项:
        JCheckBoxMenuItem item1 = new JCheckBoxMenuItem(“跑步”);
        JCheckBoxMenuItem item2 = new JCheckBoxMenuItem(“跳绳”);
        item1.setActionCommand(“跑步”);
        item1.addActionListener(this);
        menu1.add(item1);
        item2.setActionCommand(“跳绳”);
        item2.addActionListener(this);
        menu1.add(item2);

    参考资料:http://www.makeru.com.cn/course/1427.html?v=java_v1.1?s=26056

    Java学习交流群:259038500

    展开全文
  • Fragment+FragmentTabHost实现仿新浪微博底部菜单栏效果(源码)
  • 之前我向大家介绍了史上最简单的滑动菜单的实现方式,相信大家都还记得。如果忘记了其中的实现原理或者还没看过的朋友,请先去看一遍之前的文章 Android滑动菜单特效实现,仿人人客户端侧滑效果,史上最简单的侧滑...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8744400


    之前我向大家介绍了史上最简单的滑动菜单的实现方式,相信大家都还记得。如果忘记了其中的实现原理或者还没看过的朋友,请先去看一遍之前的文章 Android滑动菜单特效实现,仿人人客户端侧滑效果,史上最简单的侧滑实现 ,因为我们今天要实现的滑动菜单框架也是基于同样的原理的。


    之前的文章中在最后也提到了,如果是你的应用程序中有很多个Activity都需要加入滑动菜单的功能,那么每个Activity都要写上百行的代码才能实现效果,再简单的滑动菜单实现方案也没用。因此我们今天要实现一个滑动菜单的框架,然后在任何Activity中都可以一分钟引入滑动菜单功能。


    首先还是讲一下实现原理。说是滑动菜单的框架,其实说白了也很简单,就是我们自定义一个布局,在这个自定义布局中实现好滑动菜单的功能,然后只要在Activity的布局文件里面引入我们自定义的布局,这个Activity就拥有了滑动菜单的功能了。原理讲完了,是不是很简单?下面我们来动手实现吧。


    在Eclipse中新建一个Android项目,项目名就叫做RenRenSlidingLayout。


    新建一个类,名叫SlidingLayout,这个类是继承自LinearLayout的,并且实现了OnTouchListener接口,具体代码如下:

    public class SlidingLayout extends LinearLayout implements OnTouchListener {
    
    	/**
    	 * 滚动显示和隐藏左侧布局时,手指滑动需要达到的速度。
    	 */
    	public static final int SNAP_VELOCITY = 200;
    
    	/**
    	 * 屏幕宽度值。
    	 */
    	private int screenWidth;
    
    	/**
    	 * 左侧布局最多可以滑动到的左边缘。值由左侧布局的宽度来定,marginLeft到达此值之后,不能再减少。
    	 */
    	private int leftEdge;
    
    	/**
    	 * 左侧布局最多可以滑动到的右边缘。值恒为0,即marginLeft到达0之后,不能增加。
    	 */
    	private int rightEdge = 0;
    
    	/**
    	 * 左侧布局完全显示时,留给右侧布局的宽度值。
    	 */
    	private int leftLayoutPadding = 80;
    
    	/**
    	 * 记录手指按下时的横坐标。
    	 */
    	private float xDown;
    
    	/**
    	 * 记录手指移动时的横坐标。
    	 */
    	private float xMove;
    
    	/**
    	 * 记录手机抬起时的横坐标。
    	 */
    	private float xUp;
    
    	/**
    	 * 左侧布局当前是显示还是隐藏。只有完全显示或隐藏时才会更改此值,滑动过程中此值无效。
    	 */
    	private boolean isLeftLayoutVisible;
    
    	/**
    	 * 左侧布局对象。
    	 */
    	private View leftLayout;
    
    	/**
    	 * 右侧布局对象。
    	 */
    	private View rightLayout;
    
    	/**
    	 * 用于监听侧滑事件的View。
    	 */
    	private View mBindView;
    
    	/**
    	 * 左侧布局的参数,通过此参数来重新确定左侧布局的宽度,以及更改leftMargin的值。
    	 */
    	private MarginLayoutParams leftLayoutParams;
    
    	/**
    	 * 右侧布局的参数,通过此参数来重新确定右侧布局的宽度。
    	 */
    	private MarginLayoutParams rightLayoutParams;
    
    	/**
    	 * 用于计算手指滑动的速度。
    	 */
    	private VelocityTracker mVelocityTracker;
    
    	/**
    	 * 重写SlidingLayout的构造函数,其中获取了屏幕的宽度。
    	 * 
    	 * @param context
    	 * @param attrs
    	 */
    	public SlidingLayout(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    		screenWidth = wm.getDefaultDisplay().getWidth();
    	}
    
    	/**
    	 * 绑定监听侧滑事件的View,即在绑定的View进行滑动才可以显示和隐藏左侧布局。
    	 * 
    	 * @param bindView
    	 *            需要绑定的View对象。
    	 */
    	public void setScrollEvent(View bindView) {
    		mBindView = bindView;
    		mBindView.setOnTouchListener(this);
    	}
    
    	/**
    	 * 将屏幕滚动到左侧布局界面,滚动速度设定为30.
    	 */
    	public void scrollToLeftLayout() {
    		new ScrollTask().execute(30);
    	}
    
    	/**
    	 * 将屏幕滚动到右侧布局界面,滚动速度设定为-30.
    	 */
    	public void scrollToRightLayout() {
    		new ScrollTask().execute(-30);
    	}
    
    	/**
    	 * 左侧布局是否完全显示出来,或完全隐藏,滑动过程中此值无效。
    	 * 
    	 * @return 左侧布局完全显示返回true,完全隐藏返回false。
    	 */
    	public boolean isLeftLayoutVisible() {
    		return isLeftLayoutVisible;
    	}
    
    	/**
    	 * 在onLayout中重新设定左侧布局和右侧布局的参数。
    	 */
    	@Override
    	protected void onLayout(boolean changed, int l, int t, int r, int b) {
    		super.onLayout(changed, l, t, r, b);
    		if (changed) {
    			// 获取左侧布局对象
    			leftLayout = getChildAt(0);
    			leftLayoutParams = (MarginLayoutParams) leftLayout.getLayoutParams();
    			// 重置左侧布局对象的宽度为屏幕宽度减去leftLayoutPadding
    			leftLayoutParams.width = screenWidth - leftLayoutPadding;
    			// 设置最左边距为负的左侧布局的宽度
    			leftEdge = -leftLayoutParams.width;
    			leftLayoutParams.leftMargin = leftEdge;
    			leftLayout.setLayoutParams(leftLayoutParams);
    			// 获取右侧布局对象
    			rightLayout = getChildAt(1);
    			rightLayoutParams = (MarginLayoutParams) rightLayout.getLayoutParams();
    			rightLayoutParams.width = screenWidth;
    			rightLayout.setLayoutParams(rightLayoutParams);
    		}
    	}
    
    	@Override
    	public boolean onTouch(View v, MotionEvent event) {
    		createVelocityTracker(event);
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			// 手指按下时,记录按下时的横坐标
    			xDown = event.getRawX();
    			break;
    		case MotionEvent.ACTION_MOVE:
    			// 手指移动时,对比按下时的横坐标,计算出移动的距离,来调整左侧布局的leftMargin值,从而显示和隐藏左侧布局
    			xMove = event.getRawX();
    			int distanceX = (int) (xMove - xDown);
    			if (isLeftLayoutVisible) {
    				leftLayoutParams.leftMargin = distanceX;
    			} else {
    				leftLayoutParams.leftMargin = leftEdge + distanceX;
    			}
    			if (leftLayoutParams.leftMargin < leftEdge) {
    				leftLayoutParams.leftMargin = leftEdge;
    			} else if (leftLayoutParams.leftMargin > rightEdge) {
    				leftLayoutParams.leftMargin = rightEdge;
    			}
    			leftLayout.setLayoutParams(leftLayoutParams);
    			break;
    		case MotionEvent.ACTION_UP:
    			// 手指抬起时,进行判断当前手势的意图,从而决定是滚动到左侧布局,还是滚动到右侧布局
    			xUp = event.getRawX();
    			if (wantToShowLeftLayout()) {
    				if (shouldScrollToLeftLayout()) {
    					scrollToLeftLayout();
    				} else {
    					scrollToRightLayout();
    				}
    			} else if (wantToShowRightLayout()) {
    				if (shouldScrollToContent()) {
    					scrollToRightLayout();
    				} else {
    					scrollToLeftLayout();
    				}
    			}
    			recycleVelocityTracker();
    			break;
    		}
    		return isBindBasicLayout();
    	}
    
    	/**
    	 * 判断当前手势的意图是不是想显示右侧布局。如果手指移动的距离是负数,且当前左侧布局是可见的,则认为当前手势是想要显示右侧布局。
    	 * 
    	 * @return 当前手势想显示右侧布局返回true,否则返回false。
    	 */
    	private boolean wantToShowRightLayout() {
    		return xUp - xDown < 0 && isLeftLayoutVisible;
    	}
    
    	/**
    	 * 判断当前手势的意图是不是想显示左侧布局。如果手指移动的距离是正数,且当前左侧布局是不可见的,则认为当前手势是想要显示左侧布局。
    	 * 
    	 * @return 当前手势想显示左侧布局返回true,否则返回false。
    	 */
    	private boolean wantToShowLeftLayout() {
    		return xUp - xDown > 0 && !isLeftLayoutVisible;
    	}
    
    	/**
    	 * 判断是否应该滚动将左侧布局展示出来。如果手指移动距离大于屏幕的1/2,或者手指移动速度大于SNAP_VELOCITY,
    	 * 就认为应该滚动将左侧布局展示出来。
    	 * 
    	 * @return 如果应该滚动将左侧布局展示出来返回true,否则返回false。
    	 */
    	private boolean shouldScrollToLeftLayout() {
    		return xUp - xDown > screenWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;
    	}
    
    	/**
    	 * 判断是否应该滚动将右侧布局展示出来。如果手指移动距离加上leftLayoutPadding大于屏幕的1/2,
    	 * 或者手指移动速度大于SNAP_VELOCITY, 就认为应该滚动将右侧布局展示出来。
    	 * 
    	 * @return 如果应该滚动将右侧布局展示出来返回true,否则返回false。
    	 */
    	private boolean shouldScrollToContent() {
    		return xDown - xUp + leftLayoutPadding > screenWidth / 2
    				|| getScrollVelocity() > SNAP_VELOCITY;
    	}
    
    	/**
    	 * 判断绑定滑动事件的View是不是一个基础layout,不支持自定义layout,只支持四种基本layout,
    	 * AbsoluteLayout已被弃用。
    	 * 
    	 * @return 如果绑定滑动事件的View是LinearLayout,RelativeLayout,FrameLayout,
    	 *         TableLayout之一就返回true,否则返回false。
    	 */
    	private boolean isBindBasicLayout() {
    		if (mBindView == null) {
    			return false;
    		}
    		String viewName = mBindView.getClass().getName();
    		return viewName.equals(LinearLayout.class.getName())
    				|| viewName.equals(RelativeLayout.class.getName())
    				|| viewName.equals(FrameLayout.class.getName())
    				|| viewName.equals(TableLayout.class.getName());
    	}
    
    	/**
    	 * 创建VelocityTracker对象,并将触摸事件加入到VelocityTracker当中。
    	 * 
    	 * @param event
    	 *            右侧布局监听控件的滑动事件
    	 */
    	private void createVelocityTracker(MotionEvent event) {
    		if (mVelocityTracker == null) {
    			mVelocityTracker = VelocityTracker.obtain();
    		}
    		mVelocityTracker.addMovement(event);
    	}
    
    	/**
    	 * 获取手指在右侧布局的监听View上的滑动速度。
    	 * 
    	 * @return 滑动速度,以每秒钟移动了多少像素值为单位。
    	 */
    	private int getScrollVelocity() {
    		mVelocityTracker.computeCurrentVelocity(1000);
    		int velocity = (int) mVelocityTracker.getXVelocity();
    		return Math.abs(velocity);
    	}
    
    	/**
    	 * 回收VelocityTracker对象。
    	 */
    	private void recycleVelocityTracker() {
    		mVelocityTracker.recycle();
    		mVelocityTracker = null;
    	}
    
    	class ScrollTask extends AsyncTask<Integer, Integer, Integer> {
    
    		@Override
    		protected Integer doInBackground(Integer... speed) {
    			int leftMargin = leftLayoutParams.leftMargin;
    			// 根据传入的速度来滚动界面,当滚动到达左边界或右边界时,跳出循环。
    			while (true) {
    				leftMargin = leftMargin + speed[0];
    				if (leftMargin > rightEdge) {
    					leftMargin = rightEdge;
    					break;
    				}
    				if (leftMargin < leftEdge) {
    					leftMargin = leftEdge;
    					break;
    				}
    				publishProgress(leftMargin);
    				// 为了要有滚动效果产生,每次循环使线程睡眠20毫秒,这样肉眼才能够看到滚动动画。
    				sleep(20);
    			}
    			if (speed[0] > 0) {
    				isLeftLayoutVisible = true;
    			} else {
    				isLeftLayoutVisible = false;
    			}
    			return leftMargin;
    		}
    
    		@Override
    		protected void onProgressUpdate(Integer... leftMargin) {
    			leftLayoutParams.leftMargin = leftMargin[0];
    			leftLayout.setLayoutParams(leftLayoutParams);
    		}
    
    		@Override
    		protected void onPostExecute(Integer leftMargin) {
    			leftLayoutParams.leftMargin = leftMargin;
    			leftLayout.setLayoutParams(leftLayoutParams);
    		}
    	}
    
    	/**
    	 * 使当前线程睡眠指定的毫秒数。
    	 * 
    	 * @param millis
    	 *            指定当前线程睡眠多久,以毫秒为单位
    	 */
    	private void sleep(long millis) {
    		try {
    			Thread.sleep(millis);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }

    看到这里,我相信大家一定会觉得这些代码非常熟悉。没错,基本上这些代码和之前那篇文章的代码大同小异,只不过以前这些代码是写在Activity里的,而现在我们移动到了自定义的View当中。


    接着我来说明一下和以前不同的部分。我们可以看到,这里将onLayout方法进行了重写,使用getChildAt(0)获取到的布局作为左边布局,使用getChildAt(1)获取到的布局作为右边布局。并将左边布局的宽度重定义为屏幕宽度减去leftLayoutPadding,将右侧布局的宽度重定义为屏幕宽度。然后让左边布局偏移出屏幕,这样能看到的就只有右边布局了。因此在这里我们也可以看出,使用SlidingLayout这个布局的前提条件,必须为这个布局提供两个子元素,第一个元素会作为左边布局偏移出屏幕,第二个元素会作为右边布局显示在屏幕上。


    然后我们看一下setScrollEvent方法,这个方法接收一个View作为参数,然后为这个View绑定了一个touch事件。这是什么意思呢?让我们来想象一个场景,如果右侧布局是一个LinearLayout,我可以通过监听LinearLayout上的touch事件来控制左侧布局的显示和隐藏。但是如果右侧布局的LinearLayout里面加入了一个ListView,而这个ListView又充满了整个LinearLayout,这个时候LinearLayout将不可能再被touch到了,这个时候我们就需要将touch事件注册到ListView上。setScrollEvent方法也就是提供了一个注册接口,touch事件将会注册到传入的View上。


    最后还有一个陌生的方法,isBindBasicLayout。这个方法就是判断了一下注册touch事件的View是不是四个基本布局之一,如果是就返回true,否则返回false。这个方法在整个SlidingLayout中起着非常重要的作用,主要用于控制onTouch事件是返回true还是false,这将影响到布局当中的View的功能是否可用。由于里面牵扯到了Android的事件转发机制,内容比较多,就不在这里详细解释了,我会考虑以后专门写一篇文章来介绍Android的事件机制。这里就先简单记住如果是基本布局就返回true,否则就返回false。


    好了,我们的SlidingLayout写完了,接下来就是见证奇迹的时刻,让我们一起看看如何一分钟在Activity中引入滑动菜单功能。


    创建或打开layout目录下的activity_main.xml文件,加入如下代码:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal"
        tools:context=".MainActivity" >
    
        <!-- 使用自定义的侧滑布局,orientation必须为水平方向 -->
    
        <com.example.slide.SlidingLayout
            android:id="@+id/slidingLayout"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="horizontal" >
    
            <!--
    	        侧滑布局的根节点下,有且只能有两个子元素,这两个子元素必须是四种基本布局之一,
    	        即LinearLayout, RelativeLayout, FrameLayout或TableLayout。
    	        第一个子元素将做为左侧布局,初始化后被隐藏。第二个子元素将做为右侧布局,
    	        也就是当前Activity的主布局,将主要的数据放在里面。
            -->
    
            <RelativeLayout
                android:id="@+id/menu"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="#00ccff" >
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="This is menu"
                    android:textColor="#000000"
                    android:textSize="28sp" />
            </RelativeLayout>
    
            <LinearLayout
                android:id="@+id/content"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="vertical" >
    
                <Button
                    android:id="@+id/menuButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Menu" />
    
                <ListView
                    android:id="@+id/contentList"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent" >
                </ListView>
            </LinearLayout>
        </com.example.slide.SlidingLayout>
    
    </LinearLayout>

    我们可以看到,在根布局的下面,我们引入了自定义布局com.example.slide.SlidingLayout,然后在它里面加入了两个子元素,一个RelativeLayout和一个LinearLayout。RelativeLayout中比较简单,就加入了一个TextView。LinearLayout里面我们加入了一个按钮和一个ListView。


    然后创建或打开MainActivity作为程序的主Activity,加入代码:

    public class MainActivity extends Activity {
    
    	/**
    	 * 侧滑布局对象,用于通过手指滑动将左侧的菜单布局进行显示或隐藏。
    	 */
    	private SlidingLayout slidingLayout;
    
    	/**
    	 * menu按钮,点击按钮展示左侧布局,再点击一次隐藏左侧布局。
    	 */
    	private Button menuButton;
    
    	/**
    	 * 放在content布局中的ListView。
    	 */
    	private ListView contentListView;
    
    	/**
    	 * 作用于contentListView的适配器。
    	 */
    	private ArrayAdapter<String> contentListAdapter;
    
    	/**
    	 * 用于填充contentListAdapter的数据源。
    	 */
    	private String[] contentItems = { "Content Item 1", "Content Item 2", "Content Item 3",
    			"Content Item 4", "Content Item 5", "Content Item 6", "Content Item 7",
    			"Content Item 8", "Content Item 9", "Content Item 10", "Content Item 11",
    			"Content Item 12", "Content Item 13", "Content Item 14", "Content Item 15",
    			"Content Item 16" };
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		slidingLayout = (SlidingLayout) findViewById(R.id.slidingLayout);
    		menuButton = (Button) findViewById(R.id.menuButton);
    		contentListView = (ListView) findViewById(R.id.contentList);
    		contentListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
    				contentItems);
    		contentListView.setAdapter(contentListAdapter);
    		// 将监听滑动事件绑定在contentListView上
    		slidingLayout.setScrollEvent(contentListView);
    		menuButton.setOnClickListener(new OnClickListener() {
    			@Override
    			public void onClick(View v) {
    				// 实现点击一下menu展示左侧布局,再点击一下隐藏左侧布局的功能
    				if (slidingLayout.isLeftLayoutVisible()) {
    					slidingLayout.scrollToRightLayout();
    				} else {
    					slidingLayout.scrollToLeftLayout();
    				}
    			}
    		});
    	}
    
    }

    上述代码重点是调用SlidingLayout的setScrollEvent方法,为ListView注册touch事件。同时给按钮添加了一个点击事件,实现了点击一下显示左边布局,再点击一下隐藏左边布局的功能。


    最后还是老规矩,给出AndroidManifest.xml的代码:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.slide"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="8" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.NoTitleBar" >
            <activity
                android:name="com.example.slide.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    好了,现在让我们运行一下吧。首先是程序打开的时候,显示的是右边布局。用手指在界面上向右滑动,可以看到左边布局出现。


                    


    而当左边布局完全显示的时候,效果图如下:


                               


    除此之外,点击Menu按钮也可以控制左边布局的显示和隐藏,大家可以自己试一下。


    使用自定义布局的话,就可以用简单的方式在任意Activity中加入滑动菜单功能,即使你有再多的Activity也不用怕了,一分钟引入滑动菜单妥妥的。


    再总结一下吧,向Activity中加入滑动菜单功能只需要两步:

    1. 在Acitivty的layout中引入我们自定义的布局,并且给这个布局要加入两个直接子元素。

    2. 在Activity中通过setScrollEvent方法,给一个View注册touch事件。


    好了,今天的讲解到此结束,有疑问的朋友请在下面留言。


    源码下载,请点击这里


    补充:

    由于这段文章写的比较早了,那时写的滑动菜单还存在着不少问题,我之后又将上面的代码做了不少改动,编写了一个修正版的滑动菜单,这个版本主要修正了以下内容:


    1.将滑动方式改成了覆盖型。

    2.ListView上下滚动时不会轻易滑出菜单。

    3.正在滑动时屏蔽掉内容布局上的事件。

    4.当菜单布局展示时,点击一下右侧的内容布局,可以将菜单隐藏。

    5.修复刚打开程序时,菜单可能会短暂显示一下,然后瞬间消失的bug。


    修正版源码下载,请点击这里


    另外,有对双向滑动菜单感兴趣的朋友请转阅  Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • JAVA 菜单条、菜单菜单

    千次阅读 2018-06-18 21:22:45
    菜单条、菜单菜单项 菜单条、菜单菜单项是窗口常用的组件,菜单放在菜单条里,菜单项放在菜单里。 1、菜单条 JComponent类的子类JMenubar负责创建菜单条,即JMemubar的个实例就是一个菜单条。JFrame类有个将...
  • 2)服务号可以申请自定义菜单; 3)使用QQ登录的公众号,可以升级为邮箱登录; 4)使用邮箱登录的公众号,可以修改登录邮箱; 5)编辑图文消息可选填作者; 6)群发消息可以同步到腾讯微博。 其中,大家议论...
  • android底部菜单栏demo

    千次下载 热门讨论 2012-07-13 19:49:11
    android底部菜单栏demo
  • Bootstrap4下拉菜单 鼠标移入显示菜单、鼠标移出隐藏菜单
  • 我想要做一个左侧是菜单栏,然后点击菜单在右侧显示内容的一个页面,并且不刷新左侧的菜单~求助各位大神~很多人都说用ajax做,但是新手没有接触过,给点例子什么的最好了~
  • Qt添加菜单有两种方法,一是用代码直接手动添加,二是在Qtdesigner中在界面上直接添加。 先介绍用代码如何添加。 需要用到两个类QMenu和QAction,例如我的Demo程序界面如下: 对于“新建”,“编辑”这些主菜...
  • 访问控制第一层级:根据当前登录用户动态加载菜单
  • Android仿微信底部菜单栏+顶部菜单栏(附源码)

    千次下载 热门讨论 2015-03-07 23:11:29
    Android仿微信底部菜单栏+顶部菜单栏,效果看博文http://blog.csdn.net/evankaka/article/details/44121457
  • Android左右菜单滑动

    千次下载 热门讨论 2013-04-09 14:55:04
    这是一个可以从左,或右端滑出菜单菜单中可以添加ListView,并写了个公共控件来处理上下,左右手势处理,避免冲突。
  • 1、在刷新后保持菜单选中 ANTD的API中提供了一个defaultSelectedKeys参数 描述:初始选中的菜单项 key 数组 类型: string[] 自己手动实验得知意思就是在数组中填入字符串 例如[‘key’] 默认值为空 在菜单标签中...
  • ivew的menu封装成二级菜单和无限极菜单 demo中有注释,此处不赘述了 github地址: 二级菜单封装: <template> <div class='con'> <Menu :theme="theme2" style='width:240px;float:left'> &...
  • QMenu和QMenuBar是Qt中的菜单类和菜单栏类,其中,菜单QMenu挂载在菜单栏QMenuBar上。本文主要总结QMenu的三种常用用法,分别为常规用法、继承QWidgetAction自定义菜单项用法、将QMenu当QWidget挂载一个布局用法。 ...
  • Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭

    万次阅读 多人点赞 2014-09-15 09:19:36
    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39257409,本文出自【张鸿洋的博客】上一篇博客带...的确,上一篇也承诺过,稍微修改上一篇的代码,实现QQ5.0侧滑菜单~~好了,下面就开始为大家展
  • Android滑动菜单框架Demo修正版

    千次下载 热门讨论 2013-08-21 21:13:51
    此版本修正了以下内容: 1.将滑动方式改成了覆盖型。...2.ListView上下滚动时不会轻易滑出菜单。 3.正在滑动时屏蔽掉内容布局上的事件。 4.当菜单布局展示时,点击一下右侧的内容布局,可以将菜单隐藏。
  • DIV+CSS制作二级菜单(横排二级下拉菜单)以及二级菜单出现错位解决方法
  • WPS右键菜单添加自定义菜单

    千次阅读 2019-03-22 11:31:49
    关于在OFFICE EXCEL右键菜单中加入自定义菜单,网上例子一抓一大把,这里就不在赘述。 今天主要说的是在WPS中如何往右键菜单添加自定义事件。其实说白了就是找到右键菜单在WPS中的索引,废话不说,直接上代码:...
  • 菜单Menu和菜单项MenuItem

    千次阅读 2018-04-27 13:47:00
    一.程序的功能介绍 文件子菜单下面有新建,打开和退出子选项。...(2)然后在主菜单中添加两个子菜单——文件子菜单fileItem和视图子菜单viewItem; 类型是菜单选项(MenuItem)样式是可以有子菜单(SWT....
  • 在使用eclipse 开发工具时,经常有小伙伴会遇到点击new菜单后没有新建java project或class选项的问题,这是一个比较好的解决方案
  • Menu菜单,MenuBar菜单栏,MenuItem菜单

    千次阅读 2016-10-22 11:29:09
    Menu菜单,MenuBar菜单栏,MenuItem菜单菜单栏: public class MenuDemo { public static void main(String args[]) { Frame f = new Frame("Menu菜单"); MenuBar mb = new MenuBar(); f.setMenuBar(mb)...
  • 下拉菜单(二级菜单

    千次阅读 2019-05-16 15:31:09
    鼠标移动到上面二级菜单显示 鼠标移动到二级菜单上: HTML代码: <li class="list-inline-item menuDiv"> <a href="#" class="menuA">菜单一</a> <ul class="menuUL"> ...
  • 在后台管理系统中,常常会因为不同的权限,展现不同的菜单。但这仅仅是显示控制,而我们要做的是没有的菜单权限,直接输入URL也不可访问,真正的实现菜单权限控制。 一、动态菜单显示 1. 后端返回的菜单数据处理 ...
  • 菜单,下拉菜单,单选菜单,选择菜单,弹出菜单菜单绑定等功能的实现
  • 父级菜单下有多个字菜单的父级都可以正常显示,只有父级下是一个子菜单的父级菜单不显示。所以断定是因为只有一个子菜单,父级隐藏不显示属性引起的。在处理从后台接口拿到的菜单数据时设置alwaysShow: true...
  • 1. 菜单栏、菜单菜单项之间的关系:  1) 菜单栏(MenuBar)就是窗口中常见的顶层菜单栏,包含文件、编辑、格式等等子菜单菜单条,即包含菜单的容器;  2) 菜单(Menu)是必定包含菜单项或者菜单(嵌套包含菜单...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 387,380
精华内容 154,952
关键字:

菜单