寫在開始之前,從本篇開始我們用具體的小項目例子來進行我們的Android學習之旅。
希望通過這一篇文章對於沒有接觸過
Android開發的朋友有所幫助,有過知識儲備的請跳過,因爲這是對你們沒有什麼作用的。
從本篇文章開始到後面幾篇都是基於一個程序員常見面試題的答題程序爲例來進行學習。
開發工具我們使用Android Studio,下載地址:https://developer.android.google.cn/studio
目前最新版本爲3.5.2,大家可以根據具體的需要進行安裝。
創建Android項目
接着選擇我們項目模板,一般都會選擇‘Empty Activity’:
上面還有選項能夠選擇設備類型,這裏選擇手機和平板設備,其他設備我們不做了解。
首先來看下我們的Android 項目創建完成後是什麼樣子
我們今天要實現的很簡單,就是實現一個能夠顯示題目和選擇答案的頁面。
在Android中,佈局和頁面的實現邏輯是分開的,爲什麼這麼做,這裏沒必要深究。
大家可以從創建好的項目中可以看到,Android Studio已經默認爲我們創建好了一個名爲MainActivity.java和activity_main.xml的文件。
activity_main.xml就是以後我們經常會提到的佈局文件,MainActivity.java是佈局文件具體邏輯的實現。
在Android Studio中我們有兩種選擇進行用戶界面設計:
- 通過修改佈局文件,也就是上面的activity_main.xml這樣的文件。
- 通過圖形化設計工具
打開activity_main.xml文件,大家會看到design和text兩個選項
Text模式就是我們通過編輯xml文件來構建用戶界面。
Design模式就是通過圖形化的設計工具來進行設計,打開看看:
我們可以通過拖拽的方式將控件擺放在合適的位置進行頁面設計。
具體選用哪種方式看自己喜歡了,這裏我們選擇Text模式。
接下來實現我們今天的頁面佈局,修改activity_main.xml文件爲如下內容:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/question_content"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.2" />
<TextView
android:id="@+id/tv_answerA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="@string/question_answerA"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="@id/tv_question"
app:layout_constraintTop_toBottomOf="@id/tv_question" />
<TextView
android:id="@+id/tv_answerB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="@string/question_answerB"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="@id/tv_question"
app:layout_constraintTop_toBottomOf="@id/tv_answerA" />
<TextView
android:id="@+id/tv_answerC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="@string/question_answerC"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="@id/tv_question"
app:layout_constraintTop_toBottomOf="@id/tv_answerB" />
<TextView
android:id="@+id/tv_answerD"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="@string/question_answerD"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="@id/tv_question"
app:layout_constraintTop_toBottomOf="@id/tv_answerC" />
<TextView
android:id="@+id/tv_confirm_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:text="@string/question_confirm_title"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="@id/tv_question"
app:layout_constraintTop_toBottomOf="@id/tv_answerD" />
<EditText
android:id="@+id/et_confirm_answer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:text=""
android:textSize="18sp"
android:maxLength="1"
app:layout_constraintTop_toTopOf="@id/tv_confirm_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_confirm_title" />
<Button
android:id="@+id/bt_confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:minWidth="200dp"
android:text="@string/question_ok"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_confirm_answer" />
</androidx.constraintlayout.widget.ConstraintLayout>
最終實現的效果如下:
這裏我們總結一下要注意的知識點:
組件屬性
在上面的代碼中,類似下面這種格式的其實都是組件屬性的設置方式,每個組件都有許多屬性,這裏沒辦法全部列出。
app:layout_constraintEnd_toEndOf="parent"
最常見的控件屬性:
android:layout_width
android:layout_height
可選值如下:
match_parent: 視圖和父視圖大小相同
wrap_parent: 視圖根據其內容大小自動調整
TextView
用來顯示靜態文字的控件,這裏就說兩個屬性:
android:text="@string/question_confirm_title"
android:textSize="18sp"
android:maxLength="1"
text:用來設置顯示的文字內容
textSize: 用來設置字體的大小。sp作爲字體大小單位,會隨着系統的字體大小改變。
maxLength: 限制可輸入字符數
上面的代碼大家也看到了,在設置文字的時候,我們使用了:
android:text="@string/question_confirm_title"
@string/question_confirm_title
到底是什麼東西呢?在Android中專業術語我們將之稱之爲字符串資源(string resources).
字符串資源(string resources)
在Android中,字符串文件默認被命名爲strings.xml,該文件位於res/values目錄下,當然了,文件的名字我們可以按照個人喜好命名。
一個項目可以有多個字符串文件,只要這些文件處在正確的目錄下,即res/values目錄,只要字符串文件含有一個resources根元素以及多個string子元素,那麼字符串定義就能被我們找到,使用方式如上。
在Android Studio中,我們可以通過下面的方式生成字符串資源:
將鼠標定位到我們要添加的文字上,使用Alt+Enter組合鍵,此時會出現如下的菜單:
選擇:Extract string resources後,在下面的界面中輸入名稱確定即可。
佈局文件到這裏我們就簡單完成了,此時的頁面並不具備和用戶進行交互的能力。
要完成和用戶交互邏輯,我們就得看看Android Studio爲我們默認生成的MainActivity.java文件。默認生成好的文件如下:
代碼很簡潔,MainActivity類中只有一個重寫的onCreate方法。onCreate方法是做什麼的,我們可以簡單的認爲這個方法就是創建我們剛纔寫好的佈局的,當然了還有其他的事情可以做。
在onCreate方法中,有這麼一句代碼:
setContentView(R.layout.activity_main);
它會將指定id的佈局的視圖生成並且將其顯示在屏幕上。 R.layout.activity_main
就是我們上面編寫的activity_main.xml的id,我們可以理解爲id就是該資源的一個別名,通過這個名詞,程序可以找到對應的資源。
資源和資源id
什麼是資源呢?我們可以將一切非代碼形式的內容,比如圖片,視頻以及xml文件等等統統稱之爲資源。
所以我們上面編寫的activity_main.xml也是一種資源。項目的資源文件全部存放在res目錄下。
那麼不同名字的目錄代表什麼,可參考官方網站的圖表:
我們這裏要了解的是R.layout.activity_main
,很顯然,我們的佈局文件能夠在一個名爲R.java的文件下面找到對應的定義,所以程序才能夠找到。
R.java文件是Android項目在編譯的過程中自動生成的。Android會爲所有的佈局文件以及各個字符串生成資源id。
爲控件指定id的方法在上面的佈局文件中也有體現:
android:id="@+id/控件id"
在以後的代碼學習過程中,我們可能還會遇到這中寫法:
@id/控件id
那麼這兩種方式有什麼區別呢?
@+id/some_value: 如果R.java中沒有some_value, 則在R.java中生成一個some_value值;如果有則直接使用已經存在的值.
@id/some_value: 如果R.java中存在some_value, 則使用此值。否則會造成編譯錯誤.
R.java文件可以在下面的目錄下找到:
看看關於我們控件的內容:
獲取視圖控件
前面提到了,佈局文件是一種資源,那麼其中的控件自然也可以通過id獲取到,然後進行相關的操作,修改MainActivity代碼如下:
package com.qiushangge.androidstudy;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private EditText et_confirm_answer;
private Button bt_confirm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_confirm_answer = findViewById(R.id.et_confirm_answer);
bt_confirm = findViewById(R.id.bt_confirm);
}
}
在Android Studio中會自動爲我們導入相關的類包,這裏就不在做介紹。
findViewById
在上面的代碼中我們使用了findViewById方法,它用來引用已經生成的組件。該方法接受組件的資源id作爲參數,返回一個視圖對象。
或許大家也會看到類似這樣的寫法:
bt_confirm = (Button)findViewById(R.id.bt_confirm);
在獲取到視圖對象後,需要進行強制類型轉化爲對應的組件,在新一點的版本中,該方法不需要進行類型轉化。
獲取到組件之後,我們給Button按鈕綁定點擊事件,當用戶點擊的時候,我們給出回答正確還是錯誤的提示。
bt_confirm.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
}
});
關於監聽器推薦使用內部匿名類的方式實現,也就是上面的格式。具體的概念如果不太清楚,那應該去查閱下java文檔。
接下來我們先修改下string.xml,存入我們問題的答案以及回答結果,同時修改下字符串資源的名稱。
接下來我們實現答題的邏輯:
bt_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String answer = et_confirm_answer.getText().toString().trim();
if (answer.toUpperCase().equals(getString(R.string.Q1_S))) {
Toast.makeText(MainActivity.this, R.string.question_correct, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, R.string.question_incorrect, Toast.LENGTH_SHORT).show();
}
}
});
首先我們通過EditView的getText方法獲取到用戶輸入,然後和存儲在字符串資源文件中的值進行比較,如果相同,告知用戶答對了,反之亦然。
注意點:在android和java中,使用==比較字符串其實比較的是字符串的內存地址,如果要想比較兩個值是否相等,那麼請使用equals方法
,小坑一個請留意。
Toast
我們通常使用Toast來顯示一些提示信息,格式如下:
Toast.makeText( context , text , duration).show();
context: 傳入Activity本身,即類名.class的形式,這裏就是MainActivity.this
text: 要顯示的提示信息文字
duration: 顯示時間的長短,可選值:
Toast.LENGTH_SHORT(短時間提示)
Toast.LENGTH_LONG (長時間提示)。
show()方法最終顯示提示組件。
最後一步就是使用我們的模擬器運行應用了。
如果你沒有安裝模擬器,那麼可以按照下面的步驟創建一個模擬器:
- 打開avd管理器
- 因爲我已經創建了一個模擬器,所以打開後界面或沒有創建的不同,找到下圖的按鈕點擊開始創建。
創建完成後運行我們的模擬器:
在Android Studio中運行程序:
運行結果:
輸入答案:
好了,今天就到這裏,我們通過一個最簡單的應用程序,把開發過程中遇到的問題點做了簡單的介紹,如果需要更多地瞭解相關知識,參考官方文檔。