TextView+Fragment实现底部导航栏

来源:互联网 发布:单片机开发论坛 编辑:程序博客网 时间:2024/05/19 05:41

前言:项目第二版刚上线没多久,产品又对需求进行了大改动,以前用的是左滑菜单,现在又要换成底部导航栏,于是今天又苦逼加班了.花了几个小时实现了一个底部导航栏的demo,然后总结一下.写一篇博客.供自己以后参考.也可以给没有做过的朋友进行参考.以后大家有类似的功能就可以在我的demo上就行修改.


一.先上效果图:   本来是打算用FragmentTabHost实现的,但是中间那个按钮有点麻烦,想到我们项目好几个产品经理,并且经常改需求,于是最后决定  用 TextView+Fragment去实现.                     



二.查看代码实现.代码是我们最好的老师.

主界面布局文件  activity_main.xml   外层一个FrameLayout+ImageView+LinearLayout     TextView选中跟未选中时 图片和颜色 切换都用布局去实现.

1).FrameLayout  用于显示fragment

2).ImageView  显示底部最中间那个图标

3).LinearLayout  显示底部四个图标   我这里用weight分成了5份,第三个控件啥都没有就用View控件占了一个位置

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <FrameLayout        android:id="@+id/main_container"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_above="@+id/view_line"/>    <View        android:id="@+id/view_line"        android:layout_height="1dp"        android:layout_width="match_parent"        android:background="#DCDBDB"        android:layout_above="@+id/rl_bottom"/>        <LinearLayout        android:id="@+id/rl_bottom"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:paddingTop="5dp"        android:paddingBottom="5dp"        android:background="#F2F2F2"        android:orientation="horizontal" >        <TextView            android:id="@+id/tv_main"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:layout_weight="1"            android:drawableTop="@drawable/tab_item_main_img_selector"            android:drawablePadding="@dimen/main_tab_item_image_and_text"            android:focusable="true"            android:gravity="center"            android:text="@string/main"            android:textColor="@drawable/tabitem_txt_sel" />        <TextView            android:id="@+id/tv_dynamic"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:layout_weight="1"            android:drawableTop="@drawable/tab_item_dynamic_img_selector"            android:drawablePadding="@dimen/main_tab_item_image_and_text"            android:focusable="true"            android:gravity="center"            android:text="@string/dynamic"            android:textColor="@drawable/tabitem_txt_sel" />        <View            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1" />        <TextView            android:id="@+id/tv_message"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:layout_weight="1"            android:drawableTop="@drawable/tab_item_message_img_selector"            android:drawablePadding="@dimen/main_tab_item_image_and_text"            android:focusable="true"            android:gravity="center"            android:text="@string/message"            android:textColor="@drawable/tabitem_txt_sel" />        <TextView            android:id="@+id/tv_person"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:layout_weight="1"            android:drawableTop="@drawable/tab_item_person_img_selector"            android:drawablePadding="@dimen/main_tab_item_image_and_text"            android:focusable="true"            android:gravity="center"            android:text="@string/person"            android:textColor="@drawable/tabitem_txt_sel"/>    </LinearLayout>    <ImageView        android:id="@+id/iv_make"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:paddingBottom="10dp"        android:src="@drawable/icon_tab_make_select"/></RelativeLayout>


图片选择器   tab_item_main_img_selector.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <!-- Non focused states -->    <item android:drawable="@drawable/icon_tab_main_normal" android:state_focused="false" android:state_pressed="false" android:state_selected="false"/>    <item android:drawable="@drawable/icon_tab_main_select" android:state_focused="false" android:state_pressed="false" android:state_selected="true"/>    <!-- Focused states -->    <item android:drawable="@drawable/icon_tab_main_select" android:state_focused="true" android:state_pressed="false" android:state_selected="false"/>    <item android:drawable="@drawable/icon_tab_main_select" android:state_focused="true" android:state_pressed="false" android:state_selected="true"/>    <!-- Pressed -->    <item android:drawable="@drawable/icon_tab_main_select" android:state_pressed="true" android:state_selected="true"/>    <item android:drawable="@drawable/icon_tab_main_select" android:state_pressed="true"/></selector>


文字颜色选择器   tabitem_txt_sel.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <!-- Non focused states -->    <item android:state_focused="false" android:state_pressed="false" android:state_selected="false" android:color="@color/main_tab_item_text_normal"/>    <item android:state_focused="false" android:state_pressed="false" android:state_selected="true" android:color="@color/main_tab_item_text_select"/>        <!-- Focused states -->    <item android:state_focused="true" android:state_pressed="false" android:state_selected="false" android:color="@color/main_tab_item_text_select"/>    <item android:state_focused="true" android:state_pressed="false" android:state_selected="true" android:color="@color/main_tab_item_text_select"/>        <!-- Pressed -->    <item android:state_pressed="true" android:state_selected="true" android:color="@color/main_tab_item_text_select"/>    <item android:state_pressed="true" android:color="@color/main_tab_item_text_select"/></selector>


MainActivity.java   对fragment的切换,底部图标颜色的切换.我也不详细介绍了.代码里面我都有写注释.

/** * 对fragment的切换,底部图标颜色的切换 * @author ansen * @create time 2015-09-08 */public class MainActivity extends FragmentActivity {//要切换显示的四个Fragmentprivate MainFragment mainFragment;private DynamicFragment dynamicFragment;private MessageFragment messageFragment;private PersonFragment personFragment;private int currentId = R.id.tv_main;// 当前选中id,默认是主页private TextView tvMain, tvDynamic, tvMessage, tvPerson;//底部四个TextView@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tvMain = (TextView) findViewById(R.id.tv_main);tvMain.setSelected(true);//首页默认选中tvDynamic = (TextView) findViewById(R.id.tv_dynamic);tvMessage = (TextView) findViewById(R.id.tv_message);tvPerson = (TextView) findViewById(R.id.tv_person);/** * 默认加载首页 */mainFragment = new MainFragment();getSupportFragmentManager().beginTransaction().add(R.id.main_container, mainFragment).commit();tvMain.setOnClickListener(tabClickListener);tvDynamic.setOnClickListener(tabClickListener);tvMessage.setOnClickListener(tabClickListener);tvPerson.setOnClickListener(tabClickListener);findViewById(R.id.iv_make).setOnClickListener(onClickListener);}private OnClickListener onClickListener=new OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.iv_make:Intent intent=new Intent(MainActivity.this, MakeActivity.class);startActivity(intent);break;}}};private OnClickListener tabClickListener = new OnClickListener() {@Overridepublic void onClick(View v) {if (v.getId() != currentId) {//如果当前选中跟上次选中的一样,不需要处理changeSelect(v.getId());//改变图标跟文字颜色的选中 changeFragment(v.getId());//fragment的切换currentId = v.getId();//设置选中id}}};/** * 改变fragment的显示 *  * @param resId */private void changeFragment(int resId) {FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();//开启一个Fragment事务hideFragments(transaction);//隐藏所有fragmentif(resId==R.id.tv_main){//主页if(mainFragment==null){//如果为空先添加进来.不为空直接显示mainFragment = new MainFragment();transaction.add(R.id.main_container,mainFragment);}else {transaction.show(mainFragment);}}else if(resId==R.id.tv_dynamic){//动态if(dynamicFragment==null){dynamicFragment = new DynamicFragment();transaction.add(R.id.main_container,dynamicFragment);}else {transaction.show(dynamicFragment);}}else if(resId==R.id.tv_message){//消息中心if(messageFragment==null){messageFragment = new MessageFragment();transaction.add(R.id.main_container,messageFragment);}else {transaction.show(messageFragment);}}else if(resId==R.id.tv_person){//我if(personFragment==null){personFragment = new PersonFragment();transaction.add(R.id.main_container,personFragment);}else {transaction.show(personFragment);}}transaction.commit();//一定要记得提交事务}/** * 显示之前隐藏所有fragment * @param transaction */private void hideFragments(FragmentTransaction transaction){if (mainFragment != null)//不为空才隐藏,如果不判断第一次会有空指针异常transaction.hide(mainFragment);if (dynamicFragment != null)transaction.hide(dynamicFragment);if (messageFragment != null)transaction.hide(messageFragment);if (personFragment != null)transaction.hide(personFragment);}/** * 改变TextView选中颜色 * @param resId */private void changeSelect(int resId) {tvMain.setSelected(false);tvDynamic.setSelected(false);tvMessage.setSelected(false);tvPerson.setSelected(false);switch (resId) {case R.id.tv_main:tvMain.setSelected(true);break;case R.id.tv_dynamic:tvDynamic.setSelected(true);break;case R.id.tv_message:tvMessage.setSelected(true);break;case R.id.tv_person:tvPerson.setSelected(true);break;}}}


MainFragment.java  首页有三个页面(关注,推荐,动态),我用到了ViewPager滑动,增加了滑动指示状态.并且给标题栏的三个TextView设置了点击效果.

/** * 首页 * @author Ansen * @create time 2015-09-08 */public class MainFragment extends Fragment {private ViewPager vPager;private List<Fragment> list = new ArrayList<Fragment>();private MessageGroupFragmentAdapter adapter;private ImageView ivShapeCircle;private TextView tvFollow,tvRecommend,tvLocation;    private int offset=0;//偏移量216  我这边只是举例说明,不同手机值不一样    private int currentIndex=1;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View rootView = inflater.inflate(R.layout.fragment_main, null);/** * 初始化三个Fragment  并且填充到ViewPager */vPager = (ViewPager) rootView.findViewById(R.id.viewpager_home);DynamicFragment dynamicFragment = new DynamicFragment();MessageFragment messageFragment = new MessageFragment();PersonFragment personFragment = new PersonFragment();list.add(dynamicFragment);list.add(messageFragment);list.add(personFragment);adapter = new MessageGroupFragmentAdapter(getActivity().getSupportFragmentManager(), list);vPager.setAdapter(adapter);vPager.setOffscreenPageLimit(2);vPager.setCurrentItem(1);vPager.setOnPageChangeListener(pageChangeListener);ivShapeCircle = (ImageView) rootView.findViewById(R.id.iv_shape_circle);tvFollow=(TextView) rootView.findViewById(R.id.tv_follow);tvRecommend=(TextView) rootView.findViewById(R.id.tv_recommend);tvRecommend.setSelected(true);//推荐默认选中tvLocation=(TextView) rootView.findViewById(R.id.tv_location);/** * 标题栏三个按钮设置点击效果 */tvFollow.setOnClickListener(clickListener);tvRecommend.setOnClickListener(clickListener);tvLocation.setOnClickListener(clickListener);initCursorPosition();return rootView;}private OnClickListener clickListener=new OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.tv_follow://当我们设置setCurrentItem的时候就会触发viewpager的OnPageChangeListener借口,//所以我们不需要去改变标题栏字体啥的vPager.setCurrentItem(0);break;case R.id.tv_recommend:vPager.setCurrentItem(1);break;case R.id.tv_location:vPager.setCurrentItem(2);break;}}};private void initCursorPosition() {DisplayMetrics metric = new DisplayMetrics();getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric);int width = metric.widthPixels;Matrix matrix = new Matrix();//标题栏我用weight设置权重  分成5份//(width / 5) * 2  这里表示标题栏两个控件的宽度//(width / 10)  标题栏一个控件的2分之一//7  约等于原点宽度的一半matrix.postTranslate((width / 5) * 2 + (width / 10)-7,0);//图片平移ivShapeCircle.setImageMatrix(matrix);//一个控件的宽度  我的手机宽度是1080/5=216 不同的手机宽度会不一样哦offset=(width / 5);}/** * ViewPager滑动监听,用位移动画实现指示器效果 *  * TranslateAnimation 强调一个地方,无论你移动了多少次,现在停留在哪里,你的起始位置从未变化过. * 例如:我这个demo里面  推荐移动到了同城,指示器也停留到了同城下面,但是指示器在屏幕上的位置还是推荐下面. */private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {@Overridepublic void onPageSelected(int index) {changeTextColor(index);translateAnimation(index);}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {}};/** * 改变标题栏字体颜色 * @param index */private void changeTextColor(int index){tvFollow.setSelected(false);tvRecommend.setSelected(false);tvLocation.setSelected(false);switch (index) {case 0:tvFollow.setSelected(true);break;case 1:tvRecommend.setSelected(true);break;case 2:tvLocation.setSelected(true);break;}}/** * 移动标题栏点点点... * @param index */private void translateAnimation(int index){TranslateAnimation animation = null;switch(index){case 0:if(currentIndex==1){//从推荐移动到关注   X坐标向左移动216animation=new TranslateAnimation(0,-offset,0,0);}else if (currentIndex == 2) {//从同城移动到关注   X坐标向左移动216*2  记住起始x坐标是同城那里                animation = new TranslateAnimation(offset, -offset, 0, 0);              }break;case 1:            if(currentIndex==0){//从关注移动到推荐   X坐标向右移动216            animation=new TranslateAnimation(-offset,0,0,0);}else if(currentIndex==2){//从同城移动到推荐   X坐标向左移动216animation=new TranslateAnimation(offset, 0,0,0);}break;case 2:if (currentIndex == 0) {//从关注移动到同城   X坐标向右移动216*2  记住起始x坐标是关注那里                animation = new TranslateAnimation(-offset, offset, 0, 0);            } else if(currentIndex==1){//从推荐移动到同城   X坐标向右移动216animation=new TranslateAnimation(0,offset,0,0);}break;}animation.setFillAfter(true);animation.setDuration(300);ivShapeCircle.startAnimation(animation);currentIndex=index;}}

首页显示的MainFragment.java的布局文件  fragment_main.xml 

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <LinearLayout        android:id="@+id/ll_title"        android:layout_width="match_parent"        android:layout_height="44dp"        android:background="#00ceaa"        android:orientation="vertical" >        <LinearLayout            android:layout_width="match_parent"            android:layout_height="30dp"            android:orientation="horizontal" >            <View                android:id="@+id/view_empty"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1" />            <TextView                android:id="@+id/tv_follow"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:paddingTop="5dp"                android:text="关注"                android:gravity="center_horizontal"                android:textColor="@drawable/main_title_txt_sel"                android:textSize="20sp" />            <TextView                android:id="@+id/tv_recommend"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:paddingTop="5dp"                android:text="推荐"                android:gravity="center_horizontal"                android:textColor="@drawable/main_title_txt_sel"                android:textSize="20sp" />            <TextView                android:id="@+id/tv_location"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:paddingTop="5dp"                android:text="同城"                android:gravity="center_horizontal"                android:textColor="@drawable/main_title_txt_sel"                android:textSize="20sp" />            <View                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1" />        </LinearLayout>        <ImageView            android:id="@+id/iv_shape_circle"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:layout_marginTop="2dp"            android:scaleType="matrix"            android:src="@drawable/shape_circle" />    </LinearLayout>    <android.support.v4.view.ViewPager        android:id="@+id/viewpager_home"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_below="@+id/ll_title" /></RelativeLayout>

MessageGroupFragmentAdapter.java    ViewPager的适配器.

public class MessageGroupFragmentAdapter extends FragmentStatePagerAdapter {private List<Fragment>list;public MessageGroupFragmentAdapter(FragmentManager fm, List<Fragment> list) {super(fm);this.list = list;}public MessageGroupFragmentAdapter(FragmentManager fm) {super(fm);}@Overridepublic Fragment getItem(int arg0) {return list.get(arg0);}@Overridepublic int getCount() {return list.size();}}

这个demo的核心代码就在这里了,其他几个Fragment的代码跟布局文件我就不贴出来了....有需要的可以去下载我的源码.....又到了10点半了....回家.....


点击下载源码


相关文章:EventBus实现activity跟fragment交互数据


后记:如果你运行之后首页会出现空白的情况,viewpager滑动也会出现问题了,那是MainFragment类初始化viewpager的adpater有问题.

修改后代码如下,大概在MainFragment中125行:

adapter = new MessageGroupFragmentAdapter(getChildFragmentManager(), list);


推荐一个Android开发者公众号,每周都有原创干货



1 0
原创粉丝点击