1. 前戏
当前80%的移动客户端都是此种布局,包括主流的QQ,微信,通过下方的控制tab来操作进行切换当前的界面,当然方法有很多,但是能有封装,能有控件我认为当然用可行的,废话不多说了,看图。
2. 干货
xml布局如下,一定要注意几点:
1.这个布局为了要用weight,所以一定要使用LinearLayout布局
2.为了优化fragment之间切换的流畅和灵活性,可以对google的控件FragmentTabHost进行自定义的修改,所以这里我使用的自定义控件,至于修改的地方,网上实际上的都一样,我也是看大牛的,开始没想过这个问题,这里推荐两个文章。
点击打开链接(强力推荐),
点击打开链接.。
3.xml代码中有两个framelayou,注意一个是真的,一个是假的,并且要严格按照这代码的id写,weight=1的是真的,weight=0的是假的
4.我们在使用这个控件时,可能会报错java.lang.IllegalStateException: No tab known for tag null,如图,但是不用担心,都是这样的,实际并没有什么影响。如果有疑问,推荐
点击打开链接,但是我看了好像然并卵。
MainActivity中代码要注意以下几点:
1. 使用这个FragmentTabHost的activity一定要继承FragmentActivity,但是我们如果使用V7包的
AppCompatActivity,则不用管,因为这个继承了FragmentActivity。
2. FragmentTabHost的大致使用规范,第一步得到fragmenttabhost,第二步调用setup方法,具体见代码,第三步得到tabspec 第四步 加载我们需要的view,使用setIndivator(),第五,添加tab,使用addTab(),因为我这里使用的图文并茂的tab形式,并没有用官方demo中的单一的文字,所以例外要写个view,布局xml代码一起放在下面。
3. 因为一个一个添加tab太浪费代码,所以这里进行了封装,封装的代码很好用,可以直接使用。
4. 选择器selector这里就不用多说了,我直接上其中一个tab图片的代码和tab文字的代码
package com.guozhaohui.fragmenttabhost;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TextView;
import com.guozhaohui.fragmenttabhost.bean.Tab;
import com.guozhaohui.fragmenttabhost.fragment.EatFragment;
import com.guozhaohui.fragmenttabhost.fragment.GameFragment;
import com.guozhaohui.fragmenttabhost.fragment.SleepFragment;
import com.guozhaohui.fragmenttabhost.widget.FragmentTabHost;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private FragmentTabHost fragmentTabHost;
private LayoutInflater layoutInflater;
private List
tabs = new ArrayList(3);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layoutInflater = LayoutInflater.from(this);
fragmentTabHost = (FragmentTabHost) this.findViewById(R.id.tabhost);
/**
* This method is deprecated. Don't call the original TabHost setup,
* you must instead call setup(Context, FragmentManager) or setup(Context, FragmentManager, int).
* 注意这个方法中第三个参数的意义,在布局文件中,里面那个framelayout只是假的,并且id一定要写成
* android:id="@android:id/tabcontent",但是这里用的是 android:id="@+id/realtabcontent",是外面那个id
*
* */
fragmentTabHost.setup(this,getSupportFragmentManager(),R.id.realtabcontent);
//这是FragmentTabHost添加tab的详细过程 要实现就要写三份一样,下面封装
// TabHost.TabSpec tabSpec = fragmentTabHost.newTabSpec("eat");
// View view = layoutInflater.inflate(R.layout.indicator_tabspec, null);
// ImageView tab_iv = (ImageView) view.findViewById(R.id.tab_iv);
// TextView tab_tv = (TextView) view.findViewById(R.id.tab_tv);
// tab_iv.setImageResource(R.mipmap.eat2);
// tab_tv.setText("吃饭");
// tabSpec.setIndicator(view);
// fragmentTabHost.addTab(tabSpec, EatFragment.class,null);
//这是官方的写法,但是太过单一
// fragmentTabHost.addTab(fragmentTabHost.newTabSpec("eat").setIndicator("吃饭"),EatFragment.class,null);
// fragmentTabHost.addTab(fragmentTabHost.newTabSpec("sleep").setIndicator("睡觉"),SleepFragment.class,null);
// fragmentTabHost.addTab(fragmentTabHost.newTabSpec("game").setIndicator("游戏"),GameFragment.class,null);
initTab();
for(Tab tab:tabs){
TabHost.TabSpec tabSpec = fragmentTabHost.newTabSpec(getString(tab.getTextResId()));
tabSpec.setIndicator(getTabSpecView(tab));
fragmentTabHost.addTab(tabSpec,tab.getTab_fragment(),null);
}
fragmentTabHost.getTabWidget().setShowDividers(LinearLayout.SHOW_DIVIDER_NONE); //去掉每个tab之间的分割线
}
private View getTabSpecView(Tab tab) {
View view = layoutInflater.inflate(R.layout.indicator_tabspec, null);
ImageView tab_iv = (ImageView) view.findViewById(R.id.tab_iv);
TextView tab_tv = (TextView) view.findViewById(R.id.tab_tv);
tab_iv.setImageResource(tab.getIconResId());
tab_tv.setText(tab.getTextResId());
return view;
}
private void initTab() {
Tab tab_eat = new Tab(R.drawable.selector_eat,R.string.eat,EatFragment.class);
Tab tab_sleep = new Tab(R.drawable.selector_sleep,R.string.sleep,SleepFragment.class);
Tab tab_game = new Tab(R.drawable.selector_game,R.string.game,GameFragment.class);
tabs.add(tab_eat);
tabs.add(tab_sleep);
tabs.add(tab_game);
}
}
3.道友留步
源代码地址
点击打开链接。好像没什么其他的了,双十一来了,哎是不是要买点什么,没钱啊,靠