Android实现下拉导航选择菜单效果
本文介绍在Android中如何实现下拉导航选择菜单效果。
关于下拉导航选择菜单效果在新闻客户端中用的比较多,当然也可以用在其他的项目中,这样可以很方便的选择更多的菜单。我们可以让我们的应用顶部有左右滑动或进行切换的导航菜单,也可以为了增强用户体验在应用中添加这样的下拉导航选择菜单效果。
关于它的实现原理,其实也是挺简单的,就是使用PopupWindow来进行展现,在显示时控制其高度并配置以相应的动画效果。在PopupWindow中我使用GridView来控制里面的菜单项,每个菜单项对应相应的图片和文字。当然了,也有其他的实现方式。为了大家能够清楚的理解,让我们先看下效果图,如下所示:


以上就是我实现的示例图,大家已经看到了,就是点击应用顶部中间的文字时展现出来,在我们点击其中一项菜单时隐藏并加载相应菜单的内容,同时该菜单处于选中状态。好了,下面就让我们开始我们的实现过程,还是先看下程序结构图吧:

在程序结构图中,PulldownMenuView是对PopupWindow进行的封装类,PulldownMenuItem是菜单项类,这是两个重要的类。在我们点击应用顶部中间的文字时,要进行展现,展现的同时,要实现对菜单的初始化工作,首先是初始化数据,其主要代码如下:

/**
* 初始化数据,将数据加载到对应的View中
*/
private void initData(){
PulldownMenuItem item = new PulldownMenuItem(context);
item.setMenuAlign(menuAlign);
item.setMenuTextColor(menuTextColor);
item.setMenuTextSize(menuTextSize);
int txtLength = menuTexts.length;
int imgLength = menuImageRes.length; if (txtLength != 0 && imgLength != 0){
for (int i = 0; i < imgLength; i++){
PulldownMenuItem menuItem = new PulldownMenuItem(context, item); if(!currentItem.equals(menuTexts[i])){
menuItem.setImageRes(menuImageRes[i]);
menuItem.setMenuText(menuTexts[i]);
}else{
menuItem.setMenuText(menuTexts[i]);
menuItem.setMenuTextColor(Color.parseColor("#4FA7F9"));
menuItem.setImageRes(ConstantCategoryMenu.newsImageResPress[i]);
} menuMenuItems.add(menuItem);
}
} else{
if (txtLength != 0){
for (int i = 0; i < txtLength; i++){
PulldownMenuItem menuItem = new PulldownMenuItem(context, item); if(!currentItem.equals(menuTexts[i])){
menuItem.setMenuText(menuTexts[i]);
}else{
menuItem.setMenuText(menuTexts[i]);
menuItem.setMenuTextColor(Color.parseColor("#4FA7F9"));
} menuMenuItems.add(menuItem);
}
}else if (imgLength != 0){
for (int i = 0; i < imgLength; i++){
PulldownMenuItem menuItem = new PulldownMenuItem(context, item);
menuItem.setImageRes(menuImageRes[i]);
menuMenuItems.add(menuItem);
}
}
}
}

currentItem代表当前的选择项,在初始化数据过程中,需要检测哪项菜单被选中了,如果某项菜单被选中,则在展开时需要将该项菜单图片和文字颜色设置成相应状态,表示该项菜单被选中。在初始化过程中分为三种情况:第一种是菜单项既有图片也有文字;第二种是菜单项只有文字;第三种是菜单项只有图片;所以在上面代码中需要进行相应判断。上面是初始化菜单中的数据,下面是初始化菜单中的内容:

/**
* 初始化菜单内容
* @param context
* @param columns 菜单的列数
* @return
*/
private GridView getMenuGirdView(Context context, int columns){
if (menuMenuItems.isEmpty()){
// 初始化菜单数据
initData();
} if (null != menuGridView){
return menuGridView;
} GridView gridView = new GridView(context);
gridView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
// 设置数据适配器
gridView.setAdapter(new PulldownMenuAdapter(menuMenuItems));
gridView.setVerticalSpacing(1);
gridView.setNumColumns(columns);
gridView.setGravity(Gravity.CENTER);
gridView.setVerticalScrollBarEnabled(false); if (menuBackground != 0){
gridView.setBackgroundResource(menuBackground);
} if (menuSelector != -1){
gridView.setSelector(menuSelector);
} gridView.setHorizontalScrollBarEnabled(false);
setMenuListener(gridView); return gridView;
}

