这样做,十五天就能拥有一款属于自己的安卓APP

微信搜索【凯小白学编程】,陆续推送分享各种好玩的小代码,小程序。定期分享源码资源

摘要

此篇文章是以我开发的一款打卡APP来介绍APP开发的。现在的各种技术,让APP并不是那么遥不可及了,普通学生也可以在短时间内完成一款APP的开发。但是因为是自己一个人开发,也需要有一定的数据库,前端,java或者python或者go或者php基础。此次讲的不是原生APP开发,一个完整的原生APP不是一个人就能开发出来的,因为完整的APP设计的功能还是很多的。说到这来介绍一下三种类型的APP。
这也是最后一篇分享类博客了,以后开始分享技术python,数据结构,计算机组成等等

APP开发类型

原生应用程序:(NativeApp)
原生APP就是利用Android、iOS平台官方的开发语言、开发类库、工具进行开发。比如安卓的java语言,iOS的object-c 语言。在应用性能上和交互体验上应该是最好的,尤其是在页面方面,原生应用程序的动画效果是其他任何app都不能比的。
混合应用程序(Hybrid App)
即利用了原生APP的开发技术还应用了HTML5开发技术,是原生和HTML5技术的混合应用。混合比例不限。包含一些原生开发的内容,同时也嵌入的前端技术,可以快速上手实现一些需要的功能。但是在页面交互方面,肯定不如原生应用程序一样流畅
Web版APP (Web App)
本质就是浏览器功能的叠加,用普通Web开发语言开发的,通过浏览器运行。
功能特性

打卡app展示

视频展示:点击观看
现在已经完成了所有的开发,也有许多小伙伴在用了。
想体验的话,点击下载体验

开发过程

微信小程序开发

起初只想开发一个小程序作为自己的打卡记录,但是当第一版小程序发布之后,后期进行过一次完善。发现小程序的功能完全不能满足自己的需求,于是着手开发安卓和ios,因为安卓和ios对于软件的大小没有限制。虽然也不是安卓和ios的原生开发,但是限制终归比微信小程序少。
微信小程序的缺点
微信小程序的限制比较多。
1,首先如果要发布就必须有自己的域名,而且域名必须支持https访问。要在小程序后台配置上自己的安全域名。
2,服务类目限制,如果是个人小程序,对你的限制非常多,有很多功能都不能开发
3,代码包,单包最大2M,总项目最大16M,这多多少少也会限制自己的操作。
小程序码
这是已经发布的小程序,可以去看看一部分功能,是安卓app的一小部分功能。

开发选择

之前接触过安卓,也学过一段时间,所以知道自己一个人开发原生安卓很难,因为还要页面设计,内部逻辑啊等等,很多很多,所以就放弃了原生安卓和原生ios的开发。而当时遇到一套代码,多端发布的内容,于是就想试试。
当时看的是uniapp还有flutter,经过简单的对比之后选择了uniapp,因为uniapp采用的是vue语法,以前接触过上手比较简单。这里就要多提一点了,我一直都是学的后端,对于前端的掌握程度知识会用一些css和js,而且在开发这款app之前并没有对前端进行学习,直接上手,十五天就完成了第一版功能。所以你也可以,从这里就能看出,现在的app开发对于开发者真的很友好。

正式开发

页面设计

页面设计是开发的最开始,我们需要根据页面展示的数据来调用后台传输需要的数据进行渲染。

首页设计

首页设计至关重要,一个好看的首页才能留住用户。而对于一个打卡app,首页就是自己给自己定的习惯或者是加入的圈子,所以圈子显示卡片的美观度很重要。于是就选择了组件库的catd卡片,然后进行二次开发。

