Android权威编程--GeoQuiz游戏app

移动开发技术课程作业

QuizGame(猜谜游戏)

      一、案例描述

  • 完成Android权威编程中的GeoQuiz项目,要求:
  1. 额外添加一个登录的Activity,登录后打开答题界面,用户名为本人学号,密码为111111。(用户名和密码必须匹配方可登陆成功,可采用SharedPreference存储用户名和密码)。
  2. 实现对中英文操作的支持(题目可以采用英文,但操作界面需提供中英文支持)。

二、其他要求:

1、包的名称中必须包含本人姓名的拼音,如:com.xuerenjie。

2、用户名为本人学号,未使用本人学号者视为抄袭

 

三、提交内容:

1、打包整个工程的源代码

2、生成apk

3、基本步骤的实验报告。

 

 

 

四、实现基本步骤:

 

1、两个要求

   1、要求额外添加一个登录的Activity,登录后打开答题界面,用户名为我的学号1610421084,密码为111111,同时要求使用SharedPreference来存储用户名和密码。

   在解决问题之前,先讲解下我的三两想法,用户名密码就两条数据,其实我觉得完全可以在登录时进行实时检测,也就是用两个字符串进行存储并匹配,或者用个全局变量的String数组存进去,然后登录的时候检测匹配一下即可。不过在这我还是讲下使用SharedPreference方法(因为我是用这种方法的,当然这种方法有个明显的弊端,后面讲述)

   首先,我们新建一个LoginActivity同时会自动生成一个xml,xml布局文件很简单,就使用之前实验做过的登录界面即可,用来输入用户和密码,源码和运行效果如下图:

Android权威编程--GeoQuiz游戏app_第1张图片

Android权威编程--GeoQuiz游戏app_第2张图片

 

 

 

   接下来需要对LoginActivity交互逻辑进行编码,如下图一中,我们先对布局组件初始化绑定,然后对登录按钮绑定监听事件,其中的跳转还是使用Intent对象来完成,但是登录之前我们需要判断账号密码是否正确,而要判断则需要有准确数据来和用户输入的数据进行对比,所以这个数据的来源就是我们使用SharedPreference提前存进去的。如下图二中所示,刚才我说的弊端就在这,因为设定死了账号密码所以我们需要写一个保存账号密码的方法提前将数据写进data.xml文件中,重点是新版本的Androidstudio打开data/data下的文件很麻烦,所以我们是无法通过文件直接写入的,而要用新建函数,不过这里的一个解决方案就是添加一个注册按钮,用来调用该保存信息的函数。登录页面完成后,只要账号密码匹配成功即可登录游戏的主页面。

Android权威编程--GeoQuiz游戏app_第3张图片

Android权威编程--GeoQuiz游戏app_第4张图片

 

 

 

   2、要求实现中英文操作的支持,即可以提供中英文转换。

   大概讲解下修改的步骤:首先如下,在res目录下创建一个values-zh-rCN用来存放中文的xml文件。这里需要注意,两个文件中的name要统一对应,不然待会翻译的时候就会错乱出现bug。

Android权威编程--GeoQuiz游戏app_第5张图片

 

   在答题页面xml中新增两个按钮,用于转换中英文。

Android权威编程--GeoQuiz游戏app_第6张图片

 

   然后在QuizActivity中为两个按钮添加监听事件,一个用于中文转换,一个用于英文转换,创建一个changeAppLanguage()方法进行对语言显示的转换。这两个方法源码如下。

Android权威编程--GeoQuiz游戏app_第7张图片

 

   运行效果如图:

Android权威编程--GeoQuiz游戏app_第8张图片

Android权威编程--GeoQuiz游戏app_第9张图片

 

 

 

 

 

 

2、注意的点(坑):

 

   1、在Question类中,其R.String.会设置为整型数据。

   变量mTextResId用来保存地理知识问题字符串的资源ID。资源ID总是int类型,所以这里设置它为int类型。稍后会处理需要用到的问题字符串资源

 

2、在回答按钮处写死的true代表答对,false代表打错,但是题目本身是有对错的,所以这里需要添加对错的逻辑部分。

 

3、在设备进行屏幕旋转的时候,会出现题目回到第一道题。

原因:每次旋转设备,当前QuizActivity实例会完全销毁,实例中的mCurrentIndex当前值会从内存里被抹掉。 旋转后, Android重新创建了QuizActivity新实例, mCurrentIndex在onCreate(Bundle)方法中被初始化为0。一切重头再来,用户又看到第一道题。

解决方法:

1.创建备选资源即水平模式布局(因为在设备旋转时,屏幕会发生横屏,则重新设置一个横屏的布局),新建一个布局的xml文件,其中设置为FrameLayout,其他的无需变化。

