仿新浪微博布局学习——妙用TabHost
前言
为了更好的开发Android应用程序,除了熟练掌握基本的UI组件和API外,还需要掌握一些技巧,而这些技巧可以通过阅读一些代码来提高,本系列将与大家分享一些新浪微博布局方面的收获,欢迎交流!
转载,
博客园:http://www.cnblogs.com
农民伯伯:http://www.cnblogs.com/over140
版本
新浪微博 weibo_10235010.apk
正文
一、效果图
红色部分是本文要实现的目标。
二、实现
maintabs.xml
[html] view plain copy- <?xmlversion="1.0"encoding="UTF-8"?>
- <TabHostandroid:id="@android:id/tabhost"android:layout_width="fill_parent"android:layout_height="fill_parent"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <LinearLayoutandroid:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent">
- <FrameLayoutandroid:id="@android:id/tabcontent"android:layout_width="fill_parent"android:layout_height="0.0dip"android:layout_weight="1.0"/>
- <TabWidgetandroid:id="@android:id/tabs"android:visibility="gone"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="0.0"/>
- <RadioGroupandroid:gravity="center_vertical"android:layout_gravity="bottom"android:orientation="horizontal"android:id="@id/main_radio"android:background="@drawable/maintab_toolbar_bg"android:layout_width="fill_parent"android:layout_height="wrap_content">
- <RadioButtonandroid:text="@string/main_home"android:checked="true"android:id="@+id/radio_button0"android:layout_marginTop="2.0dip"android:drawableTop="@drawable/icon_1_n"style="@style/main_tab_bottom"/>
- <RadioButtonandroid:id="@+id/radio_button1"android:layout_marginTop="2.0dip"android:text="@string/main_news"android:drawableTop="@drawable/icon_2_n"style="@style/main_tab_bottom"/>
- <RadioButtonandroid:id="@+id/radio_button2"android:layout_marginTop="2.0dip"android:text="@string/main_my_info"android:drawableTop="@drawable/icon_3_n"style="@style/main_tab_bottom"/>
- <RadioButtonandroid:id="@+id/radio_button3"android:layout_marginTop="2.0dip"android:text="@string/menu_search"android:drawableTop="@drawable/icon_4_n"style="@style/main_tab_bottom"/>
- <RadioButtonandroid:id="@+id/radio_button4"android:layout_marginTop="2.0dip"android:text="@string/more"android:drawableTop="@drawable/icon_5_n"style="@style/main_tab_bottom"/>
- </RadioGroup>
- </LinearLayout>
- </TabHost>
styles.xml
- <stylename="main_tab_bottom">
- <itemname="android:textSize">@dimen/bottom_tab_font_size</item>
- <itemname="android:textColor">#ffffffff</item>
- <itemname="android:ellipsize">marquee</item>
- <itemname="android:gravity">center_horizontal</item>
- <itemname="android:background">@drawable/home_btn_bg</item>
- <itemname="android:paddingTop">@dimen/bottom_tab_padding_up</item>
- <itemname="android:layout_width">fill_parent</item>
- <itemname="android:layout_height">wrap_content</item>
- <itemname="android:button">@null</item>
- <itemname="android:singleLine">true</item>
- <itemname="android:drawablePadding">@dimen/bottom_tab_padding_drawable</item>
- <itemname="android:layout_weight">1.0</item>
- </style>
home_btn_bg.xml
- <selector
- xmlns:android="http://schemas.android.com/apk/res/android">
- <itemandroid:state_focused="true"android:state_enabled="true"android:state_pressed="false"android:drawable="@drawable/home_btn_bg_s"/>
- <itemandroid:state_enabled="true"android:state_pressed="true"android:drawable="@drawable/home_btn_bg_s"/>
- <itemandroid:state_enabled="true"android:state_checked="true"android:drawable="@drawable/home_btn_bg_d"/>
- <itemandroid:drawable="@drawable/transparent"/>
- </selector>
代码说明:
1. 需要注意的是他这里把TabWidget的Visibility设置成了gone!也就是默认难看的风格不见了:,取而代之的是5个带风格的单选按钮.
2. 注意为单选按钮设置的style,其中最重要的是为其background设置了home_btn_bg.xml,也就是自定义了选中效果。
Java文件
[java] view plain copy- publicclassMainTabActivityextendsTabActivityimplements
- OnCheckedChangeListener{
- privateTabHostmHost;
- privateIntentmMBlogIntent;
- privateIntentmMoreIntent;
- privateIntentmInfoIntent;
- privateIntentmSearchIntent;
- privateIntentmUserInfoIntent;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.maintabs);
- //~~~~~~~~~~~~初始化
- this.mMBlogIntent=newIntent(this,HomeListActivity.class);
- this.mSearchIntent=newIntent(this,SearchSquareActivity.class);
- this.mInfoIntent=newIntent(this,MessageGroup.class);
- this.mUserInfoIntent=newIntent(this,MyInfoActivity.class);
- this.mMoreIntent=newIntent(this,MoreItemsActivity.class);
- initRadios();
- setupIntent();
- }
- /**
- *初始化底部按钮
- */
- privatevoidinitRadios(){
- ((RadioButton)findViewById(R.id.radio_button0)).setOnCheckedChangeListener(this);
- ((RadioButton)findViewById(R.id.radio_button1)).setOnCheckedChangeListener(this);
- ((RadioButton)findViewById(R.id.radio_button2)).setOnCheckedChangeListener(this);
- ((RadioButton)findViewById(R.id.radio_button3)).setOnCheckedChangeListener(this);
- ((RadioButton)findViewById(R.id.radio_button4)).setOnCheckedChangeListener(this);
- }
- /**
- *切换模块
- */
- @Override
- publicvoidonCheckedChanged(CompoundButtonbuttonView,booleanisChecked){
- if(isChecked){
- switch(buttonView.getId()){
- caseR.id.radio_button0:
- this.mHost.setCurrentTabByTag("mblog_tab");
- break;
- caseR.id.radio_button1:
- this.mHost.setCurrentTabByTag("message_tab");
- break;
- caseR.id.radio_button2:
- this.mHost.setCurrentTabByTag("userinfo_tab");
- break;
- caseR.id.radio_button3:
- this.mHost.setCurrentTabByTag("search_tab");
- break;
- caseR.id.radio_button4:
- this.mHost.setCurrentTabByTag("more_tab");
- break;
- }
- }
- }
- privatevoidsetupIntent(){
- this.mHost=getTabHost();
- TabHostlocalTabHost=this.mHost;
- localTabHost.addTab(buildTabSpec("mblog_tab",R.string.main_home,
- R.drawable.icon_1_n,this.mMBlogIntent));
- localTabHost.addTab(buildTabSpec("message_tab",R.string.main_news,
- R.drawable.icon_2_n,this.mInfoIntent));
- localTabHost.addTab(buildTabSpec("userinfo_tab",R.string.main_my_info,
- R.drawable.icon_3_n,this.mUserInfoIntent));
- localTabHost.addTab(buildTabSpec("search_tab",R.string.menu_search,
- R.drawable.icon_4_n,this.mSearchIntent));
- localTabHost.addTab(buildTabSpec("more_tab",R.string.more,
- R.drawable.icon_5_n,this.mMoreIntent));
- }
- privateTabHost.TabSpecbuildTabSpec(Stringtag,intresLabel,intresIcon,
- finalIntentcontent){
- returnthis.mHost
- .newTabSpec(tag)
- .setIndicator(getString(resLabel),
- getResources().getDrawable(resIcon))
- .setContent(content);
- }
代码说明
1. 由于TabWidget被隐藏,所以相关的事件也会无效,这里取巧用RadioGroup与RadioButton的特性来处理切换,然后监听事件调用setCurrentTabByTag来切换Activity。
2. 注意即使TabWidget被隐藏,也要为其设置indicator,否则会保持。
三、总结
在这之前如果要做这种效果我恐怕第一时间就会想到用ActivityGroup来做,主要是因为TabHost的TabWidget非常难看,用起来也不方便。其实从源码可以看出,TabActivity也是继承自ActivityGroup,这里结合了单选按钮和TabHost,各取其长,有时间可以专门写一个这样的自定义控件:)
自定义TabHost,TabWidget样式 .
分类:Android 2012-04-12 14:48 9142人阅读 评论(7) 收藏 举报 android layout tabs encoding null button 大家好,今天我为大家分享TabHost中怎样修改TabWidget样式。在很多界面美观的应用中很多都用到了TabHost,但他们要比系统默认的要漂亮得多。先看几张图:
京东商城底部菜单栏
新浪微博底部菜单栏
好了,看到这些漂亮的菜单栏是不是很惊讶,你可能会说用Button就可以实现啊 ,可是用Button的话控制显示的内容很麻烦,不如用TabHost控制效率更高。很想知道用TabHost是怎么实现的吧,下面就来研究如何实现这种漂亮的TabHost。先看一下效果图:
界面比较简单,要想做得漂亮换几张图片就可以了。
第一步:先在布局(这里用了main.xml创建时自动生成的)里面放上TabHost ,只要将TabHost控件托至屏幕中就可:
[html] view plain copy- <?xmlversion="1.0"encoding="utf-8"?>
- <TabHostandroid:id="@+id/tabhost"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <LinearLayoutandroid:layout_width="fill_parent"
- android:id="@+id/linearLayout1"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <TabWidgetandroid:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:id="@android:id/tabs"></TabWidget>
- <FrameLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@android:id/tabcontent">
- <LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@+id/tab1"></LinearLayout>
- <LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@+id/tab2"></LinearLayout>
- <LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@+id/tab3"></LinearLayout>
- </FrameLayout>
- </LinearLayout>
- </TabHost>
这里我们已经把LinearLayout和TextView去掉了,并将“xmlns:android="……" ”添加大TabHost里了,这里要注意我们将TabHost的id定义为自己定义的id比不用android规定的id="@android:id/tabhost"。
第二步:创建显示此TabWidget的布局tabmini.xml:
[html] view plain copy- <?xmlversion="1.0"encoding="utf-8"?>
- <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="40dp"
- android:paddingLeft="5dip"
- android:paddingRight="5dip"
- android:background="@drawable/head_bg">
- <TextViewandroid:id="@+id/tab_label"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:gravity="center"
- android:textColor="#000000"
- android:textStyle="bold"
- android:background="@drawable/tabmini"/>
- </RelativeLayout>
第三步:创建一个selector在drawable里面 命名tabmini.xml,用来点击TabHost的一个tab时TextView的变化:
- <?xmlversion="1.0"encoding="utf-8"?>
- <selector
- xmlns:android="http://schemas.android.com/apk/res/android">
- <itemandroid:state_selected="true"
- android:drawable="@drawable/add_managebg_down"/>
- <itemandroid:state_selected="false"
- android:drawable="@drawable/add_managebg"/>
- </selector>
第四步:在Activity里实现TabHost:
- packagecn.li.tabstyle;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.view.LayoutInflater;
- importandroid.view.View;
- importandroid.widget.TabHost;
- importandroid.widget.TextView;
- publicclassTabHostStyleActivityextendsActivity{
- /**Calledwhentheactivityisfirstcreated.*/
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- ViewniTab=(View)LayoutInflater.from(this).inflate(R.layout.tabmini,null);
- TextViewtext0=(TextView)niTab.findViewById(R.id.tab_label);
- text0.setText("ni");
- ViewwoTab=(View)LayoutInflater.from(this).inflate(R.layout.tabmini,null);
- TextViewtext1=(TextView)woTab.findViewById(R.id.tab_label);
- text1.setText("wo");
- ViewtaTab=(View)LayoutInflater.from(this).inflate(R.layout.tabmini,null);
- TextViewtext2=(TextView)taTab.findViewById(R.id.tab_label);
- text2.setText("ta");
- ViewweTab=(View)LayoutInflater.from(this).inflate(R.layout.tabmini,null);
- TextViewtext3=(TextView)weTab.findViewById(R.id.tab_label);
- text3.setText("we");
- TabHosttabHost=(TabHost)findViewById(R.id.tabhost);
- tabHost.setup();//Callsetup()beforeaddingtabsifloadingTabHostusingfindViewById().
- tabHost.addTab(tabHost.newTabSpec("nitab").setIndicator(niTab).setContent(R.id.tab1));
- tabHost.addTab(tabHost.newTabSpec("wotab").setIndicator(woTab).setContent(R.id.tab2));
- tabHost.addTab(tabHost.newTabSpec("tatab").setIndicator(taTab).setContent(R.id.tab3));
- tabHost.addTab(tabHost.newTabSpec("wetab").setIndicator(weTab).setContent(R.id.tab4));
- }
- }
这里我们用findViewById创建了TabHost,这样的话我们就需要在添加tab时调用TabHost的setup()方法;这里我们添加内容时添加的是布局,我们完全可以换成自己创建的Activity。
好了,让我们来看看运行效果吧:
好了,我们自定义的TabHost算是结束了。不过看到Activity里的代码很多都是重复的我们可以这样把他们简化:
[java] view plain copy- packagecn.li.tabstyle;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.view.LayoutInflater;
- importandroid.view.View;
- importandroid.widget.TabHost;
- importandroid.widget.TextView;
- publicclassTabHostStyleActivityextendsActivity{
- /**Calledwhentheactivityisfirstcreated.*/
- String[]title=newString[]{"ni","wo","ta","we"};
- ViewuserTab,articeTab,feedTab,weTab;
- View[]tabs=newView[]{userTab,articeTab,feedTab,weTab};
- int[]tabIds=newint[]{R.id.tab1,R.id.tab2,R.id.tab3,R.id.tab4};
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- TabHosttabHost=(TabHost)findViewById(R.id.tabhost);
- tabHost.setup();//Callsetup()beforeaddingtabsifloadingTabHostusingfindViewById().
- for(inti=0;i<tabs.length;i++){
- tabs[i]=(View)LayoutInflater.from(this).inflate(R.layout.tabmini,null);
- TextViewtext=(TextView)tabs[i].findViewById(R.id.tab_label);
- text.setText(title[i]);
- tabHost.addTab(tabHost.newTabSpec(title[i]).setIndicator(tabs[i]).setContent(tabIds[i]));
- }
- }
- }
另外相关资料:
在上一篇文章中,我们花了大量的篇幅来讲解Fragment这个新引进类的使用,目的就是为了让大家能够牢牢的掌握它的使用方法,以便读者在今后的开发中能够熟练的使用它。
一、实现效果图
二、项目工程结构
三、详细代码编写
1、主tab布局界面,main_tab_layout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <? xml version = "1.0" encoding = "utf-8" ?> < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "fill_parent" android:layout_height = "fill_parent" android:orientation = "vertical" > < FrameLayout android:id = "@+id/realtabcontent" android:layout_width = "fill_parent" android:layout_height = "0dip" android:layout_weight = "1" /> < android.support.v4.app.FragmentTabHost android:id = "@android:id/tabhost" android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:background = "@drawable/maintab_toolbar_bg" > < FrameLayout android:id = "@android:id/tabcontent" android:layout_width = "0dp" android:layout_height = "0dp" android:layout_weight = "0" /> </ android.support.v4.app.FragmentTabHost > </ LinearLayout > |
2、Tab按钮选项布局,tab_item_view.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <? xml version = "1.0" encoding = "utf-8" |
更多相关文章
- Android(安卓)在一个程序中启动另一个程序(包名,或者类名)
- #Android项目# ——day03 Android(安卓)沉浸式状态栏的解决方案
- 浅谈Android五大布局——LinearLayout、FrameLayout、AbsoulteLa
- Android(安卓)zygote与进程创建(一)
- adroid之Sqlite篇
- android 自学日记(五) ——ListView
- ubuntu12.04 64bit编译android ics4.0代码出现的/usr/bin/ld.bfd
- 【Android开篇】开始 Hello Android
- android listview滑动删除