加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2021-05-21 05:00:55 所属栏目:大数据 来源: https://www.jb51.cc
导读:关于底部菜单是什么,我想没必要介绍了,在市场上的APP里太常见了,这里提供两种方式来实现。 记得之前写过几篇关于底部菜单实现的方法,有兴趣的朋友可以看看: 1、《安卓开发复习笔记——TabHost组件(一)(实现底部菜单导航)》 2、《安卓开发复习笔记——

关于底部菜单是什么,我想没必要介绍了,在市场上的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_height10         android:layout_centerInParent="true"
11         android:text="微信"
12         android:textSize="20dp" 
13         android:textColor="#ffffff"/>
14 
15 </RelativeLayout>
View Code

activity_bottom.xml(底部布局)

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

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

    android:orientationinclude layout="@layout/activity_top"  8 
 9     android.support.v4.view.ViewPager
10         ="@+id/vp_content"
        android:background14 ="1" 15     android.support.v4.view.ViewPager16 
17     ="@layout/activity_bottom" 18 
19 >
View Code

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

="match_parent" 5 
 6      7          8 ="我是微信首页"
="30dp" 12 
13 >
View Code

?

具体实现代码:

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

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

?

MainActivity(主界面代码)

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

  2 
  3  java.util.ArrayList;
  4   5 
  6  android.app.Activity;
  7  android.os.Bundle;
  8  android.support.v4.view.ViewPager;
  9  android.support.v4.view.ViewPager.OnPageChangeListener;
 10  11  android.view.View.OnClickListener;
 12  android.widget.ImageView;
 13  android.widget.LinearLayout;
 14  android.widget.TextView;
 15 
 16 class MainActivity extends Activity implements OnClickListener,OnPageChangeListener{
 17 
 18     // 底部菜单4个Linearlayout
 19     private LinearLayout ll_home;
 20      LinearLayout ll_address;
 21      LinearLayout ll_friend;
 22      LinearLayout ll_setting;
 23 
 24      底部菜单4个ImageView
 25      ImageView iv_home;
 26      ImageView iv_address;
 27      ImageView iv_friend;
 28      ImageView iv_setting;
 29 
 30      底部菜单4个菜单标题
 TextView tv_home;
 32      TextView tv_address;
 33      TextView tv_friend;
 34      TextView tv_setting;
 35 
 36      中间内容区域
 37      ViewPager viewPager;
 39      ViewPager适配器ContentAdapter
 40      ContentAdapter adapter;
 41 
 42      43 
 44  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  initEvent() {
 57          设置按钮监听
 58         ll_home.setOnClickListener(this);
 59         ll_address.setOnClickListener( 60         ll_friend.setOnClickListener( 61         ll_setting.setOnClickListener( 62         
设置ViewPager滑动监听
 64         viewPager.setOnPageChangeListener( 65  66 
 67      initView() {
 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          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          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);
 中间内容区域ViewPager
 88         this.viewPager = (ViewPager) findViewById(R.id.vp_content);
 89 
 90          适配器
 91         View page_01 = View.inflate(MainActivity.this,R.layout.page_01,1)">null 92         View page_02 = View.inflate(MainActivity. 93         View page_03 = View.inflate(MainActivity. 94         View page_04 = View.inflate(MainActivity. 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);
        viewPager.setAdapter(adapter);
104 
105 106 
107 108      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(0xff1B940A116             viewPager.setCurrentItem(0117             break;
118          R.id.ll_address:
119             iv_address.setImageResource(R.drawable.tab_address_pressed);
120             tv_address.setTextColor(0xff1B940A121             viewPager.setCurrentItem(1122             123          R.id.ll_friend:
124             iv_friend.setImageResource(R.drawable.tab_find_frd_pressed);
125             tv_friend.setTextColor(0xff1B940A126             viewPager.setCurrentItem(2127             128          R.id.ll_setting:
129             iv_setting.setImageResource(R.drawable.tab_find_frd_pressed);
130             tv_setting.setTextColor(0xff1B940A131             viewPager.setCurrentItem(3132             133 
134         default:
135             136         }
137 
138 139 
140      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(0xffffffff148         tv_address.setTextColor(0xffffffff149         tv_friend.setTextColor(0xffffffff150         tv_setting.setTextColor(0xffffffff151 152 
153 154     void onPageScrollStateChanged( arg0) {
155         
156 157 
158 159     void onPageScrolled(int arg0,1)">float arg1,1)"> arg2) {
160         
161 162 
163 164     void onPageSelected(165 166         当前view被选择的时候,改变底部菜单图片,文字颜色
167          (arg0) {
168         case 0169 170             tv_home.setTextColor(0xff1B940A171             172         case 1173 174             tv_address.setTextColor(0xff1B940A175             176         case 2177 178             tv_friend.setTextColor(0xff1B940A179             180         case 3181 182             tv_setting.setTextColor(0xff1B940A183             184 
185         186             187 188         
189 190 
191 }

?

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

布局文件:

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

FrameLayout
="@+id/fl_content"
FrameLayout>
View Code

?

具体实现代码:

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

Frgament(HomeFragment,AddressFragment,FriendFragment,SettingFragment)

@H_302_1404@

 4  android.support.annotation.Nullable;
 android.support.v4.app.Fragment;
 android.view.LayoutInflater;
 9 
class HomeFragment  Fragment {
12     public View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {
13         return inflater.inflate(R.layout.page_01,container,1)">false14 15 
16 }
View Code

?

MainActivity(主界面代码)

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

  5  android.support.v4.app.FragmentActivity;
 android.support.v4.app.FragmentManager;
 android.support.v4.app.FragmentTransaction;
 13 
extends FragmentActivity  OnClickListener {
 15      16      17      23      26 
 32 
 4个Fragment
 Fragment homeFragment;
 35      Fragment addressFragment;
 Fragment friendFragment;
 Fragment settingFragment;
 39  41          42  44          45  48          初始化并设置当前Fragment
 49         initFragment(0 50 
 51  52 
void initFragment( index) {
 54          由于是引用了V4包下的Fragment,所以这里的管理器要用getSupportFragmentManager获取
 55         FragmentManager fragmentManager = getSupportFragmentManager();
 56          开启事务
 57         FragmentTransaction transaction = fragmentManager.beginTransaction();
 58          隐藏所有Fragment
 59         hideFragment(transaction);
 60          (index) {
 61          62             if (homeFragment == ) {
 63                 homeFragment =  HomeFragment();
 64                 transaction.add(R.id.fl_content,homeFragment);
 65             } else {
 66                 transaction.show(homeFragment);
 67             }
 68              70             if (addressFragment ==  71                 addressFragment =  AddressFragment();
 72  73             }  74                 transaction.show(addressFragment);
 75  76 
 77              79             if (friendFragment ==  80                 friendFragment =  FriendFragment();
 81  82             }  83                 transaction.show(friendFragment);
 84  85 
 86              88             if (settingFragment ==  89                 settingFragment =  SettingFragment();
 90  91             }  92                 transaction.show(settingFragment);
 93  94 
 95              96 
 97          98             100 
101          提交事务
102         transaction.commit();
103 
104 105 
106     隐藏Fragment
107      hideFragment(FragmentTransaction transaction) {
108         if (homeFragment != 109             transaction.hide(homeFragment);
if (addressFragment != 112             transaction.hide(addressFragment);
113 114         if (friendFragment != 115             transaction.hide(friendFragment);
116 117         if (settingFragment != 118             transaction.hide(settingFragment);
120 
121 122 
123     124         125         ll_home.setOnClickListener(126         ll_address.setOnClickListener(127         ll_friend.setOnClickListener(128         ll_setting.setOnClickListener(129 
130 131 
132     135         136         137         138         140         142         143         144         145 
147         148         149         150         151 
152 153 
154 155     156 
157         159         160         161         162 163             tv_home.setTextColor(0xff1B940A164             initFragment(0165             167 168             tv_address.setTextColor(0xff1B940A169             initFragment(1170             171         172 173             tv_friend.setTextColor(0xff1B940A174             initFragment(2178             tv_setting.setTextColor(0xff1B940A179             initFragment(3180             181 
182         184 185 
186 187 
188     189         190 191 192 193 194         195         tv_home.setTextColor(0xffffffff196         tv_address.setTextColor(0xffffffff197         tv_friend.setTextColor(0xffffffff198         tv_setting.setTextColor(0xffffffff199 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、界面不可滑动,比较死板。

?

补充:如果既想有ViewPager的滑动效果,又想ViewPager的页卡里嵌套Fragment,可以使用FragmentPagerAdapter作为适配器,但需要注意Fragment生命周期的管理。

?

?

作者:Balla_兔子
出处:http://www.cnblogs.com/lichenwei/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

?

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读