2024年安卓最新小程序如何生成海报分享朋友圈,阿里ios面试题

结尾

最后,针对上面谈的内容,给大家推荐一个Android资料,应该对大家有用。

首先是一个知识清单:(对于现在的Android及移动互联网来说,我们需要掌握的技术)

泛型原理丶反射原理丶Java虚拟机原理丶线程池原理丶
注解原理丶注解原理丶序列化
Activity知识体系(Activity的生命周期丶Activity的任务栈丶Activity的启动模式丶View源码丶Fragment内核相关丶service原理等)
代码框架结构优化(数据结构丶排序算法丶设计模式)
APP性能优化(用户体验优化丶适配丶代码调优)
热修复丶热升级丶Hook技术丶IOC架构设计
NDK(c编程丶C++丶JNI丶LINUX)
如何提高开发效率?
MVC丶MVP丶MVVM
微信小程序
Hybrid
Flutter

接下来是资料清单:(敲黑板!!!


1.数据结构和算法

2.设计模式

3.全套体系化高级架构视频;七大主流技术模块,视频+源码+笔记

4.面试专题资料包(怎么能少了一份全面的面试题总结呢~)

不论遇到什么困难,都不应该成为我们放弃的理由!共勉~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);

ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内

ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片

这里举个例子说下如何绘制文字,比如我要绘制如下这个“字”,需要动态获取前面字数的总宽度,这样才能设置“字”的x轴坐标,这里我本来是想通过measureText来测量字体的宽度,但是在iOS端第一次获取的宽度值不对,关于这个问题,我还在微信开发者社区提了bug,所以我想用另一个方法来实现,就是先获取正常情况下一个字的宽度值,然后乘以总字数就获得了总宽度,亲试是可以的。

let allReading = 97 / 6 / app.globalData.ratio * wordNumber.toString().length + 325;

ctx.font = ‘normal normal 30px sans-serif’;

ctx.setFillStyle(‘#ffffff’)

ctx.fillText(‘字’, allReading, 150);

④绘制公众号二维码,和获取头像是一样的,也是先通过接口返回图片网络地址,然后再通过getImageInfo获取公众号二维码图片信息⑤如何绘制小程序码,具体官网文档也给出生成无限小程序码接口,通过生成的小程序可以打开任意一个小程序页面,并且二维码永久有效,具体调用哪个小程序二维码接口有不同的应用场景,具体可以看下官方文档怎么说的,也就是说前端通过传递参数调取后端接口返回的小程序码,然后绘制在画布上(和上面写的绘制头像和公众号二维码一样的)

ctx.drawImage(‘小程序码的本地地址’, x轴, Y轴, 宽, 高)

⑥最终绘制完把canvas画布转成图片并返回图片地址

wx.canvasToTempFilePath({

canvasId: ‘myCanvas’,

success: function (res) {

canvasToTempFilePath = res.tempFilePath // 返回的图片地址保存到一个全局变量里

that.setData({

showShareImg: true

})

wx.showToast({

title: ‘绘制成功’,

})

},

fail: function () {

wx.showToast({

title: ‘绘制失败’,

})

},

complete: function () {

wx.hideLoading()

wx.hideToast()

}

})

⑦保存到系统相册;先判断用户是否开启用户授权相册,处理不同情况下的结果。比如用户如果按照正常逻辑授权是没问题的,但是有的用户如果点击了取消授权该如何处理,如果不处理会出现一定的问题。所以当用户点击取消授权之后,来个弹框提示,当它再次点击的时候,主动跳到设置引导用户去开启授权,从而达到保存到相册分享朋友圈的目的。

// 获取用户是否开启用户授权相册

if (!openStatus) {

wx.openSetting({

success: (result) => {

if (result) {

if (result.authSetting[“scope.writePhotosAlbum”] === true) {

openStatus = true;

wx.saveImageToPhotosAlbum({

filePath: canvasToTempFilePath,

success() {

that.setData({

showShareImg: false

})

wx.showToast({

title: ‘图片保存成功,快去分享到朋友圈吧~’,

icon: ‘none’,

duration: 2000

})

},

fail() {

wx.showToast({

title: ‘保存失败’,

icon: ‘none’

})

}

})

}

}

},

fail: () => { },

complete: () => { }

});

} else {

wx.getSetting({

success(res) {

// 如果没有则获取授权

if (!res.authSetting[‘scope.writePhotosAlbum’]) {

wx.authorize({

scope: ‘scope.writePhotosAlbum’,

success() {

openStatus = true

wx.saveImageToPhotosAlbum({

filePath: canvasToTempFilePath,

success() {

that.setData({

showShareImg: false

})

wx.showToast({

title: ‘图片保存成功,快去分享到朋友圈吧~’,

icon: ‘none’,

duration: 2000

})

},

fail() {

wx.showToast({

title: ‘保存失败’,

icon: ‘none’

})

}

})

},

fail() {

// 如果用户拒绝过或没有授权,则再次打开授权窗口

openStatus = false

console.log(‘请设置允许访问相册’)

wx.showToast({

title: ‘请设置允许访问相册’,

icon: ‘none’

})

}

})

} else {

// 有则直接保存

openStatus = true

wx.saveImageToPhotosAlbum({

filePath: canvasToTempFilePath,

success() {

that.setData({

showShareImg: false

})

wx.showToast({

title: ‘图片保存成功,快去分享到朋友圈吧~’,

icon: ‘none’,

duration: 2000

})

},

fail() {

wx.showToast({

title: ‘保存失败’,

icon: ‘none’

})

}

})

}

},

fail(err) {

console.log(err)

}

})

}

总结

至此所有的步骤都已实现,在绘制的时候会遇到一些异步请求后台返回的数据,所以我用promise和async和await进行了封装,确保导出的图片信息是完整的。在绘制的过程确实遇到一些坑的地方。比如初开始导出的图片比例大小不对,还有用measureText测量文字宽度不对,多次绘制(可能受网络原因)有时导出的图片上的文字颜色会有误差等。如果你也遇到一些比较坑的地方可以一起探讨下做个记录,下面附下完整的代码

import regeneratorRuntime from ‘…/…/utils/runtime.js’ // 引入模块

const app = getApp(),

api = require(‘…/…/service/http.js’);

var ctx = null, // 创建canvas对象

canvasToTempFilePath = null, // 保存最终生成的导出的图片地址

openStatus = true; // 声明一个全局变量判断是否授权保存到相册

// 获取微信公众号二维码

getCode: function () {

return new Promise(function (resolve, reject) {

api.fetch(‘/wechat/open/getQRCodeNormal’, ‘GET’).then(res => {

console.log(res, ‘获取微信公众号二维码’)

if (res.code == 200) {

console.log(res.content, ‘codeUrl’)

resolve(res.content)

}

}).catch(err => {

console.log(err)

})

})

},

// 生成海报

async createCanvasImage() {

let that = this;

// 点击生成海报数据埋点

that.setData({

generateId: ‘点击生成海报’

})

if (!ctx) {

let codeUrl = await that.getCode()

wx.showLoading({

title: ‘绘制中…’

})

let code = new Promise(function (resolve) {

wx.getImageInfo({

src: codeUrl,

success: function (res) {

resolve(res.path)

},

fail: function (err) {

console.log(err)

wx.showToast({

title: ‘网络错误请重试’,

icon: ‘loading’

})

}

})

})

let headImg = new Promise(function (resolve) {

wx.getImageInfo({

src: ${app.globalData.baseUrl2}${that.data.currentChildren.headImg},

success: function (res) {

resolve(res.path)

},

fail: function (err) {

console.log(err)

wx.showToast({

title: ‘网络错误请重试’,

icon: ‘loading’

})

}

})

})

Promise.all([headImg, code]).then(function (result) {

const ctx = wx.createCanvasContext(‘myCanvas’)

console.log(ctx, app.globalData.ratio, ‘ctx’)

let canvasWidthPx = 690 * app.globalData.ratio,

canvasHeightPx = 1085 * app.globalData.ratio,

avatarurl_width = 60, //绘制的头像宽度

avatarurl_heigth = 60, //绘制的头像高度

avatarurl_x = 28, //绘制的头像在画布上的位置

avatarurl_y = 36, //绘制的头像在画布上的位置

codeurl_width = 80, //绘制的二维码宽度

codeurl_heigth = 80, //绘制的二维码高度

codeurl_x = 588, //绘制的二维码在画布上的位置

codeurl_y = 984, //绘制的二维码在画布上的位置

wordNumber = that.data.wordNumber, // 获取总阅读字数

// nameWidth = ctx.measureText(that.data.wordNumber).width, // 获取总阅读字数的宽度

// allReading = ((nameWidth + 375) - 325) * 2 + 380;

// allReading = nameWidth / app.globalData.ratio + 325;

allReading = 97 / 6 / app.globalData.ratio * wordNumber.toString().length + 325;

console.log(wordNumber, wordNumber.toString().length, allReading, ‘获取总阅读字数的宽度’)

ctx.drawImage(‘/img/study/shareimg.png’, 0, 0, 690, 1085)

ctx.save(); // 先保存状态 已便于画完圆再用

ctx.beginPath(); //开始绘制

//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针

ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);

ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内

ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片

ctx.restore(); //恢复之前保存的绘图上下文状态 可以继续绘制

ctx.setFillStyle(‘#ffffff’); // 文字颜色

ctx.setFontSize(28); // 文字字号

ctx.fillText(that.data.currentChildren.name, 103, 78); // 绘制文字

ctx.font = ‘normal bold 44px sans-serif’;

ctx.setFillStyle(‘#ffffff’); // 文字颜色

ctx.fillText(wordNumber, 325, 153); // 绘制文字

ctx.font = ‘normal normal 30px sans-serif’;

ctx.setFillStyle(‘#ffffff’)

ctx.fillText(‘字’, allReading, 150);

ctx.font = ‘normal normal 24px sans-serif’;

ctx.setFillStyle(‘#ffffff’); // 文字颜色

ctx.fillText(‘打败了全国’, 26, 190); // 绘制文字

ctx.font = ‘normal normal 24px sans-serif’;

ctx.setFillStyle(‘#faed15’); // 文字颜色

ctx.fillText(that.data.percent, 154, 190); // 绘制孩子百分比

ctx.font = ‘normal normal 24px sans-serif’;

ctx.setFillStyle(‘#ffffff’); // 文字颜色

ctx.fillText(‘的小朋友’, 205, 190); // 绘制孩子百分比

ctx.font = ‘normal bold 32px sans-serif’;

ctx.setFillStyle(‘#333333’); // 文字颜色

ctx.fillText(that.data.singIn, 50, 290); // 签到天数

ctx.fillText(that.data.reading, 280, 290); // 阅读时长

ctx.fillText(that.data.reading, 508, 290); // 听书时长

// 书籍阅读结构

ctx.font = ‘normal normal 28px sans-serif’;

ctx.setFillStyle(‘#ffffff’); // 文字颜色

ctx.fillText(that.data.bookInfo[0].count, 260, 510);

ctx.fillText(that.data.bookInfo[1].count, 420, 532);

ctx.fillText(that.data.bookInfo[2].count, 520, 594);

ctx.fillText(that.data.bookInfo[3].count, 515, 710);

ctx.fillText(that.data.bookInfo[4].count, 492, 828);

ctx.fillText(that.data.bookInfo[5].count, 348, 858);

ctx.fillText(that.data.bookInfo[6].count, 212, 828);

ctx.fillText(that.data.bookInfo[7].count, 148, 726);

ctx.fillText(that.data.bookInfo[8].count, 158, 600);

ctx.font = ‘normal normal 18px sans-serif’;

ctx.setFillStyle(‘#ffffff’); // 文字颜色

ctx.fillText(that.data.bookInfo[0].name, 232, 530);

ctx.fillText(that.data.bookInfo[1].name, 394, 552);

ctx.fillText(that.data.bookInfo[2].name, 496, 614);

ctx.fillText(that.data.bookInfo[3].name, 490, 730);

ctx.fillText(that.data.bookInfo[4].name, 466, 850);

ctx.fillText(that.data.bookInfo[5].name, 323, 878);

ctx.fillText(that.data.bookInfo[6].name, 184, 850);

ctx.fillText(that.data.bookInfo[7].name, 117, 746);

ctx.fillText(that.data.bookInfo[8].name, 130, 621);

ctx.drawImage(result[1], codeurl_x, codeurl_y, codeurl_width, codeurl_heigth); // 绘制头像

ctx.draw(false, function () {

// canvas画布转成图片并返回图片地址

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

【Android高级架构视频学习资源】

**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

讯、网易、字节跳动、阿里等公司2021年的高频面试题**,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

[外链图片转存中…(img-XspD5liw-1715106257406)]

【Android高级架构视频学习资源】

**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 19
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值