IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 仿qq底部Tab导航,安卓app开发软件 -> 正文阅读

[移动开发]仿qq底部Tab导航,安卓app开发软件

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


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


第一步 ,先看布局文件

<?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”

<FrameLayout

android:id="@+id/fl"

android:layout_width=“match_parent”

android:layout_height=“0dp”

android:layout_weight=“1”>

<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=“我的”/>

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

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

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

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,显示下一个

}

}

/**

  • 这个方法用老替换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

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的切换

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切换


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

<?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”

<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

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=“我的”/>

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

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);

}

});

}

}

思路解析如下

  • 实例化ViewPager和RadioGroup

mViewPager = (ViewPager) findViewById(R.id.viewPager);

mRg = (RadioGroup) findViewById(R.id.rg);

  • 第二步,初始化ViewPager的适配器和选中 那个tab

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之间的联系

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,显示下一个

}

}

/**

  • 这个方法用老替换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通常 会有预加载机制,默认情况下会先加载左右一页的数据,有时候我们想等待页面可见的时候在去加载网络 数据 ,解决方案如下

下面 先贴出代码

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);

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);

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-16 17:47:32  更:2021-12-16 17:49:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:15:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码