移动设备交互应用 实验三 我的校园

一、实验目的与内容:

目的:掌握安卓中活动的编写、自定义用户界面的开发、碎片开发、广播机制以及数据持久化技术等;并能通过对课堂知识进行扩展来完善该界面,并使界面尽量美观。
内容要求:

  1. 请尽量模拟如下深大校园主页的功能,参考:
    https://www1.szu.edu.cn/
    在这里插入图片描述

  2. 具体要求:
    ①该实现的界面在某些地方应体现出如下功能:
    a. 界面能对平板与手机平台进行自适应(参考第4章碎片);
    b. 能对用户身份有强制下线的功能,比如网络中断,登录界面强行退出并显示提示错误的界面;
    c. 界面某些地方体现数据持久化的技术,如文件数据的读取、存储的多种实现方式,并简单阐述几种实现方式具体的适用场景;
    d. 界面要比较工整,没必要实现参考界面上的所有子项,能保证自己的界面实现能有扩展到参考界面的能力即可。
    ②功能并不局限于上面的要求,可以根据自己的理解设计一些新的功能,并在报告文档中进行详细的阐述,作为报告的亮点;
    ③APP的布局尽快模仿参考界面,如果有较大的困难,可以只实现出右半边部分的界面,并尽量按上面要求进行完善;
    ④对于某一种功能,可以在不同的子项处采用多种实现方式,并比较这些实现方式的不同及优劣势。

  3. 参考:尽量多的应用参考书《第一行代码 Android》第二版第2章活动、第3章UI开发第4章碎片、第5章广播机制与第6章数据持久化技术的各个知识点。

注意:

  1. 实验报告中需要有功能的描述、实验结果的截屏图像及详细说明;
  2. 也欢迎采用其它章节的知识点完成本次实验报告,如果实现的功能言之合理,会考虑酌情加分。

二、实验过程和代码与结果

项目亮点:
①通过数据库实现了登录效果
②页面更贴近实际校园类APP,页面更简洁
③采用动态绘制以适应不同横宽比的设备
④按钮区分各个功能,使进入各个功能更方便
⑤采用listview进行布局各条数据,不将各个数据写死,方便真正投入实用
⑥将每个Adapter和对应的类区分成不同的目录,方便查找

1.“我的校园”APP的构建过程及结果

我将主要分为以下三个方面进行介绍:主页面,登录界面,成绩查询。

①主页面

在这里插入图片描述
布局分析:
主页面应该是一个垂直方向的LinearLayout:

(1)显示校园图片的banner:

Banner采用轮播进行布局,先布局好所有的child,每个child都充满整个屏幕,然后拦截touch事件,根据手指滑动的距离调用scrollBy()来滚动,当手指停下的时候计算下个要到达第几个child的意图,根据Scroller和回调函数computeScroll()函数来完成接下来的滚动,这个只是child的滚动,我们看到下面还有四个小圆点,这个我叫做指示器,指示当前到了哪个图片,因为它不用响应事件,完全可以画出来,所以我重写了ViewGroup的draw()方法,在super.draw()之后绘制指示器,计算坐标。注意:重绘的时候需要调用setWillNotDraw(false)这个方法,否则将失效。
在这里插入图片描述

(2)一个GridLayout布局

中间的八个功能按钮使用GridLayout完成布局。
在这里插入图片描述
在这里插入图片描述

(3)一个ListView用来显示新闻

此处定义了一个ListView来进行展示对应的新闻,由于这些数据在实际应用中都来自学校服务器,故应采用一个model来完成数据的交互。
在这里插入图片描述
使用ListView时需要一个adapter,此处我自定义了一个adapter。 其中,每一条新闻的布局也是通过xml直接堆叠出来。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(4)底部菜单栏

分析得知,整个菜单栏是一个RelativeLayout,然后里面嵌套一个水平方向的LinearLayout,每一个菜单都是一个垂直方向的LinearLayout。
在这里插入图片描述
从上图中可以看到,中间的菜单比其他的菜单要往上面突起一点,也就说超过了父容器LinearLayout的高度,这个属性可以在最外层的RelativeLayout中设置一个属性android:clipChildren属性,否则子child是不能超出父容器的。
此外,要将突出的中间的菜单变为圆角,需要使用shape完成这个操作。
在这里插入图片描述

(5)顶部ActionBar

在这里插入图片描述
我这里使用了ActionBar,对于默认的ActionBar,要加一个右上角的用户头像,关于左上角的文字直接调用Activity的setTitle()就可以更改了,先加右上角的头像,然后重写Activity的一个回调函数,这样就能创建右上角的用户头像。
在这里插入图片描述

②登录界面

在这里插入图片描述

点击右上角头像,即可滑出登录界面,此处有一侧滑菜单

(1)侧滑菜单的实现

若要加入侧滑菜单,则要先编写侧滑出菜单的布局。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
要实现这种侧滑效果,首先自定义一个滑动Layout继承自RelativeLayout,里面有两个View分别是用来存放内容和菜单布局的,然后记录手指一动的距离更改内容View的leftMargin(注意:只有leftMargin的值是负数才能够向左偏移,如果是正数的话那么会向右压缩),在内容View移动的同时,调用菜单的setTranslateX()方法就可以达到菜单移动了。
实现菜单侧滑的几个主要函数

