首页 > 其他分享 >高德地图SDK Android版开发 8 覆盖物示例2动画

高德地图SDK Android版开发 8 覆盖物示例2动画

时间:2024-08-25 16:52:31浏览次数:13  
标签:动画 示例 float ANIMATION animation new Android Animation 高德

高德地图SDK Android版开发 8 覆盖物示例2动画

前言

前文介绍了高德地图Marker支持多种动画类型:

  • 帧动画;
  • Animation动画(包括平移、旋转、透明、缩放和组合动画)。

本文重点介绍Marker动画相关的类和接口,以及示例代码。

动画相关的类和接口

帧动画

帧动画的功能通过MarkerOptions类来设置,一次传入一个Icon列表,通过period设定刷新的帧间隔。

MarkerOptions

类型方法说明
MarkerOptionsicons(ArrayList< BitmapDescriptor > icons)设置Marker覆盖物的动画帧图标列表,多张图片模拟gif的效果。
MarkerOptionsperiod(int period)设置多少帧刷新一次图片资源,Marker动画的间隔时间,值越小动画越快。

Animation动画

Marker还支持设置旋转、缩放、平移、透明和组合动画效果。通过Marker类setAnimation方法设置。

说明说明
voidsetAnimation(Animation animation)设置动画。动画包含,旋转,缩放,消失,平移以及它们的组合动画
booleanstartAnimation()开始动画

Animation类及其子类

动画类别说明
抽象类Animation动画,可用于支持动画的覆盖物。使用方法如同Android系统自带的Animation
移动动画TranslateAnimation控制移动的动画类
旋转动画RotateAnimation控制旋转的动画类
透明度动画AlphaAnimation控制透明度的动画类
缩放动画ScaleAnimation控制缩放的动画类
组合动画AnimationSet动画集合
TranslateAnimation +TranslateAnimation(latLng) #String getAnimationType() Animation +int getFillMode() +int getRepeatCount() +int getRepeatMode() +void setAnimationListener(listener) +void setDuration(duration) +void setFillMode(fillMode) +void setInterpolator(interpolator) +void setRepeatCount(repeatCount) +void setRepeatMode(repeatMode) RotateAnimation +RotateAnimation(fromdegree, todegree) #String getAnimationType() AlphaAnimation +AlphaAnimation(fromAlpha, toAlpha) #String getAnimationType() ScaleAnimation +ScaleAnimation(fromX, toX, fromY, toY) #String getAnimationType() AnimationSet +AnimationSet(shareInterpolator) +void addAnimation(animation) +void cleanAnimation() #String getAnimationType()
Animation
说明说明
intgetFillMode()获取动画执行完成后的状态
intgetRepeatCount()获取动画重复执行的次数
intgetRepeatMode()重复执行的模式
voidsetAnimationListener(Animation.AnimationListener listener)设置动画监听器
voidsetDuration(long duration)设置动画持续时间。如果设置为负数,会修正为0
voidsetFillMode(int fillMode)设置动画执行完成后的状态。默认FILL_MODE_FORWARDS
voidsetInterpolator(Interpolator interpolator)设置插值器。默认是线性插值器
voidsetRepeatCount(int repeatCount)设置动画重复执行的次数。默认为0
voidsetRepeatMode(int repeatMode)重复执行的模式。默认RESTART
  • 常量
类型常量说明
static intFILL_MODE_BACKWARDS动画执行后保持在第一帧
static intFILL_MODE_FORWARDS动画执行后保持在最后一帧
static intINFINITE无限期地重复动画
static intRESTART动画结束后从头播放,最大重复次数受Animation.setRepeatCount(int) 限制
static intREVERSE动画结束后从尾倒放,最大重复次数受Animation.setRepeatCount(int) 限制
// 设置重复执行的模式
animation.setRepeatMode(Animation.RESTART);
// 设置动画执行后保持在第一帧
animation.setFillMode(Animation.FILL_MODE_BACKWARDS);
// 设置无限期地重复动画
animation.setRepeatCount(Animation.INFINITE);
  • AnimationListener 动画侦听
// 动画监听,包含动画开始和结束时的回调
public interface AnimationListener {
    // 动画开始回调
    void onAnimationStart();