Android权威编程--GeoQuiz游戏app_第10张图片

 

2.保存数据以应对设备旋转。因为每次设备旋转时,系统会自动销毁当前的Activity,然后创建一个新的Activity导致index又回到了初始值,所以需要想办法在设备旋转时的当前index并保存下来。

其中使用重写onSaveInstanceState(Bundle)是一种解决方案,该方法通常在onStop()方法之前由系统调用,其默认实现要求所有的Activity视图将自身状态数据保存在Bundle中,所以在重建onCreate()创建Activity后就会将保存信息的Bundle对象传入(源码如下)。

Android权威编程--GeoQuiz游戏app_第11张图片

Android权威编程--GeoQuiz游戏app_第12张图片

Android权威编程--GeoQuiz游戏app_第13张图片

 

 

   4、在新建Activity的布局文件中用于给用户查看答案的TextView有一个特殊的属性tools:text。这个命名空间可以覆盖某个组件的任何属性,也就是在预览中可以看见效果,但是在运行时“Answer”字体却不会显示出来。

Android权威编程--GeoQuiz游戏app_第14张图片

 

   5、在判断用户是否作弊时,使用的是Intent进行数据传递,其实在之前的实验中使用过,Activity间的数据传递与回传。注意:这里比较复杂的就是需要在QuizActivity中将正确答案传递到CheatActivity中,并在该Activity的布局中通过点击“showanswer”按钮用TextView显示出来。而判断用户是否作弊,就是通过判断该按钮是否被点击。进而再将是否被点击传递回QuizActivity中。

Android权威编程--GeoQuiz游戏app_第15张图片

Android权威编程--GeoQuiz游戏app_第16张图片

Android权威编程--GeoQuiz游戏app_第17张图片

 

 

 

   因为在CheatActivity销毁之后会回调QuizActivity中的onActivityResult()方法,所以我们需要重写该方法,如下图,也就是取出其中回传过来的是否作弊的标记。

Android权威编程--GeoQuiz游戏app_第18张图片

 

 

 

3、挑战练习:

 

   1.1、定制toast消息:

   如下图源码,对新建的Toast对象进行重新设置setGravity属性即可,注意该方法中的三个参数是位置及坐标,第一个设为TOP,后两个及中间的位置0,0。

Android权威编程--GeoQuiz游戏app_第19张图片

  

 

   2.7、为TextView添加监听器

   如下源码,这部分很简单,就是对TextView添加一个监听事件即可,主要是其中点击事件设置为当前题目的index递增1并对TextView的内容进行更新。

Android权威编程--GeoQuiz游戏app_第20张图片

 

  

2.8、添加后退按钮

   如图,初始的按钮只有进入下一题,没有返回的按钮,所以添加一个返回按钮很简单。

Android权威编程--GeoQuiz游戏app_第21张图片

 

   如下源码,需要在布局文件中新加一个线性布局用于放置返回和继续的按钮,同时要设置返回的按钮的图片背景以及text内容,则需要与Next按钮一样,在String.xml文件中新加一个字段。

Android权威编程--GeoQuiz游戏app_第22张图片

 

 

   布局文件添加完的效果:

Android权威编程--GeoQuiz游戏app_第23张图片

 

   布局文件写完以后,不要忘了,还需要添加交互代码,不然这个Prev按钮就只是一个摆设,没有实际作用的。如下源码,需要做一个按钮的监听事件绑定,并且设置点击事件的效果就是返回上一题。而这个返回上一题的实现就和Next一样,都通过控制Question数组中的index来实现,但是不同的是需要用(mCurrentIndex + mQuestionBank.length - 1) % mQuestionBank.length来实现(小技巧)。这样就可以完成题目的返回了。

Android权威编程--GeoQuiz游戏app_第24张图片

 

 

   2.9、从按钮到图标按钮

   其实这个挑战练习很简单,就是将Button设置为ImageView并在交互代码中将属性改为ImageView即可。

Android权威编程--GeoQuiz游戏app_第25张图片

 

   实现的效果如下,将按钮的text去掉,显得更加简洁清晰。

Android权威编程--GeoQuiz游戏app_第26张图片

 

 

   3.7、禁止一题多答(答完每一题即禁用答题按钮)

   禁止一题多答,其实就是添加一个标记,用于记录答题者是否已经点击true/false按钮,如果点击,则将答题按钮设置为不可点击。

   这里说下我的方法,我开始是觉得可以直接在住Activity中设置一个boolean常量,用于记录true/false按钮是否被点击,然后在这两个按钮的监听事件中添加判断,如果被点击则设置当前的按钮属性不可点击,如下源码,我设置了在点击next时重新激活按钮的可点击,是有一定的禁用效果的,但是,但是,注意问题来了,就是如果返回的话也会重新激活,所以这就不是我们想要的效果,而且这样的话对于用户是否答题时实时的没有记录,也就是说进入上一题或者下一题刚才这题是否答过就不知道了,这样就会造成作弊,所以我们使用新的方法就是在Question类中添加一个isAnswer属性用来记录。

Android权威编程--GeoQuiz游戏app_第27张图片

 

   需要在Question类中添加判断是否作答的Boolean属性,同时在构造函数中初始化为false,也就是默认是未作答;然后如下图二中,需要在QuizActivity中添加判断是否作答的方法,先get当前Question中的isAnswered属性,如果已做答则设置这道题的答题按钮不可点击,否则相反。记住,还有一个重点就是:在第一次作答完毕next之后Activity显示之前也就是在用户点击next按钮之后要将按钮的不可点击还原,因为在第一遍作答中next的题目是没有答过的,所以需要设置初始化,其实也就是在update中添加一个判断就好,如下图三。

Android权威编程--GeoQuiz游戏app_第28张图片

Android权威编程--GeoQuiz游戏app_第29张图片

Android权威编程--GeoQuiz游戏app_第30张图片

 

 

 

   运行结果:

Android权威编程--GeoQuiz游戏app_第31张图片

 

   3.8、评分(用户答完全部题后显示toast消息,给出百分比形式的评分)

   如题可知,题目要求在答完全部题以后再显示分数,但是我在想是不是可以在每一次做完题以后都进行提示当前做题的正确率,然后在最后做完所有题后再进行一个toast提示:已完成作答,正确率…这样的话可能会比较有用户体验。

   首先添加一个全局变量,并需要在答题正确时进行递增1,如下1图,然后添加一个用于计算答题分数以及显示百分比的函数,如下2图,能够看到先遍历Question数组,来查看其是否所有题目都已回答完毕,然后我们通过这个情况来分情况讨论,则显示的内容不一样,然后还需计算正确率。最后在回答按钮的点击事件中添加该函数,即在每一次作答完毕后进行显示正确率。

   注意:如下图2,我分了一个情况讨论,就是每一次答完题后就判断当前答过的所有题数,然后使用不同的计算方法来展示当前的正确率或者所有的正确率。

Android权威编程--GeoQuiz游戏app_第32张图片

Android权威编程--GeoQuiz游戏app_第33张图片

Android权威编程--GeoQuiz游戏app_第34张图片

 

 

 

   运行结果:

Android权威编程--GeoQuiz游戏app_第35张图片

Android权威编程--GeoQuiz游戏app_第36张图片

 

 

   4.3、探索布局检查器

   4.4、探索内存分配跟踪

   这两个挑战练习用于debug时使用,在这就没进行查看深入。

 

   5.5、堵住漏洞

   5.5.1、用户作弊后可以旋转CheatActivity来清除作弊痕迹

   确实,因为前面已经说过,关于旋转设备过程中Activity的生命周期经历,就是在旋转时,会销毁当前的Activity并重新create一个新的Activity,这样的话之前的数据就会消失,所以我们需要设置一个与前面相同的对象记录,用onSaveInstanceState(Bundle)方法将当前Activity中的作弊信息保存下来,并传给新建的这个Activity,这样就仍然可以对做过弊的题目答题按钮禁用。

 

   5.5.2、作弊返回后,用户可以旋转QuizActivity来清除mIsCheater变量值

   这题同上,而且结合下面的5.5.3,即直接将作弊属性添加进Question类中,并在旋转设备时使用Bundle对象保存起来返回给新的Activity这样就可以防止作弊信息丢失。

 

   5.5.3、用户可以不断点击NEXT按钮,跳到偷看过答案的问题,从而使作弊记录丢失。

   可以给每一道题Question类设置一个属性,就是是否作弊的属性,同时与是否作答的属性绑定在一起,如果已作弊则已做答,并直接禁用了答题按钮,这样的话只要是在查看完答案后返回答题界面则直接禁用按钮,这样无论你怎样next这道题就已经是无法解答了。

运行效果:

Android权威编程--GeoQuiz游戏app_第37张图片

 

 

4、自我优化

   1、在答完一道题后就添加一个TextView来显示该题目已做答,同时在判断完用户是否作弊完如果作弊则将按钮禁用,并在该TextView上显示已作弊,这样就显得比较人性化。

   2、在用户答题完成以后提供一个查看所有答案的按钮,用来反映用户答题的情况以及答错题的正确答案。

5、项目源代码(网址):

GeoQuiz_Android源码

 

你可能感兴趣的:(Android权威编程--GeoQuiz游戏app)