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 实现
相关文章:
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 …...
ASP.NET Core----基础学习07----ViewStart ViewImports文件的使用
文章目录 1._ViewStart.cshtml的使用2.更换Layout文件3._ViewImports.cshtml文件的使用 1._ViewStart.cshtml的使用 step1: 在Views文件夹下面创建_ViewStart.cshtml文件 step2: 删掉视图文件中的Layout设置行 step3: 最终显示效果ÿ…...
铁威马教程丨如何收集NAS的日志
适用版本: 适用于TOS 5.0.xxx、TOS5.1.xxx版本。 适用机型: TNAS型号(除F2-210、F4-210) 故障现象: 当TNAS宕机导致网页不可访问且PC无法搜索到该设备时,重启后TOS网页的系统报告缺失相关日志,不利于异常…...
Taro自定义FromData实现本地路径转换为文件
在用Taro写头像上传功能时,因为需要对获得的图片进行剪切成圆形或方形。使用组件剪切完之后返回的是一个本地图片的相对路径。这个时候我们就需要自己实现将本地路径重新转换为二进制文件。 引入两个js文件 mimeMap.js module.exports {"0.001": &quo…...
React+TS前台项目实战(二十九)-- 首页构建之性能优化实现首页Echarts模块数据渲染
文章目录 前言Echart模块源码功能分析数据渲染一、HashRateEchart统计图1. 功能分析2. 代码详细注释 二、BlockTimeChart统计图1. 功能分析2. 代码详细注释 三、使用方式四. 数据渲染后效果如下 总结 前言 还记得之前我们创建的 高性能可配置Echarts组件 吗?今天我…...
接口测试返回参数的自动化对比!
引言 在现代软件开发过程中,接口测试是验证系统功能正确性和稳定性的核心环节。接口返回参数的对比不仅是确保接口功能实现的手段,也是测试过程中常见且重要的任务。为了提高对比的效率和准确性,我们可以通过自动化手段实现这一过程。本文将…...
React基础学习-Day02
React基础学习-Day02 1.受控表单绑定 在 React 中,受控表单(controlled form)是一种通过 React 组件状态(state)来管理表单元素值的方式。使用受控表单,可以将表单元素的值与 React 组件的状态保持同步&a…...
切换网页visibilitychange,的升级版实现
目录 1 需求场景 2 用到的技术 3 日常检测方法 4 一个有意思的场景 5 升级版实现一 5.1 新建 /utils/browser.js 5.2 项目业务组件中使用 6 升级版实现二 6.1 安装js-tool-big-box工具库 6.2 引入 browserBox 对象 6.3 以控制累加定时器为例 6.4 查看定时器效果 1…...
基于pytesseract的OCR图片识别
简介 pytesseract是基于谷歌的tesseract的OCR包,支持识别一些简单的数字、字母、中文。 安装 安装引擎 下载地址:https://digi.bib.uni-mannheim.de/tesseract/ 一般是Windows 64位系统最新版: 如果要识别中文,注意选中中文…...
Docker_指令篇
Docker 的常用指令 1. 启动docker systemctl start docker2. 关闭docker systemctl stop docker3. 重启docker systemctl restart docker4. 设置自启动 systemctl enable docker5. 查看运行状态 systemctl status docker6. 查看帮助命令 docker pull --help7. 查看镜像 …...
HAL_UART_Transmit()函数用法
HAL_UART_Transmit函数用法 HAL_UART_Transmit()是 HAL 库中的一个函数,用于向指定的串口发送数据。它的函数原型如下: HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)其中各参数的含…...
OpenCV一个简单的摄像头调用与关闭
在使用OpenCV(Open Source Computer Vision Library)进行摄像头调用与关闭时,通常使用cv2.VideoCapture()函数来调用摄像头,并通过适当的方式关闭它。 调用摄像头 首先,需要导入OpenCV库(通常简写为cv2&a…...
深度学习5 神经网络
生物神经网络是指人的大脑,这是人工神经网络的技术原型。根据生物神经网络的原理,人们用计算机复现了简化的神经网络。当然,人工神经网络是机器学习的一大分支。 1.基本组成 1.1神 经 元 神经元是神经网络的基本组成。激活函数又称作激励函…...
js中! 、!!、?.、??、??=的用法及使用场景
js中! 、 !. 、!、?.、.?、??、??的用法及使用场景 !!!?.??????、?? 区别 !. (ts)注意 ! (非空断言符号) 用于取反一个布尔值或将一个值转换为布尔类型并取反 const a true; const b false; const value !a; // false const value !…...
嵌入式面试高频八股文面试题及参考答案
目录 什么是嵌入式系统?请简要描述其特点。 请解释实时操作系统(RTOS)的概念。 请列举几种常见的嵌入式操作系统。 请解释中断、异常和竞态条件在嵌入式系统中的作用。 什么是死锁?请举例说明如何避免死锁的发生。 请解释进程和线程的区别。 请解释同步和互斥的概念…...
前端练习小项目——方向感应名片
前言:在学习完HTML和CSS之后,我们就可以开始做一些小项目了,本篇文章所讲的小项目为——方向感应名片 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 在开始学习之前,先让我们看一…...
【Vim】为什么程序员喜欢用 Vim
1. Vim介绍 Vim是一款高度可配置的文本编辑器,它被设计成作为一个工具,可以非常高效地进行文本编辑工作。以下是关于Vim的一些基本介绍: 历史:Vim 是 Vi 文本编辑器的改进版,最初由布莱姆米勒(Bram Moole…...
stm32h743 NetXduo 实现http server CubeIDE+CubeMX
在这边要设置mpu的大小,要用到http server,mpu得设置的大一些 我是这么设置的,做一个参考 同样,在FLASH.ld里面也要对应修改,SECTIONS里增加.tcp_sec和 .nx_data两个区,我们用ram_d2区域去做网络,这个就是对应每个数据在d2区域的起点。 在CubeMX里,需要用到filex、dhc…...
ubuntu服务器部署vue springboot前后端分离项目
上传构建好的vue前端文件 vscode构建vue项目,会生成dist目录 npm run build在服务器root目录新建/projects/www目录,把dist目录下的所有文件,上传到此目录中 上传ssl证书 上传ssl证书到/projects目录中 配置nginx 编辑 /etc/nginx/site…...
【python】pandas报错:UnicodeDecodeError详细分析,解决方案以及如何避免
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
