最近一个项目中用到了TabActivity,遇到了不少问题,而且发现论坛中也有类似的问题,所以在这里写个TabActivity的例子,望大家多多指教。
在这里给大家介绍两种TabActivity效果,一种是用TabActivity实现,另外一种是ViewFlipper实现。
话不多说,先给个效果图,不然有人说我无图无真相了。
附近中有的都是一些小技巧很好用,
比如,图片中的菜单,是利用RadioGroup做成的,而且有选中的效果,RadioGroup做成菜单,网络上面也有不少的例子,今天我也顺便说下原理。
Radiogroup中之能有一个是选中的效果,这个刚刚好,为菜单中选中提供了方便,但是系统提供的背景和图标是很好用,所以我们要自己自定义一个,这里就用到了style和shape,详细情况大家可以看代码。
选中的效果是一个图片背景的切换,这个定义在shape的xml文件里面。
- <RadioGroup
- android:id="@+id/rg"
- android:layout_width="fill_parent"
- android:layout_height="50px"
- android:background="#f00"
- android:orientation="horizontal" >
-
- <RadioButton
- android:id="@+id/rb01"
- style="@style/menu_item"
- android:checked="true"
- android:drawableTop="@drawable/menu_home"
- android:text="主页" />
-
- <RadioButton
- android:id="@+id/rb02"
- style="@style/menu_item"
- android:drawableTop="@drawable/menu_clear"
- android:text="清除" />
-
- <RadioButton
- android:id="@+id/rb03"
- style="@style/menu_item"
- android:drawableTop="@drawable/menu_refresh"
- android:text="刷新" />
-
- <RadioButton
- android:id="@+id/rb04"
- style="@style/menu_item"
- android:drawableTop="@drawable/menu_save"
- android:text="保存" />
-
- <RadioButton
- android:id="@+id/rb05"
- style="@style/menu_item"
- android:drawableTop="@drawable/menu_more"
- android:text="更多" />
- </RadioGroup>
复制代码
- <style name="menu_item">
- <item name="android:layout_width">fill_parent</item>
- <item name="android:layout_height">fill_parent</item>
- <item name="android:button">@null</item>
- <item name="android:gravity">center_horizontal</item>
- <item name="android:background">@drawable/menu_item_bg</item>
- <item name="android:layout_weight">1</item>
- </style>
复制代码
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="false" android:state_checked="false" android:drawable="@drawable/menu_normal" />
- <item android:state_checked="true" android:drawable="@drawable/menu_press" />
- <item android:state_pressed="true" android:drawable="@drawable/menu_press" />
- </selector>
复制代码
系统在中自带TabActivity,TabHost是在顶部的,如果要改变位置的话,比如,放在底部,就可以改变xml中的位置,那么显示的位置当然也在底部了,本实例中我们不需要系统自带的Tabhost,我就把他隐藏了, android:visibility="gone" ,使用我们自己设置的菜单栏。
另外Tabhost切换的动画,也是大家关注的问题。
- public class TabMainActivity extends TabActivity {
-
- TabHost tab;
- Context context;
- RadioGroup rg;
-
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.tab_main);
-
- tab = getTabHost();
- context = this;
-
- tab.addTab(tab.newTabSpec("A").setIndicator("A").setContent(new Intent(context, AActivity.class)));
- tab.addTab(tab.newTabSpec("B").setIndicator("B").setContent(new Intent(context, BActivity.class)));
- tab.addTab(tab.newTabSpec("C").setIndicator("C").setContent(new Intent(context, CActivity.class)));
- tab.addTab(tab.newTabSpec("D").setIndicator("D").setContent(new Intent(context, DActivity.class)));
- tab.addTab(tab.newTabSpec("E").setIndicator("E").setContent(new Intent(context, EActivity.class)));
-
- rg = (RadioGroup) findViewById(R.id.rg);
- rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {
- public void onCheckedChanged(RadioGroup group, int checkedId) {
- int idx = -1;
- if (checkedId == R.id.rb01) {
- idx = 0;
- } else if (checkedId == R.id.rb02) {
- idx = 1;
- } else if (checkedId == R.id.rb03) {
- idx = 2;
- } else if (checkedId == R.id.rb04) {
- idx = 3;
- } else if (checkedId == R.id.rb05) {
- idx = 4;
- }
- switchActivity(idx);
- }
- });
- }
-
- protected void switchActivity(int idx) {
- int n = tab.getCurrentTab();
-
- if (idx < n) {
- tab.getCurrentView().startAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_left_out));
- } else if (idx > n) {
- tab.getCurrentView().startAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_right_out));
- }
- tab.setCurrentTab(idx);
- if (idx < n) {
- tab.getCurrentView().startAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_left_in));
- } else if (idx > n) {
- tab.getCurrentView().startAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_right_in));
- }
-
- RadioButton rb = (RadioButton) rg.getChildAt(idx);
- rb.setChecked(true);
- }
-
- private Map<String, Object> data = new HashMap<String, Object>();
-
- protected void put(String key, String value) {
- data.put(key, value);
- }
-
- protected Object get(String key) {
- return data.get(key);
- }
- }
复制代码
主要的核心代码在上面的代码中,原理是先使当前的界面播放退出的动画,然后切换界面,最后播放新的界面进入的动画,请注意播放动画的代码是
tab.getCurrentView().startAnimation();
而不是
tab.getCurrentTabView().startAnimation();
我在开始写代码的时候,就发了这样的错误,找了好几天才把这个bug给找到,真郁闷。
还有TabActivity是一个Main,其他Activity相当于一个Sub,通常在一个sub中切换到另外一个sub中就比较麻烦了
,
可以使用如下的代码实现功能
BActivity----->CActivity
- public class BActivity extends Activity{
-
- Button btn;
- TabMainActivity main;
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.b);
- btn = (Button) findViewById(R.id.button1);
- main = (TabMainActivity) getParent();
- btn.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- main.put("test", "abc123");
- main.switchActivity(2);
- }
- });
- }
- }
复制代码
在BActivity中使用getParent();得带的就是MainActivity,我们可以在main写一个切换的方法,然后在B中就可以调用了,如果两个Activity之间要传递数据,那么也可以使用上面的方法,切换前先把数据放在main中,切换后在从main中取得数据。
下面说一说,ViewFlipper是一个很不错的组建,用的情况也是比较多的
ViewFlipper的子View中可以有好几个,但是显示只显示一个,利用这个原理可以做好多事情,比如,做一个类似于Window资源管理器中的视图切换,一个是网格布局,一个是列表布局, 那么就可以利用ViewFlipper来切换,
同理可以可以实现类似于TabActivity的功能,我在附件的源码中有例子。
TabActivity也有缺点,比如,在sub中不能使用startActivityForResult这样的方法,就算可以使用,那么返回的响应也不再sub中而是在main中,
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- }
复制代码
那么就可以使用ViewFlippler来实现一个此功能
还有一个重要地方,就是ViewFlipper可以很简单的实现两个View之间的动画切换。
- public class VfActivity extends Activity {
-
- ViewFlipper vf;
- RadioGroup rg;
- Context context;
-
- AView a;
- BView b;
- CView c;
- DView d;
- EView e;
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.vf);
-
- vf = (ViewFlipper) findViewById(R.id.vf);
-
- rg = (RadioGroup) findViewById(R.id.rg);
- context = this;
- a = new AView(this);
- b = new BView(this);
- c = new CView(this);
- d = new DView(this);
- e = new EView(this);
-
- vf.addView(a.makeNewView());
- vf.addView(b.makeNewView());
- vf.addView(c.makeNewView());
- vf.addView(d.makeNewView());
- vf.addView(e.makeNewView());
-
- rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {
-
- public void onCheckedChanged(RadioGroup group, int checkedId) {
- int idx = -1;
- if (checkedId == R.id.rb01) {
- idx = 0;
- } else if (checkedId == R.id.rb02) {
- idx = 1;
- } else if (checkedId == R.id.rb03) {
- idx = 2;
- } else if (checkedId == R.id.rb04) {
- idx = 3;
- } else if (checkedId == R.id.rb05) {
- idx = 4;
- }
- changeViewByHorizontalnAnim(vf, idx);
- }
- });
- }
-
- public void changeViewByHorizontalnAnim(ViewFlipper vf, int idx) {
-
- int currentIdx = vf.getDisplayedChild();
- if (idx == currentIdx) {
- return;
- }
- Animation leftIn = AnimationUtils.loadAnimation(context, R.anim.left_in);
- Animation leftOut = AnimationUtils.loadAnimation(context, R.anim.left_out);
- Animation rightIn = AnimationUtils.loadAnimation(context, R.anim.right_in);
- Animation rightOut = AnimationUtils.loadAnimation(context, R.anim.right_out);
- Animation in = null;
- Animation out = null;
- if (idx > currentIdx) {
- in = leftIn;
- out = leftOut;
- } else if (idx < currentIdx) {
- in = rightIn;
- out = rightOut;
- } else {
- return;
- }
- vf.setInAnimation(in);
- vf.setOutAnimation(out);
- vf.setDisplayedChild(idx);
- }
- }
复制代码
项目的结构如上图,Vf(ViewFlipper的简写,输入法来回切换太麻烦,希望大家能看懂,见谅啊,:-))
,vf在实现tab的时候,我先顶一个抽象类,
- public abstract class AbstractView {
-
- protected Context context;
- protected VfActivity activity;
-
- public AbstractView(VfActivity va) {
- context = va;
- activity = va;
- }
-
- public abstract View makeNewView();
- }
复制代码
构造方法,把vf所在的activity穿进去,然后有个makenewview的方法,子类实现此方法,就可以得到一个界面
然后使用vf.addView(xxx.makeNewView());就行了,这里就不介绍vf的使用方法了,网上这方面的例子也很多。
终于写完了,如果有什么不同意见,可以留言,大家一起探讨探讨。写了好几个小时,累死了。
打完收工。。。。。。。
转自:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=114362