项目地址:Android-课程设计-图书馆选座-论文-Android文档类资源-CSDN下载
如何运行blog:
Android studio2020.3.1如何运行as2.几版本项目或module_刘建杰的博客-CSDN博客
简介
- 项目时间:2020年6月学校的安卓课程设计
- 项目亮点:2D可视化的编辑地图,灵感和代码来源于贪吃蛇项目的编辑地图,曾有一家互联网公司借鉴了本小项目的编辑地图的页面功能
- 项目简要:
管理员编辑图书馆楼层的2D地图,学生在图书馆2D地图上选座。
用户管理:登录、注册、修改个人信息、更改头像 。
楼层管理:添加、修改、编辑、删除楼层地图、保存为模板 。
模板管理:修改、删除、生成为楼层地图 。
选座管理:查询座位、我的座位、修改座位、预约座位(当时没写取消预约功能) 。
知识点:application+sqlite+canvas+碎片+recycleviw。 - 视频链接:基于Android的图书馆选座系统app_哔哩哔哩_bilibili
Android实践 |
2019-2020第二学期期末项目考试 |
班级: 安卓1802 学号: 183052745 姓名: 刘建杰 得分: |
目录
一、项目目的及意义
1.1项目设计目的
1.复习、巩固Android的基础知识,进一步加深对Android的理解和掌握。
2.为我提供一个动手动脑,独立实践的机会,将课本上的知识和实际应用有机结合起来,锻炼分析我实际解决问题的能力。
3.提高我面对对象分析与设计能力以及实际项目进行综合开发能力。
1.2项目设计意义
我开发的这个项目是图书馆在线选座,学生在手机app上,对今天明天图书馆的座位进行选座,这样可以避免早起排长队,选座的界面需要2D平面地图化,不是单纯的数字座位。
对我个人来说是展示个人能力的项目,开发项目过程中是以工程为目的的开发模式,系统模块分明,功能完善。
二、相关技术及工具
2.1 Android
安卓(Android)是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。主要使用于移动设备,如智能手机和平板电脑,由美国Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视、数码相机、游戏机、智能手表等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。 2013年的第四季度,Android平台手机的全球市场份额已经达到78.1%。2013年09月24日谷歌开发的操作系统Android在迎来了5岁生日,全世界采用这款系统的设备数量已经达到10亿台。
2.2 Sqlite
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2021年已经接近有21个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
2.3 Canvas
Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。大部分2D使用的api都在android.graphics和android.graphics.drawable包中。他们提供了图形处理相关的: Canvas、ColorFilter、Point(点)和RetcF(矩形)等,还有一些动画相关的:AnimationDrawable、 BitmapDrawable和TransitionDrawable等。以图形处理来说,我们最常用到的就是在一个View上画一些图片、形状或者自定义的文本内容,这里我们都是使用Canvas来实现的。你可以获取View中的Canvas对象,绘制一些自定义形状,然后调用View. invalidate方法让View重新刷新,然后绘制一个新的形状,这样达到2D动画效果。下面我们就主要来了解下Canvas的使用方法。
三、系统设计及功能
3.1功能需求
一、项目基本内容
学生在手机app上,对今天明天图书馆的座位进行选座,这样可以避免早起排长队,像天猫电影院订座一样有座位分布图显示,地图界面需要2D平面地图化,不是单纯的数字座位。图书馆管理员在app上编辑修改图书馆楼层地图分布显示。
二、大体功能
1.用户管理
- 用户登录
- 用户注册
- 用户找回密码
- 用户修改个人信息
2.选座功能
- 查看每个楼层的地图
- 查询座位根据不同时间段剩余的座位信息
- 选座要选的座位
- 取消原先座位
- 选择坐多久:上午、下午、晚上
- 我的座位信息
3.管理员
- 设置楼层数目
- 设置一层的2D地图
- 编辑一层的2D地图
- 删除一层的2D地图
- 设置为第几层的2D地图
3.2系统总体设计
3.3模块设计
3.4数据库相关设计
一、实体关系分析
二、数据库表设计
表1.1 用户信息表(user)
列名 | 数据类型 | 是否允许为空 | 说明 |
uid | int | 否 | 序号(主键) |
username | text | 否 | 昵称 |
userpwd | text | 否 | 密码 |
role | Int | 是 | 角色(0普通用户,1管理员) |
headimg | text | 是 | 头像 |
phone | text | 是 | 电话 |
表1.2楼层地图表(floormap)
列名 | 数据类型 | 是否允许为空 | 说明 |
fid | int | 否 | 序号(主键) |
flayer | int | 否 | 第几层 |
flayermap | varchar(15) | 是 | *地图数据* |
表1.3座位信息表(seatinfo)
列名 | 数据类型 | 是否允许为空 | 说明 |
sid | int | 否 | 序号(主键) |
uid | int | 否 | 用户id |
fid | Int | 否 | 楼层id |
sday | Text | 否 | 日期 |
stime | Int | 否 | 时间段int值(0上午,1下午,2晚上,3无) |
snumber | text | 否 | 座位号 |
Sx | Int | 否 | X坐标 |
sy | Int | 否 | Y坐标 |
表1.4地图模板表(mapmoudlesql)
列名 | 数据类型 | 是否允许为空 | 说明 |
mid | int | 否 | 序号(主键) |
mname | Text | 否 | 模板名称 |
mlayermap | text | 否 | 地图数据 |
四、系统实现及关键代码分析
4.1 程序运行
1.用户打开程序显示“登录界面”,登录界面会显示上一个登录的用户头像,并且账号和密码已输好,下面一行左右两侧分别是忘记密码?和用户注册。
2.按照国际案列,先注册,点击“登录页面”的新用户注册,会跳转到“用户注册”页面。此页面和登录界面比较像,输入昵称和密码即可注册。
3.回到“登录页面”登录管理员账号
4.输入完账号密码点击登录会跳转到程序的“主页面”,此页面分为上中下3部分,上:是标题、返回、功能按钮,中:是显示各个楼层的预览图,下是3个模块切换,第一个选中的模块是楼层模块,第二个是楼层模板模块,第三个是用户模块
5.我们先点击第三个模块“用户信息页面”,对用户信息可以修改,更改头像、个人用户信息、密码、管理员可以删除指定用户等
1)用户信息页面
2)修改手机
3)修改头像可以拍照和从图库选择
4)查看所有用户
5)可以删除用户
6.用户相关模块讲完,回到选座主题。点开第一个楼层模块。
点击右上角的+号图标可以进行对空白地图编辑,跳转到“编辑地图”页面。
此页面分两块,左边是显示由右边控制按钮操作的地图结果,右边是控制按钮。
对地图适当编辑后显示的地图。
其中,凳子图片代表座位,木头的图标代表书架,深灰色的图标代表墙壁。
可以根据不同地图的平面设置不同的地图。
7. 我们切换到普通用户,进行座位选座,首先登录普通用户账号后,楼层管理并没有编辑和删除按钮,只有选座的功能按钮。
用户选择相应楼层的座位,在“选座地图”中,手先单击座位,屏幕用绿色标记次座位,再右边控制按钮点击选座,此时将所选座位选中,并用黄色标记。
此“选择地图”页面和“编辑地图”页面大体相似,不过是为了用户选座而设计,不能对地图编辑,只能选择相应座位。
8.一个用户选座完成,另一个用户再登录选择这个座位会提示选择失败,需另选择座位。
9.选完座位,可以在“个人信息”界面的我的座位按钮点击进入“我的座位”信息界面,显示自己的座位信息
4.2 程序模块细分
总体目录
1.页面模块包
2.列表适配器包
3.实体bean包
4.数据库表操作包
5.canvas绘图包
6.工具包
4.3主要功能关键代码分析
编辑地图
Xml代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="10">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="8">
<!-- 地图view -->
<com.example.libraryselection.mappack.EditMapLayerView
android:id="@+id/edfloormap_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true">
</com.example.libraryselection.mappack.EditMapLayerView>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2">
<!-- 控件组件view -->
<ScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
>
<LinearLayout
android:id="@+id/edfloormap_linear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/edfloormap_tx_showfloorc"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="@string/firstfloornamestr"
android:gravity="center"/>
<Button
android:id="@+id/edfloormap_bt1_setseat"
android:layout_width="100dp"
android:layout_height="35dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/setseatstr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt_setshujia"
android:layout_marginTop="5dp"
android:layout_width="100dp"
android:layout_height="35dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/setshujia"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt2_setbar"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/setbarstr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt3_setfield"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/setfieldstr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt_setseatno"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/setseatnostr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt_setcancleseatno"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/setcanleseatnostr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="12sp"/>
<Button
android:id="@+id/edfloormap_bt_editmap_geneyqseat"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/geneyqseatstr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt_editmap_recover"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/recoverstr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<!-- <Button -->
<!-- android:id="@+id/edfloormap_bt4_save" -->
<!-- android:layout_width="100dp" -->
<!-- android:layout_height="35dp" -->
<!-- android:layout_marginTop="5dp" -->
<!-- android:background="@drawable/bt_editmap_shape" -->
<!-- android:text="@string/savestr" -->
<!-- android:layout_gravity="center" -->
<!-- android:textColor="#fff" -->
<!-- android:textSize="14sp"/> -->
<Button
android:id="@+id/edfloormap_bt5_savemold"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/setmoldstr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt7_lastlayer"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="上一层"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt8_nextlayer"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="下一层"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
<!-- 放一起试试,是修改模板的控件 -->
<Button
android:id="@+id/edfloormap_bt9_geneMapLayer"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="设为新楼层"
android:layout_gravity="center"
android:visibility="gone"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt10_lastmoudle"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="上一模板"
android:layout_gravity="center"
android:visibility="gone"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt11_lastmoudle"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="下一模板"
android:layout_gravity="center"
android:visibility="gone"
android:textColor="#fff"
android:textSize="14sp"/>
<Button
android:id="@+id/edfloormap_bt6_quit"
android:layout_width="100dp"
android:layout_height="35dp"
android:layout_marginTop="5dp"
android:background="@drawable/bt_editmap_shape"
android:text="@string/quitstr"
android:layout_gravity="center"
android:textColor="#fff"
android:textSize="14sp"/>
</LinearLayout>
</ScrollView>
</RelativeLayout>
</LinearLayout>
这是编辑地图的xml代码,线性布局里面套相对布局,右边scrollview包围,左边显示地图是自定义canvas的视图,是在代码里写的,如下:
// 选择座位的地图的view,还是公用原始地图与当前地图,不过能变得东西少了,只有座位
public class ChooseSeatMapLayerView extends View{
// 上级
Context supercon;
// 很重要的
ChooseSeatMapActivity chooseactivity;
private Paint yuxuanpaint;// 预选位置的paint,不填充并且绿色
private Paint myseatpaint;// 我选择的座位
private Paint beichooseseatpaint;// 被选择的座位
// 地图范围
// private int mapdata[][];
public ChooseSeatMapLayerView(Context context, AttributeSet attrs) {
super(context, attrs);
supercon = context;
// 需要强制转换
chooseactivity = (ChooseSeatMapActivity)context;
// 直接从maplist获取地图数据
initData();
initPaint();
Log.i("library", "ChooseSeatMapLayerView构造函数");
// 图片大小是固定的
mSrcRect = new Rect(0, 0, MapConstant.MapBigimgWidth, MapConstant.MapBigimgHeight);
}
public void initData(){
EditMapDataUtil.getMapDataFromMapList();
invalidate();
}
protected void initPaint(){
yuxuanpaint = new Paint();
yuxuanpaint.setColor(Color.GREEN);
yuxuanpaint.setStyle(Paint.Style.STROKE);
yuxuanpaint.setStrokeWidth(2);
myseatpaint = new Paint();
myseatpaint.setColor(Color.YELLOW);
myseatpaint.setStyle(Paint.Style.STROKE);
myseatpaint.setStrokeWidth(2);
beichooseseatpaint = new Paint();
beichooseseatpaint.setColor(Color.RED);
beichooseseatpaint.setStyle(Paint.Style.STROKE);
beichooseseatpaint.setStrokeWidth(2);
}
@Override
public void invalidate() {
// TODO Auto-generated method stub
// 重新更新画布
super.invalidate();
}
// 根据pix大小设置 图片显示区域
private Rect mSrcRect;
// 测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Log.e("library", "onMeasure--widthMode-->" + widthMode);
Log.e("library", "onMeasure--widthSize-->" + widthSize);
Log.e("library", "onMeasure--heightMode-->" + heightMode);
Log.e("library", "onMeasure--heightSize-->" + heightSize);
// 通过height设置width,
// 因为height是match ,height减去100, 要居中
heightSize = heightSize - 100;
// 向下取整绘制像素大小
int pix = (int) Math.floor(heightSize / (double)MapConstant.i);
// 设为全局的像素
MapConstant.MapPiexl = pix;
Log.e("library", "onMeasure--pix-->" + pix);
// Toast.makeText(supercon, "pix:"+pix, Toast.LENGTH_SHORT).show();
// 因为绘制像素向下取整,偏小了,就小下去
heightSize = pix * MapConstant.i;
// 根据绘制像素得到width
widthSize = pix * MapConstant.j;
//取最小边为控件的宽高的最小值
setMeasuredDimension(widthSize,heightSize);
}
// 触碰函数
/*直接变为预选*/
int lasti,lastj;
int mychoosei, mychoosej;
@Override
public boolean onTouchEvent(MotionEvent event) {
// 让这个位置 /40
mychoosej = (int) (event.getX() / MapConstant.MapPiexl);
mychoosei = (int) (event.getY() / MapConstant.MapPiexl);
switch(event.getAction()){
// 手指按下
case MotionEvent.ACTION_DOWN:
break;
// 手指松开, 选择的位置预选
case MotionEvent.ACTION_UP:
// 1.先恢复之前选择的预选位置。,这个只需指定是哪一个ij就行
if(!EditMapDataUtil.isOverLine(lasti, lastj)){
EditMapDataUtil.recoverDataFromYuanByIJ(lasti, lastj);
}
// 2.当前位置变为预选,前提不是边界
if(!EditMapDataUtil.isOverLine(mychoosei, mychoosej)){
EditMapDataUtil.setIjBeYu(mychoosei, mychoosej);
// 得放这里
lasti = mychoosei;
lastj = mychoosej;
}
// 更新绘图
invalidate();
break;
}
// return super.onTouchEvent(event);
return true;
}
// 设为预选位置为选座,需要判断是否座位
// 1.判断是否座位
// 2.判断是否是不可用座位
// 2.判断这个座位是否被其它人占了,是不能选
// 3.判断这个时间段,这天,我是否有其它座位,询问是否取消之前座位。是:修改原来座位,如果是同一层更新view
// 返回bean 为了通信
public void MapDatayuToMySeat(){
if(!EditMapDataUtil.isOverLine(mychoosei, mychoosej)){
// 1
int zhi = EditMapDataUtil.yuanMapData[mychoosei][mychoosej];
//2
if(zhi == MapConstant.SEATNO){
Constant.commonToast(supercon, "此座位不可用");
return;
}
if(zhi == MapConstant.SEAT){
// 2
boolean isoccur = thiseatIsOccur(mychoosei, mychoosej);
if(!isoccur){
// 3
if(!isThisTimeIhadSeat(mychoosei, mychoosej)){
// SeatInfoBean seat = new SeatInfoBean();
// // 添加到数据库中,当前i,j,fid,sday,stime,等
// seat.setSnumber(mychoosei+""+mychoosej);
// seat.setSx(mychoosej);
// seat.setSy(mychoosei);
// 将预选的位置数组恢复
if(!EditMapDataUtil.isOverLine(mychoosei, mychoosej)){
EditMapDataUtil.recoverDataFromYuanByIJ(mychoosei, mychoosej);
}
chooseactivity.insertOneSeatToSqiteAndList(mychoosei, mychoosej);
}
}else{
Constant.commonToast(supercon, "此座位已被占用,请选择其它");
}
}else{
Constant.commonToast(supercon, "请选择座位");
}
}else{
Constant.commonToast(supercon, "请先选择座位");
}
// invalidate();
}
// 判断这个座位是否被占
public boolean thiseatIsOccur(int i, int j){
for(int z = 0; z < MapConstant.curallseatlist.size(); z++){
SeatInfoBean seat = MapConstant.curallseatlist.get(z);
// x, j
int m = seat.getSx();
int n = seat.getSy();
if(m == j && n == i){
return true;
}
}
return false;
}
// 判断我这个时间段是否有了座位
public boolean isThisTimeIhadSeat(int i, int j){
// 一般只有一条
for(int z = 0; z < MapConstant.myseatlist.size(); z++){
SeatInfoBean oldseat = MapConstant.myseatlist.get(z);
// 弹框
SeatInfoBean newseat = new SeatInfoBean();
newseat.setSy(i);
newseat.setSx(j);
newseat.setSnumber(i+""+j);
// 放入新楼层的fid
newseat.setFid(MapConstant.getCurLayerZhujian());
chooseactivity.generateHadSeatDialog(oldseat, newseat);
// chooseactivity.generateHadSeatDialog(seat.getSid(), seat.getSy(), seat.getSx(), MapConstant.getLayerNumberByFid(seat.getFid()), i, j, MapConstant.getLayerNumber());
return true;
}
return false;
}
// 绘画函数
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// i是行,j是列
for(int i = 0; i < MapConstant.i; i++){
for(int j = 0; j < MapConstant.j; j++){
int leftj = j * MapConstant.MapPiexl;
int lefti = i * MapConstant.MapPiexl;
int righti = j * MapConstant.MapPiexl + MapConstant.MapPiexl;
int rightj = i * MapConstant.MapPiexl + MapConstant.MapPiexl;
// 实时目标位置要计算的。
Rect rc = new Rect(leftj, lefti, righti, rightj);
// 如果是墙
if(EditMapDataUtil.currMapData[i][j] == MapConstant.BAR){
// canvas.drawBitmap(MapConstant.bigwallbitmap, leftj, lefti, null);
canvas.drawBitmap(MapConstant.bigwallbitmap, mSrcRect, rc, null);
}
// 如果是预选地图
else if(EditMapDataUtil.currMapData[i][j] == MapConstant.YU){
canvas.drawRect(rc, yuxuanpaint);
}
// 如果是座位
else if(EditMapDataUtil.currMapData[i][j] == MapConstant.SEAT){
// canvas.drawBitmap(MapConstant.bigseatbitmap, leftj, lefti, null);
canvas.drawBitmap(MapConstant.bigseatbitmap, mSrcRect, rc, null);
}
// 如果是地板
else if(EditMapDataUtil.currMapData[i][j] == MapConstant.FIELD){
// canvas.drawBitmap(MapConstant.bigfloorbitmap, leftj, lefti, null);
canvas.drawBitmap(MapConstant.bigfloorbitmap, mSrcRect, rc, null);
}
// 如果是书架
else if(EditMapDataUtil.currMapData[i][j] == MapConstant.SHUJIA){
// canvas.drawBitmap(MapConstant.bigshujiabitmap, leftj, lefti, null);
canvas.drawBitmap(MapConstant.bigshujiabitmap, mSrcRect, rc, null);
}
// 如果是不可用座位
else if(EditMapDataUtil.currMapData[i][j] == MapConstant.SEATNO){
// canvas.drawBitmap(MapConstant.bigseatnobitmap, leftj, lefti, null);
canvas.drawBitmap(MapConstant.bigseatnobitmap, mSrcRect, rc, null);
}
}
}
// 绘制被学生选座的地图,循环
// 直接根据ij将指定位置绘制, 需要判断楼层是否对应
Paint curp = new Paint();
for(int z = 0; z < MapConstant.curallseatlist.size(); z++){
SeatInfoBean seat = MapConstant.curallseatlist.get(z);
if(seat.getFid() == MapConstant.getCurLayerZhujian()){
// 如果这个座位是我订的,换Paint
if(seat.getUid() == MyApplication.user.getUid()){
curp = myseatpaint;
}else{
curp = beichooseseatpaint;
}
// x, j
int j = seat.getSx();
int i = seat.getSy();
int leftj = j * MapConstant.MapPiexl;
int lefti = i * MapConstant.MapPiexl;
int righti = j * MapConstant.MapPiexl + MapConstant.MapPiexl;
int rightj = i * MapConstant.MapPiexl + MapConstant.MapPiexl;
Rect rc = new Rect(leftj, lefti, righti, rightj);
canvas.drawRect(rc, curp);
}
}
}
}
主要是继承View类,然后重写onDraw绘图函数,进行绘图。
其它:编辑地图是一块比较难的地方,只要做好了这块其它功能就可以相对简单了。
五、收获与体会
5.1 项目总结
1. 完成度80%,大体完善
2. 有许多改进和增加功能方向,比如用户可以取消预选地图、用户查看我的座位可以跳转到相应的地图界面、管理员可以拖动楼层更改楼层顺序等细节问题
3. 充分利用Canvas绘图,完成编辑地图、显示地图这难点,并适用于不同手机
4. 利用面向对象思想 使类划分细明,更容易实现效果
5. 采用了一点点mvc模式,bean代表model模型
6. 使用Sqlite表保存地图数据
5.2 收获与体会
- 开发程序必须要有设计,设计项目中存在的对象,提取出属性和行为,再关联各个类之间的关系,才能写出高效和可扩展的代码
- 知识面太窄,需要多学习,才能扩展思维,实现更好的程序
- 算法以及数据结构很重要
- 提高写代码的效率,不能写代码10分钟,找bug1小时,太耗时间,应该先有思路再写,可在本子上先验算下
- 特别注意数组是引用类型的问题
- 提高找bug的精确性,先要理清思路,逐步跟踪,特别是可以利用调试功能 一步一步下去。