/** 
  * 切换菜单的显示和隐藏 
  */  
 public void switchMenu() {  
     if( mLeftParams.leftMargin == 0) {  
         showMenu();  
     } else {  
         hideMenu();  
     }  
 }  
  
 /** 
  * 显示菜单 
  */  
 public void showMenu() {  
     new SmoothScrollTack().execute(-mLeftEdge, mLeftParams.leftMargin);  
 }  
  
 /** 
  * 隐藏菜单 
  */  
 public void hideMenu() {  
     new SmoothScrollTack().execute(0, mLeftParams.leftMargin);  
 }  
(2)登录的实现

此处的登录借助了数据库SQLite进行登录数据验证,获取从文本框输入的字符之后,将获取的用户名与密码与数据库进行比对,并返回结果。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

③成绩查询

同样地,成绩查询也采用了ListView以便于实际使用,由于前面介绍过,故不再详细说明。代码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 请详细说明“我的校园”APP的功能、出现的关键问题及解决方案

(1)主要功能:

①主页面

在这里插入图片描述

②登录功能:

效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

③课表查询:

点击“我的课表”即可查看课表,也可点击周数进行周数切换
在这里插入图片描述
在这里插入图片描述

④成绩查询:

点击“我的通知”即可查看成绩
在这里插入图片描述

(2)遇到问题及解决办法:

Q:ViewGroup为什么不会调用onDraw
A: 正常情况下,我们重写LinearLayout的onDraw方法,它是不会被调用的。下面将分析原因并做解释。
在完成主页面功能栏的布局中,遇到了问题重写LinearLayout的onDraw方法时不会被调用,从而导致错误。

   <com.test.demo.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  
    android:id="@+id/ll_absolute"  
  
    android:orientation="vertical"  
  
    android:layout_width="fill_parent"  
  
    android:layout_height="fill_parent"  
  
    android:background="#FF000000">  
  
</com.test.demo.MyLinearLayout>  

大概的代码层次是,MyLinearLayout从LinearLayout派生出来,然后在程序中重载OnDraw。但是,onDraw不会被调用。我们可能会遇到这个问题:如果不给LinearLayout设置一个背景,系统是不会调用onDraw时,也就是说,我们重写的onDraw是不会调用的。当设置一个背景后,onDraw就会被调用。
造成这种现象的原因是继承自LinearLayout,而LinearLayout这是一个容器,ViewGroup本身并没有任何可画的东西,它是一个透明的控件,因些并不会触发onDraw,但是如果给LinearLayout设置一个背景色,其实这个背景色不管你设置成什么颜色,系统会认为LinearLayout上面有东西可画了,因此会调用onDraw方法。
我们可以仔细分析View的源码,它有一个方法View#draw(Canvas)方法,这里面有两个地方调用onDraw,它的条件都是:if (!dirtyOpaque) onDraw(canvas);
也就是说,如果dirtyOpaque是true的话,onDraw就不会调用,而dirtyOpaque的值的计算代码如下:

final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&  
             (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);  

此外,View还提供了一个重要的方法:setWillNotDraw:

	public void setWillNotDraw(boolean willNotDraw) {  
     setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);  
 } 

通过查阅资料,得知如果想重写onDraw,应调用这个方法来清除flag,所以如果想要重写LinearLayout的onDraw,可以在其构造方法中调用setWillNotDraw方法。 在ViewGroup初始他时,它调用了一个私有方法:initViewGroup,其中setFlags(WILL_NOT_DRAW, DRAW_MASK); 相当于调用了setWillNotDraw(true),因此对于ViewGroup,它就认为是透明的了。
如果我们想要重写onDraw,就需要调用setWillNotDraw(false)

综上所述:
①ViewGroup默认情况下,会被设置成WILL_NOT_DRAW,这是从性能考虑,这样一来,onDraw就不会被调用了。
②如果要重写一个ViweGroup的onDraw方法,有两种方法:在构造函数里面,给其设置一个颜色,如#00000000或在构造函数里面,调用setWillNotDraw(false),去掉其WILL_NOT_DRAW flag。

三、实验总结

①透明进度条bug

我的透明进度条原理是不断重绘一个背景图片,然后使用Matrix旋转图片,原先的代码是死循环,代码如下:

protected Void doInBackground(Void... params) {  
    while( true ) {  
        try {  
            Thread.sleep(100);  
        } catch(InterruptedException e) {  
            e.printStackTrace();  
        }  
        publishProgress();  
    }  
    return null;  
} 

这样就有一个bug,因为是死循环,当ProgressDialog被dismiss掉之后这个循环并不会销毁,而是一直在循环,这样造成的一个bug就是使用了透明进度条之后侧滑菜单点击就没有反应了,并且,透明进度条在Activity下次启动并不会有旋转的效果,这里修改的办法是将这个while(true)改成判断while( mLoop ) 然后重写ProgressDialog的dismiss()方法:

public void dismiss() {  
     super.dismiss();  
     mProgressView.setLoop(false);  
 } 

②通过android绘图来绘课程表界面:

受超级课程表等APP的启发,我自学了android绘图,通过绘图,可以更美观的完成课程表的展示。
分析页面可知:
整个界面是一个垂直的LinearLayout布局,里面放着四个子View:使用include标签加载的布局,普通的LinearLayout,自定义View和周数,自定义View与课程表。
通过CourseDateUI和CourseUI完成绘制:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

③实验感想:

通过本次实验,我学会了如何完成不同设备的自适应,也学会了通过数据持久化技术完成登录与用户验证,以及各个文件图片的存储。
也学会了熟练使用UI开发,碎片,广播机制与数据持久化技术的各个知识点。更通过自学,学会了安卓绘图,完成了精美的课程表的制作。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上山打老虎D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值