当前位置: 首页 > news >正文

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;@Overridepublic 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@Overridepublic 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>() {@Overridepublic 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>() {@Overridepublic void onChanged(Object collect) {if (collect == null) {//跳转到登录界面LoginActivity.start(getActivity());}}});}@Overridepublic 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;@Overrideprotected 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() {@Overridepublic 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>() {@Overridepublic 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;}}@Overrideprotected 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);}@Overrideprotected void handleIntent(Intent intent) {}@Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overrideprotected int getLayoutResId() {return R.layout.activity_main;}@Overrideprotected void initViewModel() {mViewModel = new ViewModelProvider(this).get(MainViewModel.class);}@Overrideprotected void bindViewModel() {}private List<Fragment> fragmentList;private ContentPagerAdapter contentPagerAdapter;@Overrideprotected 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() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {// 当页面滑动时调用super.onPageScrolled(position, positionOffset, positionOffsetPixels);changeState(position);}@Overridepublic void onPageSelected(int position) {// 当页面被选中时调用super.onPageSelected(position);}@Overridepublic 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;}}@Overrideprotected void onResume() {super.onResume();}/*** 初始view*/private void initView() {}@Overridepublic 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.ConstraintLayoutandroid:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"><androidx.viewpager2.widget.ViewPager2android: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" /><LinearLayoutandroid: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"><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"><TextViewandroid: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><TextViewandroid: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" /><TextViewandroid: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" /><TextViewandroid: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" /><TextViewandroid: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> {@Overrideprotected int getLayoutResId() {return R.layout.home_fragment_layout;}@Overrideprotected void initViewModel() {}@Overrideprotected void bindViewModel() {}@Overrideprotected 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.ConstraintLayoutandroid:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"android:background="@color/color_red"><TextViewandroid: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> {@Overrideprotected int getLayoutResId() {return R.layout.shopping_fragment_layout;}@Overrideprotected void initViewModel() {}@Overrideprotected void bindViewModel() {}@Overrideprotected 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.ConstraintLayoutandroid:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"android:background="@color/green"><TextViewandroid: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> {@Overrideprotected int getLayoutResId() {return R.layout.life_services_fragment_layout;}@Overrideprotected void initViewModel() {}@Overrideprotected void bindViewModel() {}@Overrideprotected 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.ConstraintLayoutandroid:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"android:background="@color/color_red"><TextViewandroid: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> {@Overrideprotected int getLayoutResId() {return R.layout.edu_stewar_fragment_layout;}@Overrideprotected void initViewModel() {}@Overrideprotected void bindViewModel() {}@Overrideprotected 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.ConstraintLayoutandroid:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"android:background="@color/color_red"><TextViewandroid: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> {@Overrideprotected int getLayoutResId() {return R.layout.person_center;}@Overrideprotected void initViewModel() {}@Overrideprotected void bindViewModel() {}@Overrideprotected 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.ConstraintLayoutandroid:layout_width="@dimen/dp_640"android:layout_height="@dimen/dp_400"><TextViewandroid: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 实现

http://www.lryc.cn/news/400897.html

相关文章:

  • ASP.NET Core----基础学习07----ViewStart ViewImports文件的使用
  • 铁威马教程丨如何收集NAS的日志
  • Taro自定义FromData实现本地路径转换为文件
  • React+TS前台项目实战(二十九)-- 首页构建之性能优化实现首页Echarts模块数据渲染
  • 接口测试返回参数的自动化对比!
  • React基础学习-Day02
  • 切换网页visibilitychange,的升级版实现
  • 基于pytesseract的OCR图片识别
  • Docker_指令篇
  • HAL_UART_Transmit()函数用法
  • OpenCV一个简单的摄像头调用与关闭
  • 深度学习5 神经网络
  • js中! 、!!、?.、??、??=的用法及使用场景
  • 嵌入式面试高频八股文面试题及参考答案
  • 前端练习小项目——方向感应名片
  • 【Vim】为什么程序员喜欢用 Vim
  • stm32h743 NetXduo 实现http server CubeIDE+CubeMX
  • ubuntu服务器部署vue springboot前后端分离项目
  • 【python】pandas报错:UnicodeDecodeError详细分析,解决方案以及如何避免
  • FlinkModule加载HiveModule异常
  • 计算机硬件---如何更新自己电脑的BLOS
  • AI算法17-贝叶斯岭回归算法Bayesian Ridge Regression | BRR
  • 唯众物联网综合实训台 物联网实验室建设方案
  • 深入浅出 Vue.js:从基础到进阶的全面总结
  • 路网双线合并单线——ArcGISpro 解决方法
  • 邮箱验证码功能开发
  • 2024-07-15 Unity插件 Odin Inspector3 —— Button Attributes
  • 根据脚手架archetype快速构建spring boot/cloud项目
  • 安灯系统在电力设备制造业中的应用效果
  • 代码随想录打卡第二十五天