Android 底部导航栏实现

依赖库

    implementation "androidx.viewpager2:viewpager2:1.0.0"

fragment基类

/**
 * Fragment的基类
 *
 * @param <DB> data binding
 * @param <VM> view model
 * @author shizhiyin
 */
public abstract class BaseFragment<DB extends ViewDataBinding, VM extends BaseViewModel>
        extends Fragment {

    protected DB mDataBinding;

    protected VM mViewModel;

    private FragmentBaseBinding mFragmentBaseBinding;

    private ViewLoadingBinding mViewLoadingBinding;

    private ViewLoadErrorBinding mViewLoadErrorBinding;

    private ViewNoNetworkBinding mViewNoNetworkBinding;

    private ViewNoDataBinding mViewNoDataBinding;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args = getArguments();
        if (args != null) {
            handleArguments(args);
        }

        initViewModel();

        // ViewModel订阅生命周期事件
        if (mViewModel != null) {
            getLifecycle().addObserver(mViewModel);
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mFragmentBaseBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_base, container, false);
        mDataBinding = DataBindingUtil.inflate(inflater, getLayoutResId(),
                mFragmentBaseBinding.flContentContainer, true);
        bindViewModel();
        mDataBinding.setLifecycleOwner(this);
        initLoadState();

        initCollectState();

        init();

        return mFragmentBaseBinding.getRoot();
    }

    private void initLoadState() {
        if (mViewModel != null && isSupportLoad()) {
            mViewModel.loadState.observe(getViewLifecycleOwner(), new Observer<LoadState>() {
                @Override
                public void onChanged(LoadState loadState) {
                    switchLoadView(loadState);
                }
            });

        }
    }


    /**
     * 根据加载状态 , 切换不同的View
     *
     * @param loadState
     */
    private void switchLoadView(LoadState loadState) {
        removeLoadView();

        switch (loadState) {
            case LOADING:
                if (mViewLoadingBinding == null) {
                    mViewLoadingBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_loading,
                            mFragmentBaseBinding.flContentContainer, false);
                }
                mFragmentBaseBinding.flContentContainer.addView(mViewLoadingBinding.getRoot());
                break;

            case NO_NETWORK:
                if (mViewNoNetworkBinding == null) {
                    mViewNoNetworkBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_network,
                            mFragmentBaseBinding.flContentContainer, false);
                    mViewNoNetworkBinding.setViewModel(mViewModel);
                }
                mFragmentBaseBinding.flContentContainer.addView(mViewNoNetworkBinding.getRoot());
                break;

            case NO_DATA:
                if (mViewNoDataBinding == null) {
                    mViewNoDataBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_data,
                            mFragmentBaseBinding.flContentContainer, false);
                }
                mFragmentBaseBinding.flContentContainer.addView(mViewNoDataBinding.getRoot());
                break;

            case ERROR:
                if (mViewLoadErrorBinding == null) {
                    mViewLoadErrorBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_load_error,
                            mFragmentBaseBinding.flContentContainer, false);
                    mViewLoadErrorBinding.setViewModel(mViewModel);
                }
                mFragmentBaseBinding.flContentContainer.addView(mViewLoadErrorBinding.getRoot());
                break;

            default:
                break;
        }
    }


    private void removeLoadView() {
        int childCount = mFragmentBaseBinding.flContentContainer.getChildCount();
        if (childCount > 1) {
            mFragmentBaseBinding.flContentContainer.removeViews(1, childCount - 1);
        }
    }

    @SuppressLint("FragmentLiveDataObserve")
    private void initCollectState() {
        if (mViewModel == null) {
            return;
        }
        mViewModel.getCollectStatus().observe(this, new Observer<Object>() {
            @Override
            public void onChanged(Object collect) {
                if (collect == null) {
                
                    //跳转到登录界面
                    LoginActivity.start(getActivity());
                }
            }
        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // ViewModel订阅生命周期事件
        if (mViewModel != null) {
            getLifecycle().removeObserver(mViewModel);
        }
        removeLoadView();
    }


    /**
     * 处理参数
     *
     * @param args 参数容器
     */
    protected void handleArguments(Bundle args) {

    }


    /**
     * 是否支持页面加载。默认不支持
     *
     * @return true表示支持,false表示不支持
     */
    protected boolean isSupportLoad() {
        return false;
    }

    /**
     * 获取当前页面的布局资源ID
     *
     * @return 布局资源ID
     */
    protected abstract int getLayoutResId();

    /**
     * 初始化ViewModel
     */
    protected abstract void initViewModel();

    /**
     * 绑定ViewModel
     */
    protected abstract void bindViewModel();

    /**
     * 初始化
     */
    protected abstract void init();
}

baseActivity

/**
 * Activity的基类
 *
 * @param <DB> data binding
 * @param <VM> view model
 * @author shizhiyin
 */
public abstract class BaseActivity<DB extends ViewDataBinding, VM extends BaseViewModel>
        extends AppCompatActivity {

    public DB mDataBinding;

    protected VM mViewModel;

    private ActivityBaseBinding mActivityBaseBinding;

    private ViewLoadingBinding mViewLoadingBinding;

    private ViewLoadErrorBinding mViewLoadErrorBinding;

    private ViewNoNetworkBinding mViewNoNetworkBinding;

    private ViewNoDataBinding mViewNoDataBinding;

    private BatteryReceiver receiver;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        handleIntent(getIntent());

        if (isNoActionBar()) {
            setNoActionBar();
        }

        mActivityBaseBinding = DataBindingUtil.setContentView(this, R.layout.activity_base);
        mDataBinding = DataBindingUtil.inflate(getLayoutInflater(), getLayoutResId(),
                mActivityBaseBinding.flContentContainer, true);

        initViewModel();
        bindViewModel();

        mDataBinding.setLifecycleOwner(this);

        initLoadState();
        init();

        //注册设备电池监听广播

        receiver = new BatteryReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                super.onReceive(context, intent);

                BatteryManager batteryManager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
                int batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
//                int battery = batteryManager.getIntProperty(BatteryManager.BATTERY_STATUS_CHARGING);
                int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);

                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                    boolean isCharging = false;

                    if (status == 2) {
                        isCharging = true;
                    }

                    handtBatteryData(batteryLevel, isCharging);
                }

                //wifi监测
                Boolean isWifiConnected = isNetworkAvailable(context);

                if (!isWifiConnected) {//没连网络
                    handtWifiData(false, 1);

                } else {//已连网络
                    handtWifiData(true, 2);
                }

            }
        };
        IntentFilter filter2 = new IntentFilter();
        filter2.addAction(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(receiver, filter2);

        // ViewModel订阅生命周期事件
        if (mViewModel != null) {
            getLifecycle().addObserver(mViewModel);
        }
    }

    /**
     * 设置沉浸式状态栏
     */
    private void setNoActionBar() {
        Window window = getWindow();
        View decorView = window.getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
        }
    }


    private void initLoadState() {
        if (mViewModel != null && isSupportLoad()) {
            mViewModel.loadState.observe(this, new Observer<LoadState>() {
                @Override
                public void onChanged(LoadState loadState) {
                    switchLoadView(loadState);
                }
            });
        }
    }

    private void removeLoadView() {
        int childCount = mActivityBaseBinding.flContentContainer.getChildCount();
        if (childCount > 1) {
            mActivityBaseBinding.flContentContainer.removeViews(1, childCount - 1);
        }
    }

    private void switchLoadView(LoadState loadState) {
        removeLoadView();

        switch (loadState) {
            case LOADING:
                if (mViewLoadingBinding == null) {
                    mViewLoadingBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_loading,
                            mActivityBaseBinding.flContentContainer, false);
                }
                mActivityBaseBinding.flContentContainer.addView(mViewLoadingBinding.getRoot());
                break;

            case NO_NETWORK:
                if (mViewNoNetworkBinding == null) {
                    mViewNoNetworkBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_network,
                            mActivityBaseBinding.flContentContainer, false);
                    mViewNoNetworkBinding.setViewModel(mViewModel);
                }
                mActivityBaseBinding.flContentContainer.addView(mViewNoNetworkBinding.getRoot());
                break;

            case NO_DATA:
                if (mViewNoDataBinding == null) {
                    mViewNoDataBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_no_data,
                            mActivityBaseBinding.flContentContainer, false);
                }
                mActivityBaseBinding.flContentContainer.addView(mViewNoDataBinding.getRoot());
                break;

            case ERROR:
                if (mViewLoadErrorBinding == null) {
                    mViewLoadErrorBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.view_load_error,
                            mActivityBaseBinding.flContentContainer, false);
                }
                mActivityBaseBinding.flContentContainer.addView(mViewLoadErrorBinding.getRoot());
                break;

            default:
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

    /**
     * 电池
     * 连接状态
     */
    protected void handtBatteryData(int batteryLevel, boolean isCharging) {

    }

    /**
     * wifi
     * 连接状态
     */
    protected void handtWifiData(boolean isConnected, int level) {

    }

    /**
     * 处理参数
     *
     * @param intent 参数容器
     */
    protected void handleIntent(Intent intent) {

    }

    /**
     * 是否为沉浸模式
     *
     * @return true表示支持,false表示不支持
     */
    protected boolean isNoActionBar() {
        return false;
    }


    /**
     * 是否支持页面加载。默认不支持
     *
     * @return true表示支持,false表示不支持
     */
    protected boolean isSupportLoad() {
        return false;
    }

    /**
     * 获取当前页面的布局资源ID
     *
     * @return 布局资源ID
     */
    protected abstract int getLayoutResId();

    /**
     * 初始化ViewModel
     */
    protected abstract void initViewModel();

    /**
     * 绑定ViewModel
     */
    protected abstract void bindViewModel();

    /**
     * 初始化
     */
    protected abstract void init();

}

