[关闭]
@xujun94 2016-10-16T09:24:49.000000Z 字数 18225 阅读 1533

仿qq底部tab导航

本篇博客主要实现以下效果:

效果图

老规矩,废话 不多说,先看效果图

FragmentTabHost实现qq底部Tab实践的效果图

RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab效果图

使用FragmentTabHost实现qq底部Tab切换

第一步先看布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <!--用来填充FragemntFrayLayout-->
  7. <FrameLayout
  8. android:id="@+id/main_layout_content"
  9. android:layout_width="match_parent"
  10. android:layout_height="0dp"
  11. android:layout_weight="1">
  12. </FrameLayout>
  13. <!--FragmentTabHost-->
  14. <android.support.v4.app.FragmentTabHost
  15. android:id="@android:id/tabhost"
  16. android:layout_width="match_parent"
  17. android:layout_height="wrap_content"
  18. android:background="#F6F6F6"
  19. android:paddingBottom="5dp"
  20. android:paddingTop="5dp">
  21. <FrameLayout
  22. android:id="@android:id/tabcontent"
  23. android:layout_width="0dp"
  24. android:layout_height="0dp"/>
  25. </android.support.v4.app.FragmentTabHost>
  26. </LinearLayout>

其实很简单,没什么好说的 ,就是一个vertical的LinearLayout中放置着一个FrameLayout和FragmentTabHost

接下来我们来看一下代码

  1. public class FirstStyleActivity extends AppCompatActivity {
  2. FragmentTabHost mTabHost;
  3. private TabWidget mTabWidget;
  4. private List<FragmentInfo> mFragmentEntities;
  5. private static final String TAG = "xujun";
  6. private static final String tag = "tag";
  7. public static final String[] mTiltles = new String[]{
  8. "首页", "课程", "直播", "个人"
  9. };
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_first_style);
  14. mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
  15. mTabHost.setup(this, getSupportFragmentManager(), R.id.main_layout_content);
  16. mTabWidget = mTabHost.getTabWidget();
  17. // 去掉分割线
  18. mTabWidget.setDividerDrawable(null);
  19. mFragmentEntities = MainFragmentFactory.getInstance().getList();
  20. initListener();
  21. initData();
  22. }
  23. private void initData() {
  24. int size = mFragmentEntities.size();
  25. for (int i = 0; i < size; i++) {
  26. Log.i(TAG, "size:=" + size);
  27. FragmentInfo fragmentInfo = mFragmentEntities.get(i);
  28. String title = fragmentInfo.getTitle();
  29. TabHost.TabSpec tabSpec = mTabHost.newTabSpec(title).setIndicator(getTabView
  30. (i));
  31. Bundle bundle = new Bundle();
  32. bundle.putString(tag, mTiltles[i]);
  33. mTabHost.addTab(tabSpec, fragmentInfo.getClz(), bundle);
  34. }
  35. updateTab(0);
  36. }
  37. private void initListener() {
  38. mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
  39. @Override
  40. public void onTabChanged(String tabId) {
  41. int currentTab = mTabHost.getCurrentTab();
  42. Log.i(TAG, "onTabChanged:currentTab:=" + currentTab);
  43. updateTab(currentTab);
  44. }
  45. });
  46. }
  47. private View getTabView(int i) {
  48. View view = View.inflate(this, R.layout.tab_layout, null);
  49. int currentTab = mTabHost.getCurrentTab();
  50. Log.i(TAG, "currentTab:=" + currentTab);
  51. setSingleView(view, currentTab, i);
  52. return view;
  53. }
  54. private void setSingleView(View view, int currentTab, int index) {
  55. FragmentInfo fragmentInfo = mFragmentEntities.get(index);
  56. int[] imagIds = fragmentInfo.getImagIds();
  57. int[] colors = fragmentInfo.getColors();
  58. TextView tv = (TextView) view.findViewById(R.id.tab_tv);
  59. ImageView iv = (ImageView) view.findViewById(R.id.tab_icon);
  60. tv.setText(fragmentInfo.getTitle());
  61. Resources resources = getResources();
  62. if (index == currentTab) {
  63. tv.setTextColor(resources.getColor(colors[1]));
  64. iv.setImageDrawable(resources.getDrawable(imagIds[1]));
  65. } else {
  66. tv.setTextColor(getResources().getColor(colors[0]));
  67. iv.setImageDrawable(resources.getDrawable(imagIds[0]));
  68. }
  69. }
  70. private void updateTab(int currentTab) {
  71. int childCount = mTabWidget.getChildCount();
  72. for (int i = 0; i < childCount; i++) {
  73. View view = mTabWidget.getChildTabViewAt(i);
  74. setSingleView(view, currentTab, i);
  75. }
  76. }
  77. }

