转自:http://www.eoeandroid.com/thread-169095-1-1.html 本文给大家介绍在Android中如何实现顶部导航菜单左右滑动效果。 今天给大家介绍在Android中实现顶部导航菜单左右滑动效果的二种解决方案。 第一种解决方案: 在以前的一篇博文中我使用android-support-v4.jar实现了左右滑动指引效果,有兴趣的朋友可以查看:http://www.cnblogs.com/hanyonglu/archive/2012/04/07/2435589.html 那么今天第一个示例我仍然使android-support-v4.jar来实现菜单左右滑动效果,关于这个包的信息,不再详述,大家可以查看官方文档。 实现原理是使用android-support-v4.jar包中ViewPager控件,在ViewPager控件中设置流布局,再在流布局中设置几项TextView,给每一个TextView设置相关参数,事件等。关于ViewPager控件可以设置全屏幕滑动效果,当然也可以实现局部滑动效果,下面介绍导航菜单。 关于导航菜单,相信大家对它并不陌生,比如在新闻客户端中就经常使用左右滑动菜单来显示不同类别的新闻。网上也有关于这方面的一些示例,但是许多都是使用Tabhost来做的,实现了图片平滑动画效果,但没有实现菜单左右滑动的效果。我们先来看下本示例的效果图: 以上是效果图,以下让我们来看来如何才能实现,先建立程序结构,结构图如下: 在程序中,我们需要导入android-support-v4.jar包。在SlideMenuUtil类中设置导航菜单项标签,如下: - package com.slide.util;
-
- /**
- * 滑动菜单选项类
- * @Description: 滑动菜单选项类
- * @FileName: SlideMenuUtil.java
- * @Package com.slide.util
- * @Author Hanyonglu
- * @Date 2012-4-20 下午04:51:24
- * @Version V1.0
- */
- public class SlideMenuUtil {
- // 菜单选项
- public static String ITEM_MOBILE = "移动";
- public static String ITEM_WEB = "Web";
- public static String ITEM_CLOUD = "云计算";
- public static String ITEM_DATABASE = "数据库";
- public static String ITEM_EMBED = "嵌入式";
- public static String ITEM_SERVER = "服务器";
- public static String ITEM_DOTNET = ".NET";
- public static String ITEM_JAVA = "JAVA";
- public static String ITEM_SAFE = "安全";
- public static String ITEM_DOMAIN = "业界";
- public static String ITEM_RESEASRCH = "研发";
- public static String ITEM_MANAGE = "管理";
- // 菜单项计数器
- public int count = 0;
- }
复制代码 为了实现导航菜单上的左右图片,需要在main.xml布局文件中设置相对布局。 我这个示例中,是把左右导航的图片显示在文字上方,在点击上图中右三角图片时会显示下一个页面导航,具体大家可以看下面代码。 main.xml中设置左右图片的相对布局代码: - <RelativeLayout
- android:id="@+id/linearLayout01"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
- <android.support.v4.view.ViewPager
- android:id="@+id/slideMenu"
- android:layout_width="fill_parent"
- android:layout_height="35dp"
- android:background="@drawable/top_bg" />
- <RelativeLayout
- android:id="@+id/linearLayout01"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
-
- <ImageView
- android:id="@+id/ivPreviousButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:paddingTop="10dp"
- android:paddingLeft="5dp"
- android:visibility="invisible"
- android:src="@drawable/previous_button" />
-
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/linearLayout01"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <ImageView
- android:id="@+id/ivNextButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:paddingTop="10dp"
- android:paddingRight="5dp"
- android:visibility="invisible"
- android:src="@drawable/next_button" />
- <!--
- <ImageView
- android:id="@+id/ivMenuBackgroundCopy"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:paddingTop="2dp"
- android:src="@drawable/menu_bg" />
- -->
-
- </RelativeLayout>
- <ImageView
- android:id="@+id/ivMenuBackground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_marginLeft="2dp"
- android:layout_toRightOf="@+id/ivPreviousButton"
- android:paddingTop="2dp"
- android:visibility="gone"
- android:src="@drawable/menu_bg" />
- </RelativeLayout>
复制代码 代码中id为ivMenuBackground的图片是为了在点击一项菜单后设置其背景图片,菜单中默认选中第一项“移动”。 在程序结构图中的item_xxx.xml是为了在选一项菜单后显示下面的布局内容。这只是个示例,有兴趣的朋友可以改造成其它的布局内容。 我使用二维数组存储导航菜单项: - private String[][] menus = {{SlideMenuUtil.ITEM_MOBILE,SlideMenuUtil.ITEM_WEB,
- SlideMenuUtil.ITEM_CLOUD,SlideMenuUtil.ITEM_DATABASE},
- {SlideMenuUtil.ITEM_EMBED,SlideMenuUtil.ITEM_SERVER,
- SlideMenuUtil.ITEM_DOTNET,SlideMenuUtil.ITEM_JAVA},
- {SlideMenuUtil.ITEM_SAFE,SlideMenuUtil.ITEM_DOMAIN,
- SlideMenuUtil.ITEM_RESEASRCH,SlideMenuUtil.ITEM_MANAGE}};
复制代码 上例代码中:数组的第一维是用来显示几页数据,第二维是用来显示每一页中的几个菜单项。 在刚开始时,需要初始化导航菜单内容: -
-
- LayoutInflater inflater = getLayoutInflater();
- menuViews = [color=#0000ff]new[/color] ArrayList<View>();
- SlideMenuLayout menu = [color=#0000ff]new[/color] SlideMenuLayout([color=#0000ff]this[/color]);
-
- for(int i = 0;i < menus.length;i++){
- menuViews.add(menu.getSlideMenuLinerLayout(menus[i],screenWidth));
- }
-
- main = (ViewGroup)inflater.inflate(R.layout.main, [color=#0000ff]null[/color]);
-
-
- 其中,menuViews是用来装载页面布局控件,有3个页面menuViews就有3项。screenWidth是代表屏幕宽度。这里还使用到SlideMenuLayout类的实例方法: getSlideMenuLinerLayout(String[] menuTextViews,int layoutWidth)
- menuTextViews是代表每页中有几项菜单,layoutWidth是屏幕宽度。该方法中代码如下:
- * 顶部滑动菜单布局
-
- public View getSlideMenuLinerLayout(String[] menuTextViews,int layoutWidth){
- 包含TextView的LinearLayout
- LinearLayout menuLinerLayout =new LinearLayout(activity);
- menuLinerLayout.setOrientation(LinearLayout.HORIZONTAL);
-
- 参数设置
- LinearLayout.LayoutParams menuLinerLayoutParames =new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.WRAP_CONTENT,
- 1);
- menuLinerLayoutParames.gravity = Gravity.CENTER_HORIZONTAL;
-
- 添加TextView控件
- for(int i = 0;i < menuTextViews.length; i++){
- TextView tvMenu =new TextView(activity);
- 设置标识值
- tvMenu.setTag(menuTextViews[i]);
- tvMenu.setLayoutParams([color=#0000ff]new[/color] LayoutParams(layoutWidth / 4,30));
- tvMenu.setPadding(30, 14, 30, 10);
- tvMenu.setText(menuTextViews[i]);
- tvMenu.setTextColor(Color.WHITE);
- tvMenu.setGravity(Gravity.CENTER_HORIZONTAL);
- tvMenu.setOnClickListener(SlideMenuOnClickListener);
-
- 菜单项计数
- menuUtil.count ++;
-
- 设置第一个菜单项背景
- if(menuUtil.count == 1){
- tvMenu.setBackgroundResource(R.drawable.menu_bg);
- }
-
- menuLinerLayout.addView(tvMenu,menuLinerLayoutParames);
- menuList.add(tvMenu);
- }
-
- returnmenuLinerLayout;
- }
复制代码 上例代码只是初始化菜单效果,我是使用TextView做为每一项菜单,当然还要给每一项菜单设置事件,事件代码如下: - 单个菜单事件
- OnClickListener SlideMenuOnClickListener =new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- String menuTag = v.getTag().toString();
-
- if(v.isClickable()){
- textView = (TextView)v;
- Log.i("SlideMenu",
- "width:" + textView.getWidth() +
- "height:" + textView.getHeight());
-
- textView.setBackgroundResource(R.drawable.menu_bg);
-
- for(inti = 0;i < menuList.size();i++){
- if(!menuTag.equals(menuList.get(i).getText())){
- menuList.get(i).setBackgroundDrawable
- NULL;
- }
- }
- 点击菜单时改变内容
- slideMenuOnChange(menuTag);
- }
- }
- };
复制代码 上面代码中的for循环是为了清除其它菜单项的背景,slideMenuOnChange(menuTag)方法是为了显示下面的内容。该方法中代码如下: - 点击时改内容
- private void slideMenuOnChange(String menuTag){
- LayoutInflater inflater = activity.getLayoutInflater();
- ViewGroup llc = (ViewGroup)activity.findViewById(R.id.linearLayoutContent);
- llc.removeAllViews();
-
- if(menuTag.equals(SlideMenuUtil.ITEM_MOBILE)){
- llc.addView(inflater.inflate(R.layout.item_mobile,null));
- }else if(menuTag.equals(SlideMenuUtil.ITEM_WEB)){
- llc.addView(inflater.inflate(R.layout.item_web,null));
- }else if(menuTag.equals(SlideMenuUtil.ITEM_CLOUD)){
- llc.addView(inflater.inflate(R.layout.item_cloud, null));
- }elseif[/color](menuTag.equals(SlideMenuUtil.ITEM_DATABASE)){
- llc.addView(inflater.inflate(R.layout.item_database, null));
- }elseif[/color](menuTag.equals(SlideMenuUtil.ITEM_EMBED)){
- llc.addView(inflater.inflate(R.layout.item_embed, null));
- }elseif[/color](menuTag.equals(SlideMenuUtil.ITEM_SERVER)){
- llc.addView(inflater.inflate(R.layout.item_server, null));
- }else if(menuTag.equals(SlideMenuUtil.ITEM_DOTNET)){
- llc.addView(inflater.inflate(R.layout.item_dotnet, null));
- }elseif(menuTag.equals(SlideMenuUtil.ITEM_JAVA)){
- llc.addView(inflater.inflate(R.layout.item_java, null));
- }else if(menuTag.equals(SlideMenuUtil.ITEM_SAFE)){
- llc.addView(inflater.inflate(R.layout.item_safe,null));
- }else if(menuTag.equals(SlideMenuUtil.ITEM_DOMAIN)){
- llc.addView(inflater.inflate(R.layout.item_domain, nul));
- }else if(menuTag.equals(SlideMenuUtil.ITEM_RESEASRCH)){
- llc.addView(inflater.inflate(R.layout.item_research,null));
- }elseif(menuTag.equals(SlideMenuUtil.ITEM_MANAGE)){
- llc.addView(inflater.inflate(R.layout.item_manage,null));
- }
- }
复制代码 另外,为了设置左右导航菜单中的图片,需要在ViewPager控件中的onPageSelected监听事件中更改图片状态: -
-
- @Override
- public void onPageSelected(int arg0) {
- int[/color] pageCount = menuViews.size() - 1;
- pagerIndex = arg0;
-
- (arg0 >= 0 && arg0 < pageCount){
- imageNext.setVisibility(View.VISIBLE);
- }else{
- imageNext.setVisibility(View.INVISIBLE);
- }
-
- 显示左边导航图片
- if(arg0 > 0 && arg0 <= pageCount){
- imagePrevious.setVisibility(View.VISIBLE);
- }else{
- imagePrevious.setVisibility(View.INVISIBLE);
- }
- }
-
- 说明:如果有多个页面,则直接显示右边导航图片:
-
- if(menuViews.size() > 1){
- imageNext.setVisibility(View.VISIBLE);
- }
复制代码 如果到达最后一页时,则隐藏右边导航图片;如果当前页不是第一页,则直接显示左边导航图片。 另外,还需要给这两个导航图片设置单击事件,在点击时直接显示下一页菜单或是上一页菜单: - 右导航图片按钮事件
- class ImageNextOnclickListener implements OnClickListener{
- @Override
- publicvoid onClick(View v) {
- pagerIndex ++;
- viewPager.setCurrentItem(pagerIndex);
- }
- }
-
- 左导航图片按钮事件class ImagePreviousOnclickListener implements OnClickListener{
- @Override
- public void onClick(View v) {
- pagerIndex --;
- viewPager.setCurrentItem(pagerIndex);
- }
- }
复制代码 到此,第一种解决方案大致思路和代码就已经完了,不过我这里的实现效果是在滑动时直接显示下一页菜单,本页菜单就给隐藏掉了。有的朋友可能注意到,要想实现一点一点向左滑动或是向右滑动,而不是整个页面的滑动,也就是如果没有滑到下一页会反弹到原来的那页,就不能用这个方法了,那么就需要用到HorizontalScrollView,关于HorizontalScrollView实现的滑动菜单使用及示例,请看下面的第二种解决方案。 另外,在本示例中我没有实现背景图片的平滑向右或是向左的动画效果,有兴趣的的朋友可以把这样的效果加上,网上有一些实现这样的效果示例。 |