横幅条(自定义控件)的编写

常可以看见ViewPager翻页视图下有几个圆点,并随着图片变化而变化。

我们称之为横幅条,横幅条自定义控件的编写有两种:(1)使用Paint与Canvas绘制;(2)使用RadioButton组合

第一种编写方法的优势是可以显示滑动过程中的位置,劣势是无法点击圆点。

第二种编写方法的优势是可以点击圆点,劣势是无法显示滑动过程中的位置。

一、使用Paint与Canvas绘制(自定义控件)

核心原理:

1. 重写Java构造方法(不使用可不重写)

2. 重写XML构造方法(及属性数组XML文件)(获取属性值)

3. 重写onMeasure()方法,获取尺寸(使用MeasureSpec.getMode()方法MeasureSpec.getSize()方法),设置尺寸(使用setMeasuredDimension()方法

4. 重写dispatchDraw()方法,绘制图像(大底色圆,小选中圆)

5. 创建其他设置UI参数方法(使用invalidate()方法进行即时重绘控件);如,设置选中按钮的方法、设置选中按钮及偏移量的方法、设置选中颜色的方法

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import android.widget.RelativeLayout;

/**
 * 复制时请携带MyBar属性(数组XML文件)
 */
public class MyBar extends RelativeLayout {
    int oCount;//数量
    int oRDp;//半径dp
    int oRPx;//半径px
    int oSpacerDp;//间隔Dp
    int oSpacerPx;//间隔Px
    int viewWidth;//控件宽度
    Context context;//环境
    int[] oi;//底色圆心像素位置数组
    int selectONum;//选中圆心Num
    float selectOffset;//选中偏移量比例
    int selectColor;//选中颜色
    int unselectColor;//底色
    float selectFloat;//选中圆占底色比例 0~1
    float density;

    //Java构造方法
    public MyBar(Context context) {
        super(context);
        this.context=context;
        getAttrs(context);
    }

    //XML构造方法
    public MyBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        //在XML布局文件中使用的方法
        this.context=context;
        getAttrs(context, attrs);
    }

    /**
     * 获取XML属性
     */
    @SuppressLint("ResourceAsColor")
    private void getAttrs(Context context, AttributeSet attrs){
        //获取属性值
        TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.MyBar);

        oCount=typedArray.getInt(R.styleable.MyBar_oCount,1);
        oRDp=typedArray.getInt(R.styleable.MyBar_oRDp,5);
        oSpacerDp=typedArray.getInt(R.styleable.MyBar_oSpacerDp,12);
        selectONum=typedArray.getInt(R.styleable.MyBar_selectONum,1);
        selectFloat=typedArray.getFloat(R.styleable.MyBar_selectFloat,0.7f);
        selectColor=typedArray.getColor(R.styleable.MyBar_selectColor,Color.RED);
        unselectColor=typedArray.getColor(R.styleable.MyBar_unselectColor,R.color.teal_700);
        selectOffset=typedArray.getFloat(R.styleable.MyBar_selectOffset,0);

        //修正错误参数
        //选中数大于总数
        if(selectONum>oCount){
            selectONum=oCount;
            selectOffset=0;
        }
        //间隔小于半径*2
        if(oSpacerDp<oRDp*2){
            oSpacerDp=oRDp*2;
        }
        //偏移量过大或过小
        if(selectOffset<-1|selectOffset>1){
            selectOffset=0;
        }

        //获取density
        WindowManager windowManager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics=new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        density= displayMetrics.density;
        //获取圆像素大小
        oRPx= (int) (oRDp*density);
        //获取间隔像素大小
        oSpacerPx= (int) (oSpacerDp*density);

        //回收
        typedArray.recycle();
    }

    /**
     * Java构建方法的属性
     */
    public void getAttrs(Context context){
        //默认属性值
        oCount=1;
        oRDp=5;
        oSpacerDp=12;
        selectONum=1;
        selectFloat=0.7f;
        selectColor=Color.RED;
        unselectColor=R.color.teal_700;
        selectOffset=0;
        //获取density
        WindowManager windowManager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics=new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        density= displayMetrics.density;
        //获取圆像素大小
        oRPx= (int) (oRDp*density);
        //获取间隔像素大小
        oSpacerPx= (int) (oSpacerDp*density);
    }

    /**
     * 获取尺寸,修改尺寸
     */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width=MeasureSpec.getSize(widthMeasureSpec);
        int height=MeasureSpec.getSize(heightMeasureSpec);
        //Log.d("OK",MeasureSpec.getMode(widthMeasureSpec)+"&&&"+MeasureSpec.getMode(heightMeasureSpec));
        if(MeasureSpec.getMode(widthMeasureSpec)==MeasureSpec.UNSPECIFIED){
            //具体值--
            width=oSpacerPx*(oCount-1)+oRPx*2;
        }
        else if (MeasureSpec.getMode(widthMeasureSpec)==MeasureSpec.AT_MOST) {
            //wrap--
            width=oSpacerPx*(oCount-1)+oRPx*2;
        }
        else {
            //match--具体值
        }

        if(MeasureSpec.getMode(heightMeasureSpec)==MeasureSpec.UNSPECIFIED){
            //具体值--
            height=oRPx*2;
        }
        else if(MeasureSpec.getMode(heightMeasureSpec)==MeasureSpec.AT_MOST){
            //wrap--
            height=oRPx*2;
        }
        else {
            //match--具体值
        }

        setMeasuredDimension(width,height);
    }

    /**
     * 绘制图像
     */
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        //获取控件宽度
        viewWidth=getWidth();
        //圆心像素位置数组
        oi=new int[oCount];
        int oi1=(viewWidth-oSpacerPx*(oCount-1))/2;
        for (int i=0;i<oCount;i++){
            oi[i]=oi1;
            oi1=oi1+oSpacerPx;
        }

        //绘制底色
        Paint paint=getPaint(unselectColor);
        for(int i=0;i<oi.length;i++){
            canvas.drawCircle(oi[i],oRPx,oRPx,paint);
        }

        //绘制选中
        paint=getPaint(selectColor);
        canvas.drawCircle(oi[selectONum-1]+oSpacerPx*selectOffset,oRPx,oRPx*selectFloat,paint);
    }

    /**
     * 设置圆数量
     * @param oCount
     */
    protected void setoCount(int oCount){
        this.oCount=oCount;
        if(selectONum>oCount){
            selectONum=oCount;
        }
        //立即重绘
        invalidate();
    }

    /**
     * 设置圆半径
     * @param oRDp 半径dp值
     */
    protected void setoRDp(int oRDp){
        if(oRDp*2>this.oSpacerDp){
            this.oSpacerDp=oRDp*2;
            this.oSpacerPx= (int) (oSpacerDp*density);
        }
        this.oRDp=oRDp;
        this.oRPx= (int) (oRDp*density);
        //立即重绘
        invalidate();
    }

    /**
     * 设置圆心间隔
     * @param oSpacerDp 间隔dp值
     */
    protected void setoSpacerDp(int oSpacerDp){
        if(oSpacerDp<this.oRDp*2){
            oSpacerDp=this.oRDp*2;
        }
        this.oSpacerDp=oSpacerDp;
        this.oSpacerPx= (int) (oSpacerDp*density);
        //立即重绘
        invalidate();
    }

    /**
     * 设置选中
     * @param num 选中的圆位置
     */
    protected void setSelect(int num){
        if(num>oCount){
            num=oCount;
        }
        this.selectONum=num;
        this.selectOffset=0;
        //立即重绘
        invalidate();
    }

    /**
     * 设置选中
     * @param num 选中的圆位置
     * @param selectOffset 偏移量比例 -1~1
     */
    protected void setSelect(int num,float selectOffset){
        if(num>oCount){
            num=oCount;
        }
        this.selectONum=num;
        this.selectOffset=selectOffset;
        //立即重绘
        invalidate();
    }

    /**
     * 获取指定颜色画笔
     */
    private Paint getPaint(int color){
        Paint paint=new Paint();
        //设置画笔
        paint.setColor(color);
        //抗锯齿
        paint.setAntiAlias(true);
        return paint;
    }

    /**
     * 设置选中圆点颜色
     * @param color
     */
    private void setSelectColor(int color){
        selectColor=color;
        //立即重绘
        invalidate();
    }

    /**
     * 设置未选中圆底色
     * @param color
     */
    private void setUnselectColor(int color){
        unselectColor=color;
        //立即重绘
        invalidate();
    }


}
<!-- 属性数组XML文件 !-->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyBar">
        <attr name="oCount" format="integer"/><!-- 圆数量 !-->
        <attr name="oRDp" format="integer"/><!-- 圆半径dp !-->
        <attr name="oSpacerDp" format="integer"/><!-- 圆心间隔dp !-->
        <attr name="selectONum" format="integer"/><!-- 选中圆(1开始) !-->
        <attr name="selectFloat" format="float"/><!-- 选中圆占原圆大小 !-->
        <attr name="selectColor" format="color"/><!-- 选中圆颜色 !-->
        <attr name="unselectColor" format="color"/><!-- 未选中圆底色 !-->
        <attr name="selectOffset" format="float"/><!-- 偏移量(-1~1) !-->
    </declare-styleable>