其实说起来也很简单,主要分为以下步骤
- 第一步,实例化FragmentTabHost并设置相关样式

  1. mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
  2. mTabHost.setup(this, getSupportFragmentManager(), R.id.main_layout_content);
  3. mTabWidget = mTabHost.getTabWidget();
  4. // 去掉分割线
  5. mTabWidget.setDividerDrawable(null);
  1. for (int i = 0; i < size; i++) {
  2. Log.i(TAG, "size:=" + size);
  3. FragmentInfo fragmentInfo = mFragmentEntities.get(i);
  4. String title = fragmentInfo.getTitle();
  5. TabHost.TabSpec tabSpec = mTabHost.newTabSpec(title).setIndicator(getTabView
  6. (i));
  7. Bundle bundle = new Bundle();
  8. bundle.putString(tag, mTiltles[i]);
  9. mTabHost.addTab(tabSpec, fragmentInfo.getClz(), bundle);
  10. }
  1. mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
  2. @Override
  3. public void onTabChanged(String tabId) {
  4. int currentTab = mTabHost.getCurrentTab();
  5. Log.i(TAG, "onTabChanged:currentTab:=" + currentTab);
  6. updateTab(currentTab);
  7. }
  8. });

运行上述代码及可以看到如下效果图


使用RadioGroup和RadioButton实现仿qq底部切换

第一步 ,先看布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. android:id="@+id/activity_second_style"
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. >
  9. <!--用来填充FragemntFrayLayout-->
  10. <FrameLayout
  11. android:id="@+id/fl"
  12. android:layout_width="match_parent"
  13. android:layout_height="0dp"
  14. android:layout_weight="1">
  15. </FrameLayout>
  16. <!--使用RadioGroup来实现tab的切换-->
  17. <RadioGroup
  18. android:id="@+id/rg"
  19. android:layout_width="match_parent"
  20. android:layout_height="wrap_content"
  21. android:orientation="horizontal"
  22. >
  23. <RadioButton
  24. android:id="@+id/rb_home"
  25. style="@style/bottom_tab"
  26. android:drawableTop="@drawable/sel_home"
  27. android:text="首页"/>
  28. <RadioButton
  29. android:id="@+id/rb_course"
  30. style="@style/bottom_tab"
  31. android:drawableTop="@drawable/sel_course"
  32. android:text="课程"/>
  33. <RadioButton
  34. android:id="@+id/rb_direct_seeding"
  35. style="@style/bottom_tab"
  36. android:drawableTop="@drawable/sel_direct_seeding"
  37. android:text="直播"/>
  38. <RadioButton
  39. android:id="@+id/rb_me"
  40. style="@style/bottom_tab"
  41. android:drawableTop="@drawable/sel_me"
  42. android:text="我的"/>
  43. </RadioGroup>
  44. </LinearLayout>

其实每一个tab的选中时利用RadioGroup中RadioButton的互相排斥的特性,即每一次只能选中一个 RadioButton

至于bottom_tab的style,只不过是将相同的arr提取出来,减少布局的代码量和方便统一修改而已,平时我们在写布局代码 的时候也可以这样

  1. <style name="bottom_tab">
  2. <item name="android:layout_width" >0dp</item>
  3. <item name="android:layout_height" >wrap_content</item>
  4. <item name="android:layout_weight" >1</item>
  5. <item name="android:text" >0dp</item>
  6. <item name="android:gravity" >center</item>
  7. <item name="android:textColor" >@drawable/sel_bottom_tab_text</item>
  8. <item name="android:padding" >8dp</item>
  9. <item name="android:button" >@null</item>
  10. </style>

第二步,我们来看一下Activity的 代码

  1. public class ThreeActivity extends AppCompatActivity {
  2. FrameLayout mFl;
  3. RadioGroup mRg;
  4. private FragmentManager mFragmentManager;
  5. private int position = 0;
  6. public static final String[] mTiltles = new String[]{
  7. "首页", "课程", "直播", "个人"
  8. };
  9. private List<Fragment> mFragments;
  10. private Fragment mCurFragment;
  11. @Override
  12. protected void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.activity_three);
  15. mFl = (FrameLayout) findViewById(R.id.fl);
  16. mRg = (RadioGroup) findViewById(R.id.rg);
  17. mFragments = new ArrayList<>();
  18. for (int i = 0; i < mTiltles.length; i++) {
  19. ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
  20. mFragments.add(itemFragement);
  21. }
  22. mCurFragment = mFragments.get(position);
  23. replaceFragment(mCurFragment);
  24. ((RadioButton)mRg.getChildAt(position)).setChecked(true);
  25. initListener();
  26. }
  27. private void initListener() {
  28. mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
  29. @Override
  30. public void onCheckedChanged(RadioGroup group, int checkedId) {
  31. RadioButton radioButton = (RadioButton) group.findViewById(checkedId);
  32. if (false == radioButton.isChecked()) {
  33. return;
  34. }
  35. switch (checkedId) {
  36. case R.id.rb_home:
  37. position = 0;
  38. break;
  39. case R.id.rb_course:
  40. position = 1;
  41. break;
  42. case R.id.rb_direct_seeding:
  43. position = 2;
  44. break;
  45. case R.id.rb_me:
  46. position = 3;
  47. break;
  48. default:
  49. position = 0;
  50. break;
  51. }
  52. LUtils.i("position==" + position);
  53. Fragment to = mFragments.get(position);
  54. showFragment(mCurFragment, to);
  55. mCurFragment = to;
  56. }
  57. });
  58. }
  59. private void showFragment(Fragment from, Fragment to) {
  60. FragmentManager supportFragmentManager = getSupportFragmentManager();
  61. FragmentTransaction transaction = supportFragmentManager.beginTransaction();
  62. if (!to.isAdded()) { // 先判断是否被add过
  63. transaction.hide(from).add(R.id.fl, to).commit(); // 隐藏当前的fragment,add下一个到Activity中
  64. } else {
  65. transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个
  66. }
  67. }
  68. /**
  69. * 这个方法用老替换fragment
  70. * xujun
  71. * 2016/5/3 17:28.
  72. */
  73. private void replaceFragment(Fragment fragmeny) {
  74. FragmentManager supportFragmentManager = getSupportFragmentManager();
  75. FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
  76. fragmentTransaction.replace(R.id.fl, fragmeny).commit();
  77. }
  78. }

思路解析
- 实例化各个控件,这里代码就不贴出来了
- 初始化 Fragemnt 和选中各个tab

  1. mFragments = new ArrayList<>();
  2. for (int i = 0; i < mTiltles.length; i++) {
  3. ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
  4. mFragments.add(itemFragement);
  5. }
  6. mCurFragment = mFragments.get(position);
  7. replaceFragment(mCurFragment);
  8. ((RadioButton)mRg.getChildAt(position)).setChecked(true);
  9. private void replaceFragment(Fragment fragmeny) {
  10. FragmentManager supportFragmentManager = getSupportFragmentManager();
  11. FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
  12. fragmentTransaction.replace(R.id.fl, fragmeny).commit();
  13. }
  1. mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
  2. @Override
  3. public void onCheckedChanged(RadioGroup group, int checkedId) {
  4. RadioButton radioButton = (RadioButton) group.findViewById(checkedId);
  5. if (false == radioButton.isChecked()) {
  6. return;
  7. }
  8. switch (checkedId) {
  9. case R.id.rb_home:
  10. position = 0;
  11. break;
  12. case R.id.rb_course:
  13. position = 1;
  14. break;
  15. case R.id.rb_direct_seeding:
  16. position = 2;
  17. break;
  18. case R.id.rb_me:
  19. position = 3;
  20. break;
  21. default:
  22. position = 0;
  23. break;
  24. }
  25. LUtils.i("position==" + position);
  26. Fragment to = mFragments.get(position);
  27. showFragment(mCurFragment, to);
  28. mCurFragment = to;
  29. }
  30. });

