使用RadioGroup和RadioButton实现仿qq底部切换
第一步 ,先看布局文件
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” android:id="@+id/fl" android:layout_width=“match_parent” android:layout_height=“0dp” android:layout_weight=“1”> android:id="@+id/rg" android:layout_width=“match_parent” android:layout_height=“wrap_content” android:orientation=“horizontal” android:id="@+id/rb_home" android:drawableTop="@drawable/sel_home" android:text=“首页”/> android:id="@+id/rb_course" android:drawableTop="@drawable/sel_course" android:text=“课程”/> android:id="@+id/rb_direct_seeding" android:drawableTop="@drawable/sel_direct_seeding" android:text=“直播”/> android:id="@+id/rb_me" android:drawableTop="@drawable/sel_me" android:text=“我的”/> 其实每一个tab的选中时利用RadioGroup中RadioButton的互相排斥的特性,即每一次只能选中一个 RadioButton 至于bottom_tab的style,只不过是将相同的arr提取出来,减少布局的代码量和方便统一修改而已,平时我们在写布局代码 的时候也可以这样 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 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,显示下一个 } } private void replaceFragment(Fragment fragmeny) { FragmentManager supportFragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.fl, fragmeny).commit(); } } 思路解析 实例化各个控件,这里代码就不贴出来了 初始化 Fragemnt 和选中各个tab 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(); } 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切换 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”
android:id="@+id/viewPager" android:layout_width=“match_parent” android:layout_height=“0dp” android:layout_weight=“1”> android:id="@+id/rg" android:layout_width=“match_parent” android:layout_height=“wrap_content” android:orientation=“horizontal” android:id="@+id/rb_home" android:drawableTop="@drawable/sel_home" android:text=“首页”/> android:id="@+id/rb_course" android:drawableTop="@drawable/sel_course" android:text=“课程”/> android:id="@+id/rb_direct_seeding" android:drawableTop="@drawable/sel_direct_seeding" android:text=“直播”/> android:id="@+id/rb_me" android:drawableTop="@drawable/sel_me" android:text=“我的”/> public class SecondStyleActivity extends AppCompatActivity { public static final String[] mTiltles = new String[]{ “首页”, “课程”, “直播”, “个人” }; private List mFragments; ViewPager mViewPager; RadioGroup mRg; pr 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》 【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享 ivate 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); } }); } } 思路解析如下 mViewPager = (ViewPager) findViewById(R.id.viewPager); 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); } baseFragmentAdapter fragmentAdapter = new baseFragmentAdapter (getSupportFragmentManager(), mFragments, mTiltles); mViewPager.setAdapter(fragmentAdapter); mViewPager.setCurrentItem(position); ((RadioButton) mRg.getChildAt(position)).setChecked(true); 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 数量 // 设置左右页面 能缓存的fragment 数量 mViewPager.setOffscreenPageLimit(fragmentAdapter.getCount() - 1); 到此仿qq底部tab切换的集中方法已经讲解完毕,之所以讲解了 三种方法,是想让大家了解多种实现方式,因为每一个人的习惯都不一样,有些人习惯使用与第一种方式,有人习惯使用第二种方式 。。。。。。了解多种 实现方式以后,我们要读懂别人的代码也容易得多了,其实我们还可以使用自定义控件来实现,方法也比较简单,这里就不讲解了,有兴趣的话,可以自行搜索 下面我将为大家讲解Fragment的 一些优化 解决Fragment多次实例化的几种方案 目前本人了解到的解决方案 ,无非是利用一下两种思想 在onCreateView中避免多次实例化View,可通过判断View是否为空,来实现相应的 逻辑操作,核心代码如下 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的切换: 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,显示下一个 } } 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通常 会有预加载机制,默认情况下会先加载左右一页的数据,有时候我们想等待页面可见的时候在去加载网络 数据 ,解决方案如下 下面 先贴出代码 public abstract class basePageFragment extends Fragment { protected View mView; 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); s().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);
第一步,我们 同样先看布局代码



