Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东

这篇具有很好参考价值的文章主要介绍了Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

iv.setImageDrawable(animatedVectorDrawable)
val animatable = iv.drawable as Animatable
animatable.start()
}
}

实战

输入搜索动画

  1. 利用在线绘制 SVG 图标网站 制作搜索图标

可以自己随意捣鼓绘制,绘制好了之后点击视图->源代码,将 SVG 代码复制出来保存成 search_svg.xml

  1. 在线转换 svg2vector

点击空白或者直接将 SVG 拖拽指定区域进行转换

  1. 将转换好的 Android 格式的 vector 导入 AS

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

  1. 开始制作动画关联

//1.在 /res/aniamator 文件夹下 定义动画

<?xml version="1.0" encoding="utf-8"?>

<objectAnimator xmlns:android=“http://schemas.android.com/apk/res/android”
android:propertyName=“trimPathStart”
android:valueFrom=“1”
android:valueTo=“0”
android:duration=“2000”

//2. 在/res/drawable/ 定义 vector

<?xml version="1.0" encoding="utf-8"?>




//3. 在/res/drawable/ 关联动画和 vector

<?xml version="1.0" encoding="utf-8"?>
  1. 效果

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

警车灯闪烁

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

今日头条下拉刷新动画

来一个复杂组合动画,请看下面效果图:

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

  1. 准备 vector 数据




  1. 定义顺时针执行动画并做 pathData 变换

这里拿其中一个位置变化来举例说明:

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android=“http://schemas.android.com/apk/res/android”

android:ordering=“sequentially”>//按顺序执行

//依次执行 pathData 位置变换

<objectAnimator

android:duration=“600”
android:interpolator=“@android:interpolator/decelerate_cubic”
android:propertyName=“pathData”
android:valueFrom="
M100,30
L180,30
M180,30
L180,90
M180,90
L100,90
M100,90
L100,30"
android:valueTo="
M100,120
L180,120
M180,120
L180,180
M180,180
L100,180
M100,180
L100,120"
android:valueType=“pathType” />
<objectAnimator

android:duration=“600”
android:interpolator=“@android:interpolator/decelerate_cubic”
android:propertyName=“pathData”
android:valueFrom="
M100,120
L180,120
M180,120
L180,180
M180,180
L100,180
M100,180
L100,120"
android:valueTo="
M20,120
L100,120
M100,120
L100,180
M100,180
L20,180
M20,180
L20,120"
android:valueType=“pathType” />
<objectAnimator

android:duration=“600”
android:interpolator=“@android:interpolator/decelerate_cubic”
android:propertyName=“pathData”
android:valueFrom="
M20,120
L100,120
M100,120
L100,180
M100,180
L20,180
M20,180
L20,120"
android:valueTo="
M20,30
L100,30
M100,30
L100,90
M100,90
L20,90
M20,90
L20,30"
android:valueType=“pathType” />

如果对标签中的定义还不了解的先去看下文章中 path 标签 中的说明。如果不理解标签意思,根本就看不懂。

  1. 进行关联
<?xml version="1.0" encoding="utf-8"?>

<animated-vector xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools”
android:drawable=“@drawable/ic_toutiao”

tools:targetApi=“lollipop”>

  1. 代码控制重复执行

class SVGDemo1Activity : AppCompatActivity() {

var reStartTT = @SuppressLint(“HandlerLeak”)
object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
startAnimatabe(R.drawable.line_animated_toutiao, true)
}
}

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_svg)

//水滴动画
startWaterDropAnimator.setOnClickListener {
startAnimatabe(R.drawable.line_animated_vector, false)
}
//搜索动画
startSearchAnimator.setOnClickListener {
startAnimatabe(R.drawable.line_animated_search, false)
}
//执行警车动画
startPoliceCarAnimator.setOnClickListener {
startAnimatabe(R.drawable.line_animated_car, false)
}
//执行头条动画
startTTAnimator.setOnClickListener {
startAnimatabe(R.drawable.line_animated_toutiao, true)
}
}