</resources>

在XML布局中使用:

<!-- 自定义控件MyBar的使用 !-->
<xxx.MyBar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    app:oCount="10"
    app:selectONum="4"
    app:oRDp="9"
    app:oSpacerDp="20"
    
    />

二、使用RadioButton组合(组合自定义控件)

核心原理:

1. 创建包含ViewPagerRadioGroupXML布局文件

2. 重写Java构造方法(不使用可不重写)

3. 重写XML构造方法(及属性数组XML文件)(获取属性值,向单选组添加单选按钮

4. 重写onMeasure()方法,获取尺寸(使用MeasureSpec.getMode()方法MeasureSpec.getSize()方法),设置尺寸(使用setMeasuredDimension()方法

5. 创建设置翻页适配器的方法,该方法需要在设置适配器的同时修改按钮数(初始化按钮);并为单选组及翻页视图设置监听器,在点击单选按钮时修改翻页视图,在翻页时修改选中的单选按钮

6. 创建其他设置UI参数方法(使用invalidate()方法进行即时重绘控件);如,设置选中按钮的方法、设置按钮数的方法

<!-- XML布局文件 !-->
<!-- bar_view_pager_layout.xml !-->

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools">
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck"/>
    <RadioGroup
        android:id="@+id/radioGroup"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:paddingBottom="5dp"
        android:background="#00BB86FC"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:gravity="center_horizontal"/>
</RelativeLayout>
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;

import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;

/**
 * 复制时请携带
 * MyBarViewPager属性(数组XML文件)
 * 组合控件布局文件(bar_view_pager_layout.xml)
 */
public class MyBarViewPager extends RelativeLayout {
    int buttonCount;//按钮数
    View nowView;//当前控件
    int width;//控件宽px
    int height;//控件高px
    RadioGroup radioGroup;//单选组
    RadioButton[] radioButtons;//单选按钮数组
    ViewPager viewPager;//翻页视图
    Context context;
    boolean haveAdapter=false;//是否设置适配器
    /**
     * Java构造方法
     */
    public MyBarViewPager(Context context) {
        super(context);
        //获取属性
        getAttrs(context);
        //添加布局
        nowView=LayoutInflater.from(context).inflate(R.layout.bar_view_pager_layout,null,false);
        addView(nowView);
        //添加按钮
        initRadioButton();
    }
    /**
     * XML构造方法
     */
    public MyBarViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context=context;
        //获取属性
        getAttrs(context, attrs);
        //添加布局
        nowView=LayoutInflater.from(context).inflate(R.layout.bar_view_pager_layout,null,false);
        addView(nowView);
        //添加按钮
        initRadioButton();
    }

    /**
     * 获取XML属性
     */
    private void getAttrs(Context context, AttributeSet attrs){
        TypedArray typedArray= context.obtainStyledAttributes(attrs,R.styleable.MyBarViewPager);
        buttonCount=typedArray.getInt(R.styleable.MyBarViewPager_buttonCount,1);
    }

    /**
     * Java构建方法的属性
     */
    private void getAttrs(Context context){
        buttonCount=1;
    }

    /**
     * 设置尺寸
     */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width=MeasureSpec.getSize(widthMeasureSpec);
        height=MeasureSpec.getSize(heightMeasureSpec);
        //设置最小宽高值
        WindowManager windowManager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics=new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        float density=displayMetrics.density;
        int minWidth= (int) (5*density*buttonCount);
        int minHeight= (int) (30*density);
        if(height<minHeight){
            height=minHeight;
        }
        if(width<minWidth){
            width=minWidth;
        }
        setMeasuredDimension(width,height);
    }

    /**
     * 初始化按钮
     */
    private void initRadioButton(){
        //获取单选组
        radioGroup=nowView.findViewById(R.id.radioGroup);
        //创建按钮数组
        radioButtons=new RadioButton[buttonCount];
        //添加按钮
        for(int i=0;i<buttonCount;i++){
            RadioButton radioButton=new RadioButton(context);
            radioButtons[i]=radioButton;
            radioGroup.addView(radioButton);
        }
        //默认选中
        radioButtons[0].setChecked(true);
    }

    /**
     * 设置适配器
     * @param pagerAdapter 翻页适配器
     */
    protected void setPagerAdapter(PagerAdapter pagerAdapter){
        if(pagerAdapter==null|pagerAdapter.getCount()<1){
            return;
        }
        haveAdapter=true;
        //移除按钮
        radioGroup.removeAllViews();
        //添加按钮
        buttonCount=pagerAdapter.getCount();
        initRadioButton();
        //获取翻页视图
        viewPager=nowView.findViewById(R.id.viewPager);
        //设置适配器
        viewPager.setAdapter(pagerAdapter);
        //按钮关联翻页视图
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                viewPager.setCurrentItem(i);
            }
        });
        //翻页视图关联按钮
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener(){
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }
            public void onPageSelected(int position) {
                radioButtons[position].setSelected(true);
            }
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    /**
     * 设置选中按钮
     * @param num 选中按钮位置(1开始)
     */
    protected void setSelected(int num){
        if(num>radioButtons.length){
            num=radioButtons.length;
        }
        radioButtons[num-1].setSelected(true);
        if(haveAdapter){
            viewPager.setCurrentItem(num-1);
        }
    }

    /**
     * 设置按钮数(在设置适配器后不生效)
     * @param buttonCount
     */
    protected void setButtonCount(int buttonCount) {
        if (!haveAdapter){
            this.buttonCount = buttonCount;
            //立即重绘
            invalidate();
        }
    }

    /**
     * 判断是否已设置翻页适配器
     * @return
     */
    public boolean havePagerAdapter(){
        return haveAdapter;
    }


}
<!-- 属性数组XML文件 !-->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyBarViewPager">
        <attr name="buttonCount" format="integer"/> <!-- 按钮数 !-->
    </declare-styleable>