<view class="tui-card-class tui-card " :class="[full?'tui-card-full':'',border?'tui-card-border':'']" @tap="handleClick"
	 @longtap="longTap">
		<view class="tui-card-header " :class="{'tui-header-line':header.line}" :style="{background:header.bgcolor || '#fff'}">
			<view class="tui-header-left">
				<image :src="image.url" class="tui-header-thumb" :class="{'tui-thumb-circle':image.circle}" mode="widthFix" v-if="image.url"
				 :style="{height:px(image.height || 60),width:px(image.width || 60)}"></image>
				<text class="tui-header-title" :style="{fontSize:px(title.size || 30),color:(title.color || '#7A7A7A')}" v-if="title.text">{{title.text}}</text>
			</view>
			<view class="tui-header-right" :style="{fontSize:px(tag.size || 24),color:(tag.color || '#b2b2b2')}" v-if="tag.text">
				{{tag.text}}
			</view>
		</view>
		<view class="tui-card-body">
			<slot name="body"></slot>
		</view>
		<view class="tui-card-footer">
			<slot name="footer"></slot>
		</view>
	</view>
.tui-card-border {
		position: relative;
		box-shadow: none !important
	}

	.tui-card-border::after {
		content: ' ';
		position: absolute;
		height: 200%;
		width: 200%;
		border: 1px solid #ddd;
		transform-origin: 0 0;
		-webkit-transform-origin: 0 0;
		-webkit-transform: scale(0.5);
		transform: scale(0.5);
		left: 0;
		top: 0;
		border-radius: 20upx;
		box-sizing: border-box;
	}

	.tui-card-header {
		width: 100%;
		padding: 20upx;
		display: flex;
		align-items: center;
		justify-content: space-between;
		position: relative;
		box-sizing: border-box;
		overflow: hidden;
		border-top-left-radius: 10upx;
		border-top-right-radius: 10upx;
	}

	.tui-card-header::after {
		content: '';
		position: absolute;
		border-bottom: 1upx solid #eaeef1;
		-webkit-transform: scaleY(0.5);
		transform: scaleY(0.5);
		bottom: 0;
		right: 0;
		left: 0;
	}

	.tui-header-line::after {
		border-bottom: 0 !important;
	}

效果图
展示

发现页

发现页主要包括轮播图,还有一些热门圈子的展示。还有一个话题功能还没有加。
其实最主要的就是轮播图,好看的轮播图才能吸引人呢。

<view class="tui-banner-box" style="margin-top: 100rpx;">
			<swiper :indicator-dots="true" :autoplay="true" :interval="5000" :duration="150" class="tui-banner-swiper" :circular="true"
			 previous-margin="60rpx" next-margin="60rpx" @change="change">
				<swiper-item v-for="(item,index) in banner" :key="index" class="tui-banner-item">
					<image :src="'../../static/banner/'+item" class="tui-slide-image" :class="[current!=index?'tui-banner-scale':'']"
					 mode="scaleToFill" @tap="detail" :data-id="index" />
				</swiper-item>
			</swiper>
		</view>
.tui-banner-box {
		width: 100%;
		padding-top: 20rpx;
		box-sizing: border-box;
		background: #fff;
	}

	.tui-banner-swiper {
		width: 100%;
		height: 240rpx;
	}

	.tui-banner-item {
		padding: 0 16rpx;
		box-sizing: border-box;
	}

	.tui-slide-image {
		width: 100%;
		height: 240rpx;
		display: block;
		border-radius: 12rpx;
		/* transition: all 0.1s linear; */
	}

	.tui-banner-scale {
		transform: scaleY(0.9);
		transform-origin: center center;
	}

	/* #ifdef APP-PLUS || MP */
	.tui-banner-swiper .wx-swiper-dot {
		width: 8rpx;
		height: 8rpx;
		display: inline-flex;
		background: none;
		justify-content: space-between;
	}

	.tui-banner-swiper .wx-swiper-dot::before {
		content: '';
		flex-grow: 1;
		background: rgba(255, 255, 255, 0.8);
		border-radius: 16rpx;
		overflow: hidden;
	}

	.tui-banner-swiper .wx-swiper-dot-active::before {
		background: #fff;
	}

	.tui-banner-swiper .wx-swiper-dot.wx-swiper-dot-active {
		width: 16rpx;
	}

在这里插入图片描述
说到这就要说一下uniapp的内容了,因为uniapp是一套代码多端发布,但是不同的平台的语法是不同的,因此有些样式就会改变,这个时候就需要用到判断了。

/* #ifdef APP-PLUS || MP */
样式代码
/* #endif */

这样就可以根据当前的客户端来显示对应的内容了。

用户页

这个代码比较杂就不发出来了
看一下样式
在这里插入图片描述

问题处理

刘海屏适配问题

因为这个类似于前端,而且现在各种各样的屏幕都有,所以我们一定要进行屏幕适配,如果不适配的话很容易导致样式错乱
在页面的json文件中,加入

{
  "navigationStyle": "custom"
}

获取当前手机型号状态栏的高度(也就是刘海屏或者水滴屏的高度)


wx.getSystemInfo({
    success: e => {
      t.barheight = e.statusBarHeight; //状态栏高
    }
})

获取的宽度我们要应用在页面中,并且固定在顶部(如果有需要的话)

可以加上这样的前端代码

<view style="position:fixed;top:0rpx;width: 100%;background-color: #FFFFFF;height:{{barheight}}px">
    <view style="background-color:#FFFFFF;"></view>
</view>

canvas绘图

对于一个打卡app来说,每天的打卡卡片至关重要,这标志着是否已完成打卡。同时,打卡卡片还能起到推广的作用,所以这个是必不可少的功能。
这是我写的一个 绘图并且保存的 卡片
可以根据自己的需要进行更改