使用RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab切换

第一步,我们 同样先看布局代码

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. android:id="@+id/activity_second_style"
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. >
  9. <!--用来填充FragemntViewPager-->
  10. <android.support.v4.view.ViewPager
  11. android:id="@+id/viewPager"
  12. android:layout_width="match_parent"
  13. android:layout_height="0dp"
  14. android:layout_weight="1">
  15. </android.support.v4.view.ViewPager>
  16. <!--使用RadioGroup来实现tab的切换-->
  17. <RadioGroup
  18. android:id="@+id/rg"
  19. android:layout_width="match_parent"
  20. android:layout_height="wrap_content"
  21. android:orientation="horizontal"
  22. >
  23. <RadioButton
  24. android:id="@+id/rb_home"
  25. style="@style/bottom_tab"
  26. android:drawableTop="@drawable/sel_home"
  27. android:text="首页"/>
  28. <RadioButton
  29. android:id="@+id/rb_course"
  30. style="@style/bottom_tab"
  31. android:drawableTop="@drawable/sel_course"
  32. android:text="课程"/>
  33. <RadioButton
  34. android:id="@+id/rb_direct_seeding"
  35. style="@style/bottom_tab"
  36. android:drawableTop="@drawable/sel_direct_seeding"
  37. android:text="直播"/>
  38. <RadioButton
  39. android:id="@+id/rb_me"
  40. style="@style/bottom_tab"
  41. android:drawableTop="@drawable/sel_me"
  42. android:text="我的"/>
  43. </RadioGroup>
  44. </LinearLayout>

第二步,我们一起来看一下Activity代码

  1. public class SecondStyleActivity extends AppCompatActivity {
  2. public static final String[] mTiltles = new String[]{
  3. "首页", "课程", "直播", "个人"
  4. };
  5. private List<Fragment> mFragments;
  6. ViewPager mViewPager;
  7. RadioGroup mRg;
  8. private int position = 0;
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_second_style);
  13. mViewPager = (ViewPager) findViewById(R.id.viewPager);
  14. mRg = (RadioGroup) findViewById(R.id.rg);
  15. initListener();
  16. initData();
  17. }
  18. private void initData() {
  19. mFragments = new ArrayList<>();
  20. for (int i = 0; i < mTiltles.length; i++) {
  21. ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
  22. mFragments.add(itemFragement);
  23. }
  24. BaseFragmentAdapter fragmentAdapter = new BaseFragmentAdapter
  25. (getSupportFragmentManager(), mFragments, mTiltles);
  26. mViewPager.setAdapter(fragmentAdapter);
  27. mViewPager.setCurrentItem(position);
  28. ((RadioButton) mRg.getChildAt(position)).setChecked(true);
  29. }
  30. private void initListener() {
  31. mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
  32. @Override
  33. public void onPageSelected(int position) {
  34. RadioButton radioButton = (RadioButton) mRg.getChildAt(position);
  35. radioButton.setChecked(true);
  36. }
  37. });
  38. mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
  39. @Override
  40. public void onCheckedChanged(RadioGroup group, int checkedId) {
  41. RadioButton rb = (RadioButton) group.findViewById(checkedId);
  42. if (!rb.isChecked()) {
  43. return;
  44. }
  45. switch (checkedId) {
  46. case R.id.rb_home:
  47. position = 0;
  48. break;
  49. case R.id.rb_course:
  50. position = 1;
  51. break;
  52. case R.id.rb_direct_seeding:
  53. position = 2;
  54. break;
  55. case R.id.rb_me:
  56. position = 3;
  57. break;
  58. default:
  59. position = 0;
  60. break;
  61. }
  62. mViewPager.setCurrentItem(position);
  63. }
  64. });
  65. }
  66. }

思路解析如下
- 实例化ViewPager和RadioGroup

  1. mViewPager = (ViewPager) findViewById(R.id.viewPager);
  2. mRg = (RadioGroup) findViewById(R.id.rg);
  1. mFragments = new ArrayList<>();
  2. for (int i = 0; i < mTiltles.length; i++) {
  3. ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
  4. mFragments.add(itemFragement);
  5. }
  6. BaseFragmentAdapter fragmentAdapter = new BaseFragmentAdapter
  7. (getSupportFragmentManager(), mFragments, mTiltles);
  8. mViewPager.setAdapter(fragmentAdapter);
  9. mViewPager.setCurrentItem(position);
  10. ((RadioButton) mRg.getChildAt(position)).setChecked(true);
  1. mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
  2. @Override
  3. public void onPageSelected(int position) {
  4. RadioButton radioButton = (RadioButton) mRg.getChildAt(position);
  5. radioButton.setChecked(true);
  6. }
  7. });
  8. mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
  9. @Override
  10. public void onCheckedChanged(RadioGroup group, int checkedId) {
  11. RadioButton rb = (RadioButton) group.findViewById(checkedId);
  12. if (!rb.isChecked()) {
  13. return;
  14. }
  15. switch (checkedId) {
  16. case R.id.rb_home:
  17. position = 0;
  18. break;
  19. case R.id.rb_course:
  20. position = 1;
  21. break;
  22. case R.id.rb_direct_seeding:
  23. position = 2;
  24. break;
  25. case R.id.rb_me:
  26. position = 3;
  27. break;
  28. default:
  29. position = 0;
  30. break;
  31. }
  32. mViewPager.setCurrentItem(position);
  33. }
  34. });

### 注意事项
我们可以通过以下方法设置ViewPager左右页面 能缓存的fragment 数量

  1. // 设置左右页面 能缓存的fragment 数量
  2. mViewPager.setOffscreenPageLimit(fragmentAdapter.getCount() - 1);

到此仿qq底部tab切换的集中方法已经讲解完毕,之所以讲解了 三种方法,是想让大家了解多种实现方式,因为每一个人的习惯bout不一样,有些人习惯使用与第一种方式,有人习惯使用第二种方式。。。了解多种 实现方式以后,我们 要读懂别人 的代码也容易得多了,其实我们还可以使用自定义控件来实现,方法也比较简单,这里就不讲解了,有兴趣的话,可以去 阅读 这篇博客

下面我将为大家讲解Fragment的 一些优化


解决Fragment多次实例化的几种方案

目前本人了解到的解决方案 ,无非是利用一下两种思想

第一种解决方法

在onCreateView中避免多次实例化View,可通过判断View是否为空,来实现相应的 逻辑操作,核心代码如下

  1. public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
  2. Bundle savedInstanceState) {
  3. LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  onCreateView");
  4. if(mView==null){
  5. mContext = getContext();
  6. mView=View.inflate(mContext,getLayoutId(),null);
  7. initView(mView);
  8. LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  initView");
  9. }else{
  10. // 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,
  11. // 要不然会发生这个rootview已经有parent的错误。
  12. ViewGroup parent =(ViewGroup) mView.getParent();
  13. if(parent!=null){
  14. parent.removeView(mView);
  15. }
  16. LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  removeView");
  17. }
  18. return mView;
  19. }

第二种解决方案

在项目中需要进行Fragment的切换,用hide()和show()方法结合起来来替代replace()方法来实现Fragment的切换:

  1. private void showFragment(Fragment from, Fragment to) {
  2. FragmentManager supportFragmentManager = getSupportFragmentManager();
  3. FragmentTransaction transaction = supportFragmentManager.beginTransaction();
  4. if (!to.isAdded()) { // 先判断是否被add过
  5. transaction.hide(from).add(R.id.fl, to).commit(); // 隐藏当前的fragment,add下一个到Activity中
  6. } else {
  7. transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个
  8. }
  9. }
  10. /**
  11. * 这个方法用老替换fragment
  12. * xujun
  13. * 2016/5/3 17:28.
  14. */
  15. private void replaceFragment(Fragment fragmeny) {
  16. FragmentManager supportFragmentManager = getSupportFragmentManager();
  17. FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
  18. fragmentTransaction.replace(R.id.fl, fragmeny).commit();
  19. }

关于 避免Fragment的多次实例化的分析与优化到此为止,下面我们一起来看一下 则那样实现Fragemnt 的 懒加载


Fragemnt的懒加载(网上很多人称之为Fragemnt的最优加载)

关于懒加载的这部分,代码是参考这篇 博客的 ViewPager+Fragment LazyLoad最优解

