安卓开发笔记——多种方式实现底部菜单栏(仿微信界面)

来源:互联网 发布:linux怎么选中命令复制 编辑:程序博客网 时间:2024/06/16 12:45

关于底部菜单是什么,我想没必要介绍了,在市场上的APP里太常见了,这里提供两种方式来实现。

记得之前写过几篇关于底部菜单实现的方法,有兴趣的朋友可以看看:

1、《安卓开发复习笔记——TabHost组件(一)(实现底部菜单导航)》

2、《安卓开发复习笔记——TabHost组件(二)(实现底部菜单导航)》

3、《安卓开发笔记——Fragment+FragmentTabHost组件(实现新浪微博底部菜单)》

 

今天带来种相对更通俗易懂的写法,不再和过去一样去沿用TabHost了,这次我们直接用LinearLayout布局来实现,先来看下实现效果图:

中间内容区域有两种实现方式:

1、ViewPager  --可滑动界面      2、Fragment  --固定界面

   

     

 

1、界面分析

 这里有个小技巧,把底部菜单栏的每一个小的LinearLayout的宽度都设置成0dp,然后用weight权重去分配它,中间内容区域也是把高度设置成0dp,然后用weight权重去分配它。(weight默认是把界面里空闲的位置作为划分位置,所以这里的宽度或者高度要注意设置成0dp)

 

2、具体实现(内容区域为ViewPager可滑动界面)

布局文件:

activity_top.xml(顶部布局)

复制代码
 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2     xmlns:tools="http://schemas.android.com/tools" 3     android:layout_width="match_parent" 4     android:layout_height="55dp" 5     android:background="@drawable/title_bar"> 6  7     <TextView 8         android:layout_width="wrap_content" 9         android:layout_height="wrap_content"10         android:layout_centerInParent="true"11         android:text="微信"12         android:textSize="20dp" 13         android:textColor="#ffffff"/>14 15 </RelativeLayout>
复制代码

activity_bottom.xml(底部布局)

复制代码
  1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  2     xmlns:tools="http://schemas.android.com/tools"  3     android:layout_width="match_parent"  4     android:layout_height="wrap_content"  5     android:background="@drawable/bottom_bar" >  6   7     <LinearLayout  8         android:id="@+id/ll_home"  9         android:layout_width="0dp" 10         android:layout_height="wrap_content" 11         android:layout_weight="1" 12         android:gravity="center" 13         android:orientation="vertical" > 14  15         <ImageView 16             android:id="@+id/iv_home" 17             android:layout_width="wrap_content" 18             android:layout_height="wrap_content" 19             android:src="@drawable/tab_weixin_pressed" /> 20  21         <TextView 22             android:id="@+id/tv_home" 23             android:layout_width="wrap_content" 24             android:layout_height="wrap_content" 25             android:layout_marginTop="3dp" 26             android:text="首页" 27             android:textColor="#1B940A" 28             android:textStyle="bold" /> 29     </LinearLayout> 30  31     <LinearLayout 32         android:id="@+id/ll_address" 33         android:layout_width="0dp" 34         android:layout_height="wrap_content" 35         android:layout_weight="1" 36         android:gravity="center" 37         android:orientation="vertical" > 38  39         <ImageView 40             android:id="@+id/iv_address" 41             android:layout_width="wrap_content" 42             android:layout_height="wrap_content" 43             android:src="@drawable/tab_address_normal" /> 44  45         <TextView 46             android:id="@+id/tv_address" 47             android:layout_width="wrap_content" 48             android:layout_height="wrap_content" 49             android:layout_marginTop="3dp" 50             android:text="通讯录" 51             android:textColor="#ffffff" 52             android:textStyle="bold" /> 53     </LinearLayout> 54  55     <LinearLayout 56         android:id="@+id/ll_friend" 57         android:layout_width="0dp" 58         android:layout_height="wrap_content" 59         android:layout_weight="1" 60         android:gravity="center" 61         android:orientation="vertical" > 62  63         <ImageView 64             android:id="@+id/iv_friend" 65             android:layout_width="wrap_content" 66             android:layout_height="wrap_content" 67             android:src="@drawable/tab_find_frd_normal" /> 68  69         <TextView 70             android:id="@+id/tv_friend" 71             android:layout_width="wrap_content" 72             android:layout_height="wrap_content" 73             android:layout_marginTop="3dp" 74             android:text="朋友" 75             android:textColor="#ffffff" 76             android:textStyle="bold" /> 77     </LinearLayout> 78  79     <LinearLayout 80         android:id="@+id/ll_setting" 81         android:layout_width="0dp" 82         android:layout_height="wrap_content" 83         android:layout_weight="1" 84         android:gravity="center" 85         android:orientation="vertical" > 86  87         <ImageView 88             android:id="@+id/iv_setting" 89             android:layout_width="wrap_content" 90             android:layout_height="wrap_content" 91             android:src="@drawable/tab_settings_normal" /> 92  93         <TextView 94             android:id="@+id/tv_setting" 95             android:layout_width="wrap_content" 96             android:layout_height="wrap_content" 97             android:layout_marginTop="3dp" 98             android:text="设置" 99             android:textColor="#ffffff"100             android:textStyle="bold" />101     </LinearLayout>102 103 </LinearLayout>
