Android 學習之《Android程式設計權威指南》第二版 程式碼+筆記整理(四)
阿新 • • 發佈:2018-11-10
(程式碼)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_TR