最近一直在纠结用何种方式来实现Tab布局呢,先前有TabActivity和ActivityGroup。前者目前已经被Google官方废弃。估计现在已经没有人用了。现在大多是通过Fragment和FragmentActivity进行实现的。有的是通过ViewPage进行实现的。总之实现方法很多。我也很纠结到底使用哪种方法去实现这个布局呢!今天就好好整理一下我认为很容易的实现这种布局的方法。这里我是使用RadioGroup和RadioButton进行实现的。以后就决定用这种方式进行实现了。其实这种方式实现起来非常的简单。可以说让你很快的实现tab布局。
- 首先我们先定义一个TabActivity的基类它是我们实现tab的基类。
public class BaseTabActivity extends Activity {
protected FragmentManager fragmentManager=getFragmentManager();
private static final String TAG = "BaseTabActivity";
/**
* 一个初始化View的方法,用于显示布局的同时替换掉当前的布局
* @param fragment 采用多态的方式传递一个fragment,要求这个对象必须继承自Fragment
* @param layoutId 你要替换布局的id
* @param TAG 标记,表示你所在fragment的标签,是为以后找到这个标签用的
*/
public void initView(Fragment fragment, int layoutId, String TAG) {
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(layoutId, fragment, TAG);
transaction.commit();
}
}
关于这部分的说明注释已经很清楚了。这里强调一点的是这里我们采用多态的方式进行实现的。这里我们传递过来的是Fragment对象,就是接下来我们要用的BaseFragment这个基类。然后我们用作为布局的Fragment继承这个基类就可以了。下面我们就来看看这个基类。
/**
* 一个抽象的Fragment所有的Fragment继承这个基类
* Created by wanggp on 2015/12/15.
*/
public abstract class BaseFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(initView(), null);
return view;
}
/**
* 一个抽象方法,子类必须实现这个方法然后将布局塞进来
* @return
*/
public abstract int initView();
}
我们这里定义一个抽象类让他继承Fragment,然后定义一个抽象方法initView()这个方法的意义是让所有它的子类去实现这个方法,然后返回一个布局。由此我们可以定义如下的一个fragment,FirstFragment
public class FirstFragment extends BaseFragment {
private FlatButton flatButton;
@Override
public int initView() {
return R.layout.titleview;//我就是要返回的布局
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(initView(), null);
flatButton = (FlatButton) view.findViewById(R.id.warning_button);
flatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "我是TabMain的提醒呀!", Toast.LENGTH_LONG).show();//注意这里我们用getActivity来获取上下文
}
});
return view;
}
}
下面我们看看我们的主MyTabMain是如何实现的:
public class MyTabMain extends BaseTabActivity {
private RadioGroup radioGroup;
private static final String TAG = "MyTabMain";
private RadioButton weibo, me, comment, my;
private int index = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabmain);
radioGroup= (RadioGroup) findViewById(R.id.tab_main);
weibo = (RadioButton) findViewById(R.id.weibo);
me = (RadioButton) findViewById(R.id.me);
my = (RadioButton) findViewById(R.id.my);
comment = (RadioButton) findViewById(R.id.comment);
initView(new FirstFragment(),R.id.content,TAG);//让默认显示我自己定义好的布局
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if(weibo.getId()==checkedId){
index=1;
}else if(me.getId()==checkedId){
index=2;
}else if(comment.getId()==checkedId){
index=3;
}else if(my.getId()==checkedId){
index=4;
}
Fragment fragment = TabFragmentFactory.getInstanceByIndex(index);
initView(fragment, R.id.content, TAG);
}
});
}
}
这里我们需要强调的一点是在onCheckedChanged方法中checkedId其实是一个很大的随机数我们并不能通过它来作为我们的索引的。我们需要通过我们定义的布局主键的getId()方法来和checkedId进行比较然后我们返回一个索引值,然后我们再定义一个TabFragmentFactory这个工厂类来管理这些Fragment这里我们定义如下一个工厂类。
```
public class TabFragmentFactory {
public static Fragment getInstanceByIndex(int index) {
Fragment fragment = null;
switch (index) {
case 1:
fragment = new FirstFragment();
break;
case 2:
fragment = new SecondFragment();
break;
case 3:
fragment = new ThreeFragment();
break;
case 4:
fragment = new FourFragment();
break;
default:
fragment = new FirstFragment();
}
return fragment;
}
}
这里我们定义一个Fragment的工厂类用通过索引来返回一个Fragment对象然后我们进行布局的修改。这样我就完成了Tab页面的且换了。下面我的主界面布局如下tabmain.xml:
<?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:orientation="vertical">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<RadioGroup
android:id="@+id/tab_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#fffaf4ff"
android:gravity="center"
android:orientation="horizontal">
<RadioButton
android:id="@+id/weibo"
style="@style/main_tab"
android:checked="true"
android:drawableTop="@drawable/weibolist_attention_selector"
android:text="微博" />
<RadioButton
android:id="@+id/me"
style="@style/main_tab"
android:drawableTop="@drawable/weibolist_atme_selector"
android:text="\@我" />
<RadioButton
android:id="@+id/comment"
style="@style/main_tab"
android:drawableTop="@drawable/weibolist_comment_selector"
android:text="评论" />
<RadioButton
android:id="@+id/my"
style="@style/main_tab"
android:drawableTop="@drawable/weibolist_mylist_selector"
android:text="我的" />
</RadioGroup>
</LinearLayout>
这样我们就完成了Tab页面的布局是不是很简单呀!况且这个扩展性也很强只要我们以后定义的类继承这个类就可以同时定义几个Fragment就完成了。ps上面布局中涉及到drawable文件去管理图片文字的按下特效。关于这部分的布局知识我以后会详细的阐述一下,今天先不在此介绍。是不是很简单呀,以后就可以将精力放在其他的业务逻辑上不用在纠结这个布局了。还有我发现采用其他方式的布局是是定义ImageView和TextView来实现的。这里我们只用RadioButton这一个控件就可以了。不用再定义两个控件了。是不是很方便呀!