复制代码

activity_main.xml(主布局,引入上下布局)

复制代码
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2     xmlns:tools="http://schemas.android.com/tools" 3     android:layout_width="match_parent" 4     android:layout_height="match_parent" 5     android:orientation="vertical" > 6  7     <include layout="@layout/activity_top" /> 8  9     <android.support.v4.view.ViewPager10         android:id="@+id/vp_content"11         android:layout_width="match_parent"12         android:background="#ffffff"13         android:layout_height="0dp"14         android:layout_weight="1" >15     </android.support.v4.view.ViewPager>16 17     <include layout="@layout/activity_bottom" />18 19 </LinearLayout>
复制代码

page_01.xml-page_04.xml(4个ViewPager的滑动界面,由于内容简单这里只给出其中1个)

复制代码
 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2     xmlns:tools="http://schemas.android.com/tools" 3     android:layout_width="match_parent" 4     android:layout_height="match_parent"> 5  6     <TextView 7         android:layout_width="wrap_content" 8         android:layout_height="wrap_content" 9         android:layout_centerInParent="true"10         android:text="我是微信首页"11         android:textSize="30dp" />12 13 </RelativeLayout>
复制代码

 

具体实现代码:

ViewPager适配器(关于ViewPager的使用方法这里就不多说了,不清楚的朋友看我这篇文章吧《安卓开发笔记——ViewPager组件(仿微信引导界面)》)

复制代码
 1 package com.rabbit.tabdemo; 2  3 import java.util.List; 4  5 import android.support.v4.view.PagerAdapter; 6 import android.view.View; 7 import android.view.ViewGroup; 8 /** 9  * ViewPager适配器10  * @author Balla_兔子11  *12  */13 public class ContentAdapter extends PagerAdapter {14 15     private List<View> views;16 17     public ContentAdapter(List<View> views) {18         this.views = views;19     }20 21     @Override22     public int getCount() {23         return views.size();24     }25 26     @Override27     public boolean isViewFromObject(View arg0, Object arg1) {28         return arg0 == arg1;29     }30 31     @Override32     public Object instantiateItem(ViewGroup container, int position) {33         View view = views.get(position);34         container.addView(view);35         return view;36     }37 38     @Override39     public void destroyItem(ViewGroup container, int position, Object object) {40         container.removeView(views.get(position));41     }42 43 }
复制代码

 

MainActivity(主界面代码)