一、Fragment + TextView 实现

1、主界面

/**
 * 主界面
 */
public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> {

    public static void start(Context context, Boolean isLogin) {
        Intent intent = new Intent(context, MainActivity.class);
        intent.putExtra(Constants.ParamCode.PARAM1, isLogin);
        context.startActivity(intent);
    }

    @Override
    protected void handleIntent(Intent intent) {

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


    }

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initViewModel() {
        mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
    }

    @Override
    protected void bindViewModel() {

    }

    private List<Fragment> fragmentList;
    private ContentPagerAdapter contentPagerAdapter;

    @Override
    protected void init() {
        initView();

        fragmentList = new ArrayList<>();

        fragmentList.add(new HomeFragment());
        fragmentList.add(new ShoppingFragment());
        fragmentList.add(new LifeServicesFragment());
        fragmentList.add(new EduStewarFragment());
        fragmentList.add(new PersonCenterFragment());

        contentPagerAdapter = new ContentPagerAdapter(this, fragmentList);
        mDataBinding.viewPager.setAdapter(contentPagerAdapter);

        mDataBinding.textViewHome.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(0, false));
        mDataBinding.textViewShopping.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(1, false));
        mDataBinding.textViewLifeServices.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(2, false));
        mDataBinding.textviewEduStewar.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(3, false));
        mDataBinding.textviewPersonCenter.setOnClickListener(v -> mDataBinding.viewPager.setCurrentItem(4, false));

        mDataBinding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // 当页面滑动时调用
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);

                changeState(position);
            }

            @Override
            public void onPageSelected(int position) {
                // 当页面被选中时调用
                super.onPageSelected(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                // 当页面滑动状态改变时调用
                super.onPageScrollStateChanged(state);
            }
        });
    }


    /**
     * 改变
     * 导航栏样式
     */
    private void changeState(int position) {

        mDataBinding.textViewHome.setTextColor(Color.parseColor("#93A5EE"));
        mDataBinding.textViewShopping.setTextColor(Color.parseColor("#93A5EE"));
        mDataBinding.textViewLifeServices.setTextColor(Color.parseColor("#93A5EE"));
        mDataBinding.textviewEduStewar.setTextColor(Color.parseColor("#93A5EE"));
        mDataBinding.textviewPersonCenter.setTextColor(Color.parseColor("#93A5EE"));

        switch (position) {
            case 0:
                mDataBinding.textViewHome.setTextColor(Color.parseColor("#52FDFF"));
                break;
            case 1:
                mDataBinding.textViewShopping.setTextColor(Color.parseColor("#52FDFF"));
                break;
            case 2:
                mDataBinding.textViewLifeServices.setTextColor(Color.parseColor("#52FDFF"));
                break;
            case 3:
                mDataBinding.textviewEduStewar.setTextColor(Color.parseColor("#52FDFF"));
                break;
            case 4:
                mDataBinding.textviewPersonCenter.setTextColor(Color.parseColor("#52FDFF"));
                break;
            default:
                mDataBinding.textViewHome.setTextColor(Color.parseColor("#52FDFF"));
                break;
        }

    }

    @Override
    protected void onResume() {
        super.onResume();

    }


    /**
     * 初始view
     */
    private void initView() {

    }


    @Override
    public void onBackPressed() {
//        super.onBackPressed();
    }
}

2、xml布局

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="@dimen/dp_640"
        android:layout_height="@dimen/dp_400">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager"
            android:layout_width="@dimen/dp_640"
            android:layout_height="350dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <LinearLayout
            android:id="@+id/bottom_navigation"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:background="#00064F"
            android:orientation="horizontal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent">

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center">

                <TextView
                    android:id="@+id/textViewHome"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:clickable="true"
                    android:focusable="true"
                    android:gravity="center"
                    android:text="首页"
                    android:textColor="#52FDFF"
                    android:textSize="@dimen/sp_10" />
            </LinearLayout>

            <TextView
                android:id="@+id/textViewShopping"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:clickable="true"
                android:focusable="true"
                android:gravity="center"
                android:text="商城"
                android:textColor="#52FDFF"
                android:textSize="@dimen/sp_10" />

            <TextView
                android:id="@+id/textViewLifeServices"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:clickable="true"
                android:focusable="true"
                android:gravity="center"
                android:text="服务"
                android:textColor="#52FDFF"
                android:textSize="@dimen/sp_10" />

            <TextView
                android:id="@+id/textviewEduStewar"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:clickable="true"
                android:focusable="true"
                android:gravity="center"
                android:text="管家"
                android:textColor="#52FDFF"
                android:textSize="@dimen/sp_10" />

            <TextView
                android:id="@+id/textviewPersonCenter"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:clickable="true"
                android:focusable="true"
                android:gravity="center"
                android:text="个人"
                android:textColor="#52FDFF"
                android:textSize="@dimen/sp_10" />

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

