处女男学Android(十二) Android菜单(Menu)详解与应用
本篇blog将记录一下Android中菜单的使用方法,虽然在新版本中推荐使用ActionBar去替代菜单,但我认为菜单依然是挺不错的一种UI交互组件,比ActionBar好点一些,对于手指不灵活的人比起来ActionBar右上角的那个方块小按钮,或许ta会更喜欢Menu呢,废话不多说,下面就具体介绍一下Android中关于Menu的使用方法。
二、创建第一个菜单
菜单有两种创建方式,分别是:
通过Java代码创建菜单对象。通过xml资源文件定义菜单。这里我想也不必多说,肯定应该选择第二种形式,在Activity中写代码去创建菜单必然导致程序代码过于臃肿,而且也不易查看和维护,而第二种方法既容易观察菜单的结构,也降低了耦合性,下面是官方给出的将“Using a menu resource”作为最佳实践的理由,简单看一下:

所以我这里就不浪费篇幅去记录“通过代码去创建菜单”了,主要记录一下如何通过xml文件定义菜单资源以及如何在Activity中引用并设置以及使用菜单。
菜单的资源文件通常应该放在/res/menu目录下,菜单资源的根元素通常是<menu.../>元素,并且它不需要指定任何属性,仅是菜单资源文件的根标签而已。我们在eclipse中新建一个Android工程,在/res/menu下去new一个Menu Resource,可以看到Menu的基本结构:

可以看到<menu.../>元素内可包含的子元素:
<group></group><item/> 下面分别说明一下这两个标签的用法和属性,首先是最常用的<item/>,<item/>元素用于定义一个菜单项,<item/>元素中又可以包含新的<menu/>,而位于<item/>中的<menu/>自然就代表了指定<item/>的子菜单了。下面先看一下<item/>可指定的常用属性:
通常我们必须指定的属性只有一个,就是android:title,其余的属性都是可选的,这里我们创建的第一个菜单简单一些,只给出id和title即可: <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="" > <item android:id="@+id/item_1" android:title="title1"/> <item android:id="@+id/item_2" android:title="title2"/> <item android:id="@+id/item_3" android:title="title3"/> <item android:id="@+id/item_4" android:title="title4"/> <item android:id="@+id/item_5" android:title="title5"/> <item android:id="@+id/item_6" android:title="title6"/> </menu>
写好了资源文件之后,在Activity中需要重写onCreateOptionsMenu去加载菜单,加载方式也很简单,通过MenuInflater的inflate方法即可加载菜单,完全类似于我们LayoutInflater的用法。关于菜单Item的点击事件需要在Activity中重写onOptionsItemSelected,根据回调参数来判断不同的Item从而进行不同的处理,其实这些在新建Activity之后都会自动生成的,下面贴上这两个方法的代码,很简单: @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.my_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); switch (id) { case R.id.item_1: Toast.makeText(this, "item_1 has been clicked!", Toast.LENGTH_SHORT) .show(); ; break; case R.id.item_2: Toast.makeText(this, "item_2 has been clicked!", Toast.LENGTH_SHORT) .show(); break; case R.id.item_3: Toast.makeText(this, "item_3 has been clicked!", Toast.LENGTH_SHORT) .show(); break; case R.id.item_4: Toast.makeText(this, "item_4 has been clicked!", Toast.LENGTH_SHORT) .show(); break; case R.id.item_5: Toast.makeText(this, "item_5 has been clicked!", Toast.LENGTH_SHORT) .show(); break; case R.id.item_6: Toast.makeText(this, "item_6 has been clicked!", Toast.LENGTH_SHORT) .show(); break; } return true; } 最后看一下运行效果:

三、选项菜单(Options menu)和上下文菜单(Context menu)
google将菜单按功能特性分为了三种,分别是:选项菜单(Options menu)、上下文菜单(Context menu)以及弹出式菜单(Popup menu),现在就分别介绍一下前两个:选项菜单和上下文菜单。
a.选项菜单(Option menu)
首先看一下官方文档中对option menu的简介: ————————————————————————————
———————————————————————————— 简单翻译一下,“选项菜单”是一个Activity中主要的菜单项的集合,在它上面应该放置有全局性影响的功能,例如:“搜索”、“写邮件”和“设置”。说到这里我们差不多应该就能对号入座了选项菜单了,安卓系统就自带了“选项菜单”,也就是下图的这个菜单:

点击手机的Menu键,弹出的就是我们所说的options menu了,再看一下菜单上提供的功能,分别是:墙纸(Wallpaper)、APP管理器(Manage apps)和系统设置(System settings),这也和文档中提到的“放置全局性影响的功能”相吻合。但是由于从Android3.0版本开始,并不要求手机上必须提供Menu键,而且有可能部分手机将不再提供Menu键(比如我的魅族MX4),在这种情况下,google推荐我们使用ActionBar去替代options menu这种需求。 示例代码已经写过了,刚才“创建的第一个菜单”就是一个简单标准的options menu了。
b.上下文菜单(Context menu)
首先看一下官方文档对Context menu的概述:

重点是第一句话,简单翻译一下,context menu是一个浮动的菜单,当用户在某个view上执行长按操作时弹出。好了概念上就这么简单,那么一般什么情况下会用到它呢?其实这个具体看需求,不过官方也做了相关说明:

没错,经常用在ListView、GridView的Items上面,可想而知也确实如此,经常会有这种需求,长按ListView弹出一个dialog或者一个menu,比如百度搜索中应该就是一个标准的context menu了,如下图:

可以看到,当我长按一条Item的时候,会弹出这样的一个菜单,它就是context menu,下面就具体介绍一下context menu的创建方式。
与options menu类似,但是在Activity中还是有些许的差别,依旧来看一下官方文档:

可以看到,第一步就是为我们的上下文菜单注册一个View,也就是说当我们长按哪个View的时候才需要弹出菜单,当我们希望ListView或GridView的items提供相同的菜单的话,那么直接传一个ListView或GridView即可完成。下面的代码就是模仿上面百度的那个菜单的,接下来一一贴出代码,首先是在Activity中为上下文菜单注册一个View: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView lv = (ListView) findViewById(R.id.lv_test); registerForContextMenu(lv); //为上下文菜单注册一个ListView } 下面看一下接下来的需要做的事情,文档中也已经说的很清楚了:

可以看到,这里重写的是onCreatContextMenu方法,而选项菜单重写的是onOptionsMenu,这也就是它们最主要的区别了。可以看到这个方法并不需要返回值,所以直接通过MenuInflater加载一下菜单的资源文件就OK了。
如果希望应用程序能够为菜单提供响应,同样的需要再重写一个相应方法,与options menu的类似但也有些许不同: 很简单,不做单独说明了,下面就看一下仿百度的上下文菜单的完整示例代码。
首先是activity的布局文件: <LinearLayout xmlns:android="" xmlns:tools="" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ScrollView android:id="@+id/sv_4lv" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@drawable/top_part" > </LinearLayout> <com.wl.view.MyListView android:id="@+id/lv_test" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:entries="@array/hero" > </com.wl.view.MyListView> </LinearLayout> </ScrollView> </LinearLayout>
menu的布局文件也很简单: <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="" > <item android:id="@+id/item1" android:title="新窗口打开"/> <item android:id="@+id/item2" android:title="后台打开"/> <item android:id="@+id/item3" android:title="选择文本"/> <item android:id="@+id/item4" android:title="复制链接地址"/> <item android:id="@+id/item5" android:title="下载链接"/> </menu>
最后是Activity代码: package com.wl.contextmenudemo; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import com.wl.model.BaiduItem; import com.wl.view.MyListView; public class MainActivity extends Activity { private BaiduItem baiduItem; private Context context; private LayoutInflater inflater; private ScrollView sv; private MyListView mlv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; inflater = LayoutInflater.from(context); sv = (ScrollView) findViewById(R.id.sv_4lv); sv.smoothScrollTo(0, 0); MyListView lv = (MyListView) findViewById(R.id.lv_test); baiduItem = new BaiduItem(); lv.setAdapter(new Myadapter()); registerForContextMenu(lv); // 为上下文菜单注册一个ListView } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub getMenuInflater().inflate(R.menu.my_menu_2, menu); } @Override public boolean onContextItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case R.id.item1: Toast.makeText(context, "新窗口打开!", Toast.LENGTH_SHORT).show(); break; case R.id.item2: Toast.makeText(context, "后台打开!", Toast.LENGTH_SHORT).show(); break; case R.id.item3: Toast.makeText(context, "选择文本!", Toast.LENGTH_SHORT).show(); break; case R.id.item4: Toast.makeText(context, "复制链接地址!", Toast.LENGTH_SHORT).show(); break; case R.id.item5: Toast.makeText(context, "下载链接!", Toast.LENGTH_SHORT).show(); break; } return true; } @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub return super.onCreateOptionsMenu(menu); } class Myadapter extends BaseAdapter { @Override public int getCount() { // TODO Auto-generated method stub return baiduItem.items.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return baiduItem.items.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub View v = inflater.inflate(R.layout.my_item_1, null); TextView title = (TextView) v.findViewById(R.id.tv_title); title.setText(baiduItem.items.get(position).getTitle()); TextView content = (TextView) v.findViewById(R.id.tv_content); content.setText(baiduItem.items.get(position).getContent()); TextView url = (TextView) v.findViewById(R.id.tv_url); url.setText(baiduItem.items.get(position).getUrlAndDate()); return v; } }; }
代码中通过自定义ListView来处理和ScrollView滑动冲突,关于数据则通过封装好的BaiduItem这个类直接提供,数据的初始化写在这个类的静态代码块中,由于只有5条数据,所以adapter也没有用ViewHolder优化,整体很简单,只是模仿那个百度的效果装个B,重点还是理解一下context menu的适用场合,最后看一下运行效果图:

四、弹出菜单(Popup menu)
看到pop这个词很明显的可以知道它肯定是类似于popupwindow,是一个弹出式的菜单,而且肯定也和popupwindow有很多相似的特性,依旧看一下官方文档对于popupmenu的概述:

简单翻译一下,popup menu是一个停靠在固定View上的模式菜单,如果该View下方有空间,那么弹出菜单将显示在该View的下方,否则会显示在该View的上方。不难理解popup menu是依附于一个View的,也就是说在指定View的上方or下方弹出,这种菜单一般会从顶部弹出或者从底部弹出,在很多APP中都很常见这种菜单,比如微信主界面右上角的加号图标,点击就会弹出一个popupmenu。
接下来介绍一下popup menu的创建方式,同popup window很类似,仅需三步: 1.通过其构造方法new PopupMenu(Context context,View anchor)创建下拉菜单,第二个参数即表示本菜单所依附的View。 2.调用MenuInflater的inflate()方法装载menu的资源文件。 3.调用popup menu的show()方法来显示菜单即可。 很简单吧,也没啥好说的,下面就模仿微信的那个弹出菜单做一个小例子,直接贴代码。
Activity布局文件: <LinearLayout xmlns:android="" xmlns:tools="" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/ll_top_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#000" android:orientation="horizontal" android:padding="8dp" > <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:text="我不是微信" android:textColor="#ccc" android:textSize="16sp" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" > <ImageButton android:id="@+id/ibtn_search" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/ic_search" /> <ImageButton android:id="@+id/ibtn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:background="@drawable/ic_add" /> </LinearLayout> </LinearLayout> </LinearLayout>
Activity代码: package com.wl.menusdemo; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.KeyEvent; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.PopupMenu; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private ImageButton ibtnAdd; private ImageButton ibtnSearch; private PopupMenu popMenu; private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; ibtnAdd = (ImageButton) findViewById(R.id.ibtn_add); ibtnAdd.setOnClickListener(this); ibtnSearch = (ImageButton) findViewById(R.id.ibtn_search); } @Override public void onClick(View v) { // TODO Auto-generated method stub if (v == ibtnAdd) { popMenu = new PopupMenu(context, ibtnAdd); getMenuInflater().inflate(R.menu.pop_menu, popMenu.getMenu()); popMenu.show(); popMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case R.id.item_chart: Toast.makeText(context, "发起群聊!", Toast.LENGTH_SHORT) .show(); break; case R.id.item_add_friend: Toast.makeText(context, "添加朋友!", Toast.LENGTH_SHORT) .show(); break; case R.id.item_sao: Toast.makeText(context, "扫一扫!", Toast.LENGTH_SHORT) .show(); break; case R.id.item_idea: Toast.makeText(context, "意见反馈!", Toast.LENGTH_SHORT) .show(); break; } return false; } }); } } }
是不是超简单的说,下面看一下运行效果:

五、模仿手机QQ的底部弹出菜单
介绍完了所有类型的菜单之后,最后再做一个练习,可能我们也发现了菜单的样式比较局限,一般很难做一些定制的样式,所以说还有一种很不错的解决方案就是不使用Menu的API,通过监听菜单键的KEY CODE来弹出一个popup window,这样的话我们做一些个性化的样式、动画等等就没有那么多限制了,在这里我就通过这种方式来模仿一下手机QQ的功能菜单,下面是效果图:

可以看到,当我们进入QQ之后点击手机的Menu键时,会从底部弹出图中圈出的菜单,下面就结合popup window来实现这个效果,首先将需要做的事情拆分为三个步骤: step 1 在Activity中重写onKeyDown()方法,并通过KEY CODE来监听菜单键按下的事件,并在该事件中弹出一个popup window。 step 2 构造popup window对象,并编写布局文件代码,设置样式以及动画。 step 3 点击菜单键时show这个popup window,点击菜单键或者popup window之外的区域时dismiss这个popup window。
好了,接下来就按步骤去实现它,首先是第一步,重写onKeyDown()方法用来响应菜单键的单击,直接贴代码: package com.wl.menusdemo; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.KeyEvent; import android.widget.Toast; public class SecondActivity extends Activity { private Context context; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.second); context = this; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if (keyCode == KeyEvent.KEYCODE_MENU) { Toast.makeText(context, "准备好,要弹出菜单了!", Toast.LENGTH_LONG).show(); } return true; } }
很简单,看一下效果图:

第二步和第三步一起说了,编写popup window的布局文件代码,我能想到的最简单的办法就是通过一组Button来实现,然后需要为popupwindow添加一个弹出动画,直接看代码,下面分别是popupwindow的布局文件和Activity中的全部代码。
popup_menu.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn_ver_update" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/my_btn_selector_2" android:gravity="center" android:padding="5dp" android:text="版本更新" android:textColor="#62A6E7" android:textSize="20sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="2dp" android:background="#ccc" > </LinearLayout> <Button android:id="@+id/btn_help" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/my_btn_selector_3" android:gravity="center" android:padding="5dp" android:text="帮助与反馈" android:textColor="#62A6E7" android:textSize="20sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="2dp" android:background="#ccc" > </LinearLayout> <Button android:id="@+id/btn_exit_qq" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/my_btn_selector_4" android:gravity="center" android:padding="5dp" android:text="退出QQ" android:textColor="#62A6E7" android:textSize="20sp" /> <Button android:id="@+id/btn_undo" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:background="@drawable/my_btn_selector" android:gravity="center" android:padding="5dp" android:text="取消" android:textColor="#62A6E7" android:textSize="20sp" /> </LinearLayout>
Activity: package com.wl.menusdemo; import android.app.ActionBar.LayoutParams; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.PopupWindow; import android.widget.PopupWindow.OnDismissListener; import android.widget.Toast; public class SecondActivity extends Activity implements OnClickListener { private Context context; private PopupWindow popupWindow; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.second); context = this; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if (keyCode == KeyEvent.KEYCODE_MENU) { showMenu(); return true; } return super.onKeyDown(keyCode, event); } private void showMenu() { LayoutInflater inflater = getLayoutInflater(); View menuView = inflater.inflate(R.layout.pop_menu, null); Button button1 = (Button) menuView.findViewById(R.id.btn_ver_update); Button button2 = (Button) menuView.findViewById(R.id.btn_help); Button button3 = (Button) menuView.findViewById(R.id.btn_exit_qq); Button button4 = (Button) menuView.findViewById(R.id.btn_undo); button1.setOnClickListener(this); button2.setOnClickListener(this); button3.setOnClickListener(this); button4.setOnClickListener(this); // 设置PopupWindow宽高 DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); double screenWidth = metrics.widthPixels * 0.95; popupWindow = new PopupWindow(menuView, (int) screenWidth, LayoutParams.WRAP_CONTENT); // 想要让PopupWindow中的控件能够使用,就必须设置PopupWindow为focusable popupWindow.setFocusable(true); // 想做到在你点击PopupWindow以外的区域时候让PopupWindow消失就做如下两步操作 // 1:设置setOutsideTouchable为ture,这个很容易理解吧,跟AlertDialog一样的 popupWindow.setOutsideTouchable(true); popupWindow.setBackgroundDrawable(getResources().getDrawable( android.R.color.transparent)); popupWindow.setAnimationStyle(R.style.AnimationPreview); popupWindow.setOnDismissListener(onDismissListener); popupWindow.showAtLocation(getWindow().getDecorView(), android.view.Gravity.BOTTOM, 0, 0); // 设置父窗口透明度 WindowManager.LayoutParams wlp = getWindow().getAttributes(); wlp.alpha = 0.5f; getWindow().setAttributes(wlp); } private OnDismissListener onDismissListener = new OnDismissListener() { @Override public void onDismiss() { WindowManager.LayoutParams wlp = getWindow().getAttributes(); wlp.alpha = 1.0f; getWindow().setAttributes(wlp); } }; @Override public void onClick(View v) { // TODO Auto-generated method stub if (popupWindow != null && popupWindow.isShowing()) popupWindow.dismiss(); switch (v.getId()) { case R.id.btn_ver_update: Toast.makeText(context, "版本更新!", Toast.LENGTH_SHORT).show(); break; case R.id.btn_help: Toast.makeText(context, "帮助与反馈!", Toast.LENGTH_SHORT).show(); break; case R.id.btn_exit_qq: Toast.makeText(context, "退出QQ!", Toast.LENGTH_SHORT).show(); break; case R.id.btn_undo: Toast.makeText(context, "取消!", Toast.LENGTH_SHORT).show(); break; } } }
BINGO~结束了,最后看一下效果图,相似度还不错吧:

关于样式的话,每个按钮都是通过selector+shape嵌套实现的,popup window弹出的时候还设置了一个非常简单的补间动画,背景色直接用透明色值就OK了,下面把两个动画的资源文件和一个按钮的样式资源文件贴出来(其余的类似)。
anim_bottom_in.xml: <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="" > <translate android:duration="350" android:fromYDelta="100%" android:toYDelta="0.0" /> </set>
anim_bottom_out.xml: <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="" > <translate android:duration="350" android:fromYDelta="0.0" android:toYDelta="100%p" /> </set>
my_btn_selector.xml: <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android=""> <item android:state_pressed="false"><shape android:shape="rectangle"> <gradient android:endColor="#efffffff" android:startColor="#efffffff"></gradient> <!-- 设置内填充 --> <padding android:bottom="7dp" android:left="7dp" android:right="7dp" android:top="7dp" /> <!-- 设置圆角矩形 --> <corners android:radius="8dp" /> </shape></item> <item android:state_pressed="true"><shape android:shape="rectangle"> <gradient android:endColor="#ecdcdcdc" android:startColor="#ecdcdcdc"></gradient> <!-- 设置内填充 --> <padding android:bottom="7dp" android:left="7dp" android:right="7dp" android:top="7dp" /> <!-- 设置圆角矩形 --> <corners android:radius="8dp" /> </shape></item> </selector>
Over,如果新手朋友仔细看了本篇blog的话相信一定会有不少的收获的~ 我个人有以下收获: 1.学习了Android中的3种Menu的概念和简单的使用方法(Options menu、Context menu、Popup menu)。 2.学习了Android简单动画的编写和引用。 3.学习了selector和shape的嵌套。 4.学习并复习了以下的几个小知识点:改变popupwindow父窗体透明度、shape资源中关于4个corners的任意控制、根据DisplayMetrix来设置popupwindow的宽度、根据KEY CODE监听菜单键的动作、关于ScrollView嵌套ListView滚动冲突的问题等等。
六、总结
也许这一篇blog的标题不够吸引人,内容也没有别的大神写的那么深刻高端,但我认为这算是我写过的最认真的博客之一了,用了很长时间。从翻译文档、修改图片到录制gif,对每一个知识点和概念咬文嚼字,斟酌再三,不放过每一个细节,总的来说我的收获还是蛮大的,至少在我的下一个APP中我一定会用到上面写的那个仿QQ的“菜单”。在今后的blog中我还会尽我最大的努力去做到“认真”、“细心”和“完美”,因为我是处女座。好了,废话不多说,继续滚去加班写服务端了,但同时Android的学习我也绝不会拉下的,以csdn为证!加油,Raito!
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://www.juheyunku.com/jiaob/android/9911.shtml
相关文章
热门TAG
命令 权重 外链 企业网站 白帽 php 织梦教程 dedecms修改内容 javascript 织梦 功能 标签 调用 详解 服务器 网站流量 实例解析 Dedecms 织梦cms HTML tags标签 python jquery教程 jquery windows SEO优化 蜘蛛 搜索引擎 网站收录 JSP最新文章
-
Android开发_深入学习ViewP
时间:2020-12-27
-
Android Binder进程间通信 J
时间:2020-12-27
-
50个Android开发技巧11 为文
时间:2020-12-27
-
处女男学Android(十二)
时间:2020-12-27
-
手把手教你用ViewPager自定
时间:2020-12-27
-
字母条索引定位
时间:2020-12-27
-
OGEngine教程:声音加载
时间:2020-12-27
-
Notification详解
时间:2020-12-27
热门文章
-
字母条索引定位
时间:2020-12-27
-
Notification详解
时间:2020-12-27
-
OGEngine教程:声音加载
时间:2020-12-27
-
处女男学Android(十二) Android菜单(Men
时间:2020-12-27
-
Android Binder进程间通信 Java接口源代码
时间:2020-12-27
-
50个Android开发技巧11 为文字添加特效
时间:2020-12-27
-
Android开发_深入学习ViewPager控件
时间:2020-12-27
-
手把手教你用ViewPager自定义实现Banner轮播
时间:2020-12-27
