zoukankan      html  css  js  c++  java
  • TextView+Fragment实现底部导航栏

    前言:项目第二版刚上线没多久,产品又对需求进行了大改动,以前用的是左滑菜单,现在又要换成底部导航栏,于是今天又苦逼加班了.花了几个小时实现了一个底部导航栏的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 {
    	//要切换显示的四个Fragment
    	private 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
    
    	@Override
    	protected 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() {
    		@Override
    		public 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() {
    		@Override
    		public 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);//隐藏所有fragment
    		if(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;
    
    	@Override
    	public 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() {
    		@Override
    		public 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() {
    		@Override
    		public void onPageSelected(int index) {
    			changeTextColor(index);
    			translateAnimation(index);
    		}
    
    		@Override
    		public void onPageScrolled(int arg0, float arg1, int arg2) {
    		}
    
    		@Override
    		public 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坐标向左移动216
    				animation=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坐标向左移动216
    				animation=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坐标向右移动216
    				animation=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);
    	}
    
    	@Override
    	public Fragment getItem(int arg0) {
    		return list.get(arg0);
    	}
    
    	@Override
    	public int getCount() {
    		return list.size();
    	}
    }

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


    点击下载源码


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


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

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

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



  • 相关阅读:
    使用uploadify上传图片时返回“Cannot read property 'queueData' of undefined”
    用户在网站注册,网站通过微信发送验证码,这个操作是怎么实现的?
    Javascript Array和String的互转换。
    JS判断一个数组中是否有重复值的三种方法
    监控聚币网行情 并实时发送到微信
    聚币网API使用教程 demo
    sourceTree安装与使用
    SourceTree 的初次使用的两个小问题
    解决oracle语句中 含数字的字符串按数字排序问题
    使用git pull文件时和本地文件冲突怎么办
  • 原文地址:https://www.cnblogs.com/yishaochu/p/5078600.html
Copyright © 2011-2022 走看看