我们知道 ViewPager通常 会有预加载机制,默认情况下会先加载左右一页的数据,有时候我们想等待页面可见的时候在去加载网络 数据 ,解决方案如下

下面 先贴出代码

  1. public abstract class BasePageFragment extends Fragment {
  2. protected View mView;
  3. /**
  4. * 表示View是否被初始化
  5. */
  6. protected boolean isViewInitiated;
  7. /**
  8. * 表示对用户是否可见
  9. */
  10. protected boolean isVisibleToUser;
  11. /**
  12. * 表示数据是否初始化
  13. */
  14. protected boolean isDataInitiated;
  15. private Context mContext;
  16. @Override
  17. public void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19. LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onCreate");
  20. }
  21. @Nullable
  22. @Override
  23. public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
  24. Bundle savedInstanceState) {
  25. LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onCreateView");
  26. if (mView == null) {
  27. mContext = getContext();
  28. mView = View.inflate(mContext, getLayoutId(), null);
  29. initView(mView);
  30. LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  initView");
  31. } else {
  32. // 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,
  33. // 要不然会发生这个rootview已经有parent的错误。
  34. ViewGroup parent = (ViewGroup) mView.getParent();
  35. if (parent != null) {
  36. parent.removeView(mView);
  37. }
  38. LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  removeView");
  39. }
  40. return mView;
  41. }
  42. protected abstract void initView(View view);
  43. protected abstract int getLayoutId();
  44. @Override
  45. public void onActivityCreated(Bundle savedInstanceState) {
  46. super.onActivityCreated(savedInstanceState);
  47. LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onActivityCreated");
  48. isViewInitiated = true;
  49. initData();
  50. prepareFetchData();
  51. }
  52. @Override
  53. public void setUserVisibleHint(boolean isVisibleToUser) {
  54. super.setUserVisibleHint(isVisibleToUser);
  55. this.isVisibleToUser = isVisibleToUser;
  56. prepareFetchData();
  57. }
  58. public abstract void fetchData();
  59. public boolean prepareFetchData() {
  60. return prepareFetchData(false);
  61. }
  62. /***
  63. *
  64. * @param forceUpdate 表示是否在界面可见的时候是否强制刷新数据
  65. * @return
  66. */
  67. public boolean prepareFetchData(boolean forceUpdate) {
  68. if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
  69. // 界面可见的时候再去加载数据
  70. fetchData();
  71. isDataInitiated = true;
  72. return true;
  73. }
  74. return false;
  75. }
  76. @Override
  77. public void onDestroyView() {
  78. super.onDestroyView();
  79. LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onDestroyView");
  80. }
  81. protected void initData() {
  82. }
  83. }

思路解析:
其实核心思想主要在setUserVisibleHint(boolean isVisibleToUser)方法中,这个方法在Fragemnt界面切换到可见或者 不可见的时候调用,isVisibleToUser表示当前界面可见 或者不可见

setUserVisibleHint(boolean isVisibleToUser)

Set a hint to the system about whether this fragment's UI is currently visible to the user.

于是我们在prepareFetchData进行判断只有当界面可见的情况下才会尝试判断是否调用fetchData() 方法,于是我们就可以实现等到界面可见的 时候才加载网络数据,将我们加载网络数据的 逻辑的实现放在fetchData()
里面即可

  1. /***
  2. *
  3. * @param forceUpdate 表示是否在界面可见的时候是否强制刷新数据
  4. * @return
  5. */
  6. public boolean prepareFetchData(boolean forceUpdate) {
  7. if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
  8. // 界面可见的时候再去加载数据
  9. fetchData();
  10. isDataInitiated = true;
  11. return true;
  12. }
  13. return false;
  14. }

题外话

转眼间校招季已经过去了一个多月了,虽然没能进入到bat,网易之类的公司,不过也找到了相对比较喜欢的公司,接下来的日子就专心做毕业设计了,计划在十一月的时候出省旅游一次,明年春节回来的时候再去公司实习,悄悄地告诉你一件事哦,本人 还没有 出过广东省 ,哈哈,是不是很low呢?

转载请注明博客地址:http://blog.csdn.net/gdutxiaoxu/article/details/52826810

源码下载地址:https://github.com/gdutxiaoxu/QQBottomTab.git

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注