本文参考自点击这里,对其进行了重构,写下思路,供自己以后思考。
layout_tab_item.xml,每个item由一个ImageView和一个TextView组成
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<ImageView
android:id="@+id/tabImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/tabText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tabImg"
android:layout_centerHorizontal="true"
android:text="@string/app_name"
android:textColor="@android:color/white"
android:textSize="16sp" />
RelativeLayout>
RelativeLayout>
layout_bottom.xml,底部导航栏由5个item组成
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="70dp"
android:orientation="horizontal">
<include
android:id="@+id/homeLayout"
layout="@layout/layout_tab_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
android:id="@+id/chosenLayout"
layout="@layout/layout_tab_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
android:id="@+id/searchLayout"
layout="@layout/layout_tab_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
android:id="@+id/localLayout"
layout="@layout/layout_tab_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
android:id="@+id/settingLayout"
layout="@layout/layout_tab_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
LinearLayout>
这里用的是bufferKnife注解功能,不懂的请移步谷歌。主要需要注意的就是需要设置很多id的BackgroundResource和TextColor,这里我把需要重复设置的地方进行了重构,知道这点就很容易看懂了。下面多了一处回调接口,主要用于实现点击item时viewpager滑动,即fragment滑动
/**
* 底部自定义view
* Created by yyg on 2016/4/22.
*/
public class MyBottomLayout extends LinearLayout implements View.OnClickListener{
private Context context;
private RelativeLayout homeLayout;
private RelativeLayout chosenLayout;
private RelativeLayout searchLayout;
private RelativeLayout localLayout;
private RelativeLayout settingLayout;
private ICallbackListener iCallbackListener = null;
public MyBottomLayout(Context context) {
super(context);
this.context = context;
initView();
}
public MyBottomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}
public MyBottomLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initView();
}
/**
* 初始化
*/
private void initView(){
View view = LayoutInflater.from(context).inflate(R.layout.layout_bottom, this);
findView(view);
initData();
initListener();
}
/**
* 初始化数据
*/
private void initData() {
setResidAndColor(0);
}
/**
* 把所有的数据整合一起进行抽取
*/
private void changeDataItem(int[] resid, int[] color) {
initDataItem(homeLayout, resid[0], "首页", color[0]);
initDataItem(chosenLayout, resid[1], "精选", color[1]);
initDataItem(searchLayout, resid[2], "搜索", color[2]);
initDataItem(localLayout, resid[3], "本地", color[3]);
initDataItem(settingLayout, resid[4], "设置", color[4]);
}
/**
* 初始化数据的抽取方法
* @param resid
* @param name
* @param color
*/
private void initDataItem(View view, int resid, String name, int color) {
view.findViewById(R.id.tabImg).setBackgroundResource(resid);
TextView tv = (TextView) view.findViewById(R.id.tabText);
tv.setText(name);
tv.setTextColor( (color == 1) ? Color.BLUE : Color.WHITE);
}
/**
* 找到控件的方法
*
* @param view
*/
private void findView(View view) {
homeLayout = (RelativeLayout) view.findViewById(R.id.homeLayout);
chosenLayout = (RelativeLayout) view.findViewById(R.id.chosenLayout);
searchLayout = (RelativeLayout) view.findViewById(R.id.searchLayout);
localLayout = (RelativeLayout) view.findViewById(R.id.localLayout);
settingLayout = (RelativeLayout) view.findViewById(R.id.settingLayout);
}
/**
* 控件的监听事件
*/
private void initListener() {
homeLayout.setOnClickListener(this);
chosenLayout.setOnClickListener(this);
searchLayout.setOnClickListener(this);
localLayout.setOnClickListener(this);
settingLayout.setOnClickListener(this);
}
/**
* 控件的点击事件
* 点击后改变显示的图标和文字的颜色
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.homeLayout:
setResidAndColor(0);
break;
case R.id.chosenLayout:
setResidAndColor(1);
break;
case R.id.searchLayout:
setResidAndColor(2);
break;
case R.id.localLayout:
setResidAndColor(3);
break;
case R.id.settingLayout:
setResidAndColor(4);
break;
}
//这里加入了一个接口方法,留给ViewPager去实现
//功能是点击item后viewPager也会跟着变
iCallbackListener.click(v.getId());
}
/**
* 设置Res和Color
* @param i
*/
public void setResidAndColor(int i) {
switch (i) {
case 0:
changeDataItem(setResid(new int[] {1, 0, 0, 0, 0}),
new int[] {1, 0, 0, 0, 0});
break;
case 1:
changeDataItem(setResid(new int[] {0, 1, 0, 0, 0}),
new int[] {0, 1, 0, 0, 0});
break;
case 2:
changeDataItem(setResid(new int[] {0, 0, 1, 0, 0}),
new int[] {0, 0, 1, 0, 0});
break;
case 3:
changeDataItem(setResid(new int[] {0, 0, 0, 1, 0}),
new int[] {0, 0, 0, 1, 0});
break;
case 4:
changeDataItem(setResid(new int[] {0, 0, 0, 0, 1}) ,
new int[] {0, 0, 0, 0, 1});
break;
}
}
/**
* 统一设置Res的地方,留有参数和返回值
* @param resid 数组,1表示选中,0表示未选中,导航页5个item都要进行判断
* @return 返回当前设置的Res,作为changeDataItem的参数
*/
public int[] setResid(int[] resid) {
int resHome = (resid[0] == 1) ? R.mipmap.image_tabbar_button_home_down : R.mipmap.image_tabbar_button_home;
int resChosen = (resid[1] == 1) ? R.mipmap.image_tabbar_button_chosen_down : R.mipmap.image_tabbar_button_chosen;
int resSearch = (resid[2] == 1) ? R.mipmap.image_tabbar_button_search_down : R.mipmap.image_tabbar_button_search;
int resLocal = (resid[3] == 1) ? R.mipmap.image_tabbar_button_local_down : R.mipmap.image_tabbar_button_local;
int resSetting = (resid[4] == 1) ? R.mipmap.image_tabbar_button_setting_down : R.mipmap.image_tabbar_button_setting;
return new int[] {resHome, resChosen, resSearch, resLocal, resSetting};
}
//初始化接口,由需要实现activity(MainActivity)调用
//通过findviewbyid获取MyBottomLayout,进行调用
public void setOnCallbackListener(ICallbackListener iCallbackListener) {
this.iCallbackListener = iCallbackListener;
}
//自定义接口文件,click方法由调用处实现,功能是完成viewpager的滑动
public interface ICallbackListener {
public void click(int id);
}
}
此处以home_fragment.xml和HomeFragment为例
home_fragment.xml
----------------------------------
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
"true"
android:text="首页"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
HomeFragment
----------------------------------
/**
* 主页
* Created by yyg on 2016/4/22.
*/
public class HomeFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.home_fragment, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}
记得ViewPager和刚刚自定义的MyBottomLayout都要导入类全名
<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"
tools:context=".activity.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/myViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/myBottomLayout" />
<com.buaa.yyg.baidupager.view.MyBottomLayout
android:id="@+id/myBottomLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@mipmap/image_titlebar_background" />
RelativeLayout>
这一步可以省略,不过为了代码的可复用性建议加上,方便功能的添加
/**
* Created by yyg on 2016/4/22.
*/
public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
initData();
initListener();
}
@Override
public void onClick(View v) {
progress();
}
public abstract void initView();
public abstract void initData();
public abstract void initListener();
public abstract void progress();
}
需要注意的是使用了butterknife,其他初始化数据方法都需要在其之后执行。
实现了前面的回调监听接口,通过ViewPager方法改变当前的item值,实现自定义view时点击导航item改变页面的功能。
ViewPager使用addOnPageChangeListener进行页面的滑动监听,实现功能滑动时导航item跟着变化。
public class MainActivity extends BaseActivity {
@Bind(R.id.myViewPager)
ViewPager myViewPager;
@Bind(R.id.myBottomLayout)
MyBottomLayout myBottomLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
//super必须在最后,这样先setContentView然后super到
//BaseActivity的onCreate,之后才会调用initData等方法
//不这样会报空指针异常
super.onCreate(savedInstanceState);
}
@Override
public void initView() {
}
@Override
public void initData() {
myViewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager()));
}
@Override
public void initListener() {
//设值注入,初始化MyBottomLayout页面的回调实例
myBottomLayout.setOnCallbackListener(new MyCallBackListener());
//ViewPager页面监听 使用add而不是set
myViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
//0是静止,1是正在滑动,2是停止滑动
if (state == 2) {
//设置滑动ViewPager导航同步变化
myBottomLayout.setResidAndColor(myViewPager.getCurrentItem());
}
}
});
}
/**
* 实现回调监听方法,用于改变当前item值
* 在FragmentPagerAdapter的getItem方法中切换Fragment
*/
private class MyCallBackListener implements MyBottomLayout.ICallbackListener {
@Override
public void click(int id) {
switch (id) {
case R.id.homeLayout:
myViewPager.setCurrentItem(0);
break;
case R.id.chosenLayout:
myViewPager.setCurrentItem(1);
break;
case R.id.searchLayout:
myViewPager.setCurrentItem(2);
break;
case R.id.localLayout:
myViewPager.setCurrentItem(3);
break;
case R.id.settingLayout:
myViewPager.setCurrentItem(4);
break;
}
}
}
/**
* viewPager的adapter,改变当前fragment
*/
private class MyFragmentAdapter extends FragmentPagerAdapter {
public MyFragmentAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new HomeFragment();
case 1:
return new ChosenFragment();
case 2:
return new SearchFragment();
case 3:
return new LocalFragment();
case 4:
return new SettingFragment();
}
return null;
}
@Override
public int getCount() {
//一共5个页面
return 5;
}
}
@Override
public void progress() {
}
}
Demo下载地址 使用ViewPager和Fragment实现底部导航滑动重构版