(代码)GeoQuiz最终开发
GeoQuiz应用初步开发
GeoQuiz应用升级开发
解决GeoQuiz应用旋转恢复第一题的BUG
不展示编译器自动完成的代码,仅提供手动修改或者编写的代码。
省略了先前一些代码,可参照上方链接。
升级内容: 增加作弊按钮,给用户提供查看答案的作弊页面。
一、组成:
三个java类(一个实体类+两个Activity)、三个layout布局文件(一个主界面,一个作弊界面以及一个手机水平放置时的主界面)和各种资源文件(图片和字符串等)
二、界面(展示大部分效果)
三、开发
1. Android项目:
应用名称为:GeoQuiz
活动及对应布局名称为:
A. QuizActivity – activity_quiz(一垂直,一水平 两个xml)
B. CheatActivity – activity_cheat
模型类:Question
2. 用户界面设计(仅展示activity_cheat.xml 其余页面参照先前博客)
设计图:
代码:(activity_cheat.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:gravity="center"
android:orientation="vertical"
tools:context="com.example.thinkpad.geoquiz.CheatActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="24dp"
android:text="@string/warning_text"/>
<TextView
android:id="@+id/answer_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="24dp"
tools:text="Answer"/>
<!--tools & tools:text属性的命名空间比较特别,该命名空间可以覆盖组件的任何属性-->
<Button
android:id="@+id/show_answer_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/show_answer_button"/>
</LinearLayout>
3. 更新字符串资源(strings.xml):
<resources>
<string name="app_name">GeoQuiz</string>
<string name="true_button">TRUE</string>
<string name="false_button">FALSE</string>
<string name="next_button">NEXT</string>
<string name="correct_toast">Correct!</string>
<string name="incorrect_toast">Incorrect!</string>
<string name="question_oceans">
The Pacific Ocean is larger than the Atlantic Ocean.
</string>
<string name="question_mideast">
The Suez Canal connects the Red Sea and the Indian Ocean.
</string>
<string name="question_africa">
The source of the Nile River is in Egypt.
</string>
<string name="question_americas">
The Amazon River is the longest river in the Americas.
</string>
<string name="question_asia">
Lake Baikal is the world\'s oldest and deepest freshwater lake.
</string>
<string name="warning_text">
Are you sure you want to do this?
</string>
<string name="show_answer_button">
SHOW ANSWER
</string>
<string name="cheat_button">
CHEAT!
</string>
<string name="judgment_toast">
Cheating is wrong.
</string>
</resources>
4. 默认主界面布局(activity_quiz.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:gravity="center"
android:orientation="vertical"
tools:context="com.example.thinkpad.geoquiz.QuizActivity">
<TextView
android:id="@+id/question_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="24dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/true_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/true_button"
/>
<Button
android:id="@+id/false_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/false_button"
/>
</LinearLayout>
<Button
android:id="@+id/cheat_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cheat_button"/>
<Button
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next_button"
android:drawableRight="@drawable/arrow_right"
android:drawablePadding="4dp"/>
</LinearLayout>
5. 水平主界面布局(activity_quiz.xml)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/question_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="24dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/true_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/true_button"
/>
<Button
android:id="@+id/false_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/false_button"
/>
</LinearLayout>
<Button
android:id="@+id/cheat_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:text="@string/cheat_button"/>
<Button
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:text="@string/next_button"
android:drawableRight="@drawable/arrow_right"
android:drawablePadding="4dp"/>
</FrameLayout>
6. activity活动编写(QuizActivity.java )
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class QuizActivity extends AppCompatActivity {
private Button mTrueButton; //true选项按钮
private Button mFalseButton; //false选项按钮
private Button mNextButton; //next选项按钮
private Button mCheatButton; //Cheat选项按钮
private TextView mQuestionTextView; //textView文本显示
private Question[] mQuestionBank = new Question[]{ //Question对象数组
new Question(R.string.question_oceans,true),
new Question(R.string.question_mideast,false),
new Question(R.string.question_africa,false),
new Question(R.string.question_americas,true),
new Question(R.string.question_asia,true),
};
//KEY_INDEX常量作为将要存储在Bundle中的数组索引变量的键值对的键
private static final String KEY_INDEX = "index";
private int mCurrentIndex = 0; //数组索引变量
private static final int REQUEST_CODE_CHEAT = 0;//设置请求代码常量,用于区分多个不同类型的子activity
private boolean mIsCheater;//判断是否作弊的变量
private void updateQuestion(){ //更新问题文本内容函数
int question = mQuestionBank[mCurrentIndex].getTextResId(); //获取资源ID
mQuestionTextView.setText(question); //设置文本内容
}
private void checkAnswer(boolean userPressedTrue){ //检查问题答案函数
boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue(); //获取对应问题的答案
int messageResId = 0;
if(mIsCheater){
messageResId = R.string.judgment_toast;
}else{
//根据答案正确与否分配资源ID
if(userPressedTrue == answerIsTrue){
messageResId = R.string.correct_toast;
}else{
messageResId = R.string.incorrect_toast;
}
}
Toast.makeText(this,messageResId,Toast.LENGTH_SHORT).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz); //加载布局
mQuestionTextView = (TextView) findViewById(R.id.question_text_view); //获取TextView对象
mTrueButton = (Button) findViewById(R.id.true_button); //获取trueButton按钮对象
mTrueButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkAnswer(true);
}
});
mFalseButton = (Button) findViewById(R.id.false_button); //获取falseButton按钮对象
mFalseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkAnswer(false);
}
});
mNextButton = (Button) findViewById(R.id.next_button); //获取NextButton按钮对象
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCurrentIndex = (mCurrentIndex+1) % mQuestionBank.length; //索引值增加1
mIsCheater = false; //是否作弊的flag回归默认值
updateQuestion();
}
});
mCheatButton = (Button) findViewById(R.id.cheat_button); //获取CheatButton对象
mCheatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();//获取问题答案
Intent intent = CheatActivity.newIntent(QuizActivity.this,answerIsTrue);
startActivityForResult(intent,REQUEST_CODE_CHEAT);
}
});
if(savedInstanceState != null){
mCurrentIndex = savedInstanceState.getInt(KEY_INDEX,0);
}
updateQuestion(); //更新问题
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode!= Activity.RESULT_OK){
return ;
}
if(requestCode == REQUEST_CODE_CHEAT){
if(data == null){
return ;
}
mIsCheater = CheatActivity.wasAnswerShown(data);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_INDEX,mCurrentIndex);
}
}
7. activity活动编写(CheatActivity.java )
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class CheatActivity extends AppCompatActivity {
//储存在extra中的问题答案的键,使用包名修饰extra数据信息,可以避免来自不同应用的extra间发生命名冲突
private static final String EXTRA_ANSWER_IS_TRUE =
"com.example.thinkpad.geoquiz.answer_is_true";
//储存在extra中的是否显示过答案的键
private static final String EXTRA_ANSWER_SHOWN =
"com.example.thinkpad.geoquiz.answer_shown";
private boolean mAnswerIsTrue;//问题答案
private TextView mAnswerTextView; //问题答案文本
private Button mShowAnswer; //显示答案按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cheat);
//getBooleanExtra(...)第一个参数为extra的键名,第二个参数为默认值,即获取不到该键的值时的默认值
mAnswerIsTrue = getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE,false);
mAnswerTextView = (TextView) findViewById(R.id.answer_text_view);//获取AnswerTextView实例
mShowAnswer = (Button) findViewById(R.id.show_answer_button); //获取显示答案按钮实例
mShowAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//根据问题的答案显示不同的文字
if(mAnswerIsTrue){
//TextView.setText(...)方法用来设置TextView要显示的文字
mAnswerTextView.setText(R.string.true_button);
}else{
mAnswerTextView.setText(R.string.false_button);
}
setAnswerShownResult(true);
}
});
}
//创建Intent的CheatActivity实例,并且将问题答案传入其中
public static Intent newIntent(Context packageContext,boolean answerIsTrue){
//Intent的这个构造函数第一个参数为上下文,第二个参数为所要启动的Activity
Intent intent = new Intent(packageContext,CheatActivity.class);
intent.putExtra(EXTRA_ANSWER_IS_TRUE,answerIsTrue);
return intent;
}
private void setAnswerShownResult(boolean isAnswerShown){
Intent data = new Intent();
data.putExtra(EXTRA_ANSWER_SHOWN,isAnswerShown);
setResult(RESULT_OK,data);
}
//解析结果Intent
public static boolean wasAnswerShown(Intent result){
return result.getBooleanExtra(EXTRA_ANSWER_SHOWN,false);
}
}
(笔记)第5章 创建第二个activity
- 创建新的 activity 至少涉及三个文件:Java类、XML布局以及应用的manifest文件。所以建议使用 Android Studio 的新建 activity 向导功能。
- 启动activity的方法:
A. public void startActivity(Intent intent)
B. public void startActivityForResult(Intent intent,int requestCode)(可从子activity获取返回结果)
调用方法的请求发送给了操作系统的ActivityManager,由它负责创建Activity实例并调用onCreate(…)方法。 - 基于Intent通信
A. Intent有多种构造方法,其中之一为:
public Intent (Context packageContext,Class<?> cls)
该方法的第一个参数为启动活动的上下文,告诉ActivityManager在哪里可以找到它,第二个参数则告诉ActivityManager应该启动哪个activity。
B. 同一个应用中,我们使用显式的intent来启动activity。在不同的应用中,则可通过创建隐式的intent来处理。
C. 使用intent的extra来实现数据传递。
extra为一种键值结构,Xxx为某种类型
添加信息时调用intent.putExtra(String name,Xxx xx) 第一个参数固定为String类型的键,第二个参数则为多种数据类型的值。
获取信息时调用intent.getXxxExtra(name,xx) 第一个参数为键,第二个参数为默认值(即该键没有找到对应值时使用的值)。 - 从子activity获取返回结果:
A. 设置返回结果:
有以下两个方法可调用:
1.)public final void setResult(int resultCode)
2.)public final void setResult(int resultCode,Intent data)
resultCode取值:
Activity.RESULT_OK 或者 Activity.RESULT_CANCELED
(如需自己定义结果代码,还可使用RESULT_FIRST_USER)
B. 返还intent 调用setResult(int resultCode,Intent data)
C. 处理返回结果,重写onActivityResult(…)方法 - ActivityManager维护着一个非特定应用独享的回退栈。
来自一名刚刚开始学习Android的小菜鸟~