初始化菜单之后,就需要我们菜单中相应的数据,设置数据比较容易,只需要三个数组即可:第一个数组代表菜单项文字内容;第二个数组代表菜单项图片资源,第三个数组代表菜单项被选中的图片资源。如下代码:

/**
* 新闻菜单项图片资源
*/
public final static int[] newsImageRes = {
R.drawable.ic_menu_toutiao,R.drawable.ic_menu_gn,
R.drawable.ic_menu_gj,R.drawable.ic_menu_sh,
R.drawable.ic_menu_sport,R.drawable.ic_menu_nba,
R.drawable.ic_menu_blog,R.drawable.ic_menu_book,
R.drawable.ic_menu_yule,R.drawable.ic_menu_mil,
R.drawable.ic_menu_cj,R.drawable.ic_menu_tech,
R.drawable.ic_menu_mobile,R.drawable.ic_menu_women,
R.drawable.ic_menu_car,R.drawable.ic_menu_house
}; /**
* 新闻菜单项选中图片资源
*/
public final static int[] newsImageResPress = {
R.drawable.ic_menu_toutiao_press,R.drawable.ic_menu_gn_press,
R.drawable.ic_menu_gj_press,R.drawable.ic_menu_sh_press,
R.drawable.ic_menu_sport_press,R.drawable.ic_menu_nba_press,
R.drawable.ic_menu_blog_press,R.drawable.ic_menu_book_press,
R.drawable.ic_menu_yule_press,R.drawable.ic_menu_mil_press,
R.drawable.ic_menu_cj_press,R.drawable.ic_menu_tech_press,
R.drawable.ic_menu_mobile_press,R.drawable.ic_menu_women_press,
R.drawable.ic_menu_car_press,R.drawable.ic_menu_house_press
}; /**
* 新闻菜单项文字
*/
public final static String[] newsMenuTexts = {
"今日头条","国内","国际","社会","体育","NBA","博客","读书",
"娱乐","军事","财经","科技","手机","女性","汽车","房产"
};

菜单项使用GridView实现,我们还需要设置每个菜单项的监听事件,在选中一项菜单后或是点击返回键或点击菜单键时实现隐藏,代码如下:

/**
* 设置菜单项监听事件
* @param gridView
*/
private void setMenuListener(GridView gridView){
if (null == gridView.getOnItemClickListener()){
gridView.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(
AdapterView<?> parent,
View view,
int position,
long id){
if (null != menuItemListener){
menuItemListener.onMenuItemClick(parent, view, position);
} hide();
}
});
} // 按返回键或菜单键隐藏菜单
gridView.setOnKeyListener(new OnKeyListener(){
@Override
public boolean onKey(View v, int keyCode, KeyEvent event){
if (event.getAction() == KeyEvent.ACTION_DOWN){
switch (keyCode){
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
hide();
break;
}
} return false;
}
});
}

在PulldownMenuView类中的show()和hide()方法中,主要是实现菜单的显示与隐藏。在show()方法中,要计算每行存放的菜单数、设置相应的高度、菜单整体的背景、动画效果、菜单显示的位置等效果。具体不再详述。
我们在显示下拉导航选择菜单前还需要配置菜单相应的参数,比如显示位置、背景图片、高度等。这就是在MenuUtility类中要实现的,代码如下:

package com.navigation.utility; import com.navigation.acitvity.R;
import com.navigation.control.PulldownMenuView; import android.content.Context;
import android.view.View; /**
* PulldownMenuView基本操作类
* @Description: PulldownMenuView基本操作类 * @File: PulldownMenuUtility.java * @Package com.navigation.utility * @Author Hanyonglu * @Date 2012-7-30 上午11:41:04 * @Version V1.0
*/
public class MenuUtility {
private Context context = null;
// PulldownMenuView对象
private PulldownMenuView menu = null;
// 图片资源
private int[] imageRes = null;
// 文字内容
private String[] texts = null;
// 菜单高度
private int height = 0;
private View anchorView = null; /**
* 默认的构造器
*/
public MenuUtility() {
// TODO Auto-generated constructor stub
} /**
* 带Context的构造器
* @param context
*/
public MenuUtility(Context context) {
// TODO Auto-generated constructor stub
this(context,null,null,0,null);
} /**
* 带多参的构造器
* @param context
* @param imageRes
* @param texts
*/
public MenuUtility(Context context,int[] imageRes,String[] texts,int height,View anchorView){
this.context = context;
this.imageRes = imageRes;
this.texts = texts;
this.height = height;
this.anchorView = anchorView;
} /**
* 设置图片资源
* @param imageRes
*/
public void setImageRes(int[] imageRes){
this.imageRes = imageRes;
} /**
* 设置文字内容
* @param texts
*/
public void setTexts(String[] texts){
this.texts = texts;
} /**
* 设置高度
* @param height
*/
public void setHeight(int height){
this.height = height;
} /**
* 设置显示的位置
* @param anchor
*/
public void setAnchorView(View anchor){
anchorView = anchor;
} /**
* 获取PulldownMenuView对象
* 以下拉的形式展现出来菜单
* @return
*/
public PulldownMenuView getPulldownMenuView(String currentItem){
PulldownMenuView menu = new PulldownMenuView(context);
menu.setImageRes(imageRes);
menu.setMenuText(texts);
menu.setHeight(height);
menu.setAnchorView(anchorView);
menu.setCurrentItem(currentItem);
menu.setBackground(R.drawable.navigation_bg); return menu;
} /**
* 获取PulldownMenuView对象
* 以向上弹出的方式展现出来菜单
* @return
*/
public PulldownMenuView getPopupMenuView(){
PulldownMenuView menu = new PulldownMenuView(context);
menu.setImageRes(imageRes);
menu.setMenuText(texts);
// menu.setLocation(Gravity.BOTTOM | Gravity.CENTER);
menu.setAnimStyle(R.style.pulldown_in_out);
menu.setBackground(R.drawable.navigation_bg); return menu;
}
}

既然是使用PopupWindow实现我们的效果,当然了,它也可以以向上弹出的方式展现。在我这个示例中,需要它展现的位置是在顶部横条下面展现,所以设置:
menu.setAnchorView(anchorView);
另外,在MainActivity中需要设置它的显示高度,在这里高度需要在顶部横条和底部RadioGroup之间,这就需要我们获取手机屏幕的高度减去顶部横条的高度,再减去底部RadioGroup的高度,最后减去手机菜单栏的高度。在点击某项菜单后,还需要将顶部中间文字和右边三角图片进行相应的变换。代码如下所示:

package com.navigation.acitvity; import com.navigation.constant.ConstantCategoryMenu;
import com.navigation.control.PulldownMenuView;
import com.navigation.control.PulldownMenuView.OnMenuItemClickListener;
import com.navigation.utility.DeviceUtility;
import com.navigation.utility.MenuUtility; import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView; /**
* Android实现下拉导航选择菜单效果
* @Description: Android实现下拉导航选择菜单效果 * @File: MainActivity.java * @Package com.navigation.acitvity * @Author Hanyonglu * @Date 2012-7-28 下午06:08:27 * @Version V1.0
*/
public class MainActivity extends Activity {
// 今日头条LinearLayout
private LinearLayout linearLayoutTopic = null;
// 界面布局
private RelativeLayout layoutHeader = null;
private LinearLayout layoutBottom = null;
private FrameLayout layoutBody = null;
// PulldownMenuView基本操作类
private MenuUtility menuUtility = null;
// PulldownMenuView对象
private PulldownMenuView pullDownMenu = null;
private TextView tvTopic = null;
private ImageView ivTopic = null; private int height = 0; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // 初始化
initViews();
} /**
* 初始化
*/
protected void initViews(){
ivTopic = (ImageView) findViewById(R.id.imageViewTopic);
tvTopic = (TextView) findViewById(R.id.textViewTopic); linearLayoutTopic = (LinearLayout)findViewById(R.id.linearLayoutTopic);
linearLayoutTopic.setOnClickListener(TopicOnClickListener);
layoutHeader = (RelativeLayout) findViewById(R.id.layout_top_header);
layoutBottom = (LinearLayout) findViewById(R.id.layout_bottom);
layoutBody = (FrameLayout) findViewById(R.id.layout_body); height = DeviceUtility.getScreenSize(this)[1] -
layoutHeader.getLayoutParams().height -
layoutBottom.getLayoutParams().height -
DeviceUtility.getStatusBarHeight(this); menuUtility = new MenuUtility(
MainActivity.this,
ConstantCategoryMenu.newsImageRes,
ConstantCategoryMenu.newsMenuTexts,
height,layoutHeader);
} /**
* 显示PulldownMenuView
*/
protected void showPulldownMenu(){
pullDownMenu = menuUtility.getPulldownMenuView((String)tvTopic.getText());
ivTopic.setImageResource(R.drawable.ic_menu_trangle_up);
} /**
* 隐藏PulldownMenuView
*/
protected void hidePulldownMenu(){
pullDownMenu.releasePopupMenuView();
ivTopic.setImageResource(R.drawable.ic_menu_trangle_down);
} // 顶部今日头条事件监听器
private OnClickListener TopicOnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
// 开始显示下拉菜单
showPulldownMenu(); // TODO Auto-generated method stub
pullDownMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public void onMenuItemClick(AdapterView<?> parent, View view, int position) {
// TODO Auto-generated method stub
tvTopic.setText(ConstantCategoryMenu.newsMenuTexts[position]);
layoutBody.setBackgroundResource(ConstantCategoryMenu.newsBodyRes[position]);
} @Override
public void hideMenu() {
// TODO Auto-generated method stub
hidePulldownMenu();
}
}); pullDownMenu.show();
}
};
}

