Android学习笔记_41_TabHost自定义标签和TraceView性能测试
一、tabhost第一种用法,通过在帧布局放入定义好的page页面来实现,这样导致在当前activity下代码量比较大。
1、页面布局:
| | | | |--->这个部分叫TabWigdet 用来放标签的,每一个格格
|----------------------------------| 放一个标签
| |
| |-->这个部分叫FrameLayout,是一个
| | 用来显示每个标签页的内容的窗口
| |
|-----------------------------------
以上整个的合起来叫做:TabHost
使用TabHost 标签,不同的tab页可以看成是叠加在一起的界面,因此使用帧布局。在这些tab也的外面需要使用TabWidget包裹。
移除tabHost底部黑线可以重写它的样式:
<style name="removeTabHostLine" parent="android:style/Theme.Light"> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> </style>
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- tabhost用来存放标签对象 1.在标签页中,每一页和这一页的内容,是垂直摆放的所以这里用到了线性布局 --> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- 这里开始存放每个标签TabWidget ,这个标签可以存放所有的标签TabWidget --> <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" /> <!-- android:id="@android:id/tabs"这个是在系统文件中定义的,是写死的 --> <!-- 因为每个标签页相当于浮动的,所以这里每个标签页的内容用到了帧布局 --> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 这里放的是第一个标签的内容 --> <LinearLayout android:id="@+id/page1" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 第一个的标签页显示的内容 --> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="这是第一个标签页" /> </LinearLayout> <!-- 第二个的标签页显示的内容 --> <LinearLayout android:id="@+id/page2" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="这是第二个标签页" /> </LinearLayout> <!-- 第三个的标签页显示的内容 --> <LinearLayout android:id="@+id/page3" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="这是第三个标签页" /> </LinearLayout> </FrameLayout> </LinearLayout> </TabHost>
2、自定义标签页和其动画背景:
<?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:orientation="vertical" android:background="#FFFFFF" > <!-- 这里要求当用户按住textview的时候,显示一张图片,当textview被选择的时候显示一张图片,当其他状态的时候,也显示一张图片 android:background="@drawable/tab_bg"给这个TextView应用这个状态列表图像. --> <TextView android:id="@+id/name" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="1dp" android:background="@drawable/tab_bg" android:gravity="center" android:textColor="#FFFFFF" android:textSize="18sp" /> <!-- android:background="@drawable/tab_bg" //这里用到了状态列表图形,这里需要随着标签页的切换来改变图形 //这里的状态列表图形定义,可以参考api: //打开Dev Guide这个标签->然后在左侧选择-> //Framework Topics -Application Resources-> //Resource Types->Drawable->State List->然后拷贝例子代码到tab_bg.xml中 android:layout_marginRight="1dp"定义了标签页之间的间隔颜色 android:gravity="center"指定内容要居中对齐--> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/bg_selected" android:state_pressed="true"/> <!-- 当用户按下Textview的时候显示这张图片 --> <!-- pressed --> <!-- 当用户选择TextView的时候显示这张图片 --> <item android:drawable="@drawable/bg_selected" android:state_selected="true"/> <!-- 其他状态显示的是这张图片 --> <item android:drawable="@drawable/bg_normal"/> <!-- default --> </selector>
3、后台代码:
package com.example.tabhost; import android.app.Activity; import android.os.Bundle; import android.os.Debug; import android.view.Gravity; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TabHost; import android.widget.TabHost.TabSpec; import android.widget.TextView; public class MainActivity extends Activity { TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //traceview性能测试 Debug.startMethodTracing("traceview"); // 找到TabHost的标签集合 tabHost = (TabHost) this.findViewById(R.id.tabhost); tabHost.setup();// 这一句在源代码中,会根据findviewbyId()找到 // 对应的TabWidget,还需要根据findViewById()找到这个TabWidget下面对应的标签页的 // 内容.也就是FrameLayout这个显示控件. /* * 这里的第一个findviewbyId(),这个Id是系统指定的固定的id,可以查看api文档得到 * 进入文档G:\android\android-sdk-windows\docs\reference\packages.html点击 * Reference-->然后在左侧找到android-->点击然后选择:R.id-->找到tabs点击--> public static * final int tabs Since: API Level 1 Constant Value: 16908307 * (0x01020013) 这里可以看到tabs代表的值,但是为了可读性好,还是给在布局文件main.xml中给 * TagWidget控件,用这种方式定义id: android:id="@android:id/tabs"这里@代表 * 访问R文件,这里代表访问的是android包中的R文件中的id 这个类中的tabs * android是个包,R文件的类就在这个包中定义的,id是R类中的一个内部类, FrameLayout控件的id代表的是: * android:id="@android:id/tabs" */ // TabSpec这个是标签页对象. TabSpec tabSpec = tabHost.newTabSpec("page1");// 新建一个标签页对象. // tabSpec.setIndicator("首页",getResources().getDrawable(R.drawable.i1)); // 第一个参数指定标签名字,第二个,指定图片资源,汉子显示在图片的下面. tabSpec.setIndicator(createTabView("首页"));// 设置这个标签页的标题 // createTabView("首页")这里这个时候就可以替换成自己的API,也就那个切换标签页的显示内容页对应的view对象 tabSpec.setContent(R.id.page1);// 指定标签页的内容页. tabHost.addTab(tabSpec);// 把这个标签页,添加到标签对象tabHost中. tabSpec = tabHost.newTabSpec("page2"); // tabSpec.setIndicator("第二页",getResources().getDrawable(R.drawable.i2)); tabSpec.setIndicator(createTabView("第二页")); tabSpec.setContent(R.id.page2); tabHost.addTab(tabSpec); tabSpec = tabHost.newTabSpec("page3"); tabSpec.setIndicator("第三页",getResources().getDrawable(R.drawable.i7)); //tabSpec.setIndicator(createTabView("第三页")); tabSpec.setContent(R.id.page3); tabHost.addTab(tabSpec); // 这里可以设置,哪个标签页为默认的第一个页面. tabHost.setCurrentTab(0); } @Override protected void onDestroy() { Debug.stopMethodTracing(); super.onDestroy(); } // 这里可以做一个自定义标签页,返回一个view,tabSpec.setIndicator(createTabView("第二页")) // 因为这里可以传一个view进去. private View createTabView(String name) { // 通过下面的这句可以得到自定义的标签页的view对象. // View tabView = getLayoutInflater().inflate(R.layout.tab, null); // TextView textView =tabView.findViewById(R.id.name);//找到textview控件 // textView.setText(name);显示这个名称. // return tabView LinearLayout linearLayout = new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setBackgroundColor(0xFFFFFF); TextView textView = new TextView(this); textView.setText(name); textView.setBackgroundResource(R.drawable.tab_bg); textView.setTextColor(0xFFFFFF); textView.setTextSize(18.0f); textView.setGravity(Gravity.CENTER); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); linearLayout.addView(textView, params); return linearLayout; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
4、进行TraceView性能测试,加入写入SDK权限。
二、tabhost第二种用法,它内容的启动可以通过Intent对象实现。两种方式也可以混合使用。
需要注意两点:
1、需要继承ActivityGroup .
2、将原来"tabHost.setup()"的改成 "tabHost.setup(this.getLocalActivityManager())",负责会报错。tabHost的id也可以自定义。
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" > <TabHost android:id="@+id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/page1" android:layout_width="match_parent" android:layout_height="match_parent" > <include layout="@layout/account_recharge_uninstall" /> </LinearLayout> </FrameLayout> </LinearLayout> </TabHost> </LinearLayout>
public abstract class TabActivity extends ActivityGroup { protected TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tabHost = (TabHost) this.findViewById(R.id.tabhost); //必须有getLocalActivityManager tabHost.setup(this.getLocalActivityManager()); //直接加载page1.xml TabSpec tabSpec = tabHost.newTabSpec("page1"); tabSpec.setIndicator(createTabView("标签1")); tabSpec.setContent(R.id.page1); tabHost.addTab(tabSpec); tabSpec = tabHost.newTabSpec("page2"); //将原来的page2.xml放到了Activity2的setContentView方法上,在来回切换时Activity2只执行一次onCreate方法 Intent intent = new Intent(this, Activity2.class); tabSpec.setContent(intent); tabSpec.setIndicator(createTabView("标签2")); tabHost.addTab(tabSpec); tabSpec = tabHost.newTabSpec("page3"); tabSpec.setIndicator(createTabView("标签3")); intent = new Intent(this, Activity3.class); tabSpec.setContent(intent); tabHost.addTab(tabSpec); //默认使其选中 tabHost.setCurrentTabByTag("page2"); } // 创建tab标签 protected View createTabView(String name) { View tabView = getLayoutInflater().inflate(R.layout.tab_background, null); TextView textView = (TextView) tabView.findViewById(R.id.tab_name);// 找到textview控件 textView.setText(name); return tabView; } }
剩下的流程跟方法1一样。