    // 动画结束回调
    void onAnimationEnd();
}
TranslateAnimation
说明说明
TranslateAnimation(LatLng target)控制移动的动画类
protected StringgetAnimationType()
RotateAnimation
说明说明
RotateAnimation(float fromdegree, float todegree)控制旋转的动画类
protected StringgetAnimationType()
AlphaAnimation
说明说明
AlphaAnimation(float fromAlpha, float toAlpha)控制透明度的动画类。
透明度范围[0,1], 1为不透明
protected StringgetAnimationType()
ScaleAnimation
说明说明
ScaleAnimation(float fromX, float toX, float fromY, float toY)控制缩放的动画类。
比如要实现一个Marker生长动画,可以使用 (0,1,0,1)
protected StringgetAnimationType()
AnimationSet
说明说明
AnimationSet(boolean shareInterpolator)动画集合
voidaddAnimation(Animation animation)添加动画
voidcleanAnimation()清除动画
protected StringgetAnimationType()

Marker动画示例

本示例包括帧动画、Animation动画,以及官方Demo中的生长、跳跃和呼吸动画。

界面布局

在这里插入图片描述

  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MapMarkerAnimationActivity">

    <com.amap.api.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/bottomView"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/bottomView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/map">

        <RadioGroup
            android:id="@+id/RadioGroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/background_dark"
            android:gravity="center_horizontal"
            android:orientation="horizontal"
            android:paddingHorizontal="10dp">

            <RadioButton
                android:id="@+id/frameAnimation"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:checked="true"
                android:onClick="setAnimationFlag"
                android:text="帧动画"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/animation"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setAnimationFlag"
                android:text="Animation动画"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/demoAnimation"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setAnimationFlag"
                android:text="Demo动画"
                android:textColor="@color/white"
                android:textStyle="bold" />

        </RadioGroup>

    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

MapMarkAnimate类

  • 以下是MapMarkAnimate部分代码。

常量

public final static String FRAME_ANIMATION = "Frame"; // 帧动画

public final static String TRANSFORMATION_ANIMATION = "Transformation"; // 平移动画
public final static String ROTATE_ANIMATION = "Rotate"; // 旋转动画
public final static String ALPHA_ANIMATION = "Alpha"; // 透明度动画
public final static String SCALE_ANIMATION = "Scale"; // 缩放动画
public final static String SINGLE_SCALE_ANIMATION = "SingleScale"; // 单边缩放动画 X或Y方向
public final static String ANIMATION_SET = "AnimationSet"; // 组合动画

public final static String DEMO_GROW_ANIMATION = "Grow"; // Demo1 从地下生长
public final static String DEMO_JUMP_ANIMATION = "Jump"; // Demo2 跳跃
public final static String DEMO_BREATHE_ANIMATION = "Breathe"; // Demo3 呼吸

成员变量

// 覆盖物列表
List<BaseOverlay> overlays = new ArrayList<>();
// 选中的状态
List<String> selectedFlags = new ArrayList<>();
// 坐标点集
List<LatLng> points = new ArrayList<>();

ArrayList<BitmapDescriptor> bitmaps = new ArrayList<>();
BitmapDescriptor circleBitmap;

初始值

selectedFlags.add(FRAME_ANIMATION);
selectedFlags.add(FRAME_ANIMATION);
selectedFlags.add(FRAME_ANIMATION);

points.add(new LatLng(39.97923, 116.357428));
points.add(new LatLng(39.94923, 116.397428));
points.add(new LatLng(39.97923, 116.437428));
points.add(new LatLng(39.92353, 116.490705));
points.add(new LatLng(40.023537, 116.289429));
points.add(new LatLng(40.022211, 116.406137));

int[] drawableIds = BubbleIcons.Number;
for (int drawableId : drawableIds) {
    BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(drawableId);
    bitmaps.add(bitmap);
}
circleBitmap = BitmapDescriptorFactory.fromResource(R.drawable.marker_circle_64);

创建覆盖物

public void addMarkers() {
    if (selectedFlags.isEmpty())
        return;

    int markerSize = selectedFlags.size();
    for (int i = 0; i < markerSize; ++i) {
        LatLng point = points.get(i);
        String flag = selectedFlags.get(i);
        switch (flag) {
        case FRAME_ANIMATION:
            addFrameAnimation(point, bitmaps);
            break;
        case DEMO_GROW_ANIMATION:
        case DEMO_JUMP_ANIMATION:
            addSampleAnimation(point, bitmaps.get(i), flag);
            break;
        case DEMO_BREATHE_ANIMATION:
            addBreatheAnimation(point);
            break;
        default:
            addAnimation(point, bitmaps.get(i), flag);
            break;
        }
    }
}
创建Marker(帧动画)
private void addFrameAnimation(LatLng point, ArrayList<BitmapDescriptor> bitmaps) {
    MarkerOptions option = new MarkerOptions()
            .position(point) // 当前MarkerOptions对象的经纬度
            .icons(bitmaps) // Marker的动画帧列表
            .period(10); // 帧数, 刷新周期,值越小速度越快。默认为20,最小为1

    Marker marker = map.addMarker(option);
    overlays.add(marker);
}
创建Marker(Animation动画)
private void addAnimation(LatLng point, BitmapDescriptor bitmap, String flag) {
    Animation animation = null;
    switch (flag) {
    case TRANSFORMATION_ANIMATION:
        animation = getTransformation(point);
        break;
    case ROTATE_ANIMATION:
        animation = getRotateAnimation();
        break;
    case ALPHA_ANIMATION:
        animation = getAlphaAnimation();
        break;
    case SCALE_ANIMATION:
        animation = getScaleAnimation();
        break;
    case SINGLE_SCALE_ANIMATION:
        animation = getSingleScaleAnimation();
        break;
    case ANIMATION_SET:
        animation = getAnimationSet();
        break;
    }

    if (animation == null)
        return;

    MarkerOptions option = new MarkerOptions()
            .position(point)
            .icon(bitmap);

    Marker marker = map.addMarker(option);
    overlays.add(marker);
    marker.setAnimation(animation);
    marker.startAnimation();
}
创建Marker(Demo动画)
private void addSampleAnimation(LatLng point, BitmapDescriptor bitmap, String flag) {
    Animation animation = null;
    switch (flag) {
    case DEMO_GROW_ANIMATION:
        animation = getGrowAnimation();
        break;
    case DEMO_JUMP_ANIMATION:
        animation = getJumpAnimation(point);
        break;
    }

    if (animation == null)
        return;

    MarkerOptions option = new MarkerOptions()
            .position(point)
            .icon(bitmap);

    Marker marker = map.addMarker(option);
    overlays.add(marker);
    marker.setAnimation(animation);
    marker.startAnimation();
}

private void addBreatheAnimation(LatLng point) {
    // breathe marker
    MarkerOptions option = new MarkerOptions()
            .position(point)
            .icon(circleBitmap)
            .anchor(0.5f, 0.5f)
            .zIndex(1);
    Marker breatheMarker = map.addMarker(option);
    overlays.add(breatheMarker);

    // center marker
    MarkerOptions centerOption = new MarkerOptions()
            .position(point)
            .icon(circleBitmap)
            .anchor(0.5f, 0.5f)
            .zIndex(2);
    Marker centerMarker = map.addMarker(centerOption);
    overlays.add(centerMarker);

    // 动画
    Animation animation = AnimationFactory.getBreatheAnimation();
    breatheMarker.setAnimation(animation);
    breatheMarker.startAnimation();
}
创建Animation
  • 创建平移动画、旋转动画、透明度动画、缩放动画、单边缩放动画、创建组合动画、生长动画、跳跃动画、呼吸动画。
// 创建平移动画
Animation getTransformation(LatLng point) {
    Point pt1 = map.getProjection().toScreenLocation(point);
    Point pt2 = new Point(pt1.x, pt1.y - 100);
    LatLng toPoint = map.getProjection().fromScreenLocation(pt2);

    TranslateAnimation animation = new TranslateAnimation(toPoint);

    // 设置动画持续时间
    animation.setDuration(500);
    // 设置重复执行的模式
    animation.setRepeatMode(Animation.RESTART);
    // 设置动画重复执行的次数
    animation.setRepeatCount(1);
    // 动画执行后保持在第一帧
    animation.setFillMode(Animation.FILL_MODE_BACKWARDS);

    animation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart() {
            // 动画开始回调
        }

        @Override
        public void onAnimationEnd() {
            // 动画结束回调
        }
    });

    return animation;
}