我们在获取MainActivity中顶部横条和底部RadioGroup的高度时需要注意在布局文件中设置其相应的layout_height,否则,我们是获取不到其高度的。程序中间的主体部分是截取了几张图片,这个大家可以根据自己的需要设置成自己的数据格式。这点知道就可以了。
以上便是Android中实现下拉导航选择菜单效果的实现过程,是在PopupWindow中嵌入GridView实现,当然也可以在PopupWindow中嵌入ListView等各种控件实现相应的效果,也可以对PopupWindow实现各种和样的变幻效果,具体过程这里就不再详述了,有兴趣的朋友我们可以一起探讨。
最后,希望转载的朋友能够尊重作者的劳动成果,加上转载地址:http://www.cnblogs.com/hanyonglu/archive/2012/07/31/2617488.html 谢谢。
Android实现下拉导航选择菜单效果的更多相关文章
- 通过html和css做出下拉导航栏的效果
通过观察了百度的首页,对于更多产品一栏,觉得可以不涉及JS便可写出下拉导航栏的效果 1.先设计出大体的框架 <div class="nav"> <ul> & ...
- 仿网易新闻app下拉标签选择菜单
仿网易新闻app下拉标签选择菜单 仿网易新闻app下拉标签选择菜单,长按拖动排序,点击增删标签控件 ##示例 ##EasyTagDragView的使用 在layout布局里添加:
- 在 jQuery 中使用滑入滑出动画效果,实现二级下拉导航菜单的显示与隐藏效果
查看本章节 查看作业目录 需求说明: 在 jQuery 中使用滑入滑出动画效果,实现二级下拉导航菜单的显示与隐藏效果 用户将光标移动到"最新动态页"或"帮助查询" ...
- 纯CSS实现二级下拉导航菜单
这是一款纯CSS菜单,二级下拉导航效果,是最简洁的CSS导航菜单,兼容性也很棒,IE7/8.火狐等都支持,而且它还是学习CSS菜单编写的典型教程,让你学会很多CSS技巧. 运行效果截图如下: < ...
- HTML DOM部分---做竖向横向的下拉导航 下拉菜单 图片轮播(圆点、箭头) 选项卡 进度条;
1,竖向下拉导航 鼠标单击打开 再打击关闭 <style> *{ margin:0px auto; padding:0px;} div{ width:100px; height:50px; ...
- MDNavBarView下拉导航菜单(仿美团导航下拉菜单)
说到下拉导航菜单这个东西用得还真不少,细心算一下做开发以来这样的菜单已经写了第三次了,但基本都是不能复用.感觉特累人.不经意看到同事写一个类似的下拉菜单,但他引用了开源库仿大众菜单的库,大致看了一下, ...
- 一款jQuery立体感动态下拉导航菜单特效
一款jQuery立体感动态下拉导航菜单特效,鼠标经过,在菜单栏上方下拉出一个背景图片,效果十分不错的一款jquery特效. 对IE6都是兼容的,希望大家好好研究研究. 适用浏览器:IE6.IE7.IE ...
- 20款jquery下拉导航菜单特效代码分享
20款jquery下拉导航菜单特效代码分享 jquery仿京东商城左侧分类导航下拉菜单代码 jQuery企业网站下拉导航菜单代码 jQuery css3黑色的多级导航菜单下拉列表代码 jquery响应 ...
- jQuery实现淡入淡出二级下拉导航菜单的方法
本文实例讲述了jQuery实现淡入淡出二级下拉导航菜单的方法.分享给大家供大家参考.具体如下: 这是一款基于jQuery实现的导航菜单,淡入淡出二级的菜单导航,很经常见到的效果,这里使用的是jquer ...
随机推荐
- 2016集训测试赛(二十四)Problem C: 棋盘控制
Solution 场上的想法(显然是错的)是这样的: 我们假设棋子是一个一个地放置的, 考虑在放置棋子的过程中可能出现哪些状态. 我们令有序整数对\((i, j)\)表示总共控制了\(i\)行\(j\ ...
- dede实战系统:更换成kindEditor编辑器
最近由于项目需要,在搞dedeCMS,发现dede自带的ckEditor在word粘贴这方面做得不是很好,从word上面直接ctrl+V的内容跟wrod上面的表现样式相差很大,客户很不爽(因为是编辑的 ...
- 队列容易queue
/*先进先出*/#include<iostream>#include<queue> //使用队列必须包含头文件using namespace std;int main(){ q ...
- python __new__和__init__的区别
http://www.cnblogs.com/tuzkee/p/3540293.html 继承自object的新式类才有__new__ __new__至少要有一个参数cls,代表要实例化的类,此参数在 ...
- df、du、fdisk:Linux磁盘管理
磁盘是Linux系统中一项非常重要的资源,如何对其进行有效的管理直接关系到整个系统的性能问题.对Linux磁盘管理稍微有一些学习和经验的朋 友们应该都知道df.du和fdisk这三个常用命令:df用于 ...
- 2016.7.12 针对不同的数据库类型generatorConfig文件中的数据库配置
百度了很多资料,没有专门说这个的.大家都是配置自己的数据库,大部分是mysql.因为我使用的是postgresql,还是找了一会才找到配置指导. 毕竟第一次配置,还是要看着别人的指导比较安心.配置完后 ...
- axios 异步加载 导致 {{}} 中变量为 undefined 报错 的 解决方案
情景:axios 异步加载数据,当返回数据为一个 数组 时,双花括号中 这样写 会报错 {{informationDetail[0].img}} 解决方案一:通过 v-if 进行判断 解决方案二:单独 ...
- 【Excle数据透视】如何升序排列字段列表中的字段
数据透视表创建完毕,那么如何将字段列表中的字段修改为升序排列呢? 解决方案 更改"字段列表"为按"升序"排列 步骤 单击数据透视表任意单元格→右键单击→数据透视 ...
- window.opener
window.opener 实际上就是通过window.open打开的窗体的父窗体. 比如在父窗体parentForm里面 通过 window.open("subForm.html" ...
- hdu4857 & BestCoder Round #1 逃生(拓扑逆排序+优先队列)
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=4857 ----------------------------------------------- ...