感觉这主页面这块还是比较复杂的,这段时间在学习这部分的源码,一遍遍的读源码,收获比较大的一部分是主页面四个Tab页面的展现形式。 这块儿借助了枚举类来完成相应的操作,是以前没有涉及过的,感觉很新鲜。 TabHost的五个Tab初始化 总体来说就是通过枚举类来列出5个Tab对应的内容页。在源码中初始化五个Tab页的代码如下所示: //初始化底部的五个Tab页 private void initTabs() { //调用枚举类MainTab的values方法,获得MainTab枚举类数组 MainTab[] tabs = MainTab.values(); final int size = tabs.length; for (int i = 0; i < size; i++) { //根据index获得具体对应的MainTab MainTab mainTab = tabs[i]; //初始化每个Tab对应的图标、文字 TabSpec tab = mTabHost.newTabSpec(getString(mainTab.getResName())); View indicator = LayoutInflater.from(getApplicationContext()) .inflate(R.layout.tab_indicator, null); TextView title = (TextView) indicator.findViewById(R.id.tab_title); Drawable drawable = this.getResources().getDrawable( mainTab.getResIcon()); title.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); if (i == 2) { indicator.setVisibility(View.INVISIBLE); mTabHost.setNoTabChangedTag(getString(mainTab.getResName())); } title.setText(getString(mainTab.getResName())); tab.setIndicator(indicator); tab.setContent(new TabContentFactory() { @Override public View createTabContent(String tag) { return new View(MainActivity.this); } }); //为TabHost添加对应的页面内容 mTabHost.addTab(tab, mainTab.getClz(), null); //如果对应的是我的界面则添加一个消息提醒的右上角图标。 if (mainTab.equals(MainTab.ME)) { View cn = indicator.findViewById(R.id.tab_mes); mBvNotice = new BadgeView(MainActivity.this, cn); mBvNotice.setBadgePosition(BadgeView.POSITION_TOP_RIGHT); mBvNotice.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10); mBvNotice.setBackgroundResource(R.drawable.notification_bg); mBvNotice.setGravity(Gravity.CENTER); } mTabHost.getTabWidget().getChildAt(i).setOnTouchListener(this); } } Tab页的生成方式 在枚举类中来生成,代码如下: package net.oschina.app.ui; import net.oschina.app.R; import net.oschina.app.fragment.ExploreFragment; import net.oschina.app.fragment.MyInformationFragment; import net.oschina.app.viewpagerfragment.NewsViewPagerFragment; import net.oschina.app.viewpagerfragment.TweetsViewPagerFragment; public enum MainTab { //对应新闻页面 NEWS(0, R.string.main_tab_name_news, R.drawable.tab_icon_new, NewsViewPagerFragment.class), //对应动态页面 TWEET(1, R.string.main_tab_name_tweet, R.drawable.tab_icon_tweet, TweetsViewPagerFragment.class), //对应快速页面 QUICK(2, R.string.main_tab_name_quick, R.drawable.tab_icon_new, null), //对应浏览页面 EXPLORE(3, R.string.main_tab_name_explore, R.drawable.tab_icon_explore, ExploreFragment.class), //对应“我”的页面 ME(4, R.string.main_tab_name_my, R.drawable.tab_icon_me, MyInformationFragment.class); //该枚举的页面index:0、1、2、3、4 private int idx; //该枚举的页面的资源名字:综合、动弹、快速、发现、我 private int resName; //每个枚举对应的icon private int resIcon; //每个枚举对应的Fragment的class private Class<?> clz; //枚举类的构造方法 private MainTab(int idx, int resName, int resIcon, Class<?> clz) { this.idx = idx; this.resName = resName; this.resIcon = resIcon; this.clz = clz; } public int getIdx() { return idx; } public void setIdx(int idx) { this.idx = idx; } public int getResName() { return resName; } public void setResName(int resName) { this.resName = resName; } public int getResIcon() { return resIcon; } public void setResIcon(int resIcon) { this.resIcon = resIcon; } public Class<?> getClz() { return clz; } public void setClz(Class<?> clz) { this.clz = clz; } } 枚举类的学习 枚举类涉及到的方法 ordinal()用来返回枚举值在枚举类中的顺序。 compareTo ()比较两个枚举值的顺序,返回顺序之差。 values(),静态方法,返回包含一个全部枚举值的数组。 toString(),返回枚举常量的名称 valueOf(),返回指定没弄成的枚举类型的枚举常量。 Java中枚举的7中常见用法 常量 在JDK1.5 之前,我们定义常量都是: public static fianl…. 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。 public enum Color { RED, GREEN, BLANK, YELLOW } switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。 enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color = Signal.RED; public void change() { switch (color) { case RED: color = Signal.GREEN; break; case YELLOW: color = Signal.RED; break; case GREEN: color = Signal.YELLOW; break; } } } 向枚举中添加新方法 如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。 public enum Color { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } // 普通方法 public static String getName(int index) { for (Color c : Color.values()) { if (c.getIndex() == index) { return c.name; } } return null; } // get set 方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } } 覆盖枚举的方法 下面给出一个toString()方法覆盖的例子。 public enum Color { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } //覆盖方法 @Override public String toString() { return this.index+"_"+this.name; } } 实现接口 所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。 public interface Behaviour { void print(); String getInfo(); } public enum Color implements Behaviour{ RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } //接口方法 @Override public String getInfo() { return this.name; } //接口方法 @Override public void print() { System.out.println(this.index+":"+this.name); } } 使用接口组织枚举 public interface Food { enum Coffee implements Food{ BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO } enum Dessert implements Food{ FRUIT, CAKE, GELATO } } 关于枚举集合的使用 java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档。 关于枚举的实现细节和原理请参考: 参考资料:《ThinkingInJava》第四版 参考文章:Java 枚举7常见种用法