// 创建旋转动画
Animation getRotateAnimation() {
    RotateAnimation animation = new RotateAnimation(0f, 360f);

    // 设置动画持续时间
    animation.setDuration(1000);
    // 设置重复执行的模式
    animation.setRepeatMode(Animation.RESTART);
    // 设置动画重复执行的次数
    animation.setRepeatCount(1);
    // 动画执行后保持在第一帧
    animation.setFillMode(Animation.FILL_MODE_BACKWARDS);

    return animation;
}

// 创建透明度动画
Animation getAlphaAnimation() {
    float fromAlpha = 1.0f;
    float toAlpha = 0.5f;
    AlphaAnimation animation = new AlphaAnimation(fromAlpha, toAlpha);

    // 设置动画持续时间
    animation.setDuration(3000);
    // 设置重复执行的模式
    animation.setRepeatMode(Animation.RESTART);
    // 设置动画重复执行的次数
    animation.setRepeatCount(1);
    // 动画执行后保持在第一帧
    animation.setFillMode(Animation.FILL_MODE_BACKWARDS);

    return animation;
}

// 创建缩放动画
Animation getScaleAnimation() {
    float fromX = 1.0f; // 动画开始时横坐标位置
    float toX = 2.0f; // 动画结束时横坐标位置
    float fromY = 1.0f; // 动画开始时纵坐标位置
    float toY = 2.0f; // 动画结束时纵坐标位置
    ScaleAnimation animation = new ScaleAnimation(fromX, toX, fromY, toY);

    // 设置动画持续时间
    animation.setDuration(2000);
    // 设置重复执行的模式
    animation.setRepeatMode(Animation.RESTART);
    // 设置动画重复执行的次数
    animation.setRepeatCount(1);
    // 动画执行后保持在第一帧
    animation.setFillMode(Animation.FILL_MODE_BACKWARDS);

    return animation;
}

// 单边缩放动画
Animation getSingleScaleAnimation() {
    float fromX = 1.0f; // 动画开始时横坐标位置
    float toX = 2.0f; // 动画结束时横坐标位置
    float fromY = 1.0f; // 动画开始时纵坐标位置
    float toY = 1.0f; // 动画结束时纵坐标位置
    ScaleAnimation animation = new ScaleAnimation(fromX, toX, fromY, toY);

    // 设置动画持续时间
    animation.setDuration(1000);
    // 设置重复执行的模式
    animation.setRepeatMode(Animation.RESTART);
    // 设置动画重复执行的次数
    animation.setRepeatCount(1);
    // 动画执行后保持在第一帧
    animation.setFillMode(Animation.FILL_MODE_BACKWARDS);

    return animation;
}

// 添加组合动画
Animation getAnimationSet() {
    boolean shareInterpolator = true;
    AnimationSet animation = new AnimationSet(shareInterpolator);

    // 添加动画
    animation.addAnimation(getAlphaAnimation());
    animation.addAnimation(getRotateAnimation());
    animation.addAnimation(getScaleAnimation());

    // 设置插值器,默认是线性插值器
    animation.setInterpolator(new LinearInterpolator());

    return animation;
}

// 地上生长
Animation getGrowAnimation() {
    float fromX = 0.0f; // 动画开始时横坐标位置
    float toX = 1.0f; // 动画结束时横坐标位置
    float fromY = 0.0f; // 动画开始时纵坐标位置
    float toY = 1.0f; // 动画结束时纵坐标位置
    ScaleAnimation animation = new ScaleAnimation(fromX, toX, fromY, toY);
    animation.setInterpolator(new LinearInterpolator());
    animation.setDuration(1000);
    return animation;
}

// 跳跃动画
Animation getJumpAnimation(LatLng point) {
    // 根据屏幕距离计算需要移动的目标点
    Point pt1 = map.getProjection().toScreenLocation(point);
    Point pt2 = new Point(pt1.x, pt1.y - 100);
    LatLng toPoint = map.getProjection().fromScreenLocation(pt2);

    // 使用TranslateAnimation,填写一个需要移动的目标点
    Animation animation = new TranslateAnimation(toPoint);
    animation.setInterpolator(new Interpolator() {
        @Override
        public float getInterpolation(float input) {
            // 模拟重加速度的interpolator
            if (input <= 0.5) {
                return (float) (0.5f - 2 * (0.5 - input) * (0.5 - input));
            } else {
                return (float) (0.5f - Math.sqrt((input - 0.5f) * (1.5f - input)));
            }
        }
    });
    animation.setDuration(600);
    return animation;
}

// 呼吸动画
Animation getBreatheAnimation() {
    // 动画执行完成后,默认会保持到最后一帧的状态
    boolean shareInterpolator = true;
    AnimationSet animationSet = new AnimationSet(shareInterpolator);

    // 1. 透明度动画
    float fromAlpha = 0.5f;
    float toAlpha = 0f;
    AlphaAnimation alphaAnimation = new AlphaAnimation(fromAlpha, toAlpha);
    alphaAnimation.setDuration(2000);
    // 设置不断重复
    alphaAnimation.setRepeatCount(Animation.INFINITE);

    // 2. 缩放动画
    float fromX = 1.0f; // 动画开始时横坐标位置
    float toX = 3.5f; // 动画结束时横坐标位置
    float fromY = 1.0f; // 动画开始时纵坐标位置
    float toY = 3.5f; // 动画结束时纵坐标位置
    ScaleAnimation scaleAnimation = new ScaleAnimation(fromX, toX, fromY, toY);
    scaleAnimation.setDuration(2000);
    // 设置不断重复
    scaleAnimation.setRepeatCount(Animation.INFINITE);

    // 添加动画
    animationSet.addAnimation(alphaAnimation);
    animationSet.addAnimation(scaleAnimation);

    // 设置插值器,默认是线性插值器
    animationSet.setInterpolator(new LinearInterpolator());

    return animationSet;
}

移除覆盖物

public void removeOverlay() {
    // 从地图上删除所有的覆盖物(marker,circle,polyline 等对象),
    // 但myLocationOverlay(内置定位覆盖物)除外。
//    boolean isKeepMyLocationOverlay = true;
//    map.clear(isKeepMyLocationOverlay);

    for (BaseOverlay overlay : overlays) {
        if (overlay instanceof Marker) {
            Marker marker = (Marker) overlay;
            marker.remove();
        }
    }
    overlays.clear();
}

设置属性

public void setFlags(List<String> flags) {
    selectedFlags.clear();
    selectedFlags.addAll(flags);

    removeOverlay();
    addMarkers();
}

加载地图和释放地图

public void onMapLoaded() {
    addMarkers();
}

public void onMapDestroy() {
    removeOverlay();

    for (BitmapDescriptor bitmap : bitmaps) {
        bitmap.recycle();
    }
    bitmaps = null;

    if (circleBitmap != null)
        circleBitmap.recycle();
    circleBitmap = null;
}

MapMarkerAnimationActivity类

  • 以下是MapMarkerAnimationActivity类部分代码

控件响应事件

public void setAnimationFlag(View view) {
    boolean checked = ((RadioButton) view).isChecked();
    int id = view.getId();
    if (!checked)
        return;

    List<String> flags;
    if (id == R.id.frameAnimation) {
        flags = Arrays.asList(
                MapMarkerAnimation.FRAME_ANIMATION,
                MapMarkerAnimation.FRAME_ANIMATION,
                MapMarkerAnimation.FRAME_ANIMATION);
    } else if (id == R.id.animation) {
        flags = Arrays.asList(
                MapMarkerAnimation.TRANSFORMATION_ANIMATION,
                MapMarkerAnimation.ROTATE_ANIMATION,
                MapMarkerAnimation.ALPHA_ANIMATION,
                MapMarkerAnimation.SCALE_ANIMATION,
                MapMarkerAnimation.SINGLE_SCALE_ANIMATION,
                MapMarkerAnimation.ANIMATION_SET);
    } else if (id == R.id.demoAnimation) {
        flags = Arrays.asList(
                MapMarkerAnimation.DEMO_GROW_ANIMATION,
                MapMarkerAnimation.DEMO_JUMP_ANIMATION,
                MapMarkerAnimation.DEMO_BREATHE_ANIMATION);
    } else {
        return;
    }
    mapMarkerAnimation.setFlags(flags);
}

运行效果图

在这里插入图片描述

标签:动画,示例,float,ANIMATION,animation,new,Android,Animation,高德
From: https://blog.csdn.net/kikikiki001/article/details/141506298

相关文章

  • 车载Android设备启动时间优化: 新手指南
    简介车载Android设备启动时间优化新手指南,共20个优化方向。涉及bsp、系统层、apk等。目录BSP相关:1.移除了Bootloader(U-Boot/LK等)和Linux内核中的调试命令,以节省初始化时间和镜像大小。出于调试和开发目的,Bootloader中的启动延迟以及Bootloader和Linux内核中......
  • RabbitMQ 入门示例
    参考:BV15k4y1k7EpRabbitMQ相关概念及简述中简单介绍了RabbitMQ提供的6种工作模式。下面以简单模式为例,介绍RabbitMQ的使用。新建工程先新建Maven工程RabbitMQ作为父工程,在父工程下新建三个子模块:common:公共包producer:生产者consumer:消费者在三个模块中添加......
  • Android fork 进程 process(init/Zygote/SystemServer)
    ##Android的init/Zygote/SystemServer Android手机先开机,init/Zygote/SystemServer,然后启动Framework,然后启动Launcher;【安装APP(PMS),】然后启动APP(AMS)。所有的Android应用进程都是有Zygote进程fork出来的。Android系统启动流程(一)解析init进程-http://blog.csdn.net/itach......
  • ensp 中 wlan 的配置过程和示例
    一、拓朴:要求:vlan20用于笔记本上网,使用Huawei信号,vlan30用于手机上网,使用Huawei-5G信号二、配置过程:        1、SW1基本配置:        起vlanbatch102030,10为管理vlan,20、30分别为办公vlan和guestvlan        到AC接口为trunk,允许vl......
  • linux下试验中间件canal的example示例-binlog日志的实时获取显示以及阿里巴巴中间件ca
    一、linux下试验中间件canal的example示例-binlog日志的实时获取显示    今天重装mysql后,进行了canal的再次试验,原来用的mysql5.7,今天重装直接换了5.6算了。反正测试服务器的mysql也不常用。canal启动后日志显示examplepreparetofindstartpositionjustshowmaste......
  • 计算机毕业设计django+vue基于Android的婚物语APP的设计与实现【开题+论文+程序】
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着移动互联网技术的飞速发展,智能手机已成为人们日常生活中不可或缺的一部分,特别是在婚嫁领域,移动应用以其便捷性、实时性和个性化服务的......
  • 基于SpringBoot的智慧党建系统+uniapp移动端+LW示例参考
    1.项目介绍技术栈+环境:SpringBoot+thymeleaf+uniapp+IDEA+Navicat+MySQL功能介绍:后端功能:首页管理(轮播图、通知公告、新闻管理)、用户管理(用户信息、用户反馈、用户订单、用户动态)、其他管理(题库管理、任务管理)移动端:学习模块、游戏学习模块、打卡签到、积分商城、问题咨......
  • Android Content Provider最全面试题及参考答案(8万字长文)
    什么是ContentProvider?ContentProvider是Android系统中用于在不同应用程序之间共享数据的一种机制。它提供了一种统一的接口,使得不同的应用可以以标准的方式访问和操作特定类型的数据。ContentProvider就像是一个数据仓库的管理员,它负责管理数据的存储、检索、更新......
  • 基于Android的安全知识学习APP的设计与实现(论文+源码)_kaic
    基于Android的安全知识学习APP的设计与实现摘  要随着科技的进步,智能手机已经成为人们工作、学习和生活的必需品。基于Android系统的强大功能,使用Java语言、Linux操作系统,搭配AndroidStudio,并配备Android开发插件,最终实现了一款安全知识学习APP的开发,以便让用户能够轻松......
  • 基于Android的运动记录APP设计与实现(论文+源码)_kaic
      摘要随着人们生活水平和生活质量的提高,人们越来越关注自己的身体健康。而跑步成为人们最受欢迎的运动方式,运动软件可以在人们锻炼身体的时候提供极大的帮助。本文针对运动轨迹和计步,设计一款基于Android平台的运动软件。本系统通过使用百度鹰眼、重力传感器和数据库技术......