前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >仿qq底部Tab导航

仿qq底部Tab导航

作者头像
程序员徐公
发布2018-09-18 16:56:09
2K0
发布2018-09-18 16:56:09
举报

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1341884

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

  • 使用FragmentTabHost实现qq底部Tab切换
  • 使用RadioGroup和RadioButton实现仿qq底部切换
  • 使用RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab切换
  • 解决Fragment多次实例化的几种方案
  • Fragemnt的懒加载(网上很多人称之为Fragemnt的最优加载)

效果图

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

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

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

使用FragmentTabHost实现qq底部Tab切换

第一步先看布局文件

代码语言:javascript
复制
<?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">
    <!--用来填充Fragemnt的FrayLayout-->
    <FrameLayout
        android:id="@+id/main_layout_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </FrameLayout>
    <!--FragmentTabHost-->
    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#F6F6F6"
        android:paddingBottom="5dp"
        android:paddingTop="5dp">

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"/>
    </android.support.v4.app.FragmentTabHost>

</LinearLayout>

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

接下来我们来看一下代码

代码语言:javascript
复制
public class FirstStyleActivity extends AppCompatActivity {
    FragmentTabHost mTabHost;
    private TabWidget mTabWidget;
    private List<FragmentInfo> mFragmentEntities;
    private static final String TAG = "xujun";
    private static final String tag = "tag";
    public static final String[] mTiltles = new String[]{
            "首页", "课程", "直播", "个人"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first_style);
        mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);

        mTabHost.setup(this, getSupportFragmentManager(), R.id.main_layout_content);
        mTabWidget = mTabHost.getTabWidget();
        //  去掉分割线
        mTabWidget.setDividerDrawable(null);
        mFragmentEntities = MainFragmentFactory.getInstance().getList();
        initListener();
        initData();


    }

    private void initData() {
        int size = mFragmentEntities.size();
        for (int i = 0; i < size; i++) {
            Log.i(TAG, "size:=" + size);
            FragmentInfo fragmentInfo = mFragmentEntities.get(i);
            String title = fragmentInfo.getTitle();
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(title).setIndicator(getTabView
                    (i));
            Bundle bundle = new Bundle();
            bundle.putString(tag, mTiltles[i]);

            mTabHost.addTab(tabSpec, fragmentInfo.getClz(), bundle);
        }
        updateTab(0);
    }

    private void initListener() {
        mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
            @Override
            public void onTabChanged(String tabId) {
                int currentTab = mTabHost.getCurrentTab();
                Log.i(TAG, "onTabChanged:currentTab:=" + currentTab);
                updateTab(currentTab);
            }
        });
    }

    private View getTabView(int i) {
        View view = View.inflate(this, R.layout.tab_layout, null);
        int currentTab = mTabHost.getCurrentTab();
        Log.i(TAG, "currentTab:=" + currentTab);
        setSingleView(view, currentTab, i);
        return view;
    }

    private void setSingleView(View view, int currentTab, int index) {
        FragmentInfo fragmentInfo = mFragmentEntities.get(index);
        int[] imagIds = fragmentInfo.getImagIds();
        int[] colors = fragmentInfo.getColors();
        TextView tv = (TextView) view.findViewById(R.id.tab_tv);
        ImageView iv = (ImageView) view.findViewById(R.id.tab_icon);
        tv.setText(fragmentInfo.getTitle());
        Resources resources = getResources();
        if (index == currentTab) {

            tv.setTextColor(resources.getColor(colors[1]));
            iv.setImageDrawable(resources.getDrawable(imagIds[1]));
        } else {
            tv.setTextColor(getResources().getColor(colors[0]));
            iv.setImageDrawable(resources.getDrawable(imagIds[0]));
        }
    }

    private void updateTab(int currentTab) {

        int childCount = mTabWidget.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View view = mTabWidget.getChildTabViewAt(i);
            setSingleView(view, currentTab, i);

        }


    }
}

其实说起来也很简单,主要分为以下步骤

  • 第一步,实例化FragmentTabHost并设置相关样式
代码语言:javascript
复制
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);

mTabHost.setup(this, getSupportFragmentManager(), R.id.main_layout_content);
mTabWidget = mTabHost.getTabWidget();
//  去掉分割线
mTabWidget.setDividerDrawable(null);
  • 第二步,添加每一个TabHost
代码语言:javascript
复制
 for (int i = 0; i < size; i++) {
    Log.i(TAG, "size:=" + size);
    FragmentInfo fragmentInfo = mFragmentEntities.get(i);
    String title = fragmentInfo.getTitle();
    TabHost.TabSpec tabSpec = mTabHost.newTabSpec(title).setIndicator(getTabView
            (i));
    Bundle bundle = new Bundle();
    bundle.putString(tag, mTiltles[i]);

    mTabHost.addTab(tabSpec, fragmentInfo.getClz(), bundle);
}
  • 第三步,通过设置 监听器来实现底部tab颜色和图案样式的转换
代码语言:javascript
复制
 mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
    @Override
    public void onTabChanged(String tabId) {
        int currentTab = mTabHost.getCurrentTab();
        Log.i(TAG, "onTabChanged:currentTab:=" + currentTab);
        updateTab(currentTab);
    }
});

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


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

第一步 ,先看布局文件

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/activity_second_style"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
>
    <!--用来填充Fragemnt的FrayLayout-->
    <FrameLayout
        android:id="@+id/fl"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

    </FrameLayout>
    <!--使用RadioGroup来实现tab的切换-->
    <RadioGroup

        android:id="@+id/rg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
    >
        <RadioButton
            android:id="@+id/rb_home"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_home"
            android:text="首页"/>

        <RadioButton
            android:id="@+id/rb_course"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_course"
            android:text="课程"/>

        <RadioButton
            android:id="@+id/rb_direct_seeding"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_direct_seeding"
            android:text="直播"/>

        <RadioButton
            android:id="@+id/rb_me"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_me"
            android:text="我的"/>

    </RadioGroup>

</LinearLayout>

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

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

代码语言:javascript
复制
<style name="bottom_tab">
    <item name="android:layout_width" >0dp</item>
    <item name="android:layout_height" >wrap_content</item>
    <item name="android:layout_weight" >1</item>
    <item name="android:text" >0dp</item>
    <item name="android:gravity" >center</item>
    <item name="android:textColor" >@drawable/sel_bottom_tab_text</item>
    <item name="android:padding" >8dp</item>
    <item name="android:button" >@null</item>
</style>

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

代码语言:javascript
复制
public class ThreeActivity extends AppCompatActivity {

    FrameLayout mFl;
    RadioGroup mRg;
    private FragmentManager mFragmentManager;

    private int position = 0;

    public static final String[] mTiltles = new String[]{
            "首页", "课程", "直播", "个人"
    };
    private List<Fragment> mFragments;
    private Fragment mCurFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_three);
        mFl = (FrameLayout) findViewById(R.id.fl);
        mRg = (RadioGroup) findViewById(R.id.rg);
        mFragments = new ArrayList<>();
        for (int i = 0; i < mTiltles.length; i++) {
            ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
            mFragments.add(itemFragement);
        }
        mCurFragment = mFragments.get(position);
        replaceFragment(mCurFragment);

        ((RadioButton)mRg.getChildAt(position)).setChecked(true);

        initListener();
    }

    private void initListener() {
        mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {

                RadioButton radioButton = (RadioButton) group.findViewById(checkedId);

                if (false == radioButton.isChecked()) {
                    return;
                }


                switch (checkedId) {
                    case R.id.rb_home:
                        position = 0;
                        break;

                    case R.id.rb_course:
                        position = 1;
                        break;

                    case R.id.rb_direct_seeding:
                        position = 2;
                        break;

                    case R.id.rb_me:
                        position = 3;
                        break;
                    default:
                        position = 0;
                        break;

                }
                LUtils.i("position==" + position);

                Fragment to = mFragments.get(position);
                showFragment(mCurFragment, to);
                mCurFragment = to;

            }

        });
    }

    private void showFragment(Fragment from, Fragment to) {
        FragmentManager supportFragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = supportFragmentManager.beginTransaction();
        if (!to.isAdded()) {    // 先判断是否被add过
            transaction.hide(from).add(R.id.fl, to).commit(); // 隐藏当前的fragment,add下一个到Activity中
        } else {
            transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个
        }

    }

    /**
     * 这个方法用老替换fragment
     * xujun
     * 2016/5/3 17:28.
     */

    private void replaceFragment(Fragment fragmeny) {
        FragmentManager supportFragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fl, fragmeny).commit();
    }

}

思路解析

  • 实例化各个控件,这里代码就不贴出来了
  • 初始化 Fragemnt 和选中各个tab
代码语言:javascript
复制
 mFragments = new ArrayList<>();
for (int i = 0; i < mTiltles.length; i++) {
    ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
    mFragments.add(itemFragement);
}
mCurFragment = mFragments.get(position);
replaceFragment(mCurFragment);

((RadioButton)mRg.getChildAt(position)).setChecked(true);

private void replaceFragment(Fragment fragmeny) {
    FragmentManager supportFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.fl, fragmeny).commit();
}
  • 第三步,通过监听RadioGroup的 OnCheckedChangeListener事件,来实现tab和Fragemnt的切换
代码语言:javascript
复制
 mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {

        RadioButton radioButton = (RadioButton) group.findViewById(checkedId);

        if (false == radioButton.isChecked()) {
            return;
        }


        switch (checkedId) {
            case R.id.rb_home:
                position = 0;
                break;

            case R.id.rb_course:
                position = 1;
                break;

            case R.id.rb_direct_seeding:
                position = 2;
                break;

            case R.id.rb_me:
                position = 3;
                break;
            default:
                position = 0;
                break;

        }
        LUtils.i("position==" + position);

        Fragment to = mFragments.get(position);
        showFragment(mCurFragment, to);
        mCurFragment = to;

    }

});

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

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

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/activity_second_style"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
>
    <!--用来填充Fragemnt的ViewPager-->
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

    </android.support.v4.view.ViewPager>
    <!--使用RadioGroup来实现tab的切换-->
    <RadioGroup

        android:id="@+id/rg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
    >
        <RadioButton
            android:id="@+id/rb_home"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_home"
            android:text="首页"/>

        <RadioButton
            android:id="@+id/rb_course"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_course"
            android:text="课程"/>

        <RadioButton
            android:id="@+id/rb_direct_seeding"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_direct_seeding"
            android:text="直播"/>

        <RadioButton
            android:id="@+id/rb_me"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_me"
            android:text="我的"/>

    </RadioGroup>

</LinearLayout>

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

代码语言:javascript
复制
public class SecondStyleActivity extends AppCompatActivity {

    public static final String[] mTiltles = new String[]{
            "首页", "课程", "直播", "个人"
    };
    private List<Fragment> mFragments;
    ViewPager mViewPager;
    RadioGroup mRg;
    private int position = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second_style);
        mViewPager = (ViewPager) findViewById(R.id.viewPager);
        mRg = (RadioGroup) findViewById(R.id.rg);
        initListener();
        initData();


    }

    private void initData() {
        mFragments = new ArrayList<>();
        for (int i = 0; i < mTiltles.length; i++) {
            ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
            mFragments.add(itemFragement);
        }
        BaseFragmentAdapter fragmentAdapter = new BaseFragmentAdapter
                (getSupportFragmentManager(), mFragments, mTiltles);
        mViewPager.setAdapter(fragmentAdapter);
        mViewPager.setCurrentItem(position);
        ((RadioButton) mRg.getChildAt(position)).setChecked(true);
    }

    private void initListener() {
        mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                RadioButton radioButton = (RadioButton) mRg.getChildAt(position);
                radioButton.setChecked(true);
            }
        });

        mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                RadioButton rb = (RadioButton) group.findViewById(checkedId);
                if (!rb.isChecked()) {
                    return;
                }
                switch (checkedId) {
                    case R.id.rb_home:
                        position = 0;
                        break;

                    case R.id.rb_course:
                        position = 1;
                        break;

                    case R.id.rb_direct_seeding:
                        position = 2;
                        break;

                    case R.id.rb_me:
                        position = 3;
                        break;
                    default:
                        position = 0;
                        break;

                }
                mViewPager.setCurrentItem(position);
            }
        });
    }
}

思路解析如下

  • 实例化ViewPager和RadioGroup
代码语言:javascript
复制
 mViewPager = (ViewPager) findViewById(R.id.viewPager);
 mRg = (RadioGroup) findViewById(R.id.rg);
  • 第二步,初始化ViewPager的适配器和选中 那个tab
代码语言:javascript
复制
 mFragments = new ArrayList<>();
for (int i = 0; i < mTiltles.length; i++) {
    ItemFragement itemFragement = ItemFragement.newInstance(mTiltles[i]);
    mFragments.add(itemFragement);
}
BaseFragmentAdapter fragmentAdapter = new BaseFragmentAdapter
        (getSupportFragmentManager(), mFragments, mTiltles);
mViewPager.setAdapter(fragmentAdapter);
mViewPager.setCurrentItem(position);
((RadioButton) mRg.getChildAt(position)).setChecked(true);
  • 第三步,监听ViewPager 的滑动事件和RadioGroup的OnCheckedChangeListener事件,分别切换到相应的 Fragemnt 和同步ViewPager中 position 与RadioGroup之间的联系
代码语言:javascript
复制
 mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        RadioButton radioButton = (RadioButton) mRg.getChildAt(position);
        radioButton.setChecked(true);
    }
});

mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        RadioButton rb = (RadioButton) group.findViewById(checkedId);
        if (!rb.isChecked()) {
            return;
        }
        switch (checkedId) {
            case R.id.rb_home:
                position = 0;
                break;

            case R.id.rb_course:
                position = 1;
                break;

            case R.id.rb_direct_seeding:
                position = 2;
                break;

            case R.id.rb_me:
                position = 3;
                break;
            default:
                position = 0;
                break;

        }
        mViewPager.setCurrentItem(position);
    }
});

