采用 FragmentTabHost嵌套FragmentTabHost和FragmentTabHost+PagerSlidingTabStrip 与ViewPager的方式实现了子Tab导航菜单栏的效果,虽是好用,但有时候却不灵活。
本篇中将要实现自定义Tab导航菜单栏效果。
如果你对FragmentTabHost和Fragment还不熟悉,一定要先看前面的博文。
仍然先看看效果图
重写fragment_message1.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:background="#F5F7FA"
android:orientation="vertical" >
<include layout="@layout/top_sub_tab" />
<FrameLayout
android:id="@+id/id_content"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</FrameLayout>
</LinearLayout>
顶部的Tab导航为自定义top_sub_tab.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="40dp"
android:background="#eee"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="37dp"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/lin_sub1"
android:layout_width="3dp"
android:orientation="horizontal"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新闻"
android:textColor="#008000" />
</LinearLayout>
<LinearLayout
android:id="@+id/lin_sub2"
android:layout_width="3dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:text="财经" />
</LinearLayout>
<LinearLayout
android:id="@+id/lin_sub3"
android:layout_width="3dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:text="旅游" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/imv_tabline"
android:layout_width="100dp"
android:layout_height="3dp"
android:background="#FF8D42" />
</LinearLayout>
重写 FragmentMessage
public class FragmentMessage extends Fragment implements OnClickListener {
private static String TAG = FragmentMessage.class.getName();
private LinearLayout lin_sub1, lin_sub2, lin_sub3;
private Fragment subFragment1;
private Fragment subFragment2;
private Fragment subFragment3;
private ImageView mTabline;
private int mScreen1_3;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
if (null != bundle) {
//
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
T.showShort(getActivity(), "FragmentMessage==onCreateView");
View view = inflater.inflate(R.layout.fragment_message1, null);
initView(view);
setLinstener();
initData();
return view;
}
private void initView(View view) {
lin_sub1 = (LinearLayout) view.findViewById(R.id.lin_sub1);
lin_sub2 = (LinearLayout) view.findViewById(R.id.lin_sub2);
lin_sub3 = (LinearLayout) view.findViewById(R.id.lin_sub3);
mTabline = (ImageView) view.findViewById(R.id.imv_tabline);
}
protected void initData() {
// Display display = getWindow().getWindowManager().getDefaultDisplay();
Display display = getActivity().getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
mScreen1_3 = outMetrics.widthPixels / 3;
LayoutParams lp = (LayoutParams) mTabline.getLayoutParams();
lp.width = mScreen1_3;
mTabline.setLayoutParams(lp);
//初次显示设置
setSubFragment(0);
setmTabline(0);
}
protected void setLinstener() {
lin_sub1.setOnClickListener(this);
lin_sub2.setOnClickListener(this);
lin_sub3.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.lin_sub1:
setSubFragment(0);
setmTabline(0);
break;
case R.id.lin_sub2:
setSubFragment(1);
setmTabline(1);
break;
case R.id.lin_sub3:
setSubFragment(2);
setmTabline(2);
break;
default:
break;
}
}
public void setmTabline(int i) {
LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabline
.getLayoutParams();
lp.leftMargin = i * mScreen1_3;
mTabline.setLayoutParams(lp);
}
public void setSubFragment(int i){
FragmentTransaction transaction =getFragmentManager().beginTransaction();
if(0 == i ){
subFragment1 = (subFragment1 == null ? new SubFragment1():subFragment1);
transaction.replace(R.id.id_content,subFragment1);
// transaction.addToBackStack(null);
transaction.commit();
}else if(1 == i ){
subFragment2 = (subFragment2 == null ? new SubFragment2():subFragment2);
transaction.replace(R.id.id_content,subFragment2);
// transaction.addToBackStack(null);
transaction.commit();
}else if(2 == i ){
subFragment3 = (subFragment3 == null ? new SubFragment3():subFragment3);
transaction.replace(R.id.id_content,subFragment3);
// transaction.addToBackStack(null);
transaction.commit();
}
}
}
再添加 SubFragment1(这里只给出一个,其它类似)
public class SubFragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
T.showShort(getActivity(), "SubFragment1==onCreateView");
TextView tv = new TextView(getActivity());
tv.setTextSize(25);
tv.setBackgroundColor(Color.parseColor("#FFA07A"));
tv.setText("新闻");
tv.setGravity(Gravity.CENTER);
return tv;
}
}
好了,代码就这么简单……你会发现每次切换二级Tab导航菜单栏的时候,子Fragment会重新绘制,只需再稍微改造一下就OK了
/*
* 显示subFragment,subFragment不会重复onCreateView
*/
public void showSubFragment(int i) {
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
hideSubFragment(transaction);
if (0 == i) {
subFragment1 = (subFragment1 == null ? new SubFragment1()
: subFragment1);
if(!subFragment1.isAdded()){
transaction.add(R.id.id_content, subFragment1);
}
// transaction.addToBackStack(null);
transaction.show(subFragment1);
transaction.commit();
} else if (1 == i) {
subFragment2 = (subFragment2 == null ? new SubFragment2()
: subFragment2);
if(!subFragment2.isAdded()){
transaction.add(R.id.id_content, subFragment2);
}
// transaction.addToBackStack(null);
transaction.show(subFragment2);
transaction.commit();
} else if (2 == i) {
subFragment3 = (subFragment3 == null ? new SubFragment3()
: subFragment3);
if(!subFragment3.isAdded()){
transaction.add(R.id.id_content, subFragment3);
}
// transaction.addToBackStack(null);
transaction.show(subFragment3);
transaction.commit();
}
}
public void hideSubFragment(FragmentTransaction transaction) {
if (subFragment1 != null) {
transaction.hide(subFragment1);
}
if (subFragment2 != null) {
transaction.hide(subFragment2);
}
if (subFragment3 != null) {
transaction.hide(subFragment3);
}
}
几点注意的地方:
1 在transaction.add()方法时候,先判断subFragment1.isAdded(),避免该异常:java.lang.IllegalStateException: Fragment already added:
2 FragmentTransaction事务 只能执行一次commit()操作,所以定义成局部变量。
3 transaction.replace()时有一个移除操作和一个添加操作,即先remove()再add(),remove()的时候Fragment实例已经被销毁,所以在方式一种每次切换子Tab导航菜单栏,subFragment都会执行OncreateView();
4 hide()和show()方法,看字面意义就理解了。hide()只是隐藏,不会销毁,而show()就是把隐藏的显示出来。
关于Android Tab导航菜单栏--FragmentTabHost+Fragment的博客就到这里了。小生不权威,肯定有很多疏漏和出错的地方,想好好玩Android,看谷歌官方文档和Android源码才是王道。
小生这里只是写的一些超级基础的Demo,仅仅是提供思路,在实际项目开发中的情况复杂的多。
但愿小生所做的事对别人有所帮助,就算莫大的荣幸了。