1. 程式人生 > >第二行程式碼學習筆記——第三章:軟體也要拼臉蛋——UI開發的點點滴滴

第二行程式碼學習筆記——第三章:軟體也要拼臉蛋——UI開發的點點滴滴

本章要點

使用Android提供的UI來編寫程式介面。本章的內容就是學習UI方面的知識。

3.1 如何編寫程式介面

Android種編寫程式介面的方式:
1. 視覺化編輯器(不推薦)
2. 編寫XML程式碼(推薦)

3.2 常用控制元件的使用方法

建立一個UIWidgetTest專案

3.2.1 TextView

TextView的用法:
修改activity_main.xm中的程式碼,如下:

<?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">
<TextView android:id="@+id/tv" android:layout_width="match_parent"
android:layout_height="wrap_content" android:gravity="center" android:text="This is TextView" android:textColor="#00ff00" android:textSize="24sp" />
</LinearLayout>

屬性:
android:id 當前控制元件唯一標識
android:layout_width和android:layout_height 控制元件的寬度和高度(match_parent(fill_parent不推薦),wrap_content)
android:text 顯示的文字內容
android:gravity 指定文字的對齊方式(center,top,bottom,right,left)可以用”|“同時指定多個值。center同等於center_vertical|center_horizontal垂直和水平方向都居中對齊
android:textSize 指文字的大小(sp)
android:textColor 指文字的顏色

效果圖:
tv

3.2.2 Button

在activity_main.xml中加入Button:

<?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">

    ...

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button"
        android:textAllCaps="false" />

</LinearLayout>

屬性:
android:textAllCaps true(大)/false(小) 預設true,英文字母大小寫轉換

MainActivity中為Button的點選事件註冊一個監聽器:

public class MainActivity extends AppCompatActivity {

    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn= (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //新增邏輯程式碼
            }
        });
    }

使用介面的方式來進行註冊,如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn= (Button) findViewById(R.id.btn);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                //新增邏輯程式碼
                break;
            default:
                break;
        }
    }
}

3.2.3 EditText

EditText是程式與使用者互動,允許在控制元件裡輸入和編輯內容,並作相應的處理。
EditText應用場景非常普遍,發簡訊,發微博,聊QQ等等……
在activity_main.xml中加入EditText,如下:

 <EditText
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Type something here"
        android:maxLines="2" />

屬性:
android:hint 指定提示性文字
android:maxLines 指定最大行數

接下來我們通過點選按鈕獲取EditText中輸入的內容,修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;
    private EditText et;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn= (Button) findViewById(R.id.btn);
        et= (EditText) findViewById(R.id.et);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                String inputText = et.getText().toString();
                Toast.makeText(this, inputText, Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
    }
}

效果圖:
et

3.2.4 ImageView

ImageView在介面展示圖片的控制元件。”drawable“開頭的目錄下放圖片,這個目錄沒有指定解析度,所以不使用它來放圖片。新建drawable-xhdpi目錄來放圖片。

我們把準備好的兩張美女圖片放進新建的drawable-xhdpi目錄下。
在activity_main.xml中新增ImageView:

<ImageView
        android:id="@+id/iv"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/img_1" />

屬性:
android:src 指定ImageView的圖片

通過程式碼動態的修改ImageView中的圖片,修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;
    private EditText et;
    private ImageView iv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn= (Button) findViewById(R.id.btn);
        et= (EditText) findViewById(R.id.et);
        iv= (ImageView) findViewById(R.id.iv);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                iv.setImageResource(R.drawable.img_2);
                break;
            default:
                break;
        }
    }
}

效果圖:
iv

3.2.5 ProgressBar

ProgressBar顯示進度條,表示正在載入資料。

在activity_main.xml中的程式碼新增ProgressBar:

   <ProgressBar
        android:id="@+id/pb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

效果圖:
pb

可見屬性:
android:visibility (visible可見,預設值,invisible不可見,佔位,gone,不可見,不佔位)
程式碼控制可見性,setVisibility()。

按鈕點選切換顯示隱藏進度條,修改MainActivity中的程式碼如下所示:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn;
    private EditText et;
    private ImageView iv;
    private ProgressBar pb;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn= (Button) findViewById(R.id.btn);
        et= (EditText) findViewById(R.id.et);
        iv= (ImageView) findViewById(R.id.iv);
        pb= (ProgressBar) findViewById(R.id.pb);
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
               if (pb.getVisibility()==View.GONE){
                   pb.setVisibility(View.VISIBLE);
               }else{
                   pb.setVisibility(View.GONE);
               }
                break;
            default:
                break;
        }
    }
}

效果圖:
pbvg

給ProgressBar指定不同樣式,修改activity_main.xml中的程式碼如下:

<?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">

    ......

    <ProgressBar
        android:id="@+id/pb"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100" />

</LinearLayout>

屬性:
style 設定進度條的樣式
android:max 設定進度條最大的

點選按鈕動態更新進度條,修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    ......

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                int progress = pb.getProgress();
                progress=progress+10;
                pb.setProgress(progress);
                break;
            default:
                break;
        }
    }
}

效果圖:
dgxpd

3.2.6 AlertDialog

AlertDialog彈出一個對話方塊,提示一些非常重要內容或者警告資訊。

修改MainActivity中的程式碼:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    ......

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                AlertDialog.Builder dialog=new AlertDialog.Builder(MainActivity.this);
                dialog.setTitle("This is Dialog");
                dialog.setMessage("Something imporent.");
                dialog.setCancelable(false);
                dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
                dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
                dialog.show();
                break;
            default:
                break;
        }
    }
}

通過AlertDialog.Builder建立AlertDialog的例項,設定標題,內容,等屬性……
setPositiveButton() 確定按鈕的點選事件
setNegativeButton() 取消按鈕的點選
show() 顯示對話方塊

效果圖:
ad

3.2.7 ProgressDialog

ProgressDialog與AlertDialog不同的是:ProgressDialog會在對話方塊顯示進度條。表示耗時操作,讓使用者等待。

修改MainActivity中的程式碼如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    ......

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn:
                ProgressDialog progressDialog=new ProgressDialog(MainActivity.this);
                progressDialog.setTitle("This is a ProgressDialog");
                progressDialog.setMessage("Something imporent");
                progressDialog.setCancelable(true);
                progressDialog.show();
                break;
            default:
                break;
        }
    }
}

setCancelable true/false (可以通過Back鍵返回)/(不可以返回,載入完必須呼叫dismiss()來關閉對話方塊,ProgressDialog會一直存在)

效果圖:
pd

3.3 詳解4種基本佈局

佈局是一種可用用放很多控制元件,同時也可以巢狀佈局的使用,來完成一些複雜的佈局。

佈局和控制元件的關係:
bjgx

新建UILayoutTest專案。

3.3.1 線性佈局

LinearLayout稱線性佈局,將它所包含的線上性方向上依此排列。

android:orientation 指定排列方向,vertical(垂直方向排列),horizontal(水平方向排列)
修改activity_main.xml中的程式碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <Button
        android:id="@+id/btn_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2" />

    <Button
        android:id="@+id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3" />
</LinearLayout>

效果圖:
lv

修改activity_main.xml中的屬性程式碼如下:

android:orientation="horizontal"

效果圖:
lh1

android:gravity和android:layout_gravity區別:
android:gravity 指文字在元件中的對齊方式
android:layout_gravity 指控制元件在佈局中對齊方式
當排列方向為horizontal時,只有垂直方向對齊方式會生效。當為vertical時,只有水平方向對齊方式才會生效。

修改activity_main中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <Button
        android:id="@+id/btn_1"
        android:layout_gravity="top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <Button
        android:id="@+id/btn_2"
        android:layout_gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2" />

    <Button
        android:id="@+id/btn_3"
        android:layout_gravity="bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3" />
</LinearLayout>

效果圖:
lh2

android:layout_weight 比例方式控制組件的大小 。我們來編寫訊息傳送介面,修改activity_main中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <EditText
        android:id="@+id/et"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/btn"
        android:text="Send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

效果圖:
lfjm

3.3.2 相對佈局

RelativeLayout稱相對佈局,通過相對定位讓控制元件出現在佈局的任何位置。

相對於父佈局進行定位,修改activity_main.xml中的程式碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_1"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <Button
        android:id="@+id/btn_2"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2" />

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3" />

    <Button
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:id="@+id/btn_4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button4" />

    <Button
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:id="@+id/btn_5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button5" />
</RelativeLayout>

屬性:
layout_alignParentRight 該控制元件與父佈局控制元件的右對齊嗎?
layout_alignParentLeft 該控制元件與父佈局控制元件的左對齊嗎?
layout_alignParentTop 該控制元件與父佈局控制元件的頂端對齊嗎?
layout_alignParentBottom 該控制元件與父佈局控制元件的底部對齊嗎?
layout_centerInParent 該控制元件位於父佈局控制元件的中心位置嗎?
layout_centerVertical 該控制元件位於父佈局控制元件的垂直中心位置嗎?
layout_centerHorizontal 該控制元件位於父佈局控制元件的水平中心位置嗎?

效果圖:
r1

相對於控制元件進行定位(1),修改activity_main.xml中的程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3" />

    <Button
        android:id="@+id/btn_1"
        android:layout_above="@id/btn_3"
        android:layout_toLeftOf="@id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <Button
        android:id="@+id/btn_2"
        android:layout_toRightOf="@id/btn_3"
        android:layout_above="@id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2" />



    <Button
        android:layout_toLeftOf="@id/btn_3"
        android:layout_below="@id/btn_3"
        android:id="@+id/btn_4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button4" />

    <Button
        android:layout_toRightOf="@id/btn_3"
        android:layout_below="@id/btn_3"
        android:id="@+id/btn_5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button5" />
</RelativeLayout>

屬性:
layout_toRightOf 該控制元件在哪個控制元件的右側
layout_toLeftOf 該控制元件在哪個控制元件的左側
layout_above 該控制元件在哪個控制元件的上側
layout_below 該控制元件在哪個控制元件的下側

效果圖:
r2

相對於控制元件定位(2),修改activity_main.xml中的程式碼如下:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3" />

    <Button
        android:id="@+id/btn_1"
        android:layout_alignLeft="@id/btn_3"
        android:layout_above="@id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1" />

    <Button
        android:id="@+id/btn_2"
        android:layout_alignTop="@id/btn_3"
        android:layout_toRightOf="@id/btn_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2" />



    <Button
        android:layout_alignBottom="@id/btn_3"
        android:layout_toLeftOf="@id/btn_3"
        android:id="@+id/btn_4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button4" />

    <Button
        android:layout_alignRight="@id/btn_3"
        android:layout_below="@id/btn_3"
        android:id="@+id/btn_5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button5" />
</RelativeLayout>

屬性:
layout_alignRight 該控制元件與哪個控制元件的右對齊
layout_alignLeft 該控制元件與哪個控制元件的左對齊
layout_alignTop 該控制元件與哪個控制元件的頂對齊
layout_alignBottom 該控制元件與哪個控制元件的底對齊

效果圖:
r3

3.3.3 幀佈局

FrameLayout稱幀佈局(簡單佈局)。沒有定位方式,所以控制元件預設擺放左上角。

接下來我們來修改activity_main.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/tv"
        android:text="This is TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/iv"
        android:src="@mipmap/ic_launcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</FrameLayout>

效果圖:
f1

文字和圖片都位於左上角,ImageView在TextView後,因此圖片壓在文字上面。

使用 android:layout_gravity 屬性指定控制元件在佈局中的對齊方式。修改activity_main中的程式碼如下:

<?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/tv"
        android:text="This is TextView"
        android:layout_gravity="left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/iv"
        android:layout_gravity="right"
        android:src="@mipmap/ic_launcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</FrameLayout>

效果圖:
f2

3.3.4 百分比佈局

百分比佈局屬性新增佈局,提供了PercentFrameLayout和PercentRelativeLayout兩種全新的佈局,它倆是FrameLayout和RelativeLayout的功能,繼承了所有的屬性。

百分比佈局的使用:

新增依賴

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:percent:24.2.1'
}

修改activity_main中的佈局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Button
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        android:layout_gravity="left|top"
        android:id="@+id/btn_1"
        android:text="Button1" />

    <Button
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        android:layout_gravity="right|top"
        android:id="@+id/btn_2"
        android:text="Button2" />

    <Button
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        android:layout_gravity="left|bottom"
        android:id="@+id/btn_3"
        android:text="Button3" />





    <Button
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        android:layout_gravity="right|bottom"
        android:id="@+id/btn_4"
        android:text="Button4" />

</android.support.percent.PercentFrameLayout>

效果圖:
pf

PercentRelativeLayout 用法非常相似,繼承了RelativeLayout的所有屬性。

Android 中還有AbsoluteLayout,TableLayout等屬性(幾乎不用)

3.4 系統控制元件不夠用?建立自定義控制元件

常用控制元件和佈局的繼承結構:
z

新建UICustomViews專案。

3.4.1 引入佈局

標題欄,引入佈局。新建title_layout.xml程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#c2c2c2">
    <Button
        android:text="Back"
        android:textColor="#FFFFFF"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:id="@+id/btn_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:textSize="24sp"
        android:layout_gravity="center"
        android:text="This is Title"
        android:gravity="center"
        android:textColor="#FFFFFF"
        android:id="@+id/tv_title"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content" />

    <Button
        android:text="Edit"
        android:layout_margin="5dp"
        android:textColor="#FFFFFF"
        android:layout_gravity="center"
        android:id="@+id/btn_edit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

修改activity_main.xml中的程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <