BUỔI 0

1. Edit Text

<EditText android:id="@+id/edit_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />

2. Button

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />

3. String

<string name="app_name">Bai0</string>
<string name="action_settings">Settings</string>
<string name="edit_message">Enter somethings!</string>
<string name="button_send">Send</string>

4. Tạo Activity mới để gọi

1.     Respond to the Send Button

– Mở layout / activity_main.xml thêm thuộc tính cho Button:

<Button 
 ...
 android:onClick="sendMessage"
 />

2.     Build an Intent

3.     Start the Second Activity

– Mở src / MainActivity.java

– Phía trên cùng:

public class MainActivity extends Activity {

 public final static String EXTRA_MESSAGE = "com.example.bai0.EXTRA_MESSAGE";
...
}

– Thêm phương thức:

/** Called when the user clicks the Send button */
public void sendMessage(View view) {
    Intent intent = new Intent(this, DisplayMessageActivity.class);
    EditText editText = (EditText) findViewById(R.id.edit_message);
    String message = editText.getText().toString();
    intent.putExtra(EXTRA_MESSAGE, message);
    startActivity(intent);
}

Ctrl + Shift + O (tự động thêm lớp)

4.     Create the Second Activity

New / Android Activity  / Next / …

  • Project: Bai0
  • Activity Name: DisplayMessageActivity
  • Layout Name: activity_display_message
  • Navigation Type: None
  • Hierarchial Parent: com.example.bai0.MainActivity
  • Title: My Message

– Finish

5.     Receive the Intent

6.     Display the Message

– Mở src / DisplayMessageActivity.java

– Trong onCreate():

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    // Get the message from the intent
    Intent intent = getIntent();
    String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
 
    // Create the text view
    TextView textView = new TextView(this);
    textView.setTextSize(40);
    textView.setText(message);
 
    // Set the text view as the activity layout
    setContentView(textView);
}

– Tùy chỉnh AndroidManifest.xml cho phù hợp (Khoảng 19)

– Right click Project / Run As / Android Application (Nên tạo máy ảo trước, chọn Nexus One, nhưng không Start sẵn)

BUỔI 1

1. Hàm load view/widget

– Để thể hiện một UI thì trong hàm onCreate của mỗi Activity cần phải được gọi một hàm là setContentView(R.layout.main); hàm này sẽ load giao diện từ file XML lên để phân tích thành mã bytecode.

Ví dụ: Gọi giao diện được định nghĩa bởi tập tin main.xml

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

2. Xác định kích thước

Khi xây dựng một UI, ta cần phải xác định vị trí và kích thước của các view (hay widget). Sau đây là các đơn vị dùng để xác định kích thước các widget.

  • px (pixel): điểm ảnh cơ bản, nhỏ nhất, trên màn hình
  • pt (point): bằng 1/72 inch
  • dp (density – independent pixel): với màn hình có độ phân giải 160 px/inch thì 1dp = 1px, đây là đơn vị được khuyên dùng khi xác định kích thước của view trên layout, vì khí đó view có kích thước thay đổi tỉ lệ với kích thước màn hình, vị trí của nó không bị lệch khi hiển thị lên các màn hình có độ phân giải khác nhau.
  • sp (Scale – Independent pixel): gần giống dp, nhưng được khuyên dùng cho text size

Untitled

– Kích thước màn hình được định nghĩa bởi đơn vị inch theo đường kính hoặc độ phân giải theo chiều ngang và chiều dọc.

– Hình trên trình bày màn hình của điện thoại Nexus S, kích thước màn hình 4 inches đường chéo, độ phân giải 480 x 800 pixel. Chiều ngang 2,04 inches –> mật độ pixel là 480/2,04 ≈ 235 dpi (dots per inch). 

– Công thức đổi từ dp sang px: pixels = dp * (dpi / 160)

– Android định nghĩa và công nhận bốn mật độ màn hình:

  • Low density (ldpi) — 120 dpi
  • Medium density (mdpi) — 160 dpi
  • High density (hdpi) — 240 dpi (màn hình HD)
  • Extra High density (xhdpi) — 320 dpi (màn hình Full HD)

3. Các đối tượng View cơ bản

3.1. Nhóm hiển thị văn bản

  • TextView: hiển thị văn bản nhưng không cho chỉnh sửa, nằm trong gói android.widget, khi sử dụng phải khai báo import Android.widget.TextView.
  • EditText: nhập hoặc chỉnh sửa văn bản, như một TextField hoặc TextBox, nó là lớp con của TextView, khai báo import android.widget.EditText.
  • AutoCompleteTextView: tương tự EditText (lớp con của EditText), hiển thị một danh sách câu gợi ý hoàn thành một cách tự động trong khi người dùng nhập văn bản. 

3.2. Nhóm nút điều khiển

  • Button: nút nhấn tương tác hoạt động theo định nghĩa bởi người lập trình như: cancel, back, run, send…. Khai báo import android.widget.Button
  • ImageButton: tương tự như button, nhưng hiển thị một ảnh và không hiển thị văn bản. Khai báo import android.widget.ImageButton
  • CheckBox: hai trạng thái: Checked hoặc Unchecked,  nhận hai giá trị true hoặc false. Cho phép chọn nhiều mục (item) cùng một lúc. Khai báo import android.widget.CheckBox
  • RadioGroupRadioButton: hai trạng thái... Khi đã check thì không thể uncheck. RadioGroup nhóm 1/n RadioButton. Gom nhóm để có nhiều sự lựa chọn. Khai báo import android.widget.RadioGroupimport android.widget.RadioButton
  • ToggleButton: hai trạng thái…như ON (sáng lên) hoặc OFF (tắt). Khai báo import android.widget.ToggleButton

3.3. Nhóm hiển thị hình ảnh

  • ImageView: hiển thị hình ảnh tùy ý, tải hình ảnh từ nhiều nguồn khác nhau (resources hoặc content providers), thường được lưu vào thư mục drawable. Cho phép chỉnh kích thước ảnh phù hợp với Layout, chỉnh màu…. import  android.widget.ImageView.
  • ListView: hiển thị danh sách item, cuộn theo chiều dọc. Các mục này chứa trên lớp ListAdapter, ListView hiển thị dữ liệu được gói trong đó. import  android.widget.ListViewimport  android.widget.ListAdapter

Untitled

  • MapView: hiển thị bản đồ. Trình bày cụ thể trong một bài sau.

3.4. Nhóm hộp thoại

  • Dialog: hộp thoại với các tùy chọn. Trong Android, bằng cách sử dụng hộp thoại chúng ta có thể chọn một tùy chọn từ nhiều tùy chọn bằng cách sử dụng nút radio. import android.app.Dialog

Untitled

  • Toast: cơ bản tương tự Dialog nhưng Toast chỉ hiển thị một cảnh báo nhỏ mà không làm ảnh hưởng tới chương trình và nó cũng tồn tại trong một khoảng thời gian cố định (tùy chọn khi lập trình). import  android.widget.Toast

3.5. Nhóm menu

  • Options Menu: thông tin liên quan đến Activity hiện tại, cần nhấn nút Menu trên thiết bị.  import  android.view.Menu
  • Context Menu:thông tin một đối tượng View cụ thể, cần nhấn và giữ một đối tượng (Button, ImageView… đối tượng thường được sử dụng nhất là item của ListView). import  android.view.MenuItem

Capture

3.6. Nhóm điều chỉnh thời gian

  • DatePicker: chọn ngày, tháng năm. import java.util.Date;và  import  android.widget.DatePicker
  • TimePicker: chọn thời gian của một ngày, 24h hoặc AM, PM.  import  android.widget.TimePicker

*** Khai báo: thông thường các view trên layout ta khai báo trong tập tin XML và Java:

  • XML
    • định danh (id)
    • kích thước (layout_width, layout_height, textSize,..)
    • vị trí (đối với RelativeLayout và AbsoluteLayout)
    • thuộc tính text
    • các tài nguyên (string, image)
  • Java
    • Phương thức, ghi đè, override
    • Hiển thị, điều khiển, đặt lại thuộc tính
    • Xử lý sự kiện tương tác

4. Các Layout

4.1. Linear Layout

  • Bố trí theo chiều ngang hoặc chiều dọc
  • Không phụ thuộc vào kích thước và độ phân giải màn hình
  • Được trình bày theo tỷ lệ cân xứng dựa vào các ràng buộc
  • Chú ý thuộc tính android:orientation bố trí các đối tượng lần lượt theo chiều dọc – vertical hoặc chiều ngang – horizontal

Ví dụ: 

Capture

<LinearLayout ...
 android:orientation="vertical" >
<TextView... />
<EditText ... />

    <LinearLayout ... 
     android:orientation="horizontal">

     <Button ... />
     <Button ... /> 

    </LinearLayout>
</LinearLayout>

– Người ta cũng thường sử dụng 2 thuộc tính:

  • android:layout_gravity xác định hướng định vị của một View trên màn hình bởi các value, được khai báo bới các hằng sau:

Constant

Value

Description

top 0x30 Đẩy đối tượng về phía đỉnh của màn hình, kích thước không đổi.
bottom 0x50 Đẩy đối tượng về phía đáy của màn hình, kích thước không đổi.
left 0x03 Đẩy đối tượng về phía trái của màn hình, kích thước không đổi.
right 0x05 Đẩy đối tượng về phía phải của màn hình, kích thước không đổi.
center_vertical 0x10 Đặt đối tượng ở giữa màn hình theo chiều dọc, kích thước không đổi.
fill_vertical 0x70 Tăng chiều dọc của dối tượng nếu cần, vì vậy nó làm đầy hoàn toàn màn hình.
center_horizontal 0x01 Đặt đối tượng ở giữa màn hình theo chiều ngang, kích thước không đổi.
fill_horizontal 0x07 Tăng chiều ngang của dối tượng nếu cần, vì vậy nó làm đầy hoàn toàn màn hình.
center 0x11 Đặt đối tượng ở giữa màn hình, kích thước không đổi.
fill 0x77 Tăng chiều ngang và chiều dọc của dối tượng nếu cần, vì vậy nó làm đầy hoàn toàn màn hình.
clip_vertical 0x80 Tùy chọn bổ sung để các cạnh trên và / hoặc đáy của một View bị cắt đến giới hạn của màn hình. Việc cắt sẽ được dựa trên gía trị của vertical gravity: nếu là top sẽ cắt cạnh dưới, nếu là bottom sẽ cắt cạnh trên, và nếu  không khai báo sẽ cắt cả hai cạnh.
clip_horizontal 0x08 Tùy chọn bổ sung để các cạnh trên và / hoặc đáy của một View bị cắt đến giới hạn của màn hình. Việc cắt sẽ được dựa trên gía trị của horizontal gravity: nếu là left sẽ cắt cạnh phải, nếu là right sẽ cắt cạnh trái, và aiu không khai báo sẽ cắt cả hai cạnh.
  • android:layout_weight chỉ ra phần trăm không gian còn lại trong LinearLayout sẽ được phân bổ để các View liên kết với các tham số LayoutParams. Chỉ định 0 nếu View không được kéo dài. Ngược lại không gian còn lại sẽ được chia theo tỷ lệ cho tất cả các View có thông số weight  lớn hơn 0. Giá trị của tham số nguyên.

4.2. Relative Layout

– Bố trí các widget theo một trục đối xứng ngang hoặc dọc. Cần xác định các ràng buộc nhất định với các widget khác: vị trí tương đối trái, phải, trên, dưới so với một widget khác hoặc so với màn hình (parent layout). Không phụ thuộc vào kích thước và độ phân giải màn hình, giúp người lập trình dễ dàng sắp xếp các widget trên UI theo ý muốn.

Ví dụtạo ra một giao diện với RelativeLayout gồm  các đối tượng: 1 TextView; 1 EditText; 2 Button, có điểm khác là  Button OK được dời sang sát lề phải của màn hình và thêm vào một đối tượng ImageView (hiển thị ảnh) ở phía dưới của các Button và được canh giữa màn hình với kích thước xác định.

Capture

<RelativeLayout ... >
<TextView
  android:id="@+id/txtView"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentTop="true"
  android:layout_centerHorizontal="true"
  android:text="@string/text_view"
  android:textSize="18sp" />
<EditText 
  android:id="@+id/editmail"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_below="@+id/txtView"
  android:hint="@string/email"
  android:textSize="18sp" />
 
<Button 
  android:id="@+id/btnCancle"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_below="@+id/editmail"
  android:layout_alignParentLeft="true"
  android:text="@string/btnCancle" />

<Button 
  android:id="@+id/btnOK"
  android:layout_width="70dp"
  android:layout_height="wrap_content"
  android:layout_below="@+id/editmail"
  android:layout_alignParentRight="true"
  android:text="@string/btnOK" />
 
<ImageButton 
  android:id="@+id/image"
  android:src="@drawable/khoacntt"
  android:contentDescription="@string/content"
  android:layout_width="250dp"
  android:layout_height="150dp"
  android:layout_below="@+id/btnCancle"
  android:layout_centerHorizontal="true" />
</RelativeLayout>

4.3. Table Layout

– Layout này được sử dụng khi cần thiết kế một bảng chứa dữ liệu hoặc cần bố trí các widget theo các hàng và cột. Chẳng hạn như, giao diện của phần mềm máy tính cailculator hoặc một danh sách dữ liệu.

– Ví dụ: Tạo ra UI với TableLayout gồm 2 cột và 4 hàng. Ô thuộc hàng 3, cột 1 là 1 TextView trống (Hình 5-a). Nếu không khai báo 1 TextView trống, thì CheckBox “Remember Password” sẽ dời về ô này và ô trống thuộc hàng 3 cột 2 (Hình 5-b).

Capture

<TableLayout 
 ...>
 <TableRow>
   <TextView 
     android:text="Username:"
     android:width="80sp"/>
   <EditText 
     android:id="@+id/txtUsername"
     android:width="150sp"/>
 </TableRow>
 <TableRow>
   <TextView 
     android:text="Password:"/>
   <EditText 
     android:id="@+id/txtPassword"
     android:password="true"/>
 </TableRow>
 <TableRow>
   <TextView />
   <CheckBox 
     android:id="@+id/chkRePass"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="Remember Password"/>
 </TableRow>
 <TableRow>
   <Button 
     android:id="@+id/btnLogIn"
     android:text="Log in"/>
 </TableRow>
</TableLayout>

4.4. Frame Layout

FrameLayout giống như các Layer trong Photoshop. Đối tượng bên dưới sẽ bị che khuất bởi các đối tượng nằm trên.

– Thường được sử dụng khi muốn tạo ra các đối tượng có khung hình bên ngoài. Có thể thêm nhiều FrameLayout chồng lên nhau và layout mới sẽ đè lên layout trước nó.

– Ví dụ: Tạo một UI với FrameLayout,  trong đó chứa 2 đối tượng là ImageView và Button “Print”. Trong hình 11, ta thấy Button “Print” đè lên ImageView.

Capture

<FrameLayout ... >
<ImageView 
   android:layout_width="250dp"
   android:layout_height="250dp"
   android:src="@drawable/capture"/>
 <Button 
   android:layout_width="150dp"
   android:layout_height="wrap_content"
   android:text="Print"/>
</FrameLayout>

4.5. Absolute Layout

– Bố trí các layout theo tạo độ x, y. Rất ít được sử dụng, vì khi thay đổi kích thước màn hình, tỷ lệ khoảng cách sẽ ko còn chính xác.

<AbsoluteLayout ...>
    <Button
        android:layout_width="188px"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_x="126px"
        android:layout_y="361px"/>
    <Button
        android:layout_width="113px"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_x="12px"
        android:layout_y="361px"/>
</AbsoluteLayout>

5. Xử lý sự kiện

5.1. Tương tác trực tiếp- Giao diện mức cao

– Khi người dùng chạm vào các đối tượng của chương trình như: Button, TextView, EditText, CheckBox,… –> Các đối tượng này là giao diện mức cao. Bắt sự kiện dùng phương thức: public void onClick(View v) kế thừa từ lớp android.view.View

– Ví dụ:

package vidu.sukien;
import .....;
public class Vidu extends Activity {
  //Called when the activity is first created
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
//Gọi đối tượng button “btn” đã khai báo trong tập tin Layout XML. 
      Button button = (Button)this.findViewById(R.id.btn);
// Lắng nghe và xử lý sự kiện tương tác trực tiếp lên button
      button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
 // Hiển thị dòng chữ “Hello world”.
        TextView tx = (TextView)Vidu.this.findViewByid(R.id.tx);
        textview.setText("Hello world!");
 }
 };
 }
 }

5.2. Tương tác trực tiếp – Giao diện mức thấp

– Giao diện mức thấp: vẽ, viết, trò chơi, … –> bắt và xử lý sự kiện tùy biến hơn. Dùng phương thức: public boolean onTouchEvent(MotionEvent event)

– Ví dụ:

public boolean onTouchEvent(MotionEvent event) {
  int eventaction = event.getAction();
  switch (eventaction) {
         case MotionEvent.ACTION_DOWN: 
             // ...Hành động diễn ra khi gón tay chạm vào màn hình...
             break;
         case MotionEvent.ACTION_MOVE:
             //... Hành động diễn ra khi ngón tay di chuyển trên màn hình ...
             break;
         case MotionEvent.ACTION_UP:   
             // ...Hành động diễn ra khi ngón tay rời khỏi màn hình...
             break;
     }
     return true; 
 }

5.3. Sự kiện bàn phím

– Thay vì tương tác trên màn hình, ta ấn các phím. Phương thức public boolean onKey(View v, int keyCode, KeyEvent event) kế thừa từ lớp android.view.KeyEvent

– Ví dụ:

package vidu.sukien; 
import ...;
 
public class Vidu extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 //Gọi đối tượng TextView đã khai báo trong tập tin Layout XML.  
final TextView text = (TextView)Vidu.this.findViewById(R.id.tx);
// Lắng nghe và xử lý sự kiện bàn phiếm
text.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event){
// Nếu ấn phiếm trung tâm thì hiển thị dòng chữ “Hello world”.
            if (event.getAction() == KeyEvent.ACTION_DOWN 
                && keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
                        text.setText("Hello world!");
                                    return true;                    
                            }
                            else {
                              return false;
                            }
                                    }
                                    }
                        );
    }
   }

5.4. Ví dụ tổng hợp

Capture

<LinearLayout 
...
 android:orientation="vertical">
<Button 
 android:id="@+id/btnSave"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="@string/btnSave"
 android:onClick="btnSaved_clicked" //Thêm vào để xử lý sự kiện phía dưới
//Có thể copy cho nhiều button khác, bên java chỉ cần tạo 1 lớp.
/>
 
 <Button 
 android:id="@+id/btnOpen"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/btnOpen"
 android:onClick="btnOpened_Clicked" //Thêm vào để xử lý sự kiện phía dưới
/>
 
 <ImageButton 
 android:id="@+id/btnImg1"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:contentDescription="@string/content1"
 android:src="@drawable/star"/>
 
 <EditText 
 android:id="@+id/txtName"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:hint="@string/ed_message"/>
 
 <CheckBox 
 android:id="@+id/chkAutoSave"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="@string/chkAutoSave"/>
 
 <CheckBox 
 android:id="@+id/star"
 style="?android:attr/starStyle"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="@string/star"/>
 
 <RadioGroup 
 android:id="@+id/rg"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:orientation="horizontal">
 
 <RadioButton 
 android:id="@+id/rb1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/rb1"/>
 
 <RadioButton 
 android:id="@+id/rb2"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/rb2"/>
 </RadioGroup>
 
 <ToggleButton 
 android:id="@+id/toggle_1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
</LinearLayout>

– File String.xml

    <string name="app_name"> BÀI THỰC HÀNH BUỔI 11 </string>
    <string name="action_settings">Settings</string>
    <string name="rb1">Option 1</string>
    <string name="rb2">Option 2</string>
    <string name="ed_message"> Enter message</string>
    <string name="btnsave"> Save </string>
    <string name="btnOpen"> Open </string>
    <string name="chkAutosave"> Autosave </string>
    <string name="star"> Star </string>
    <string name="content1"> btnImg1 </string>

– Checkbox dạng ngôi sao: style=”?android:attr/starStyle” (cú pháp ?package:type/name)

– Tất cả các đối tượng đều có thuộc tính nhận dạng id. Chúng sẽ được nhận dạng trong mã nguồn Java bằng phương thức: View.findViewById () hoặc Activity.findViewById () 

*** Xử lý sự kiện:

– Sửa tập tin MainActivity.java thành như sau :

public ... {
//Rút gọn cú pháp, hiển thị sự kiện của button Open và Save
//Chú ý: phải thêm mã onClick... vào activity_main.xml
//Chỉ được sử dụng với những sự kiện có 1 tham số
public void btnSaved_clicked (View view) {
 DisplayToast("You have clicked the Save button");
 }
public void btnOpened_Clicked (View view) {
 DisplayToast("You have clicked the Open button");
 }

@Override
 protected void onCreate(Bundle savedInstanceState) {
 ...;
 //CheckBox
 CheckBox checkBox = (CheckBox) findViewById(R.id.chkAutoSave);
 checkBox.setOnClickListener(new View.OnClickListener()
 {
 public void onClick(View v) {
 if (((CheckBox)v).isChecked())
 DisplayToast("CheckBox is checked");
 else
 DisplayToast("CheckBox is unchecked");
 }
 });
 
 //---RadioButton---
 RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rg);
 radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener()
 {
 public void onCheckedChanged(RadioGroup group, int checkedId) {
 RadioButton rb1 = (RadioButton) findViewById(R.id.rb1);
 if (rb1.isChecked()) {
 DisplayToast("Option 1 checked!");
 } else {
 DisplayToast("Option 2 checked!");
 }
 }
 });
 
 //ToggleButton
 ToggleButton toggleButton = (ToggleButton) findViewById(R.id.toggle_1);
 toggleButton.setOnClickListener(new View.OnClickListener()
 {
 public void onClick(View v) {
 if (((ToggleButton)v).isChecked())
 DisplayToast("Toggle button is On");
 else
 DisplayToast("Toggle button is Off");
 }
 });
 }
 //Lớp hiển thị trạng thái các option được chọn
private void DisplayToast(String msg)
 {
 Toast.makeText(getBaseContext(), msg,
 Toast.LENGTH_SHORT).show();
 }
 }

*** THÔNG SỐ GỢI Ý

1. Button OK

android:layout_width="70dp" (= Button Cancle)-