</resources>

在XML布局中使用: 

<!-- 自定义控件MyBarViewPager的使用 !-->
<xxx.MyBarViewPager
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:buttonCount="5"
    android:background="@color/purple_200"
    />

tag:横幅条,RadioGroup,RadioButton,ViewPager,自定义控件,自定义组合控件,组合控件,Paint,Canvas

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/427345.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大模型之SORA技术学习

文章目录 sora的技术原理文字生成视频过程sora的技术优势量大质优的视频预训练库算力多&#xff0c;采样步骤多&#xff0c;更精细。GPT解释力更强&#xff0c;提示词(Prompt&#xff09;表现更好 使用场景参考 Sora改变AI认知方式&#xff0c;开启走向【世界模拟器】的史诗级的…

Arduino应用开发——使用GUI-Guider制作LVGL UI并导入ESP32运行

Arduino应用开发——使用GUI-Guider制作LVGL UI并导入ESP32运行 目录 Arduino应用开发——使用GUI-Guider制作LVGL UI并导入ESP32运行前言1 使用GUI-Guider设计UI1.1 创建工程1.2 设计UI 2 ESP工程导入UI2.1 移植LVGL2.2 移植UI文件2.3 调用UI文件2.4 烧录测试 结束语 前言 GU…

(UE4升级UE5)Selected Level Actor节点升级到UE5

本问所用工具为&#xff1a; UE5 UE4 插件AssetDeveTool包含&#xff1a;快速选择功能自动化批量LOD功能自动化批量展UV功能自动化批量减面功能自动化批量修改查找替换材质功能批量重命名工具碰撞器修改工具资源整理工具支持4.26 - 5.3版本https://mbd.pub/o/bread/mbd-ZZubkp…

Manomotion 实现AR手势互动-解决手势无效的问题

之前就玩过 Manomotion &#xff0c;现在有新需求&#xff0c;重新接入发现不能用了&#xff0c;不管什么办法&#xff0c;都识别不了手势&#xff0c;我记得当初是直接调用就可以的。 经过研究发现&#xff0c;新版本SDK改了写法。下边就写一下新版本的调用&#xff0c;并且实…

Windows如何安装docker-desktop

下载 docker-desktop设置环境安装wsl可能遇到的错误 下载 docker-desktop 下载官网&#xff1a;https://www.docker.com/products/docker-desktop/ 设置环境 如果没有Hyper-V选项的,按照以下步骤 添加一个文件Hyper-V.bat 添加以下内容,并双击运行后重启电脑 pushd "%~…

Android sutdio 4.1.2版本Gradle 构建和打包慢解决方法,亲测有效

1在设置里面的Gradle 找到这个目录 进入后 新建文件&#xff0c; gradle.properties 输入设置 并保存 org.gradle.daemontrue 项目第一次加载构建过程比较慢&#xff0c;需要等&#xff0c;完成后&#xff0c;修改下面的配置 gradle-3.3-all.zip 这个文件可以先提前下载好&am…

