ViewPager+RadioGroup+Fragment仿微信实现底部导航功能
今天做一个简单的仿微信底部导航功能,先简单说明一下组件,主体是一个FrameLayout,在这个帧布局上添加两个控件,ViewPager 和RadioGroup, 然后在ViePager中添加Fragment,实现导航功能.
先上布局代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ll_contnet"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
</android.support.v4.view.ViewPager>
<RadioGroup
android:id="@+id/radio_group"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
>
<RadioButton
android:id="@+id/rb1"
style="@style/TabButtonStyle"
android:checked="true"
android:drawableTop="@drawable/ic_launcher"
android:text="首页" />
<RadioButton
android:id="@+id/rb2"
style="@style/TabButtonStyle"
android:checked="true"
android:drawableTop="@drawable/ic_launcher"
android:text="首页" />
<RadioButton
android:id="@+id/rb3"
style="@style/TabButtonStyle"
android:checked="true"
android:drawableTop="@drawable/ic_launcher"
android:text="首页" />
<RadioButton
android:id="@+id/rb4"
style="@style/TabButtonStyle"
android:checked="true"
android:drawableTop="@drawable/ic_launcher"
android:text="首页" />
<RadioButton
android:id="@+id/rb5"
style="@style/TabButtonStyle"
android:checked="true"
android:drawableTop="@drawable/ic_launcher"
android:text="首页" />
</RadioGroup>
</LinearLayout>
上边是一个线性布局,把这个线性布局作为View添加到FrameLayout中
下边是具体实现逻辑:
public class MainActivity extends FragmentActivity {
private static final String TAG_CONTENT_FRAGMENT = "fl_content";
private FrameLayout fl_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setcontentFragment();
}
private void initView() {
fl_content = (FrameLayout) findViewById(R.id.fl_content);
}
private void setcontentFragment() {
//1.获取fragment管理者对象
FragmentManager supportFragmentManager = getSupportFragmentManager();
//2.开启一个事务,替换布局内部的内容,然后提交
supportFragmentManager.beginTransaction().replace(
R.id.fl_content,
new ContentFragment(),
TAG_CONTENT_FRAGMENT).commit();
}
}
首先MainAvtivity继承的是V4包提供的
FragmentActivity 用来解决android3.0没有Fragment的API
,
其次获取Fragment管理者,开启事务,替换布局内容,最后提交。
下边来看填充替换的内容:
首先我们来写一个基类BaseFragment继承Fragment:
public abstract class BaseFragment extends Fragment {
protected Activity activity;
private View rootview;
@Override
public void onCreate(Bundle savedInstanceState) {
activity = getActivity();
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootview = initView();
//如果要让子类的页面效果展示,必须在此处返回view对象
return rootview;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
initData();
super.onActivityCreated(savedInstanceState);
}
//初始化view的方法,因为fragment父类对子类的布局效果未知,所以此方法无法实现,于是抽象
public abstract View initView();
//给view填充数据方法,因为子类的fragment有什么控件未知,子类的fragment有什么数据也位置,所以此方法无法实现(定义抽象,空实现)
public void initData() {
//此方法专门留给子类重新
}
}
首先BaseFragment 继承V4包下的Fragment,重写了onCreate(),onCreateView(),onActivityCreated()三个方法,
oncreat()方法在Fragment中和Activity中的oncreta()一样,
oncreatview()在这个view创建之时调用,返回值是一个view,我们可以在这个方法内返回一个view对象,//initView() onActivitycreat()是在view添加到activity上时调用,我们可以在这个方法内做一些填充数据的操作 //initData
然后定义两个抽象方法,initView(),initData(),让其子类来实现这两个方法,
initView返回View填充到Fragment上
initData 设置数据
下边是填充FrameLayout的Fragment:
public class ContentFragment extends BaseFragment {
private View view;
private RadioGroup radio_group;
private ViewPager vp;
private ArrayList<BasePager> list;
@Override
public View initView() {
view = View.inflate(activity, R.layout.frame_content, null);
radio_group = (RadioGroup) view.findViewById(R.id.radio_group);
vp = (ViewPager) view.findViewById(R.id.vp);
return view;
}
@SuppressWarnings("deprecation")
@Override
public void initData() {
list = new ArrayList<BasePager>();
list.add(new FirstFragment(activity));
list.add(new SecondFragment(activity));
list.add(new ThirdFragment(activity));
list.add(new fourthlyFragment(activity));
list.add(new fifithFragment(activity));
radio_group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb1:
vp.setCurrentItem(0);
break;
case R.id.rb2:
vp.setCurrentItem(1);
break;
case R.id.rb3:
vp.setCurrentItem(2);
break;
case R.id.rb4:
vp.setCurrentItem(3);
break;
case R.id.rb5:
vp.setCurrentItem(4);
break;
}
}
});
vp.setAdapter(new PagerAdapter() {
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
/*
* 郜哥,这个地方下边写的假数据,只是作为一个demo
*
* 这个地方可以通过存储fragment的集合,取出fragment,返回fragment中的view对象,
* 但是呢,想点击一个radio_button,返回一个相对应的view,就得写一个list集合中五个fragment的父类
* 在父类中也定义一个initview()方法,返回每个继承这个父类的fragment的view对象,然后在这里如下写:
*
* container.addView(list.get(position).rootView);
* rootview就是父类中的在initview()中返回的view
*
*
* 上边的list集合里面的数据都没用到
*/
container.addView(list.get(position).rootview);
return list.get(position).rootview;
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
container.removeView((View) object);
}
});
vp.setCurrentItem(0);
radio_group.check(R.id.rb1);
vp.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// 当当前的viewpager状态改变的时候的时候,radiogroup也切换
int currentItem = vp.getCurrentItem();
System.out.println("currentItem==="+currentItem);
switch (currentItem) {
case 0:
radio_group.check(R.id.rb1);
break;
case 1:
radio_group.check(R.id.rb2);
break;
case 2:
radio_group.check(R.id.rb3);
break;
case 3:
radio_group.check(R.id.rb4);
break;
case 4:
radio_group.check(R.id.rb5);
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
}
首先我们继承先前写好的BaseFragment,实现initView().initData()
initView里找到我们写的布局,并返回view;
initData()下设置viewpager适配器,radiogroup的点击监听,viewpager的页面改变监听
这里面有两个地方需要注意:
1, 点击radiobutton 切换viewpager的页面,同时改变选中的radiobutton的文本颜色
调用viewpager的setCurrentItem(int);可以设置viewpager当前的页面
2,另一个是 ,滑动viewpager时,radiobutton的切换
在viewpager的滑动监听中 调用getCurrentItem()获取当前页面,
用switch语句,移动到哪个页面,就调用radiogroup的check(int),设置radiobutton的选择状态,同时选中的 radiobutton的文本会变色
代码实现很简单,其他类就不贴出来了。有什么其他不懂的地方可以看Demo.