canvasImage(){
				var that=this
				var now = new Date();
				var year = now.getFullYear();       //年
				var month = now.getMonth() + 1;     //月
				var day = now.getDate();
				var hour=now.getHours();
				var minute=now.getMinutes();
				var reallywight=uni.getSystemInfoSync().windowWidth
				var reallyhight=uni.getSystemInfoSync().windowHeight
				var wigth=uni.getSystemInfoSync().windowWidth-50
				var hight=uni.getSystemInfoSync().windowHeight-90
				var height=uni.getSystemInfoSync().windowHeight-190
				const ctx =uni.createCanvasContext('myCanvas');
				ctx.drawImage( that.imageurl , 25 ,25 ,wigth,wigth*1.77 );		//绘制图
				ctx.save() 
				var b = Math.random();
				b=b*3
				b = Math.ceil(b)
				if (b==1){
					ctx.setFillStyle("#FFFFFF")
					ctx.font = 'normal 16px sans-serif';
					ctx.fillText("每/",wigth-80,70)
					ctx.fillText("日/",wigth-56,70)
					ctx.fillText("一/",wigth-32,70)
					ctx.fillText("签",wigth-8,70)
				}else if (b==2){
					ctx.setFillStyle("#FFFFFF")
					ctx.font = 'normal 16px sans-serif';
					ctx.fillText("元/",wigth-80,70)
					ctx.fillText("气/",wigth-56,70)
					ctx.fillText("满/",wigth-32,70)
					ctx.fillText("满",wigth-8,70)
				}else if(b==3){
					ctx.setFillStyle("#FFFFFF")
					ctx.font = 'normal 16px sans-serif';
					ctx.fillText("持/",wigth-80,70)
					ctx.fillText("之/",wigth-56,70)
					ctx.fillText("以/",wigth-32,70)
					ctx.fillText("恒",wigth-8,70)
				}
				
				// 画方框
				ctx.lineWidth="2"
				ctx.strokeStyle="#FFFFFF"
				ctx.strokeRect(30, 35, 60, 70)
				ctx.moveTo(40,86)
				ctx.lineTo(80,86)
				ctx.lineWidth="4"
				ctx.stroke()
				ctx.setFillStyle("#FFFFFF")
				ctx.setFontSize(50)//设置字体大小,默认10
				ctx.textAlign = 'center'	// 设置位置
				ctx.font = 'normal 40px sans-serif';	// 字体样式
				ctx.fillText(day , 60, 80);
				ctx.save()
				ctx.font = 'normal 12px sans-serif';
				var dayy=year+"."+month
				ctx.fillText(dayy,60,100)
				ctx.font = 'normal 15px sans-serif';
				ctx.fillText("⛪枣庄市",70,130)
				ctx.font = 'normal 10px sans-serif';
				ctx.fillText("21天习惯打卡",60, wigth*1.70-45)
				ctx.save()
				var text="所有的习惯以,不可见的程度积聚起来,如百溪汇于川,百川流于海!"
				ctx.font = '30px FZShuTi';
				var str= new Array();   
				str=text.split(","); 
				// ctx.textAlign="center";
				var uphight=0
				for (var i=0;i<str.length;i++){
					ctx.font = '25px shuti';
					ctx.fillText(str[i], reallywight/2, height/2+uphight)
					uphight+=40
				}
				ctx.font = 'normal 20px FZYaoti';
				ctx.fillText("考研记录生活圈子",wigth-80,wigth*1.70-25)
				ctx.font = 'normal 20px FZYaoti';
				ctx.fillText("已打卡10天",wigth-50,wigth*1.77-15)
				
				ctx.draw()
			},
			saveimage(){
				uni.showLoading({
					title:'图片生成中'
				})
				var that=this
				uni.getImageInfo({
					src:'https://cdn.u1.huluxia.com/g4/M03/33/66/rBAAdl7DPNyAEtLOAA97lIhZixo352.jpg',
					success:function(res){
						console.log(res)
						that.imageurl=res.path
					}
				})
				console.log(that.imageurl)
				var wigth=uni.getSystemInfoSync().windowWidth-50
				var hight=uni.getSystemInfoSync().windowHeight-90
				uni.canvasToTempFilePath({	// 把画布转化成临时文件
					x: 25,
					y: 25,
					width:wigth,    // 截取的画布的宽
					height: wigth*1.77,   // 截取的画布的高
					destWidth: wigth*4,	// 保存成的画布宽度
					destHeight: wigth*1.77*4,	// 保存成的画布高度
					fileType: 'jpg',			// 保存成的文件类型
					quality: 1,					// 图片质量
					canvasId: 'myCanvas',		// 画布ID
					success(res) {
						uni.saveImageToPhotosAlbum({	// 存成图片至手机
							filePath: res.tempFilePath,
							success(res2) {
								uni.showToast({title: '图片保存成功', duration: 2000})
								uni.hideLoading()
								this.canvasCancelEvn();
							},
							fail(res3) {
								if (res3.errMsg === 'saveImageToPhotosAlbum:fail auth deny') {
									
									uni.showToast({title: '保存失败,稍后再试', duration: 2000,icon:'none'})
									uni.hideLoading();
								}else{
									uni.showToast({title: '保存失败,稍后再试', duration: 2000,icon:'none'})
									uni.hideLoading();
								}
							}
						})
					},
					fail() {
						uni.showToast({title: '保存失败,稍后再试',duration: 2000,icon:'none'})
						wx.hideLoading();
					}
				})

			}

页面展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

开发完成

当时算了算时间,从开始开发到第一版发布用时十三天,然后再加上一些功能调试大概十五天左右已经实现打卡的基本功能了。但是我们都知道软件是不断完善的,后期又进行了一些修缮,4.17日完成了所有功能的开发,现在也已经开放下载了,想体验的可以访问 点击体验

总结

其实前端的开发并不难,前端只需要和后台进行数据交互就可以,但是后台就需要很多内容了,并发控制,数据一致性,高访问处理等等…要走的路还是很长的

想要分享编程技术,微信搜索【凯小白学编程】,和我一起学习技术叭

猜你喜欢

转载自blog.csdn.net/lk888666/article/details/106240675