AI日报:埃隆·马斯克起诉OpenAI

埃隆马斯克&#xff08;ElonMusk&#xff09;正在起诉OpenAI涉嫌违约&#xff0c;声称这位ChatGPT的创建者违反了其成为非营利组织的创始承诺&#xff0c;这位科技亿万富翁表示&#xff0c;他资助并培育了这一承诺。 在一份长达46页的爆炸性投诉中&#xff0c;马斯克将OpenAI首…

分布式ID生成算法|雪花算法 Snowflake | Go实现

写在前面 在分布式领域中&#xff0c;不可避免的需要生成一个全局唯一ID。而在近几年的发展中有许多分布式ID生成算法&#xff0c;比较经典的就是 Twitter 的雪花算法(Snowflake Algorithm)。当然国内也有美团的基于snowflake改进的Leaf算法。那么今天我们就来介绍一下雪花算法…

图书管理系统的设计与实现

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 一 、设计说明 1.1 课题…

数据结构之树结构(下)

各种各样的大树 平衡二叉树 (AVL树) 普通二叉树存在的问题 左子树全部为空&#xff0c;从形式上看&#xff0c;更像一个单链表 插入速度没有影响 查询速度明显降低&#xff08;因为需要依次比较&#xff09;&#xff0c;不能发挥BST的优势&#xff0c;因为每次还需要比较左子…