注意事项

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

代码语言:javascript
复制
//  设置左右页面 能缓存的fragment 数量
mViewPager.setOffscreenPageLimit(fragmentAdapter.getCount() - 1);

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

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


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

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

第一种解决方法

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

代码语言:javascript
复制
   public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
            Bundle savedInstanceState) {
        LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  onCreateView");
        if(mView==null){
            mContext = getContext();
            mView=View.inflate(mContext,getLayoutId(),null);
            initView(mView);
            LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  initView");
        }else{
            // 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,
            // 要不然会发生这个rootview已经有parent的错误。
            ViewGroup parent =(ViewGroup) mView.getParent();
            if(parent!=null){
                parent.removeView(mView);
            }
            LUtils.i(getClass().getSimpleName()+">>>>>>>>>>>  removeView");
        }
        return mView;
    }

第二种解决方案

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

代码语言:javascript
复制
private void showFragment(Fragment from, Fragment to) {
    FragmentManager supportFragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = supportFragmentManager.beginTransaction();
    if (!to.isAdded()) {    // 先判断是否被add过
        transaction.hide(from).add(R.id.fl, to).commit(); // 隐藏当前的fragment,add下一个到Activity中
    } else {
        transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个
    }

}

/**
 * 这个方法用老替换fragment
 * xujun
 * 2016/5/3 17:28.
 */

private void replaceFragment(Fragment fragmeny) {
    FragmentManager supportFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.fl, fragmeny).commit();
}

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


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

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

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

下面 先贴出代码

代码语言:javascript
复制
public abstract class BasePageFragment extends Fragment {

    protected View mView;

    /**
     * 表示View是否被初始化
     */
    protected boolean isViewInitiated;
    /**
     * 表示对用户是否可见
     */
    protected boolean isVisibleToUser;
    /**
     * 表示数据是否初始化
     */
    protected boolean isDataInitiated;
    private Context mContext;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onCreate");
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
            Bundle savedInstanceState) {
        LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onCreateView");
        if (mView == null) {
            mContext = getContext();
            mView = View.inflate(mContext, getLayoutId(), null);
            initView(mView);
            LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  initView");
        } else {
            // 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,
            // 要不然会发生这个rootview已经有parent的错误。
            ViewGroup parent = (ViewGroup) mView.getParent();
            if (parent != null) {
                parent.removeView(mView);
            }
            LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  removeView");
        }
        return mView;
    }

    protected abstract void initView(View view);

    protected abstract int getLayoutId();

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onActivityCreated");
        isViewInitiated = true;
        initData();
        prepareFetchData();
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser = isVisibleToUser;
        prepareFetchData();
    }

    public abstract void fetchData();

    public boolean prepareFetchData() {
        return prepareFetchData(false);
    }

    /***
     * 
     * @param forceUpdate 表示是否在界面可见的时候是否强制刷新数据
     * @return
     */
    public boolean prepareFetchData(boolean forceUpdate) {
        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
            //  界面可见的时候再去加载数据
            fetchData();
            isDataInitiated = true;
            return true;
        }
        return false;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        LUtils.i(getClass().getSimpleName() + ">>>>>>>>>>>  onDestroyView");
    }

    protected void initData() {
    }

}

思路解析:

其实核心思想主要在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()

里面即可

代码语言:javascript
复制
/***
 *
 * @param forceUpdate 表示是否在界面可见的时候是否强制刷新数据
 * @return
 */
public boolean prepareFetchData(boolean forceUpdate) {
    if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
        //  界面可见的时候再去加载数据
        fetchData();
        isDataInitiated = true;
        return true;
    }
    return false;
}

题外话

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年10月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本篇博客主要实现以下效果:
  • 效果图
    • FragmentTabHost实现qq底部Tab实践的效果图
      • RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab效果图
      • 使用FragmentTabHost实现qq底部Tab切换
        • 第一步先看布局文件
          • 接下来我们来看一下代码
            • 运行上述代码及可以看到如下效果图
            • 使用RadioGroup和RadioButton实现仿qq底部切换
              • 第一步 ,先看布局文件
                • 第二步,我们来看一下Activity的 代码
                • 使用RadioGroup和ViewPager 实现可以滑动切换的仿qq底部Tab切换
                  • 第一步,我们 同样先看布局代码
                    • 第二步,我们一起来看一下Activity代码
                      • 注意事项
                      • 解决Fragment多次实例化的几种方案
                        • 第一种解决方法
                          • 第二种解决方案
                          • Fragemnt的懒加载(网上很多人称之为Fragemnt的最优加载)
                          • 题外话
                          相关产品与服务
                          云直播
                          云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档