這樣做,十五天就能擁有一款屬於自己的安卓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日完成了所有功能的開發,現在也已經開放下載了,想體驗的可以訪問 點擊體驗

總結

其實前端的開發並不難,前端只需要和後臺進行數據交互就可以,但是後臺就需要很多內容了,併發控制,數據一致性,高訪問處理等等…要走的路還是很長的

想要分享編程技術,微信搜索【凱小白學編程】,和我一起學習技術叭

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章