文章目錄
- 1 引言
- 2 開發環境配置
- 2.1 Android Studio
- 2.2 JDK
- 3 Android基礎開發
- 3.1 Activity活動
- 3.1.1 Intent
- 3.1.2 活動的生命周期
- 3.2 XML布局
- 3.2.1 線性布局
- 3.2.2 相對布局
- 3.2.3 幀布局
- 3.2.4 常用屬性
- 3.3 常用控制元件
- 3.3.1 TextView
- 3.3.2 Button
- 3.3.3 EditText
- 3.3.4 ImageView
- 3.4 日志工具
- 3.5 Fragment碎片
- 3.5.1 動態添加碎片
- 3.5.2 碎片的生命周期
- 3.6 權限申請
1 引言
畢業設計做了一些Android和Android GNSS的開發作業,做完后老師給換了方向,后面大概率不會再涉及這一塊了,因此寫個總結,如果將來再碰到,可以做個參考
另外,Android體系太龐大了,細說起來太復雜(實則筆者功力不夠),因此寫得比較簡單,主要寫一下常見、基本的用法和筆者印象比較深的幾個問題
2 開發環境配置
2.1 Android Studio
筆者沒有體驗過別的IDE,但Android Studio應該是公認的安卓開發大殺器
Android Studio官網下載
在Android Studio中,依次選擇Settings —— Appearance & Behavior —— System Settings —— Android SDK,分別下載SDK Platforms(運行平臺)、SDK Tools(開發工具)中你需要的組件
2.2 JDK
Android使用Java語言進行最上層的開發,所以需要安裝JDK
JDK官網下載
下載后進行安裝、配置環境變數
3 Android基礎開發
3.1 Activity活動
打開Android Studio創建一個Empty Activity,IDE會生成一個 MainActivity.java 和 activity_main.xml(在 res/layout 目錄下),其中前者是Java代碼,后者是xml布局檔案
package ... // 包名
import ...
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// 呼叫父類方法進行初始化
super.onCreate(savedInstanceState);
// 為該活動設定布局檔案
setContentView(R.layout.activity_main);
}
}
MainActivity是我們的app啟動時的第一個活動 ,也稱為主活動,其初始代碼如上,onCreate() 方法是活動生命周期中的一環,系統會根據不同的互動情況自動呼叫活動生命周期中的一系列函式,我們要做的就是在其中一個或幾個函式中自定義行為,在 onCreate() 方法中,為該活動設定了布局檔案,另外,初始化操作也應在該方法中完成,類似 C/C++ 中的 main() 函式,
activity_main.xml是該活動的布局檔案,它定義了主活動的可視化界面,
IDE默認創建的布局檔案使用約束布局,我們可以修改布局方式為線性布局、相對布局、幀布局等,下面的布局檔案使用了線性布局,其中有一個TextView控制元件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"> // context指明背景關系,即對應的類
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" /> // 寬度和高度適應控制元件大小,顯示文本為"Hello World!"
</LinearLayout>
3.1.1 Intent
Intent的作用:啟動下一個活動
- 指明當前組件想要執行的動作
- 在不同組件之間傳遞資料
Intent分為顯示和隱式,顯式即在代碼中通過呼叫 startActivity() 或者 startActivityForResult() 來使用Intent;隱式則是在 AndroidManifest.xml 中配置 <activity> 標簽下的 <intent-filter>
筆者主要使用顯式Intent,因為方便:只需要使用①當前活動的類實體②目的活動的類創建一個 Intent 物件,再呼叫相應的方法就能啟動下一個活動,
Intent使用實體:
/**
* 初始化視圖
*/
public void initView(){
button = findViewById(R.id.button);
//為按鈕添加監聽器
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { // onClick()方法會在 button按下時自動呼叫
// 顯示 Intent
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
// 隱式 Intent
Intent intent = new Intent("com.example.activitytest1.START_ACTION");
startActivity(intent);
// 傳遞資料
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("Data", "Hello SecondActivity, this is MainActivity");
startActivity(intent);
startActivityForResult(intent, 1);
}
});
}
/**
* 處理 startActivityForResult()的回傳結果
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
// 根據請求碼來判斷是哪一次請求
case 1:
// 根據結果碼判斷是否正確回傳
if ( resultCode==RESULT_OK ) {
String returnData = data.getStringExtra("data_return");
// 列印日志
Log.d("MainActivity", returnData);
}
break;
}
}
3.1.2 活動的生命周期

- onCreate():在活動第一次被創建時呼叫,初始化操作需要在這個函式中完成,包括頁面布局、控制元件回應函式的定義等等
- onStart():活動由不可見變為可見時呼叫
- onResume():活動準備好和用戶互動時呼叫
- onPause():系統準備去啟動或恢復另一個活動時呼叫,即被其它活動遮擋
- onStop():活動完全不可見時呼叫,即被完全遮擋
- onDestroy():活動被銷毀之前呼叫
- onRestart():活動由停止狀態變為運行狀態之前呼叫
在活動1中啟動活動2,然后點擊back回到活動1,在點擊back的動作中,活動1先onRestart(),活動2再onDestroy()
3.2 XML布局
布局是一種可用于放置很多控制元件的容器,使用XML(擴展標記語言)來定義其內部的元素及規則,它可以按照一定的規律調整內部控制元件的位置,布局的內部也可以放置布局,形成嵌套
3.2.1 線性布局
線性布局是筆者最常用的布局方式,用它可以實作大多數布局效果
一. android:orientation 指定了排列方向(horizontal/vertical),默認是horizontal
二. 線性布局允許使用 比例 的方式來指定控制元件的大小,這點非常重要而且時長會用到:
① 下面的代碼中,兩個Button的寬度被設為"0dp",而其 android:layout_weight 屬性值為1,這表示兩個Button將平分該布局的寬度(因為線性布局為默認horizontal),
② android:layout_weight 屬性值可以給任意正整數,系統最后會根據 [ 當前控制元件的weight分量值 / 當前布局中所有控制元件的weight值之和 ] 來確定當前控制元件的寬度/高度(取決于布局為水平還是垂直)
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:padding="8dp">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Reset"
android:textAllCaps="false"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Send"
android:textAllCaps="false"/>
</LinearLayout>
另外,在布局中,也可以只指定一部分控制元件的 android:layout_weight 屬性值,例如下面的代碼,該布局的效果為:首先滿足 TextView 的寬度,然后將剩下所有的寬度分配給 Button,
使用這種方式撰寫的界面,不僅在各種螢屏的適配方面會非常好,而且看起來也更加舒服,
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:padding="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Input..."
android:textAllCaps="false"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Send"
android:textAllCaps="false"/>
</LinearLayout>
3.2.2 相對布局
當有一定數量的控制元件需要按它們之間的相對位置來擺放時,需要用到相對布局,
常見的指定相對位置的方式有:
- android:layout_alignParent[ Top / Bottom / Left / Right ] =“true”
- android:layout_center[ Horizontal / InParent / Vertical ] =“true”
- android:layout_[ above / below / toLeftOf / toRightOf ] ="@id/${相對的控制元件id}" 使控制元件位于相對控制元件的上/下/左/右位置
- android:layout_align[ Top / Bottom / Left / Right ] ="@id/${相對的控制元件id}" 使控制元件和相對控制元件的上/下/左/右邊緣對齊
3.2.3 幀布局
幀布局筆者的使用情況僅限于作為碎片Fragment加載的容器/物件
3.2.4 常用屬性
下表列出了包括布局、控制元件在內的各種XML元素的常用屬性
| 屬性 | 意義 |
|---|---|
| android:layout_gravity | 指定控制元件在布局中的對齊方式 |
| android:gravity | 指定控制元件中文字的對齊方式 |
| android:alpha | 指定控制元件的透明度,0(全透明)~ 1(全不透) |
| android:layout_margin[ Top / Bottom / Left / Right ] ="_dp" | 指定控制元件和上/下/左/右的外邊緣 |
| android:padding[ Top / Bottom / Left / Right ] ="_dp" | 指定控制元件上/下/左/右的內邊緣(空白) |
| android:textSize ="_sp" | 指定字體的大小 |
| android:background | 指定控制元件背景,一般為XML定義的形狀+顏色 |
| android:text | 指定控制元件的文本 |
| android:id | 指定控制元件的標識名,不能重復 |
| android:textColor ="#ff0000" | 指定控制元件的文本顏色,16進制定義RGB |
3.3 常用控制元件
3.3.1 TextView
TextView 主要用于在界面上顯示一段文本資訊
幾個重要的屬性有:
android:text、android:gravity、android:textSize、android:textColor、android:textStyle、android:background
<TextView
android:id="@+id/tv_title"
android:text="這是TextView的內容"
android:padding="10dp"
android:textSize="18sp"
android:textColor="#ff0000"
android:background="#999999"
android:gravity="center"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
還有很多屬性就不一一介紹了,這里有 包索引,開發者指南 兩篇檔案供開發者查閱相關屬性,在開發的時候,我們的重點不是記住了一個控制元件的多少屬性,而是為了實作我們的目的,我們要意識到它應該有哪些屬性,如果是熟悉的,直接寫,如果不熟,再去查閱檔案
3.3.2 Button
Button是程式用于和用戶互動的一個重要控制元件
Button的可配置的屬性和TextView差不多,不同的是我們可以為Button注冊監聽器,相應點擊事件:
我們先在布局檔案中添加一個Button控制元件,XML代碼如下
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提交"
android:textSize="18sp"
android:padding="10dp"/>
然后在布局檔案對應的context中,獲取該控制元件,并為其注冊監聽器,代碼如下
public class RegisterActivity extends AppCompatActivity {
private Button btnSubmit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
initView();
}
public void initView() {
btnSubmit = findViewById(R.id.btn_submit); // XML中為控制元件指定的 id
btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(RegisterActivity.this, "Submit", Toast.LENGTH_SHORT).show();
}
});
}
}
也可以使用實作介面的方式來注冊監聽器,代碼如下所示:
public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {
private Button btnSubmit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
initView();
}
public void initView() {
btnSubmit = findViewById(R.id.btn_submit); // XML中為控制元件指定的 id
btnSubmit.setOnClickListener(this);
}
// 實作 View.OnClickListener 介面必須重寫該方法
@Override
public void onClick(View v){
switch (v.getId()) {
case R.id.btn_submit:
Toast.makeText(RegisterActivity.this, "Submit", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
}
3.3.3 EditText
EditText是程式用于和用戶互動的另一個重要控制元件,它允許用戶在控制元件里輸入和編輯內容,并可以在程式中對這些內容進行處理,
Android控制元件的用法基本上都很相似:給空間定義一個id,再指定控制元件的寬度和高度,然后在適當加入一些控制元件特有的屬性就差不多了,
EditText特有的屬性有:
android:hint 指定一段提示性的文本,當輸入任何內容時,提示文本會消失
android:maxLines 指定EditText的最大行數為兩行,當輸入的內容超過兩行時,文本就會向上滾動,而EditText則不會再繼續拉伸
3.3.4 ImageView
ImageView用于在界面上展示圖片,使用前要提前準備好圖片,圖片通常放在以"drawable"開頭的目錄下,專案初建時有一個空的drawable目錄,但它沒有指定具體的解析度,可以在res目錄下新建一個drawable-xhpi(xhpi指定對應的解析度),將圖片放入后就可以參考
通過 android:src 屬性即可指定要參考的圖片
<ImageView
android:id="@+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="311dp"
android:layout_gravity="top"
android:background="@android:drawable/picture_frame"
android:src="@drawable/girl" />
也可以在Java代碼中動態指定,代碼如下
public class SimpleUIComponentActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple_uicomponent);
ImageView imageView = findViewById(R.id.iv_image);
imageView.setImageResource(R.drawable.girl); // 指定 ImageView 顯示的圖片
}
}
3.4 日志工具
Android 中的日志工具類是Log(android.util.Log),這個類中提供了如下5個方法來供我們列印日志:
- Log.v() 對應級別verbose
- Log.d() 對應級別debug
- Log.i() 對應級別info
- Log.w() 對應級別warn
- Log.e() 對應級別error
不同級別的資訊區別主要體現在Log的過濾中,筆者一般直接使用Log.e(),因為其它資訊較少,可以直接看到我們列印的資訊,
下方的代碼中,我們在主活動的onCreate()方法中添加了一行Log.e()列印錯誤資訊,該方法傳入兩個引數:第一個引數是tag,一般傳入當前類名,主要用于對列印資訊進行過濾,第二個引數是msg,即想要列印的具體內容,
package ...
import ...
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("MainActivity:", "onCreate()"); // 通過列印資訊顯示執行了 onCreate() 方法
}
}
3.5 Fragment碎片
碎片是一種可以嵌入在活動當中的UI片段,它和活動非常相似,同樣都能包含布局,同樣都有自己的生命周期,
在Android Studio中新建一個碎片,IDE會給出一個碎片類(Java代碼)和一個XML布局檔案
3.5.1 動態添加碎片
我們在新建的碎片的布局檔案中做一點簡單的修改(此處我們僅修改一下背景顏色),然后去主活動(MainActivity)中通過代碼動態地加載它,主活動的布局檔案如下,其整個布局由上方一個Button,下方一個FrameLayout組成,由于這里僅需要在子布局里放入一個碎片,不需要任何定位,因此非常適合使用FrameLayout,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_load_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Fragment"
android:textAllCaps="false" />
<FrameLayout
android:id="@+id/frag"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" /> // 使碎片鋪滿余下的高度
</LinearLayout>
主活動的代碼如下,在該段代碼里,我們于主活動的onCreate()方法中,對btnLoad進行初始化,將其系結至布局檔案中的控制元件物件,然后為其設定監聽器,當點擊Button時,將執行replaceFragment()函式,動態地替換幀布局(R.id.frag)的內容,
package ...
import ...
public class MainActivity extends AppCompatActivity {
private Button btnLoad;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnLoad = findViewById(R.id.btn_load_fragment);
btnLoad.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MainActivity.this.replaceFragment(new BlankFragment());
}
});
}
private void replaceFragment(Fragment fragment) {
// getSupportFragmentManager().beginTransaction().replace(R.id.frag, fragment).commit();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.frag, fragment);
transaction.commit();
}
}
解釋一下replaceFragment()函式,實際上它也反映了動態添加碎片的一般程序:
- 創建待添加碎片的實體,即傳入的 fragment 引數
- 獲取 FragmentManager,在活動中可以呼叫 getSupportFragmentManager() 得到
- 開啟一個事務,即 beginTransaction()
- 操作容器添加、隱藏、或替換碎片,對應的有 add()、hide()、replace() 方法,第一個引數為容器的id,第二個引數為待操作的碎片實體
- 提交事務,必須提交系統才會執行事務中的操作,通過commit()方法完成
3.5.2 碎片的生命周期

我們可以給碎片生命周期中的每一個函式添加Log.e()列印出函式的執行資訊來觀察碎片在不同情況下的生命歷程,獲得更深刻的理解,
上圖中的幾個重要函式其意義如下:
- onAttach()
當碎片和活動建立關聯的時候呼叫 - onCreateView()
為碎片創建視圖(加載布局)時呼叫 - onActivityCreated()
確保與碎片關聯的活動一定已經創建完畢時呼叫 - onDestroyView()
當與碎片關聯的視圖被移除的時候呼叫 - onDetach()
當碎片和活動解除關聯的時候呼叫
此外,碎片的生命周期中還有一個 onViewCreated() 函式,該函式的執行時間位于 onCeateView() 之后,onActivityCreated()之前,該函式的意義在于,執行該函式時,碎片布局上的所有view物件都加載完畢,在該函式中獲取控制元件物件的索引將更加安全,
一個最初始的Fragment類如下
package ...
import ...
public class BlankFragment extends Fragment {
public BlankFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_blank, container, false);
}
}
該類有一個空的建構式,在onCreateView中,我們通過膨脹器引數 inflater 加載碎片對應的布局,
該類對應的初始布局檔案如下
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="#ff0000"
tools:context=".BlankFragment"> // 背景定義為紅色,突出加載效果
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
3.6 權限申請
Android中的權限分為系統權限和應用自定義權限,系統權限又分為正常權限和危險權限,使用系統權限需要在manifest檔案中注冊權限,若是危險權限,還需要在使用時動態申請,
AndroidManifest.xml 中申請權限的寫法如下所示,陳述句寫在 <manifest> 標簽中
<!-- 用于訪問GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 讀取快取資料 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 寫入擴展存盤 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--拍照(記錄結束后分享檔案需要該權限)-->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 在SDCard中創建與洗掉檔案權限 -->
<permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
上面列出的權限中,ACCESS_FINE_LOCATION、WRITE_EXTERNAL_STORAGE、CAMERA 三個權限都屬于危險權限,除了在AndroidManifest.xml中注冊,還需要動態申請,動態申請這三個權限的代碼如下
package ...
import ...
public class MainActivity extends AppCompatActivity {
private final String[] REQUIRED_PERMISSIONS = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
};
private final int REQUEST_PERMISSION_CODE = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermissionAndSetupFragment();
}
private void requestPermissionAndSetupFragment() {
if (hasPermissions()) {
setupFragments();
} else {
ActivityCompat.requestPermissions(MainActivity.this, REQUIRED_PERMISSIONS, REQUEST_PERMISSION_CODE);
}
}
private boolean hasPermissions() {
for (String p : REQUIRED_PERMISSIONS) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, p) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CODE) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this, "未擁有權限!", Toast.LENGTH_SHORT).show();
return;
}
}
setupFragments();
}
}
private void setupFragments() {}
在代碼中,我們
- 給出三個權限的字串常量 REQUIRED_PERMISSIONS
- 在主活動的 onCreate() 方法中呼叫 requestPermissionAndSetupFragment() 函式檢查是否擁有相應權限,如果有,則進行初始化操作,如果沒有,則申請權限,檢查權限和申請權限的系統函式及其用法都在代碼中,
- 在申請權限時,我們需要發送一個請求碼,這樣在得到回應時,我們才能判斷回傳的結果對應哪一次的請求,如果判斷回傳的是請求權限的結果,那么我們遍歷回傳的整型陣列,如果有一個整型值不等于系統給的申請成功對應的整型值,說明申請失敗,這時我們通過Toast顯示出來
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/287634.html
標籤:其他
上一篇:Android第一行代碼-UI
下一篇:高精度乘法
