描述符包括,存储段描述符(代码段,数据段,堆栈段),系统描述符(任务状态段TSS,局部描述符表LDT),门描述符(调用门,任务门,中断门,陷阱门),注意门描述符和系统描述符都是DT=0时候,对应的状态。存储段描述符和系统描述符如图1,门描述符如图2。
图1 存储段描述符和系统描述符
图2 门描述符
(1) P:存在(Present)位。
P=1 表示描述符对地址转换是有效的,或者说该描述符所描述的段存在,即在内存中;
P=0 表示描述符对地址转换无效,即该段不存在。使用该描述符进行内存访问时会引起异常。
(2) DPL: 表示描述符特权级(Descriptor Privilege level),共2位。它规定了所描述段的特权级,用于特权检查,以决定对该段能否访问。
(3) DT:说明描述符的类型。
对于存储段描述符而言,DT=1,以区别与系统段描述符和门描述符(DT=0)。
(4) TYPE: 说明存储段描述符所描述的存储段的具体属性。
数据段类型
类型值说明
----------------------------------
0 只读
1 只读、已访问
2 读/写
3 读/写、已访问
4 只读、向下扩展
5 只读、向下扩展、已访问
6 读/写、向下扩展
7 读/写、向下扩展、已访问
类型值
说明
代码段类型
----------------------------------
8 只执行
9 只执行、已访问
A 执行/读
B 执行/读、已访问
C 只执行、一致码段
D 只执行、一致码段、已访问
E 执行/读、一致码段
F 执行/读、一致码段、已访问
系统段类型
类型编码说明
----------------------------------
0 <未定义>
1 可用286TSS
2 LDT
3 忙的286TSS
4 286调用门
5 任务门
6 286中断门
7 286陷阱门
8 未定义
9 可用386TSS
A <未定义>
B 忙的386TSS
C 386调用门
D <未定义>
E 386中断门
F 386陷阱门
(5) G:段界限粒度(Granularity)位。
G=0 表示界限粒度为字节;
G=1 表示界限粒度为4K 字节。
注意,界限粒度只对段界限有效,对段基地址无效,段基地址总是以字节为单位。
(6) D:D位是一个很特殊的位,在描述可执行段、向下扩展数据段或由SS寄存器寻址的段(通常是堆栈段)的三种描述符中的意义各不相同。
在描述可执行段的描述符中,D位决定了指令使用的地址及操作数所默认的大小。
① D=1表示默认情况下指令使用32位地址及32位或8位操作数,这样的代码段也称为32位代码段;
② D=0 表示默认情况下,使用16位地址及16位或8位操作数,这样的代码段也称为16位代码段,它与80286兼容。可以使用地址大小前缀和操作数大小前缀分别改变默认的地址或操作数的大小。
在向下扩展数据段的描述符中,D位决定段的上部边界。
① D=1表示段的上部界限为4G;
② D=0表示段的上部界限为64K,这是为了与80286兼容。
在描述由SS寄存器寻址的段描述符中,D位决定隐式的堆栈访问指令(如PUSH和POP指令)使用何种堆栈指针寄存器。
① D=1表示使用32位堆栈指针寄存器ESP;
② D=0表示使用16位堆栈指针寄存器SP,这与80286兼容。
(7) AVL:软件可利用位。80386对该位的使用未左规定,Intel公司也保证今后开发生产的处理器只要与80386兼容,就不会对该位的使用做任何定义或规定。
(8) Dword Count:从调用者堆栈中将参数复制到被调用者堆栈(新堆栈)中,复制参数的个数由调用门中Dword Count一项来决定。如果Dword
Count为0,那么不会复制参数。
选择子图示:
┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
┃ 15 ┃ 14 ┃ 13 ┃ 12 ┃ 11 ┃ 10 ┃ 9 ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━╋━━╋━━┻━━┫
┃ 描述符索引 ┃ TI ┃ RPL ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━┻━━━━━┛
RPL(Requested Privilege Level): 请求特权级,用于特权检查。
TI(Table Indicator): 引用描述符表指示位
TI=0 指示从全局描述符表GDT中读取描述符;
TI=1 指示从局部描述符表LDT中读取描述符。
LDT中的描述符和GDT中的描述符除了选择子的bit3一个为0一个为1用于区分该描述符是在GDT中还是在LDT中外,描述符本身的结构完全一样。开始我考虑既然是这样,为什么要将LDT放在GDT中而不是像GDT那样找一个GDTR寄存器呢?
后来终于明白了原因--很简单,GDT表只有一个,是固定的;而LDT表每个任务就可以有一个,因此有多个,并且由于任务的个数在不断变化其数量也在不断变化。如果只有一个LDTR寄存器显然不能满足多个LDT的要求。因此INTEL的做法是把它放在放在GDT中。
pm.inc代码如下:
;---------------------------------------- ; 描述符类型值说明 ; 其中: ; DA_ : Descriptor Attribute ; D : 数据段 ; C : 代码段 ; S : 系统段 ; R : 只读 ; RW : 读写 ; A : 已访问 ; 其它 : 可按照字面意思理解 G D 0 AVL 0 0 0 0 P DPL(2位) DT TYPE(4位) ;---------------------------------------- DA_32 EQU 4000h ; 32 位段 0100 0000 0000 0000 DA_DPL0 EQU 00h ; DPL = 0 0000 0000 DA_DPL1 EQU 20h ; DPL = 1 0010 0000 DA_DPL2 EQU 40h ; DPL = 2 0100 0000 DA_DPL3 EQU 60h ; DPL = 3 0110 0000 ;---------------------------------------- ; 存储段描述符类型值说明 ;---------------------------------------- DA_DR EQU 90h ; 存在的只读数据段类型值 1001 0000 DA_DRW EQU 92h ; 存在的可读写数据段属性值 1001 0010 DA_DRWA EQU 93h ; 存在的已访问可读写数据段类型值 1001 0011 DA_C EQU 98h ; 存在的只执行代码段属性值 1001 1000 DA_CR EQU 9Ah ; 存在的可执行可读代码段属性值 1001 1010 DA_CCO EQU 9Ch ; 存在的只执行一致代码段属性值 1001 1100 DA_CCOR EQU 9Eh ; 存在的可执行可读一致代码段属性值 1001 1110 ;---------------------------------------- ; 系统段描述符类型值说明 ;---------------------------------------- DA_LDT EQU 82h ; 局部描述符表段类型值 1000 0010 DA_TaskGate EQU 85h ; 任务门类型值 1000 0101 DA_386TSS EQU 89h ; 可用 386 任务状态段类型值 1000 1001 DA_386CGate EQU 8Ch ; 386 调用门类型值 1000 1100 DA_386IGate EQU 8Eh ; 386 中断门类型值 1000 1110 DA_386TGate EQU 8Fh ; 386 陷阱门类型值 1000 1111 ;---------------------------------------- ;---------------------------------------- ; 选择子类型值说明 ; 其中: ; SA_ : Selector Attribute SA_RPL0 EQU 0 ; ┓00 SA_RPL1 EQU 1 ; ┣ RPL01 SA_RPL2 EQU 2 ; ┃10 SA_RPL3 EQU 3 ; ┛11 SA_TIG EQU 0 ; ┓TI 0000 SA_TIL EQU 4 ; ┛ 0100 ;---------------------------------------- ; 宏 ------------------------------------------------------------------ ; ; 描述符 ; usage: Descriptor Base, Limit, Attr ; Base: dd ; Limit: dd (low 20 bits available)低二十位可用 ; Attr: dw (lower 4 bits of higher byte are always 0)高字节的低四位始终为0 %macro Descriptor 3 ;段界限为低地址 1代表Base 2代表Limit 3代表属性 dw %2 & 0FFFFh ; 段界限 1 (2 字节) dw %1 & 0FFFFh ; 段首地址 1 (2 字节) db (%1 >> 16) & 0FFh ; 段首地址 2 (1 字节) dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节) db (%1 >> 24) & 0FFh ; 段首地址 3 (1 字节) %endmacro ; 共 8 字节 ; ; 门 ; usage: Gate Selector, Offset, DCount, Attr ; Selector: dw ; Offset: dd ; DCount: db ; Attr: db %macro Gate 4 ;1代表Selector 2代表Offset 3代表DCount 4代表Attr dw (%2 & 0FFFFh) ; 偏移 1 (2 字节) dw %1 ; 选择子 (2 字节) dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性 (2 字节) dw ((%2 >> 16) & 0FFFFh) ; 偏移 2 (2 字节) %endmacro ; 共 8 字节
原文链接:Ubuntu12.04上NFS Server安装使用过程
实现步骤:
1.服务器端:sudo apt-get install portmap
2.服务器端:sudo apt-get install nfs-kernel-server
3.客户端:sudo apt-get install nfs-common
4.服务器端配置:sudo gedit /etc/exports
添加:/home/share 192.168.1.*(rw,sync,no_root_squash)
(共享目录) (允许IP)
(rw权限是可擦写,还有ro只读,sync代表数据会同步写入到内存与硬盘中,async则代表数据会先暂存于内存当中,而非直接写入硬盘,开放客户端使用root身份来操作服务器的文件系统,那么开no_root_squash才行,root_squash不允许)
5.服务器端启动:sudo /etc/init.d/portmap restart
6.服务器端启动:sudo /etc/init.d/nfs-kernel-server restart
7.arm板连接时:
主机:sudo ifconfig eth0 192.168.1.101 netmask 255.255.255.0
arm板:ifconfig eth0 192.168.1.102 netmask 255.255.255.0
8.arm板上mount:mount -t nfs 192.168.1.101:/home/share /mnt/hosts
(主机IP和共享目录) (arm板目录)
mount上之后arm板上文件自动同步
1.出现问题:
reason given by server: Permission denied
解决:服务器端启动一定要sudo启动,不然启动失败,服务拒绝
2.出现问题:
svc: failed to register lockdv1 RPC service (errno 111).
lockd_up: makesock failed, error=-111
mount: mounting 192.168.1.101:/home/share on /mnt/hosts failed: Connection refused
则改成:
mount -t nfs -o nolock 192.168.1.101:/home/share /mnt/hosts
3.出现问题:
mount: mounting 192.168.1.101:/home/share on /mnt/hosts failed: Device or resource busy
解决:
mount上之后在进行mount命令会出现此提示,设备正在运行,不用再次mount
如果想再次mount可以先umount /mnt/hosts
)
ActivityGroup是Activity的子类,在Activity的基础上还扩充了一些东西,如可以让多个Activity程序在同一界面上运行且互不干扰。这种功能在menu比较多的地方使用起来会很方便,用途也很广泛。下面是自己整理的一些代码供大家学习使用。
1.一般来说菜单一般都包含图片,实现这种功能一般都会用到适配器,该适配器继承BaseAdapter,代码如下
package org.lxh.activity; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; public class MenuImageAdapter extends BaseAdapter{ private Context context; //所有标签的图片显示 private ImageView[] menuImg; //选中的ImageView索引 private int selectedMenuImg; public MenuImageAdapter(Context context,int imgIds[],int width,int height,int selectedMenuImg){ this.context=context; this.selectedMenuImg=selectedMenuImg; this.menuImg=new ImageView[imgIds.length]; for(int x=0;x<imgIds.length;x++){ //实例化ImageView对象 this.menuImg[x]=new ImageView(this.context); //定义图片的布局参数 this.menuImg[x].setLayoutParams(new GridView.LayoutParams(width,height)); this.menuImg[x].setAdjustViewBounds(false); this.menuImg[x].setPadding(3, 3, 3, 3); this.menuImg[x].setImageResource(imgIds[x]); } } public int getCount() { // TODO Auto-generated method stub return this.menuImg.length; } public Object getItem(int position) { // TODO Auto-generated method stub return this.menuImg[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imgView=null; if(imgView==null){ imgView=this.menuImg[position]; }else{ imgView=(ImageView)convertView; } return imgView; } public void setFocus(int selid){ for(int x=0;x<this.menuImg.length;x++){ if(x!=selid){ this.menuImg[x].setBackgroundResource(0); } } this.menuImg[selid].setBackgroundResource(this.selectedMenuImg); } }
到这里第一个适配器就好了,下面为了把功能做好一些,顺便加个弹出菜单,该菜单包含标题和内容。此类弹出菜单也需要写适配器,分别是标题适配器,内容适配器。标题适配器比较简单,只需做一下点击的效果和标题内容的显示就OK,代码如下
package org.lxh.activity; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class PopupMenuTitleAdapter extends BaseAdapter { private TextView menuTitle[] = null; // 文字显示组件 private int fontColor; private int selectedColor; private int unSelectedColor; public PopupMenuTitleAdapter(Context context, int[] titleIds, int fontColor, int fontSize, int selectedColor, int unSelectedColor) { this.fontColor = fontColor; this.selectedColor = selectedColor; this.unSelectedColor = unSelectedColor; this.menuTitle = new TextView[titleIds.length]; for (int x = 0; x < titleIds.length; x++) { this.menuTitle[x] = new TextView(context); this.menuTitle[x].setText(titleIds[x]); this.menuTitle[x].setTextSize(fontSize); this.menuTitle[x].setGravity(Gravity.CENTER); this.menuTitle[x].setPadding(10, 10, 10, 10); } } @Override public int getCount() { return this.menuTitle.length; } @Override public Object getItem(int position) { return this.menuTitle[position]; } @Override public long getItemId(int position) { return this.menuTitle[position].getId(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = null; if (convertView == null) { view = this.menuTitle[position]; } else { view = convertView; } return view; } public void setFocus(int index) { for (int x = 0; x < this.menuTitle.length; x++) { if (x != index) { this.menuTitle[x].setBackgroundDrawable(new ColorDrawable( this.unSelectedColor)); this.menuTitle[x].setTextColor(fontColor); } } this.menuTitle[index].setBackgroundColor(0x00); this.menuTitle[index].setTextColor(this.selectedColor); } }下面是弹出菜单的内容适配器,里面包含了多个Activity.
package org.lxh.activity; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; public class PopupMenuBodyAdapter extends BaseAdapter { private ImageView[] menuImg = null ; public PopupMenuBodyAdapter(Context context, int [] picIds) { this.menuImg = new ImageView[picIds.length]; for (int x = 0; x < this.menuImg.length; x++) { this.menuImg[x] = new ImageView(context) ; this.menuImg[x].setImageResource(picIds[x]) ; } } @Override public int getCount() { return this.menuImg.length; } @Override public Object getItem(int position) { return this.menuImg[position]; } @Override public long getItemId(int position) { return this.menuImg[position].getId(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = null ; if (convertView == null) { view = this.menuImg[position]; } else { view = convertView; } return view; } }
2.之后便是标题和内容的顶层了,这一层就是PopupMenu了,这个弹出菜单就包含了标题和内容
package org.lxh.activity; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.view.Gravity; import android.view.ViewGroup.LayoutParams; import android.widget.AdapterView.OnItemClickListener; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupWindow; public class PopMenu extends PopupWindow { private GridView popTitle ; // 表示标题 private GridView popBody ; // 标题主体 private PopupMenuTitleAdapter titleAdapter = null ; private LinearLayout layout = null ; public PopMenu(Context context, int titleIds[],int backgroundColor, OnItemClickListener titleCallback, OnItemClickListener bodyCallback) { super(context); // 还是需要创建弹出的组件 this.titleAdapter = new PopupMenuTitleAdapter(context, titleIds, 0xFF222222, 16, Color.LTGRAY, Color.WHITE); this.layout = new LinearLayout(context) ; this.layout.setOrientation(LinearLayout.VERTICAL) ; this.popTitle = new GridView(context); this.popTitle.setLayoutParams(new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); this.popTitle.setNumColumns(titleIds.length) ; this.popTitle.setHorizontalSpacing(1) ; this.popTitle.setVerticalSpacing(1) ; this.popTitle.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); // 拉申列宽 this.popTitle.setAdapter(this.titleAdapter) ; this.popTitle.setOnItemClickListener(titleCallback) ; this.popBody = new GridView(context) ; this.popBody.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); this.popBody.setNumColumns(5) ; this.popBody.setHorizontalSpacing(1) ; this.popBody.setVerticalSpacing(1) ; this.popBody.setPadding(10, 10, 10, 10) ; this.popBody.setGravity(Gravity.CENTER) ; this.popBody.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); // 拉申列宽 this.popBody.setOnItemClickListener(bodyCallback) ; this.layout.addView(this.popTitle) ; this.layout.addView(this.popBody) ; super.setContentView(this.layout) ; super.setWidth(LayoutParams.FILL_PARENT) ; super.setHeight(LayoutParams.WRAP_CONTENT) ; super.setBackgroundDrawable(new ColorDrawable(backgroundColor)) ; super.setFocusable(true) ; // 允许获得焦点 } public void setPopupMenuBodyAdapter(PopupMenuBodyAdapter adapter) { this.popBody.setAdapter(adapter) ; } public void setPopTitleSelected(int postion) { this.popTitle.setSelection(postion) ; this.titleAdapter.setFocus(postion) ; } public void setPopBodySelected(int position,int selectedColor) { // 设置选中后的颜色 int count = this.popBody.getChildCount() ; for (int x = 0; x < count; x++) { if (x != position) { ImageView img = (ImageView) this.popBody.getChildAt(x) ; img.setBackgroundColor(Color.TRANSPARENT) ; } } ImageView img = (ImageView) this.popBody.getChildAt(position) ; img.setBackgroundColor(selectedColor) ; } }
这里呢顺便加了点击效果,点击后背景变为灰色
3.后面就是主要的activity了。此时我们需要显示一个菜单,之后给第四个菜单加弹出式菜单,并在弹出菜单切换程序
package org.lxh.activity; import android.app.ActivityGroup; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.GridView; import android.widget.LinearLayout; import android.widget.Toast; public class PopMenuActivity extends ActivityGroup { private GridView gridviewToolbar; // 工具菜单栏 private MenuImageAdapter menu = null; // 图片适配器 private LinearLayout content = null; // 填充内容 private int menu_img[] = new int[] { R.drawable.menu_main, R.drawable.menu_news, R.drawable.menu_sms, R.drawable.menu_more, R.drawable.menu_exit }; // 填充的图片的资源 private int width = 0; // 求出平均的宽度 private int height = 0; // 求出平均的高度,定位显示 private Intent intent = null; private boolean isShow = false ; private int commonItemIds[] = new int[] { R.drawable.common_account, R.drawable.common_addmark, R.drawable.common_download, R.drawable.common_exit, R.drawable.common_fullscreen, R.drawable.common_history, R.drawable.common_night, R.drawable.common_refresh }; private int setItemIds[] = new int[] { R.drawable.set_button, R.drawable.set_mode, R.drawable.set_nophoto, R.drawable.set_rotation, R.drawable.set_scroll, R.drawable.set_skin, R.drawable.set_system, R.drawable.set_time }; private int totleItemids[] = new int[] { R.drawable.tool_back, R.drawable.tool_copy, R.drawable.tool_file, R.drawable.tool_help, R.drawable.tool_report, R.drawable.tool_report, R.drawable.tool_save, R.drawable.tool_share }; private int titleIds[] = new int[] { R.string.popmenu_common, R.string.popmenu_set, R.string.popmenu_tool }; private PopMenu popMenu = null ; private PopupMenuBodyAdapter commonAdapter = null ; private PopupMenuBodyAdapter setAdapter = null ; private PopupMenuBodyAdapter toolAdapter = null ; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.requestWindowFeature(Window.FEATURE_NO_TITLE); // 取消标题 super.setContentView(R.layout.main); this.gridviewToolbar = (GridView) super.findViewById(R.id.gridviewbar); this.content = (LinearLayout) super.findViewById(R.id.content); // 定义工具栏的一些信息显示 this.gridviewToolbar.setNumColumns(this.menu_img.length); // 求出可以保存的个数 this.gridviewToolbar.setSelector(new ColorDrawable(Color.TRANSPARENT)); this.gridviewToolbar.setGravity(Gravity.CENTER); this.gridviewToolbar.setVerticalSpacing(0); this.width = super.getWindowManager().getDefaultDisplay().getWidth() / this.menu_img.length; this.height = super.getWindowManager().getDefaultDisplay().getHeight() / 8; this.menu = new MenuImageAdapter(this, this.menu_img, this.width, this.height, R.drawable.menu_selected); this.gridviewToolbar.setAdapter(this.menu); this.switchActivity(0); // 第一个被选中 this.gridviewToolbar .setOnItemClickListener(new OnItemClickListenerImpl()); this.popMenu = new PopMenu(this, this.titleIds, 0x55123456, new PopupTitleOnItemClickListenerCallback(), new PopupBodyOnItemClickListenerCallback()); this.commonAdapter = new PopupMenuBodyAdapter(this, this.commonItemIds); this.setAdapter = new PopupMenuBodyAdapter(this, this.setItemIds); this.toolAdapter = new PopupMenuBodyAdapter(this, this.totleItemids); this.popMenu.setPopupMenuBodyAdapter(this.commonAdapter) ; this.popMenu.setPopTitleSelected(0) ; } private class OnItemClickListenerImpl implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { PopMenuActivity.this.switchActivity(position); } } private void switchActivity(int id) { // 切换选中的操作 this.menu.setFocus(id); // 设置选中图片的背景 this.content.removeAllViews(); // 删除所有的内容 switch (id) { case 0: this.intent = new Intent(PopMenuActivity.this, MyActivity.class); break; case 1: this.intent = new Intent(PopMenuActivity.this, MyActivity.class); break; case 2: this.intent = new Intent(PopMenuActivity.this, MyActivity.class); break; case 3: this.showPopupMenu() ; break; case 4: this.exitDialog() ; return; } this.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); Window subActivity = super.getLocalActivityManager().startActivity( "subActivity", this.intent); this.content.addView(subActivity.getDecorView(), LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); } private void exitDialog() { Dialog dialog = new AlertDialog.Builder(this).setIcon(R.drawable.pic_m) .setTitle("程序退出? ").setMessage("您确定要退出本程序吗?") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { PopMenuActivity.this.finish() ; } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { PopMenuActivity.this.switchActivity(0); } }).create(); dialog.show(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK) { this.exitDialog() ; } return false ; } private void showPopupMenu() { if (this.isShow) { // 已经显示了 this.popMenu.dismiss(); this.isShow = false; } else { this.popMenu.showAtLocation( PopMenuActivity.this.gridviewToolbar, Gravity.BOTTOM, 0, this.height); this.isShow = true; } } private class PopupBodyOnItemClickListenerCallback implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { PopMenuActivity.this.popMenu.setPopBodySelected(position, Color.GRAY) ; Toast.makeText(PopMenuActivity.this, "执行选项 - " + position, Toast.LENGTH_SHORT).show() ; } } private class PopupTitleOnItemClickListenerCallback implements OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { PopMenuActivity.this.popMenu.setPopTitleSelected(position) ; switch(position) { case 0: PopMenuActivity.this.popMenu .setPopupMenuBodyAdapter(PopMenuActivity.this.commonAdapter); break; case 1: PopMenuActivity.this.popMenu .setPopupMenuBodyAdapter(PopMenuActivity.this.setAdapter); break; case 2: PopMenuActivity.this.popMenu .setPopupMenuBodyAdapter(PopMenuActivity.this.toolAdapter); break; } }} }
到这里就大功告成了,下面是效果图
这些图片是我从教程里拿的,下面看看弹出菜单的效果。