初始化控件后,完成对底部菜单的4个LinearLayout的点击监听事件,在用户触发点击事件的时候,设置选择状态然后跳转相对应的界面。为了使得滑动ViewPager也能同时触发底部菜单状态的改变,这里也对ViewPager设置了滑动监听。其他的代码注释很全,看注释就可以了。

复制代码
  1 package com.rabbit.tabdemo;  2   3 import java.util.ArrayList;  4 import java.util.List;  5   6 import android.app.Activity;  7 import android.os.Bundle;  8 import android.support.v4.view.ViewPager;  9 import android.support.v4.view.ViewPager.OnPageChangeListener; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.widget.ImageView; 13 import android.widget.LinearLayout; 14 import android.widget.TextView; 15  16 public class MainActivity extends Activity implements OnClickListener,OnPageChangeListener{ 17  18     // 底部菜单4个Linearlayout 19     private LinearLayout ll_home; 20     private LinearLayout ll_address; 21     private LinearLayout ll_friend; 22     private LinearLayout ll_setting; 23  24     // 底部菜单4个ImageView 25     private ImageView iv_home; 26     private ImageView iv_address; 27     private ImageView iv_friend; 28     private ImageView iv_setting; 29  30     // 底部菜单4个菜单标题 31     private TextView tv_home; 32     private TextView tv_address; 33     private TextView tv_friend; 34     private TextView tv_setting; 35  36     // 中间内容区域 37     private ViewPager viewPager; 38  39     // ViewPager适配器ContentAdapter 40     private ContentAdapter adapter; 41  42     private List<View> views; 43  44     @Override 45     protected void onCreate(Bundle savedInstanceState) { 46         super.onCreate(savedInstanceState); 47         setContentView(R.layout.activity_main); 48  49         // 初始化控件 50         initView(); 51         // 初始化底部按钮事件 52         initEvent(); 53  54     } 55  56     private void initEvent() { 57         // 设置按钮监听 58         ll_home.setOnClickListener(this); 59         ll_address.setOnClickListener(this); 60         ll_friend.setOnClickListener(this); 61         ll_setting.setOnClickListener(this); 62          63         //设置ViewPager滑动监听 64         viewPager.setOnPageChangeListener(this); 65     } 66  67     private void initView() { 68  69         // 底部菜单4个Linearlayout 70         this.ll_home = (LinearLayout) findViewById(R.id.ll_home); 71         this.ll_address = (LinearLayout) findViewById(R.id.ll_address); 72         this.ll_friend = (LinearLayout) findViewById(R.id.ll_friend); 73         this.ll_setting = (LinearLayout) findViewById(R.id.ll_setting); 74  75         // 底部菜单4个ImageView 76         this.iv_home = (ImageView) findViewById(R.id.iv_home); 77         this.iv_address = (ImageView) findViewById(R.id.iv_address); 78         this.iv_friend = (ImageView) findViewById(R.id.iv_friend); 79         this.iv_setting = (ImageView) findViewById(R.id.iv_setting); 80  81         // 底部菜单4个菜单标题 82         this.tv_home = (TextView) findViewById(R.id.tv_home); 83         this.tv_address = (TextView) findViewById(R.id.tv_address); 84         this.tv_friend = (TextView) findViewById(R.id.tv_friend); 85         this.tv_setting = (TextView) findViewById(R.id.tv_setting); 86  87         // 中间内容区域ViewPager 88         this.viewPager = (ViewPager) findViewById(R.id.vp_content); 89  90         // 适配器 91         View page_01 = View.inflate(MainActivity.this, R.layout.page_01, null); 92         View page_02 = View.inflate(MainActivity.this, R.layout.page_02, null); 93         View page_03 = View.inflate(MainActivity.this, R.layout.page_03, null); 94         View page_04 = View.inflate(MainActivity.this, R.layout.page_04, null); 95  96         views = new ArrayList<View>(); 97         views.add(page_01); 98         views.add(page_02); 99         views.add(page_03);100         views.add(page_04);101 102         this.adapter = new ContentAdapter(views);103         viewPager.setAdapter(adapter);104 105     }106 107     @Override108     public void onClick(View v) {109         // 在每次点击后将所有的底部按钮(ImageView,TextView)颜色改为灰色,然后根据点击着色110         restartBotton();111         // ImageView和TetxView置为绿色,页面随之跳转112         switch (v.getId()) {113         case R.id.ll_home:114             iv_home.setImageResource(R.drawable.tab_weixin_pressed);115             tv_home.setTextColor(0xff1B940A);116             viewPager.setCurrentItem(0);117             break;118         case R.id.ll_address:119             iv_address.setImageResource(R.drawable.tab_address_pressed);120             tv_address.setTextColor(0xff1B940A);121             viewPager.setCurrentItem(1);122             break;123         case R.id.ll_friend:124             iv_friend.setImageResource(R.drawable.tab_find_frd_pressed);125             tv_friend.setTextColor(0xff1B940A);126             viewPager.setCurrentItem(2);127             break;128         case R.id.ll_setting:129             iv_setting.setImageResource(R.drawable.tab_find_frd_pressed);130             tv_setting.setTextColor(0xff1B940A);131             viewPager.setCurrentItem(3);132             break;133 134         default:135             break;136         }137 138     }139 140     private void restartBotton() {141         // ImageView置为灰色142         iv_home.setImageResource(R.drawable.tab_weixin_normal);143         iv_address.setImageResource(R.drawable.tab_address_normal);144         iv_friend.setImageResource(R.drawable.tab_find_frd_normal);145         iv_setting.setImageResource(R.drawable.tab_settings_normal);146         // TextView置为白色147         tv_home.setTextColor(0xffffffff);148         tv_address.setTextColor(0xffffffff);149         tv_friend.setTextColor(0xffffffff);150         tv_setting.setTextColor(0xffffffff);151     }152 153     @Override154     public void onPageScrollStateChanged(int arg0) {155         156     }157 158     @Override159     public void onPageScrolled(int arg0, float arg1, int arg2) {160         161     }162 163     @Override164     public void onPageSelected(int arg0) {165         restartBotton();166         //当前view被选择的时候,改变底部菜单图片,文字颜色167         switch (arg0) {168         case 0:169             iv_home.setImageResource(R.drawable.tab_weixin_pressed);170             tv_home.setTextColor(0xff1B940A);171             break;172         case 1:173             iv_address.setImageResource(R.drawable.tab_address_pressed);174             tv_address.setTextColor(0xff1B940A);175             break;176         case 2:177             iv_friend.setImageResource(R.drawable.tab_find_frd_pressed);178             tv_friend.setTextColor(0xff1B940A);179             break;180         case 3:181             iv_setting.setImageResource(R.drawable.tab_find_frd_pressed);182             tv_setting.setTextColor(0xff1B940A);183             break;184 185         default:186             break;187         }188         189     }190 191 }
复制代码

 

3、具体实现(内容区域为Fragment固定界面)

布局文件:

布局文件基本没变化,只是把主界面的ViewPager改成了FramLayout,其他文件保持一致,就不贴出来了。

 View Code

 

具体实现代码:

由于这次的内容是基于Fragment的,所以需要有4个Fragment文件,由于代码相同这里只贴出一个。

Frgament(HomeFragment,AddressFragment,FriendFragment,SettingFragment)

 View Code

 

MainActivity(主界面代码)

代码很简单,一看就能明白就不多说什么了,只提个需要注意的地方,由于便于向下兼容这里的Fragment是用V4包下的,在导入包的时候需要注意一下。

复制代码
  1 package com.rabbit.tabdemo;  2   3 import android.os.Bundle;  4 import android.support.v4.app.Fragment;  5 import android.support.v4.app.FragmentActivity;  6 import android.support.v4.app.FragmentManager;  7 import android.support.v4.app.FragmentTransaction;  8 import android.view.View;  9 import android.view.View.OnClickListener; 10 import android.widget.ImageView; 11 import android.widget.LinearLayout; 12 import android.widget.TextView; 13  14 public class MainActivity extends FragmentActivity implements OnClickListener { 15     // 底部菜单4个Linearlayout 16     private LinearLayout ll_home; 17     private LinearLayout ll_address; 18     private LinearLayout ll_friend; 19     private LinearLayout ll_setting; 20  21     // 底部菜单4个ImageView 22     private ImageView iv_home; 23     private ImageView iv_address; 24     private ImageView iv_friend; 25     private ImageView iv_setting; 26  27     // 底部菜单4个菜单标题 28     private TextView tv_home; 29     private TextView tv_address; 30     private TextView tv_friend; 31     private TextView tv_setting; 32  33     // 4个Fragment 34     private Fragment homeFragment; 35     private Fragment addressFragment; 36     private Fragment friendFragment; 37     private Fragment settingFragment; 38  39     @Override 40     protected void onCreate(Bundle savedInstanceState) { 41         super.onCreate(savedInstanceState); 42         setContentView(R.layout.activity_main); 43  44         // 初始化控件 45         initView(); 46         // 初始化底部按钮事件 47         initEvent(); 48         // 初始化并设置当前Fragment 49         initFragment(0); 50  51     } 52  53     private void initFragment(int index) { 54         // 由于是引用了V4包下的Fragment,所以这里的管理器要用getSupportFragmentManager获取 55         FragmentManager fragmentManager = getSupportFragmentManager(); 56         // 开启事务 57         FragmentTransaction transaction = fragmentManager.beginTransaction(); 58         // 隐藏所有Fragment 59         hideFragment(transaction); 60         switch (index) { 61         case 0: 62             if (homeFragment == null) { 63                 homeFragment = new HomeFragment(); 64                 transaction.add(R.id.fl_content, homeFragment); 65             } else { 66                 transaction.show(homeFragment); 67             } 68             break; 69         case 1: 70             if (addressFragment == null) { 71                 addressFragment = new AddressFragment(); 72                 transaction.add(R.id.fl_content, addressFragment); 73             } else { 74                 transaction.show(addressFragment); 75             } 76  77             break; 78         case 2: 79             if (friendFragment == null) { 80                 friendFragment = new FriendFragment(); 81                 transaction.add(R.id.fl_content, friendFragment); 82             } else { 83                 transaction.show(friendFragment); 84             } 85  86             break; 87         case 3: 88             if (settingFragment == null) { 89                 settingFragment = new SettingFragment(); 90                 transaction.add(R.id.fl_content, settingFragment); 91             } else { 92                 transaction.show(settingFragment); 93             } 94  95             break; 96  97         default: 98             break; 99         }100 101         // 提交事务102         transaction.commit();103 104     }105 106     //隐藏Fragment107     private void hideFragment(FragmentTransaction transaction) {108         if (homeFragment != null) {109             transaction.hide(homeFragment);110         }111         if (addressFragment != null) {112             transaction.hide(addressFragment);113         }114         if (friendFragment != null) {115             transaction.hide(friendFragment);116         }117         if (settingFragment != null) {118             transaction.hide(settingFragment);119         }120 121     }122 123     private void initEvent() {124         // 设置按钮监听125         ll_home.setOnClickListener(this);126         ll_address.setOnClickListener(this);127         ll_friend.setOnClickListener(this);128         ll_setting.setOnClickListener(this);129 130     }131 132     private void initView() {133 134         // 底部菜单4个Linearlayout135         this.ll_home = (LinearLayout) findViewById(R.id.ll_home);136         this.ll_address = (LinearLayout) findViewById(R.id.ll_address);137         this.ll_friend = (LinearLayout) findViewById(R.id.ll_friend);138         this.ll_setting = (LinearLayout) findViewById(R.id.ll_setting);139 140         // 底部菜单4个ImageView141         this.iv_home = (ImageView) findViewById(R.id.iv_home);142         this.iv_address = (ImageView) findViewById(R.id.iv_address);143         this.iv_friend = (ImageView) findViewById(R.id.iv_friend);144         this.iv_setting = (ImageView) findViewById(R.id.iv_setting);145 146         // 底部菜单4个菜单标题147         this.tv_home = (TextView) findViewById(R.id.tv_home);148         this.tv_address = (TextView) findViewById(R.id.tv_address);149         this.tv_friend = (TextView) findViewById(R.id.tv_friend);150         this.tv_setting = (TextView) findViewById(R.id.tv_setting);151 152     }153 154     @Override155     public void onClick(View v) {156 157         // 在每次点击后将所有的底部按钮(ImageView,TextView)颜色改为灰色,然后根据点击着色158         restartBotton();159         // ImageView和TetxView置为绿色,页面随之跳转160         switch (v.getId()) {161         case R.id.ll_home:162             iv_home.setImageResource(R.drawable.tab_weixin_pressed);163             tv_home.setTextColor(0xff1B940A);164             initFragment(0);165             break;166         case R.id.ll_address:167             iv_address.setImageResource(R.drawable.tab_address_pressed);168             tv_address.setTextColor(0xff1B940A);169             initFragment(1);170             break;171         case R.id.ll_friend:172             iv_friend.setImageResource(R.drawable.tab_find_frd_pressed);173             tv_friend.setTextColor(0xff1B940A);174             initFragment(2);175             break;176         case R.id.ll_setting:177             iv_setting.setImageResource(R.drawable.tab_find_frd_pressed);178             tv_setting.setTextColor(0xff1B940A);179             initFragment(3);180             break;181 182         default:183             break;184         }185 186     }187 188     private void restartBotton() {189         // ImageView置为灰色190         iv_home.setImageResource(R.drawable.tab_weixin_normal);191         iv_address.setImageResource(R.drawable.tab_address_normal);192         iv_friend.setImageResource(R.drawable.tab_find_frd_normal);193         iv_setting.setImageResource(R.drawable.tab_settings_normal);194         // TextView置为白色195         tv_home.setTextColor(0xffffffff);196         tv_address.setTextColor(0xffffffff);197         tv_friend.setTextColor(0xffffffff);198         tv_setting.setTextColor(0xffffffff);199     }200 201 }
复制代码

     

 

到这里界面效果就基本实现了,就算是旋转屏幕也能够很好的达到适配效果,最后我们还需要做的2点,可能有些朋友已经发现了,在我们旋转屏幕的时候,Fragment会重新调用onCreate方法,导致成员变量重新初始化了一次,Fragment对象也重置为空,然后就调用不到hide方法,从而出现了界面重复叠加的情况。

下面提供解决的方法,其实很简单,只需要在AndroidManifest.xml里面对应的activity里添设置改换屏幕方向等操作时不触发oncreate事件就可以。

1  android:configChanges="orientation|keyboardHidden|screenSize" 

最后我们隐藏下标题栏,在application里添加上:

1  android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" 

这样就大功告成了!

 

总结:

基于ViewPager实现的内容:

优点:

1、界面可以滑动,美观,流畅。

缺点:

1、当界面里有一些需要用手势来实现的内容会起冲突,比如我们ListView里的侧滑删除。

2、由于采用的是ViewPager,所以页面内容实现代码会严重依赖于MainActivity,代码太过冗余,不便于后期维护。

 

基于Fragment实现的内容:

优点:

1、Fragment文件单独存在,各自页面的内容各自去实现完成,有自己的生命周期,便于后期维护。

2、对于需要手势操作的一些内容不会起冲突。

缺点:

1、界面不可滑动,比较死板。

0 0
原创粉丝点击