private fun startAnimatabe(lineAnimatedVector: Int, isRegister: Boolean): Animatable {
val animatedVectorDrawable = AnimatedVectorDrawableCompat.create(this, lineAnimatedVector)
iv.setImageDrawable(animatedVectorDrawable)
val animatable = iv.drawable as Animatable
animatable.start()
animatedVectorDrawable!!.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
super.onAnimationEnd(drawable)
if (!isRegister) return
animatedVectorDrawable.unregisterAnimationCallback(this)
//重新开始在 xml 设置 restart 无效暂时用 Handler 实现了。
reStartTT.sendEmptyMessage(0)

}
})
return animatable

}
}

绘制中国地图

该篇之前实现 SVG pathData 都是利用 ImageView 来实现,并不是所有的场合都适合上面的方式,比如我想要实现 pathData 区域点击,那么上面所讲的方式应该是不能实现,下面我们以一个实例来看怎么自定义 View 实现 PathData 和 pathData 区域点击事件。

下面我们利用 path 来绘制一个中国地图,先来看一个最终效果图,如下:

看起来是不是很炫,还不错,嘿嘿,下面我们就来看一下如何实现。

  1. 准备地图 SVG
  • 首先去下载地图数据

  • 选择下载免费的地图数据

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

  • 找到对应的国家点击下载 svg 数据

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

  • 选择对应的地图数据,我这里下载的是高质量的 SVG
  1. SVG to Vector xml

将下载好的 china.svg 格式的文件转为 vector 节点的 xml 数据 或者用 AS 自带转也行,看个人爱好。

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

转好之后放入 AS 中,如下所示

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

现在有了这些数据,我们就可以解析 xml path 节点,拿到 pathData 数据我们不就可以绘制 path 了嘛。下面就开始解析 xml ,解析的方法很多种,我们这里用 dom 解析。

  1. 开始解析 xml

解析 xml 有很多种方式,这里就直接使用 DOM 解析,pathData2Path 我这里直接用 Android SDK 提供的 android.support.v4.graphics#PathParser 由于源码中它被标注了 hide 属性 ,我们需要直接将它 copy 到我们自己项目中, 具体转化请看如下代码:

/**

  • 开始解析 xml
    */
    public fun dom2xml(stream: InputStream?): MutableList {
    mapDataLists.clear()
    //dom
    val newInstance = DocumentBuilderFactory.newInstance()
    val newDocumentBuilder = newInstance.newDocumentBuilder()
    //拿到 Docment 对象
    val document = newDocumentBuilder.parse(stream)
    //获取 xml 中属于 path 节点的所有信息
    val elementsByTagName = document.getElementsByTagName(PATH_TAG)

//定义四个点,确定整个 map 的范围
var left = -1f
var right = -1f
var top = -1f
var bottom = -1f
//开始遍历标签,拿到 path 数据组
for (pathData in 0 until elementsByTagName.length) {
val item = elementsByTagName.item(pathData) as Element
val name = item.getAttribute(“android:name”)
val fillColor = item.getAttribute(“android:fillColor”)
val strokeColor = item.getAttribute(“android:strokeColor”)
val strokeWidth = item.getAttribute(“android:strokeWidth”)
val pathData = item.getAttribute(“android:pathData”)
val path = PathParser.createPathFromPathData(pathData)
mapDataLists.add(MapData(name, fillColor, strokeColor, strokeWidth, path))
//获取控件的宽高
val rect = RectF()
//获取到每个省份的边界
path.computeBounds(rect, true)
//遍历取出每个path中的left取所有的最小值
left = if (left == -1f) rect.left else Math.min(left, rect.left)
//遍历取出每个path中的right取所有的最大值
right = if (right == -1f) rect.right else Math.max(right, rect.right)
//遍历取出每个path中的top取所有的最小值
top = if (top == -1f) rect.top else Math.min(top, rect.top)
//遍历取出每个path中的bottom取所有的最大值
bottom = if (bottom == -1f) rect.bottom else Math.max(bottom, rect.bottom)
}
//MAP 的矩形区域
MAP_RECTF = RectF(left, top, right, bottom)
return mapDataLists;
}
复制代码

  1. 进行控件测量适配横竖屏切换和宽高定义 wrap_content 模式

/**

  • 开始测量
    */
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    //测量模式
    var widthMode = MeasureSpec.getMode(widthMeasureSpec)
    var heightMode = MeasureSpec.getMode(heightMeasureSpec)
    //测量大小
    widthSize = MeasureSpec.getSize(widthMeasureSpec)
    heightSize = MeasureSpec.getSize(heightMeasureSpec)

if (!MAP_RECTF.isEmpty && mMapRectHeight != 0f && mMapRectWidth != 0f) {
//显示比例
scaleHeightValues = heightSize / mMapRectHeight
scaleWidthValues = widthSize / mMapRectWidth
}

//xml 文件中宽高 wrap_content
if (widthMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.AT_MOST) {
//如果是横屏宽保留最大,高需要适配
if (widthSize < heightSize && mMapRectHeight != 0f) {
setMeasuredDimension(widthSize, (mMapRectHeight * scaleWidthValues).toInt())
} else {
setMeasuredDimension(widthSize, heightSize)
}
} else {
setMeasuredDimension(widthSize, heightSize)
}
}

  1. 开始绘制 path

/**

  • 绘制 Map 数据
    */
    @SuppressLint(“Range”)
    private fun drawMap(canvas: Canvas) {
    canvas.save()
    if (widthSize > heightSize) {
    canvas.scale(scaleWidthValues, scaleHeightValues)
    } else {
    canvas.scale(scaleWidthValues, scaleWidthValues)
    }

mapDataList.forEach { data ->
run {
if (data.isSelect) {
drawPath(data, canvas, Color.RED)
} else {
drawPath(data, canvas, Color.parseColor(data.fillColor))
}
}
}
canvas.restore()
canvas.drawText(“中国🇨🇳地图”, widthSize / 2 - mPaintTextTitle.measureText(“中国🇨🇳地图”) / 2f, 100f, mPaintTextTitle)
}

/**

  • 开始绘制 Path
    */
    private fun drawPath(
    data: MapData,
    canvas: Canvas,
    magenta: Int
    ) {
    mPaintPath.setColor(magenta)
    mPaintPath.setStyle(Paint.Style.FILL)
    mPaintPath.setTextSize(30f)
    mPaintPath.setStrokeWidth(data.strokeWidth.toFloat())
    canvas.drawPath(data.pathData, mPaintPath)
    val rectF = RectF()
    data.pathData.computeBounds(rectF, true)
    canvas.drawText(
    if (data.name.isEmpty()) “” else data.name,
    rectF.centerX() - mPaintText.measureText(data.name) / 2,
    rectF.centerY(), mPaintText
    )
    }
  1. 给地图添加各自的点击事件

override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> return true
MotionEvent.ACTION_UP -> {
handlerTouch(event.getX(), event.getY())
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

最后

我坚信,坚持学习,每天进步一点,滴水穿石,我们离成功都很近!
以下是总结出来的字节经典面试题目,包含:计算机网络,Kotlin,数据结构与算法,Framework源码,微信小程序,NDK音视频开发,计算机网络等。

字节高级Android经典面试题和答案

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试
Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!文章来源地址https://www.toymoban.com/news/detail-858094.html

涵盖了95%以上Android开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东,程序员,android,ui,面试

最后

我坚信,坚持学习,每天进步一点,滴水穿石,我们离成功都很近!
以下是总结出来的字节经典面试题目,包含:计算机网络,Kotlin,数据结构与算法,Framework源码,微信小程序,NDK音视频开发,计算机网络等。

字节高级Android经典面试题和答案

[外链图片转存中…(img-rcAyJogZ-1712371827323)]
[外链图片转存中…(img-VfSymlVQ-1712371827324)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

到了这里,关于Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图,Android面试中常问的MMAP到底是啥东东的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android-高级-UI-进阶之路-(五)-看完该篇文章-Canvas-你应该会了

    /** 1. 绘制椭圆 */ canvas.drawOval(RectF(100f,500f,600f,800f),mPaint) /** 2. 绘制圆 */ mPaint.setColor(Color.YELLOW) mPaint.alpha = 100 canvas.drawCircle(400f,400f,200f,mPaint) 绘制 Bitmap // val bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.gild_3) //第二个,第三个参数代表起点位置 canvas.drawBitmap(bitmap,100f,100

    2024年03月28日
    浏览(56)
  • 灵魂画师,Android绘制流程——Android高级UI(1)

    绘制流程从何而起 Activity 的界面结构在哪里开始形成 绘制流程如何运转起来 接下来我们就一个个目标来 conquer。 我们一说到 绘制流程 ,就会想到或是听过 onMeasure 、 onLayout 、 onDraw 这三个方法,但是有没想过为什么我们开启一个App或是点开一个Activity,就会触发这一系列流

    2024年04月17日
    浏览(72)
  • Android架构进阶之高级UI系列(精编解析,值得收藏)

    public FrameHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_DO_FRAME: // 执行doFrame // 如果启用VSYNC机制,当VSYNC信号到来时触发 doFrame(System.nanoTime(), 0); break; case MSG_DO_SCHEDULE_VSYNC: // 申请VSYNC信号,例如当前需要绘制任务时 doScheduleVsync()

    2024年04月14日
    浏览(59)
  • Android架构进阶之高级UI系列(精编解析,值得收藏),Android开发面试技能介绍

    CallbackRecord callbacks; synchronized (mLock) { final long now = System.nanoTime(); // 根据指定的类型CallbackkQueue中查找到达执行时间的CallbackRecord callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked( now / TimeUtils.NANOS_PER_MS); if (callbacks == null) { return; } mCallbacksRunning = true; if (callbackType == Choreograph

    2024年04月13日
    浏览(42)
  • Android之 SVG绘制

    一 SVG介绍 1.1 SVG(Scalable Vector Graphics)是可缩放矢量图形的缩写,它是一种图形格式,其中形状在XML中指定, 而XML又由SVG查看器呈现。 1.2 SVG可以区别于位图,放大可以做到不模糊,可以做一些图标,按钮等绘制,但太复杂的话会导致渲染速度慢,占用内存大。适合简单的图

    2024年02月09日
    浏览(34)
  • Canvas中的裁剪师讲解与实战——Android高级UI(1),Android体系化进阶学习图谱

    从今天开始我们聊一聊 Canvas 的API,因为Canvas的API较多,所以我们分为几次分享,首先分享的是裁剪类型的API使用。话不多说,先上实战图。 老夫的少女心 源码地址文末会给出,了解原理才能更好地驾驭。 分享前,我们先来聊聊,在我们生活中如何绘制一张如下的图。 我们

    2024年04月13日
    浏览(86)
  • Android基础到进阶UI祖父级 ViewGroup介绍+实用

    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); // 如果是warp_content情况下,记录宽和高 int width = 0; int height = 0; //记录每一行的宽度,width不断取最大宽度 int lineWidth = 0; //每一行的高度,累加至h

    2024年04月16日
    浏览(43)
  • 【Android Framework系列】第13章 SVG矢量图形自定义组件(绘制中国地图)

    本章节我们来了解下什么是 SVG 矢量图形,怎么通过 SVG 实现图形的绘制,通过 SVG 实现不规则的自定义控件,项目实现一个中国地图,实现每个省都能够点击,项目地址在文末请自取。 SVG 指可伸缩矢量图形 (Scalable Vector Graphics) SVG 用来定义用于网络的基于矢量的图形 SVG 使用

    2024年02月10日
    浏览(63)
  • 使用svg在元素直接绘制连线箭头

    注意:svg的图形绘制的点位置坐标是基于画布的位置坐标,相当于从左上角的点为起点。 先来个简单示例: 上面示例中可以看到, svg 画布的位置在哪, path 中点的坐标就从哪里开始,默认是从浏览器可视窗口的左上角开始。那么我们只要知道点的坐标就能绘制箭头了。 接

    2024年02月04日
    浏览(39)
  • CSS 使用 SVG 绘制动态皮筋与小球交互动画

    使用 animation 控制 SVG 的 path 属性执行动画 使用 CSS 设置 SVG 部分属性 实现上述代码后,页面效果如下: 完成上述代码后,皮筋就可以开始运动,效果图如下: 完成上述代码后就可以完成所有效果。 完整代码下载

    2024年04月12日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包