Unity 脚本-生命周期常用函数

在Unity中&#xff0c;万物皆是由组件构成的。 右键创建C&#xff03;脚本&#xff0c;拖动脚本到某物体的组件列表。 生命周期相关函数 using System.Collections; using System.Collections.Generic; using UnityEngine;// 必须要继承 MonoBehaviour 才是一个组件 // 类名…

AirPods Pro 2 耳机推送新固件,苹果Find My功能助力产品成长

苹果公司面向 AirPods Pro 2&#xff08;包括 USB-C 和 Lightning 版本&#xff09;&#xff0c;推出了全新的测试版固件更新&#xff0c;版本号为 6E188&#xff0c;高于 12 月份发布的 6B34 固件。 苹果和往常一样&#xff0c;并没有提供详细的更新日志或者说明&#xff0c…

实战——dynamic TP 可视化动态修改线程池参数配置

背景 开发环境 springboot版本号&#xff1a;2.3.12.RELEASE 集成SpringBoot 1、使用apollo动态修改线程池配置 2、使用undertow容器 3、添加maven依赖 <!-- 动态线程池适配器&#xff0c;位置要在undertow依赖前&#xff0c;否则启动报错 --><dependency><g…

用pyinstaller打包python代码为exe可执行文件并在其他电脑运行的方法

本文介绍基于Python语言中的pyinstaller模块&#xff0c;将写好的.py格式的Python代码及其所用到的所有第三方库打包&#xff0c;生成.exe格式的可执行文件&#xff0c;从而方便地在其他环境、其他电脑中直接执行这一可执行文件的方法。 有时&#xff0c;我们希望将自己电脑上的…

【外汇天眼】外汇交易风险预警:吊销牌照与高风险平台一览

监管信息早知道&#xff01;外汇天眼将每周定期公布监管牌照状态发生变化的交易商&#xff0c;以供投资者参考&#xff0c;规避投资风险。如果平台天眼评分过高&#xff0c;建议投资者谨慎选择&#xff0c;因为在外汇天眼评分高不代表平台没问题&#xff01; 以下是监管牌照发生…

错误: 找不到或无法加载主类 com.zql.springbootTest.SpringbootTestApplication

首先查看application.properties是否出现问题 然后可以尝试 maven install

从基础到高级:Go 语言中 Base32 编码的全面指南

从基础到高级&#xff1a;Go 语言中 Base32 编码的全面指南 引言基础知识base32 编码简介为什么选择 base32 encoding/base32 包概览包的结构和主要类型基本概念 实战教程开始使用 encoding/base32设置开发环境基本的 base32 编码示例解码示例 深入编码细节使用不同的编码表 错…

重保利器,企业安全巡查!亚信安全外部攻击面管理服务可以试用啦

重大安全保障期间 信息系统的稳定与安全至关重要 守在明&#xff0c;攻在暗 传统的防护多始于已知资产的保护 而未知影子资产 则很可能成为攻击者长驱直入的攻击路径 号外号外&#xff01; 亚信安全“外部攻击面管理服务” 即日起&#xff0c;面向新用户 限时试用&…

上门家政服务APP如何开发?看这一篇文章就够了

当下生活节奏快&#xff0c;工作压力大&#xff0c;人们往往无暇处理家务。上门家政APP因此成为刚需&#xff0c;提供便捷、高效的家政服务&#xff0c;满足用户各类需求&#xff0c;解放时间精力。得益于其透明的价格、严格审核的服务人员及用户评价系统&#xff0c;上门家政A…

为什么要学习三维GIS开发?从技术层面告诉你答案

大家都知道GIS开发属于GIS行业中就业薪资较高的岗位&#xff0c;并且测绘、遥感以及城规等相关专业的毕业生纷纷转行做webgis开发。 那么&#xff0c;今天小编从技术层面探讨一下&#xff0c;为什么建议大家不要仅仅停留在webgis&#xff0c;而要继续往前学习三维GIS开发&…