当前项目使用的是TabHost+Activity进行分页,目前要做个报表功能,需要在一个Tab页内进行Activity的切换。比方说我有4 个Tab页分别为Tab1,Tab2,Tab3,Tab4,现在的需求是需要将Tab1内的Activity动态切换。找了很多资料最终使用了 ActivityGroup解决了问题,在这过程中顺便尝试了一下使用Fragment+FragmentActivity+TabHost和 Fragment+FragmentActivity+ActionBar试图淘汰掉旧版的ActivityGroup和TabHost,但是发现如果要 使用Fragment,我需要修改已有的各个Tab页内的Activity,工作量较大,而使用ActionBar还有着许多版本兼容性问题,并且 ActionBar不支持多层嵌套,最终放弃。现在写一下我个人实验用的TabHost+ActivityGroup、 Fragment+FragmentActivity+TabHost和Fragment+FragmentActivity+ActionBar的 Demo,供参考。

首先是TabHost+ActivityGroup。在最初的想法中,我是使用通过清空TabHost现有内容,再添加新内容来实现动态加载Tab页效 果,具体代码不说了,举个例子:我有4个Tab页分别为Tab1、Tab2、Tab3和Tab4,存放4个Activity分别为 Tab1Activity、Tab2Activity、Tab3Activity和Tab4Activity,现在我需要将Tab1位置的 Tab1Activity变成Tab5Activity,我的做法是先全部清空,然后重新添加Tab1、Tab2、Tab3和Tab4,在添加的时候,将 Tab1指向的Activity变成Tab5Activity。这种方法无疑是非常蠢得,而且在这一切换之后,会发现Ta5Activity的生命周期出 现异常,每次在Tab1和其他Tab之间切换时,Ta5Activity都会被destroy掉重新create。这个问题我至今没找到原因。

然后找到了ActivityGroup。ActivityGroup也是继承至Activity类,可以看成是一个Actvity的容器类。 以上面的例子为例,当我们把ActivityGroup放入Tab1内时,我们就可以通过管理ActivityGroup来达到动态切换Activity 的效果,贴上ActivityGroup的代码:

public class ActivityGroup1 extends ActivityGroup {
private ScrollView container = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
//存放Activity的容器
container = (ScrollView) findViewById(R.id.containerBody);
// 模块1
ImageView btnModule1 = (ImageView) findViewById(R.id.btnModule1);
btnModule1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//清空容器内现有内容
container.removeAllViews();
//加载activity
container.addView(getLocalActivityManager().startActivity(
"Module1",
new Intent(ActivityGroup1.this, Tab1Activity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView());
}
}); // 模块2
ImageView btnModule2 = (ImageView) findViewById(R.id.btnModule2);
btnModule2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
container.removeAllViews();
container.addView(getLocalActivityManager().startActivity(
"Module2",
new Intent(ActivityGroup1.this, Tab2Activity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView());
}
}); // 模块3
ImageView btnModule3 = (ImageView) findViewById(R.id.btnModule3);
btnModule3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
container.removeAllViews();
container.addView(getLocalActivityManager().startActivity(
"Module3",
new Intent(ActivityGroup1.this, Tab3Activity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView());
}
});
}
}

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:orientation="vertical"
android:layout_height="fill_parent">
<LinearLayout android:gravity="center_horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/cust_title" android:textColor="@android:color/white"
android:textSize="28sp" android:text="模块1" android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
</LinearLayout>
<!-- 中间动态加载View -->
<ScrollView android:measureAllChildren="true" android:id="@+id/containerBody"
android:layout_weight="" android:layout_height="fill_parent"
android:layout_width="fill_parent">
</ScrollView>
<LinearLayout android:background="@android:color/black"
android:layout_gravity="bottom" android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<!-- 功能模块按钮1 -->
<ImageView android:id="@+id/btnModule1" android:src="@android:drawable/ic_dialog_dialer"
android:layout_marginLeft="7dp" android:layout_marginTop="3dp"
android:layout_marginBottom="3dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 功能模块按钮2 -->
<ImageView android:id="@+id/btnModule2" android:src="@android:drawable/ic_dialog_info"
android:layout_marginLeft="7dp" android:layout_marginTop="3dp"
android:layout_marginBottom="3dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 功能模块按钮3 -->
<ImageView android:id="@+id/btnModule3" android:src="@android:drawable/ic_dialog_alert"
android:layout_marginLeft="7dp" android:layout_marginTop="3dp"
android:layout_marginBottom="3dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>

在TabHost中的调用方式和普通的activity一样

TabSpec tabSpec=mtabHost.newTabSpec("").setIndicator("TAB1").setContent(
new Intent(this, FragmentActivity1.class));
mtabHost.addTab(tabSpec);

这样通过点击三个按钮就能达到动态切换Activity的效果了。

顺便说下,当ActivityGroup内嵌套Activity时,Activity的生命周期跟TabHost内嵌套Activity一样。具体的百度。

较新的版本中TabHost和ActivityGroup都已经被淘汰了,取而代之的是FragmentActivity+Fragment。但我很疑 惑Fragment是否真能完全取代ActivityGroup的效果。就拿上述功能来说,我要想使用FragmentActivity替换 ActivityGroup,那么我现有的Activity就必须重写,改装成Fragment。这种情况下,我在其他地方要使用这些Activity该 怎么办呢?我没找到如何使用Fragment装载Activity的办法,所以暂时就没法用FragmentActivity替代 ActivityGroup了。贴下使用FragmentActivity+Fragment+TabHost的实现代码:

Fragment1Activity:

public class FragmentActivity1 extends FragmentActivity{
public static FragmentManager fm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_acitivity_1);
fm = getSupportFragmentManager();
// 只當容器,主要內容已Fragment呈現
initFragment(new Fragment1());
}
/**
*
*/ // 切換Fragment
public static void changeFragment(Fragment f){
changeFragment(f, false);
}
// 初始化Fragment(FragmentActivity中呼叫)
public static void initFragment(Fragment f){
changeFragment(f, true);
}
private static void changeFragment(Fragment f, boolean init){
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.simple_fragment, f);
if(!init)
ft.addToBackStack(null);
ft.commit();
}
}

这里的FragmentActivity1并不显示具体内容,只做Fragment得容器使用,具体显示内容通过调用changeFragment方法动态加载。

Fragment1和Fragment2的代码如下,点击按钮两者互相切换:

public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment1, container, false);
Button tv = (Button)v.findViewById(R.id.button2);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 直接呼叫FragmentActivity1的靜態方法來做切換
FragmentActivity1.changeFragment(new Fragment2());
}
});
return v;
}
}
public class Fragment2 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment2, container, false);
Button tv = (Button)v.findViewById(R.id.button2);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 直接呼叫FragmentActivity1的靜態方法來做切換
FragmentActivity1.changeFragment(new Fragment1());
}
});
return v;
}
}

同样,在TabHost添加中跟普通的Activity一样:

TabSpec tabSpec=mtabHost.newTabSpec("").setIndicator("TAB1").setContent(
new Intent(this, FragmentActivity1.class));
mtabHost.addTab(tabSpec);

这三者的layout都很简单,就不写了。对比ActivityGroup方法发现,其实两者实现思路是一样的,都是先用一个“容器” (ActivityGroup和FragmentActivity)占住Tab1的位置,然后每次相应时,通过改变“容器”内的元素来达到动态改变的效 果,区别就是ActivityGroup存放的是Activity,而FragmentActivity存放的是Fragment。(本人目前已经知道可 以将Fragment嵌套到Activity中,是否有方法可以将Activity嵌套到Fragment中呢?那么就可以达到两个方法的完全兼容了,而 不用像我我担心的,需要改造目前已有的Activity成Fragment来达到使用FragmentActivity替换ActivityGroup的 效果)

最后说下ActionBar+FragmentActivity+Fragment来替换掉TabHost。在使用过程中发现这个ActionBar限制有点多,于是舍弃了,贴下实现代码。

public class FragmentActivity1 extends FragmentActivity implements ActionBar.TabListener{
public static FragmentManager fm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_acitivity_1);
fm = getSupportFragmentManager();
ActionBar actionBar=this.getActionBar();
this.getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
this.getActionBar().setDisplayShowTitleEnabled(false);
this.getActionBar().setDisplayShowHomeEnabled(false);
setBar("Tab 1");
setBar("Tab 2");
setBar("Tab 3");
setBar("Tab 4");
// 只當容器,主要內容已Fragment呈現
initFragment(new Fragment1());
}
/**
*
*/
private void setBar(String s) {
Tab tab = this.getActionBar().newTab();
tab.setContentDescription(s);
tab.setText(s);
tab.setTabListener(this);
getActionBar().addTab(tab);
}
// 切換Fragment
public static void changeFragment(Fragment f){
changeFragment(f, false);
}
// 初始化Fragment(FragmentActivity中呼叫)
public static void initFragment(Fragment f){
changeFragment(f, true);
}
private static void changeFragment(Fragment f, boolean init){
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.simple_fragment, f);
if(!init)
ft.addToBackStack(null);
ft.commit();
}
@Override
public void onTabReselected(Tab arg0, android.app.FragmentTransaction arg1) {
// TODO Auto-generated method stub }
@Override
public void onTabSelected(Tab arg0, android.app.FragmentTransaction arg1) {
// TODO Auto-generated method stub
if(arg0.getText().equals("Tab 1"))
{
changeFragment(new Fragment1());
}
else {
changeFragment(new Fragment2());
}
}
@Override
public void onTabUnselected(Tab arg0, android.app.FragmentTransaction arg1) {
// TODO Auto-generated method stub }
}

在minSdkVersion设置为11后就能调用getActionBar()方法了,可以给它添加tab,然后重点是为 ActionBar.TabListener写点击Tab时要实现的功能,这里我进行了Fragment的切换,以达到TabHost相同的效果。要注意 的是如果该FragmentActivity是嵌套在其他Activity中(比方说TabHost)时,getAction将会返回null,即无法进 行分页,其他情况下也有可能返回null,限制还是比较多的。

Android 动态Tab分页效果的更多相关文章

  1. Android 动态Tab分页效果实现

    当前项目使用的是TabHost+Activity进行分页,目前要做个报表功能,需要在一个Tab页内进行Activity的切换.比方说我有4个Tab页分别为Tab1,Tab2,Tab3,Tab4,现在的 ...

  2. vue2.0使用动态组件实现tab切换效果(vue-cli)

    <template> <div> <div>#动态组件实现tab切换效果#</div><br><br><br> &l ...

  3. Android项目Tab类型主界面大总结 Fragment+TabPageIndicator+ViewPager

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24740977 Android如今实现Tab类型的界面方式越来越多,今天就把常见的 ...

  4. JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有)

    前言:最近园子里多了许多谈语言.谈环境.谈逼格(格局)的文章,看看笑笑过后,殊不知其实都是然并卵.提升自己的技术才是王道.之前博主分享过多篇bootstrap组件的文章,引起了很多园友的关注和支持,看 ...

  5. ViewPager+GridView实现首页导航栏布局分页效果

    如图是效果图用ViewPager+GridView实现首页导航栏布局分页效果来实现的效果 Demo下载地址:http://download.csdn.net/detail/qq_29774291/96 ...

  6. Android之Tab类总结

    本文主要包括以下Tab类实现方式 FragmentTabHost+Fragment实现 传统的ViewPager实现 FragmentManager+Fragment实现 ViewPager+Frag ...

  7. 【转】提示框第三方库之MBProgressHUD iOS toast效果 动态提示框效果

    原文网址:http://www.zhimengzhe.com/IOSkaifa/37910.html MBProgressHUD是一个开源项目,实现了很多种样式的提示框,使用上简单.方便,并且可以对显 ...

  8. JS组件系列——基于Bootstrap Ace模板的菜单Tab页效果优化

    前言:之前发表过一篇  JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有) ,收到很多园友的反馈,当然也包括很多诟病,因为上篇只是将功能实现了,很多细节都没有处理 ...

  9. ajax实现无刷新分页效果

    基于jquery.pagination.js实现的无刷新加载分页数据效果. 简介与说明 * 该插件为Ajax分页插件,一次性加载数据,故分页切换时无刷新与延迟.如果数据量较大,加载会比较慢. * 分页 ...

随机推荐

  1. SecureCRT for Linux突破30天使用限制

    当然还有一种方法,就是当你试用点i agree到时候,在~/.vandyke/Config 会生成一个文件SecureCRT_eval.lic,删除以后就可以恢复30天试用

  2. 3.IP转发

    1. "vim  /usr/lib/sysctl.d/00-system.conf"在#Disable netfilter on bridges.栏下面添加行:"net. ...

  3. NHibernate各种查询

    NHibernate各种查询 NHibernate's methods of querying are powerful, but there's a learning curve. Longer t ...

  4. Export功能 导致 页面显示很多非法字符,还可能页面显示两次

    private void exportBinaryToExcel(byte[] bytes, string filename) { Response.AddHeader("Content-D ...

  5. NoSQL专家王涛访谈:为什么我们还要做一个NoSQL?

    ChinaUnix:各位网友大家好,今天有幸请到王涛先生到CU做客,与大家交流一些工作经验.首先请王涛先介绍一下自己. 王涛:大家好,我是王涛.过去八年里我一直在IBM多伦多实验室从事DB2引擎研发的 ...

  6. OCP考试之052

    Oracle Database 11g:Administration I 考试时间:90分钟 考试题目:70题 考试语言:英语 考试分数:66% 考试内容: 了解Oracle数据库体系结构 解释的内存 ...

  7. 【BZOJ2428】[HAOI2006]均分数据

    Description 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第 ...

  8. how to get sharepoint lookup value

    SPFieldLookup lookUp1 = properties.ListItem.ParentList.Fields.GetField("Leave_x0020_Type") ...

  9. TCP报头

    源端口和目的端口: 各占16位 ,服务相对应的源端口和目的端口. 序列号: 占32位,它的范围在[0~2^32-1],序号随着通信的进行不断的递增,当达到最大值的时候重新回到0在开始递增.TCP是面向 ...

  10. Qt播放mp3

    .pro项目文件中加入 QT += phonon 包含头    #include <phonon/Phonon> 播放文件    Phonon::MediaObject *media = ...