当前项目使用的是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. mysql主从集群定时备份脚本

    #!/bin/bash   dpath="/mysql_backup" mydays="7" username="root" mysql_p ...

  2. 【转载】GDB反向调试(Reverse Debugging)

    记得刚开始学C语言的时候,用vc的F10来调试程序,经常就是一阵狂按,然后一不小心按过了.结果又得从头再来,那时候我就问我的老师,能不能倒退回去几步.我的老师很遗憾地和我说,不行,开弓没有回头箭.这句 ...

  3. webuploader上传插件

    一:官网 http://fex.baidu.com/webuploader/ 二:示例

  4. js自运行函数

    学习闭包的基础知识: 函数声明 function fn(){ //这里是代码 }; fn(); //运行fn函数 与上面等价 var fn = function(){ //这里是代码 } fn(); ...

  5. php 字母大小写转换的函数

    分享下,在php编程中,将字母大小写进行转换的常用函数. 1.将字符串转换成小写strtolower(): 该函数将传入的字符串参数所有的字符都转换成小写,并以小定形式放回这个字符串 2.将字符转成大 ...

  6. Security log is full,only administrator can log on to fix the problem(安全日志满了)

    When you login the system and see this error  “Security log on this system is full,only administrato ...

  7. The 50 Most Essential Pieces of Classical Music

    1. Die Zauberflöte ("The Magic Flute"), K. 620: Overture London Philharmonic Orchestra 7:2 ...

  8. 使用公钥登录SSL

    在本地生成密钥对 ssh-keygen -t rsa 如果不想设置密码,可以直接点击回车. 如果你想使用DSA可以用-t DSA替换. 确保远程计算机上用户目录下有.ssh目录 确保你的连接服务器上的 ...

  9. android studio如何开启与禁用版本控制vcs

    1.开启

  10. 简单加密算法在C#中的实现

    加密是指通过某种特殊的方法,更改已有信息的内容,是的未授权的用户即使得到了加密的信息,如果没有正确的解密算法,那么也无法得到信息的内容. 方法一: //须添加对System.Web的引用 using ...