3、首页

3.1 fragment代码

public class HomeFragment extends BaseFragment<HomeFragmentLayoutBinding,HomeFragmentViewmodel> {

    @Override
    protected int getLayoutResId() {
        return R.layout.home_fragment_layout;
    }

    @Override
    protected void initViewModel() {

    }

    @Override
    protected void bindViewModel() {

    }

    @Override
    protected void init() {

    }
}

3.2 布局代码

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="@dimen/dp_640"
        android:layout_height="@dimen/dp_400"
        android:background="@color/color_red">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="首页"
            android:textColor="@color/white"
            android:textSize="@dimen/sp_16"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

4、商场页面

4.1fragment代码

public class ShoppingFragment extends BaseFragment<ShoppingFragmentLayoutBinding, ShoppingFragmentViewModel> {

    @Override
    protected int getLayoutResId() {
        return R.layout.shopping_fragment_layout;
    }

    @Override
    protected void initViewModel() {

    }

    @Override
    protected void bindViewModel() {

    }

    @Override
    protected void init() {

    }

}

4.2布局代码

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="@dimen/dp_640"
        android:layout_height="@dimen/dp_400"
        android:background="@color/green">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="小雅购物"
            android:textColor="@color/white"
            android:textSize="@dimen/sp_16"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

5、服务页面

5.1服务fragment

public class LifeServicesFragment extends BaseFragment<LifeServicesFragmentLayoutBinding, LifeServicesFragmentViewmodel> {

    @Override
    protected int getLayoutResId() {
        return R.layout.life_services_fragment_layout;
    }

    @Override
    protected void initViewModel() {

    }

    @Override
    protected void bindViewModel() {

    }

    @Override
    protected void init() {

    }

}

5.2服务布局页面

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="@dimen/dp_640"
        android:layout_height="@dimen/dp_400"
        android:background="@color/color_red">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="生活服务"
            android:textColor="@color/white"
            android:textSize="@dimen/sp_16"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

6、教育页面

6.1教育fragment代码

/**
 * 教育管家
 */
public class EduStewarFragment extends BaseFragment<EduStewarFragmentLayoutBinding, EduStewarFragmentViewmodel> {

    @Override
    protected int getLayoutResId() {
        return R.layout.edu_stewar_fragment_layout;
    }

    @Override
    protected void initViewModel() {

    }

    @Override
    protected void bindViewModel() {

    }

    @Override
    protected void init() {

    }

}

6.2教育布局代码

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="@dimen/dp_640"
        android:layout_height="@dimen/dp_400"
        android:background="@color/color_red">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="教育管家"
            android:textColor="@color/white"
            android:textSize="@dimen/sp_16"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

7、个人中心

7.1个人中心fragment

public class PersonCenterFragment extends BaseFragment<PersonCenterBinding,PersonCenterVieMOdel> {

    @Override
    protected int getLayoutResId() {
        return R.layout.person_center;
    }

    @Override
    protected void initViewModel() {

    }

    @Override
    protected void bindViewModel() {

    }

    @Override
    protected void init() {

    }
}

7.2个人中心布局页面

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="@dimen/dp_640"
        android:layout_height="@dimen/dp_400">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="个人中心"
            android:textColor="@color/black"
            android:textSize="@dimen/sp_16"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"  />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

二、RadioGroup + ViewPager 实现

三、BottomNavigationView+ViewPager+fragment 实现

四、TabLayout+fragment+viewPager 实现

相关推荐
Estar.Lee40 分钟前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯1 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey3 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!4 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟5 小时前
Android音频采集
android·音视频
小白也想学C6 小时前
Android 功耗分析(底层篇)
android·功耗
曙曙学编程6 小时前
初级数据结构——树
android·java·数据结构
闲暇部落9 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX11 小时前
Android 分区相关介绍
android
大白要努力!11 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle