Thứ Sáu, 27 tháng 6, 2014

Bài 7: Toast và Alert Dialog.

     Toast Notification và Alert Dialog trong Android dùng để xuất ra một thông báo nào đó hay bạn cũng có thể dùng để kiểm tra một điều gì khi lập trình ứng dụng cho Android. Các tiền trình của ứng dụng vẫn sẽ tiếp tục làm việc khi Toast Alert Dialog hiện ra thông báo.

1.Toast Notification:
    -Về Toast Notification chắc các bạn cũng đã được làm quen trong các ví dụ , bài tập trước. Vì vậy một số điểm đặc biệt sau của Toast Notification chắc các bạn cũng đã nắm bắt được:
        + Toast có thể được tạo và hiển thị bên trong một Activity hoặc Service
        + Không cho phép người sử dụng tương tác với nó. Chỉ đơn giản là hiển thị một điều gì đó thôi
        + Có 2 giá trị mặc định của Toast: Toast.LENGTH_SHORT hiển thị trong 2 giây và Toast.LENGTH_LONG: hiển thị trong 3.5 s.

    - Các tạo Toast Notification:

Toast toast = Toast.makeText(YourActivity.this,
 "Hiển thị gì thì ghi vào đây", Toast.LENTH_SHORT ) ;
toast.show();

Toast sẽ hiển thị dưới dạng một khung nhỏ nền đen chữ trắng ở dưới cùng màn hình.

2. Alert Dialog:

- Alert Dialog là một hộp hội thoại hiển thị cho phép người dùng tương tác với nó. Ví dụ khi mình muốn xử lý sự kiện khi bấm vào nút thoát sẽ hiển thị một hộp hội thoại hỏi có thoát hay là không. Tham khảo hình sau cho dễ hiểu nhé:
Alert Dialog
     Sau đây là code cách tạo một Alert Dialog:
+ activity_main.xml:

 <LinearLayout 
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.tonghopproject.MainActivity$PlaceholderFragment" >

       
       
        <Button
            android:id="@+id/btnThoat"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Thoát chương trình"
            />

    </LinearLayout>

+ MainActivity.java:

package com.example.tonghopproject;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnThoat = (Button)findViewById(R.id.btnThoat);
        //Khi click nút Thoát thì sẽ hiển thị ra 1 AlertDialog
        //hỏi có muốn thoát hay không
        btnThoat.setOnClickListener(new OnClickListener() {
          
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
              
                //Tạo một  AlertDialog Builder để thiết đặt các giá trị của dialog
                AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);
                //Đặt Title cho AlertDialog (Tiêu đề)
                b.setTitle("Question");
                //Đặt thông báo mà bạn muốn hiển thị
                b.setMessage("Bạn có muốn thoát hay là không ?");
                //Thiết đặt nút Yes và vị trí của nó
                b.setPositiveButton("Yes", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
                        finish();
                        //Đồng ý thì thoát chương trình
                        System.exit(0);
                    }
                });
                //Thiết đặt nút No và vị trí cho nó
                b.setNegativeButton("No", new DialogInterface.OnClickListener() {
                  
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
                        //Không đồng ý thì hủy AlertDialog
                        dialog.cancel();
                    }
                });
                //Tạo dialog và show ra màn hình.
                b.create().show();
            }
        });
    }
}

>>>Bài 8: Cách sử dụng Checkbox, Radio Button trong Android

Thứ Tư, 25 tháng 6, 2014

Bài 6: Làm quen với một số kiểu lập trình sự kiện trong android

     Ở bài tập trước, các bạn đã học được cách sử dụng một vài loại layout cơ bản giúp các bạn thiết kế giao diện chương trình. Trong bài tập này, chúng ta cùng tìm hiểu một vài kiểu lập trình sự kiện trong android với Button. Button(nút) là một trong những control quan trọng nhất trong android, vì vậy mình mong rằng các bạn cần phải thật sự hiểu và nắm chắc về nó.


1.Kiểu sự kiện Inline anonymous listener với Button.


-Ví dụ sau đây sẽ là một ví dụ đơn giản nhất: "Tính tổng 2 số". Phân tích một chút về đề bài, chúng ta phải có 2 ô Editext giúp các bạn nhập dữ liệu của 2 số, 1 nút Button để tính tổng, và một TextView giúp chúng ta hiển thị kết quả. Các bạn xem qua về giao diện mình tranh thủ thiết kế
-Giao diện rất đơn giản mình mong rằng các bạn nhìn vào đây, áp dụng kiến thức về layout trước và cố gắng thiết kế giao diện. Các bạn cũng có thể tham khảo outline của mình dưới đây
Và sau đây là code của chương trình này. Các bạn cần nghiên cữu kỹ về code và các chú thích kèm theo của mình nhé
+File giao diện activity_main.xml:
<TableLayout 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:stretchColumns="*">
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_span = "3"
            android:textColor="#FFFFFF"
            android:background="#0000A0"
            android:textSize="20sp"
            android:gravity="center"
            android:text="Chương trình tính tổng 2 số"/>
    </TableRow>
   
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <EditText
            android:id="@+id/edtSoA"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="1"
            android:inputType="number"      />
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="+"/>
        <EditText
            android:id="@+id/edtSoB"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="1"         
            android:inputType="number"   />
    </TableRow>
   
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btnTong"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_span="3"
            android:text="Tính tổng" />
           
    </TableRow>
   
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/txtKetQua"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_span = "3"
            android:textColor="#FFFFFF"
            android:background="#0000A0"
            android:textSize="20sp"
            android:gravity="center"      />
    </TableRow>
  
</TableLayout>
+File MainActivity.java:

package com.example.hellowolrd;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Tạo một đối tượng Button gọi tới Button btnTong trong
        //activity_main.xml. Đối tượng Button này xử lý các sự kiện
        //của button trong activity.
        Button btnTong = (Button)findViewById(R.id.btnTong);
        //gọi bộ lắng nghe sự kiện của nút khi Onclick.
        //Các bạn chú ý khi code thì sử dụng thêm tổ hợp Ctrl+space nhé
        //nhớ phải import đầy đủ các gói View nhé
        btnTong.setOnClickListener(new OnClickListener() {
           
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
               
                //Tương tự Button, tạo 2 object EditText thôi
                EditText soA = (EditText)findViewById(R.id.edtSoA);
                EditText soB = (EditText)findViewById(R.id.edtSoB);
                //Lấy giá trị của số nhập vào, ép kiểu sang float
                float a = Float.parseFloat(soA.getText().toString());
                float b = Float.parseFloat(soB.getText().toString());
                //Tương tự Button
                TextView kq = (TextView)findViewById(R.id.txtKetQua);
                //Hiển thị kết quả
                kq.setText(""+(a+b));
            }
        });
    }
}
Các bạn đọc code và chú thích, tự mình code lại để nhớ sâu nhé. Quan trọng nhất là setOnclickListener và đoạn tạo đối tượng Button, EditText và TextView nhé. Và đó cũng là Kiểu sự kiện Inline anonymous listener

2. Activity is listener:

- Với cách lập trình sự kiện này, Activity sẽ implements interface (Có nghĩa là kế thừa từ nhiều loại interface có sẵn). Mình sẽ ví dụ về trường hợp của Button cho các bạn có thể nắm vững.

- Đề bài: Tính chỉ số khối của cơ thể con người - chỉ số BMI. Chỉ số này sẽ đánh giá mức độ gầy hay béo của con người, giúp chúng ta xác định một người gầy hay là bếu phì.
     +Công thức tính: BMI = W/(H*H)

-Phân loại đánh giá béo - gầy:
  • BMI < 18: người gầy
  • BMI = 18 – 24,9: người bình thường
  • BMI = 25 – 29,9: người béo phì độ I
  • BMI = 30 – 34,9: người béo phì độ II
  • BMI > 35: người béo phì độ III
Theo đề bài, mình tạm thời thiết kế một giao diện chương trình như sau:
Source code activity_main.xml:
<TableLayout 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:stretchColumns="*">
 
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_span = "2"
            android:textColor="#FFFFFF"
            android:background="#0000A0"
            android:textSize="20sp"
            android:gravity="center"
            android:text="Chương trình tính chỉ số BMI"/>
    </TableRow>
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Chiều cao"/>
        <EditText
            android:id="@+id/edtChieuCao"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:ems="10"/>
    </TableRow>
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cân nặng"/>
        <EditText
            android:id="@+id/edtCanNang"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="numberSigned"
            android:ems="10"/>
    </TableRow>
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button android:id="@+id/btnTinh"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_span = "2"
            android:text="Tính chỉ số BMI"/>
    </TableRow>
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5sp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Chỉ số BMI:"/>
        <TextView
            android:id="@+id/txtChiSo"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </TableRow>
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5sp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Đánh giá: "/>
        <TextView
            android:id="@+id/txtDanhGia"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </TableRow>
  
</TableLayout>

Các bạn chú ý là tại EditText, mình có thiết lập một thuộc tính inputType với giá trị là number. Có nghĩa là khi bạn nhập chỉ được phép nhập số. Bàn phím trong android cũng chỉ hiển thị và cho phép nhập số. Các bạn có thể thử trong emulator của mình

+MainActivity.java

package com.example.hellowolrd;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
//Chú ý dòng này, có thêm implements OnclickListener
//Nhiều người quên mất đoạn này thành ra chạy sẽ lỗi
public class MainActivity extends ActionBarActivity implements OnClickListener {



    Button btnTinhBMI;
    EditText edtChieuCao, edtCanNang;
    TextView txtChiSo, txtDanhGia;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Gọi hàm lấy các control cho View
        getControlView();
        btnTinhBMI.setOnClickListener(this);
    }
   
    //Viết lại sự kiện onClick của nút
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
      
        //Chú ý hàm try-catch bắt lỗi khi bạn chưa nhập dữ liệu
        try {
            //Lấy giá trị nhập vào và ép kiểu về Float
            float chieuCao = Float.parseFloat(edtChieuCao.getText().toString());
            float canNang = Float.parseFloat(edtCanNang.getText().toString());
            float BMI = canNang/(chieuCao*chieuCao);
            txtChiSo.setText(BMI+"");
            if(BMI<18){
                txtDanhGia.setText("Bạn hơi gầy");
            }else if(18<=BMI && BMI<25){
                txtDanhGia.setText("Bạn bình thường");
            }else if(25<=BMI && BMI<30){
                txtDanhGia.setText("Bạn béo phì độ 1");
            }else if(30<=BMI && BMI<35){
                txtDanhGia.setText("Bạn béo phì độ 2");
            }else if(35<=BMI){
                txtDanhGia.setText("Bạn béo phì độ 3");
            }
        } catch (Exception e) {
            //Câu lệnh thông báo một dòng chữ nhỏ ở dưới ra màn hình
            Toast.makeText(getBaseContext(),
                    "Bạn chưa nhập dữ liệu. Làm lại nào", Toast.LENGTH_SHORT).show();
        }
      
    }


    private void getControlView() {
        // TODO Auto-generated method stub
        btnTinhBMI = (Button)findViewById(R.id.btnTinh);
        edtChieuCao = (EditText)findViewById(R.id.edtChieuCao);
        edtCanNang = (EditText)findViewById(R.id.edtCanNang);
        txtChiSo = (TextView)findViewById(R.id.txtChiSo);
        txtDanhGia = (TextView)findViewById(R.id.txtDanhGia);
    }
   
}

Trong MainActivity các bạn cần chú ý 1 vài điểm sau:
+Phải implement OnclickListener chỗ khai báo class MainActivity. Đây là cách để viết sự kiện Activity Listeners.
+Câu lệnh Toast.makeText... đưa ra thông báo một dòng chữ nhỏ ở gần dưới cùng màn hình. Ở đây thông báo khi bạn không nhập dữ liệu cho 2 ô cân nặng và chiều cao. Trong câu lệnh này có 3 đối số:
      -Đối số thứ 1: getBaseContext() : Lấy Context đang làm việc. Tìm hiêu sâu hơn về vấn đề Context trong các bài sau này
      -Đối số thứ 2: dạng String dùng để hiển thị dòng thông báo
      -Đối số thứ 3: Thời gian hiển thị thông báo. Toast có 2 hằng số là Toast.LENGTH_SHORT (2.0 giây) và Toast.LENGTH_LONG (3.5 giây)

3.Listeners in variable

-Với trường hợp này, listeners được lưu trữ trong một biến do chúng ta tạo ra. Và vì vậy, chúng ta có thể chia sẻ chung một biến sự kiện cho nhiều trường hợp control khác nhau
-Mình sẽ đi vào một ví dụ để các bạn có thể  hiểu dễ hơn. Chúng ta cùng làm một ví dụ chương trình chuyển đổi mét sang dặm. Công thức: "1 mile =1 609.344 meters"
-Sau đây là giao diện của chương trình
Listeners in variable
Các bạn hãy tự mình thiết kế giao diện cho chương trình nhé. Tốt nhất là khi nào gặp vấn đề khó không giải quyết được thì tham khảo code của mình. Làm 1,2 lần là nhớ như in ngay.
Khi tạo một project mới thì nhớ xử lý cái fragment đi.
>>>Giải quyết vấn đề với Fragment Layout

+activity_main.xml:

<TableLayout 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:stretchColumns="*">
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_span = "3"
            android:textColor="#FFFFFF"
            android:background="#0000A0"
            android:textSize="20sp"
            android:gravity="center"
            android:text="Chuyển đổi miles, metters"/>
    </TableRow>
   
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10sp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Metters"
            android:textStyle="bold"
            android:textSize="17sp"
            android:textColor="#008000"/>
        <TextView />
       
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Miles"
            android:textStyle="bold"
            android:textSize="17sp"
            android:textColor="#008000"/>
    </TableRow>
   
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10sp">
        <EditText
            android:id="@+id/edtMetters"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="5"
            android:inputType="number"/>
       
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="="/>
       
        <EditText
            android:id="@+id/edtMiles"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="5"
            android:inputType="number"/>
    </TableRow>
   
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10sp">
        <Button
            android:id="@+id/btnConvert2Mile"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/convert_2_miles"/>
       
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"/>
       
        <Button
            android:id="@+id/btnConvert2Metter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/convert_2_metters"/>
    </TableRow>
   
   
   
</TableLayout>

+strings.xml (nằm trong res/values)

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">HelloWolrd</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>

    <string name="convert_2_miles">Convert to \n miles</string>
    <string name="convert_2_metters">Convert to \n metters</string>
</resources>

+Cuối cùng là MainActivity.java

package com.example.hellowolrd;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
//Chú ý dòng này, có thêm implements OnclickListener
//Nhiều người quên mất đoạn này thành ra chạy sẽ lỗi
public class MainActivity extends ActionBarActivity  {

    Button btnConvert2Miles, btnConvert2Metters;
    EditText edtMiles, edtMetters;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Gọi hàm lấy các control cho View
        getControlView();
        //đặt bộ listerner là một biến myNewListeners
        btnConvert2Metters.setOnClickListener(myNewListeners);
        btnConvert2Miles.setOnClickListener(myNewListeners);
    }
    //Khai báo biến myNewListeners và viết lại hàm onClick
    private OnClickListener myNewListeners = new OnClickListener() {
       
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            //Nếu biến myNewListeners được đặt cho btn2Metters
            if(v == btnConvert2Metters){
                try {
                    //Lấy dữ liệu từ ô Miles. Nếu chưa nhập hoặc lỗi chuyển đổi
                    //sẽ nhẩy vào thực hiện ở vòng catch
                    float fMiles = Float.parseFloat(edtMiles.getText().toString());
                    //Tính toán và show giá trị
                    edtMetters.setText(""+fMiles/1609.344f);
                } catch (Exception e) {
                    // TODO: handle exception
                    Toast.makeText(getBaseContext(),
                            "Bạn chưa nhập dữ liệu ô Miles", Toast.LENGTH_SHORT).show();
                }
            }//Nếu biến myNewListeners được đặt cho btn2Miles
            else if(v == btnConvert2Miles){
                try {
                    float fMetters = Float.parseFloat(edtMetters.getText().toString());
                    //Tính toán và show giá trị
                    edtMiles.setText(""+fMetters*1609.344f);
                } catch (Exception e) {
                    // TODO: handle exception
                    Toast.makeText(getBaseContext(),
                            "Bạn chưa nhập dữ liệu ô Metters", Toast.LENGTH_SHORT).show();
                }
            }
        }
    };

    private void getControlView() {
        // TODO Auto-generated method stub
        btnConvert2Miles = (Button)findViewById(R.id.btnConvert2Mile);
        btnConvert2Metters = (Button)findViewById(R.id.btnConvert2Metter);
        edtMetters = (EditText)findViewById(R.id.edtMetters);
        edtMiles = (EditText)findViewById(R.id.edtMiles);
    }
}
Các bạn chú ý code phần tạo biến listener mới và cách viết hàm của nó để áp dụng vào thực tế. Code đã được chú thích đầy đủ, nếu có gì không hiểu thì comment lại đừng ngại nhé.

Vậy là qua bài tập này, các bạn đã nắm chắc được một vài kiểu lập trình sự kiện thường được sử dụng trong android và cách thiết kế giao diện kết hợp, cùng với sử dụng một vài control trong android như Button, EditText, TextView... Mình hy vọng sẽ giúp ích được các bạn trong quá trình học tập môn lập trình android này. Hẹn gặp lại các bạn trong các bài sau.

>>>Bài 7: Toast và Alert Dialog.  

Thứ Ba, 24 tháng 6, 2014

Bài 5: Các loại layout trong Android

     Để thiết kế thật tốt giao diện trong Android, các bạn phải nắm chắc việc sử dụng các loại Layout cơ bản của nó. Các Layout cơ bản của Android bao gồm:
          +FrameLayout
          +LinearLayout
          +TableLayout
          +RelativeLayout
          +AbsoluteLayout



      Việc nắm vững các loại layout trên là rất cần thiết, và để có thể thiết kế được các giao diện phức tạp, các bạn cần kết hợp đồng thời nhiều loại layout với nhau. Trước tiên chúng ta cần tìm hiểu cách tạo một layout mới và cách kết nối chúng vào Activity.

1.Tạo mới layout và kết nối vào Activity
     Khi bạn tạo mới một Android project, các bạn sẽ thấy một layout mặc định của nó là activity_main.xml.  Đó là layout được chỉ định chạy đầu tiên của chương trình. Bạn có thể tạo mới một layout khác và thay thế layout mặc định bằng layout bạn vừa tạo ra.
          +Chuột phải vào thư mục project trong Package Explorer chọn New/Others...
          +Trong cửa sổ mới xuất hiện, mở thư mục Android, và chọn Android XML Layout Files rồi chọn  Next.
          +Tại đây bạn có thể chọn loại layout mà bạn muốn tạo, đặt tên  và click finish. Ở đây mình sẽ chọn LinearLayout và đặt tên là new_layout. Kéo một vài loại View trong Palette vào cho nó chuyên nghiệp
LinearLayout

     Như vậy trong thư mục res/layout đã có một layout mới là new_layout.xml. Mở file MainActivity.java ra. (Các bạn nhớ xử lý một project android mới như mình đã hướng dẫn nhé)
>>>Giải quyết vấn đề với Fragment Layout

     Sau khi xử lý rắc rối với fragment layout thì trong MainActivity.java sẽ còn lại như sau:

package com.example.hellowolrd;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }
}
     Các bạn chú ý dòng: setContentView(R.layout.activity_main); Đây chính là dòng đặt activity được khởi tạo đầu tiên khi chạy ứng dụng. Các bạn chỉ cần thay activiti_main bằng tên file xml mới của bạn và chạy thử trên Android emulator. Chắc chắn các bạn sẽ thấy kết quả sẽ là layout mới mà bạn vừa thiết kế. Chúc các bạn may mắn.

2. Các loại layout cơ bản:
      a.Framelayout:
          - Đây là loại Layout cơ bản nhất  trong Android. Đặc điểm của layout này là các view khi được đưa vào layout sẽ được "neo giữ" tai góc trái trên cùng của màn hình. Nó sẽ không cho phép chúng ta thay đổi vị trí của các view theo một vị trí nào hết.
          - Khi các bạn đưa các view vào sau sẽ  nằm đè lên và che khuất một phần hoặc che khuất hoàn toàn view trước đó. Các bạn tham khảo đoạn code trong android_main.xml nhé:
 
<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">
  
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dòng này ở sau"
        android:textSize="40sp"
        android:textColor="#008000"/>
  
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dòng này ở trước "
        android:textSize="30sp"
        android:textColor="#000000"/>

</FrameLayout>

    
FrameLayout

     Các bạn lưu ý các dòng code sau và ý nghĩa của chúng:
+ android:layout_width="wrap_content" android:layout_height="wrap_content" : Dòng này định nghĩa chiều rộng và chiều dài của một View. Ở đây là mình lấy từ TextView. Các bạn có thể hiểu rằng độ rộng và độ dài của TextView này bằng các thành phần bên trong nó (wrap = bao bọc). Ở đây là dòng chữ hiển thị.
+ android:text="Dòng này ở sau" : Hiển thị một chuỗi ký tự ở TextView
+ android:textSize="40sp": Độ lớn của chuỗi ký tự
+ android:textColor="#008000" : Màu sắc của chuỗi ký tự.
      Ngoài ra còn rất nhiều thuộc tính của TextView. Khi code, các bạn chỉ cần viết "and" và sử dụng tổ hợp phím Ctrl+space. Sẽ có một loạt các phương thức sẵn có và các bạn có thể sử dụng để gợi ý, làm tăng tốc độ coding.

b. LinearLayout:
- Layout này cho phép sắp xếp các view theo chiều ngang(từ trái sang phải) hoặc chiều dọc (Từ trên xuống dưới).
 <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:orientation="vertical">
 
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Username:"
            android:textSize="20sp"
            android:textColor="#008000"/>
        <EditText
            android:id="@+id/edtName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="5"/>
    </LinearLayout>
 
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Password:"
            android:textSize="20sp"
            android:textColor="#008000"/>
        <EditText
            android:id="@+id/edtPass"
            android:inputType="textPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="5"/>
    </LinearLayout>

</LinearLayout>
 
Kết quả:
LinearLayout
Trong ví dụ trên, mình đã sử dụng kết hợp thêm 2 LinearLayout bên trong LinearLayout gốc. Đây chính là cách các bạn kết hợp các loại Layout với nhau để có thể tạo ra một giao diện phức tạp.
Một vài thuộc tính mà các bạn cần lưu ý:
-Trong LinearLayout:
     + android:orientation="vertical": Xác định việc LinearLayout sắp xếp các phần tử trong nó theo chiều nào. Ở đây vertical để định nghĩa sắp xếp theo chiều dọc, còn horizontal là định nghĩa theo chiều ngang
- Trong EditText :
     + Đây là view cho phép người dùng nhập dữ liệu vào (Giống textbox). Các bạn phải định nghĩa id của nó với câu lệnh android:id. Việc định nghĩa id sau này sẽ giúp các bạn lấy các view này ra để thực hiện các công việc trong phần code.
     + android:inputType="textPassword": định nghĩa loại dữ liệu nhập vào. Ở đây là loại dữ liệu password sẽ hiện dấu chấm thay vì các ký tự (che đi cho nó bảo mật). Ngoài ra ở đây cũng có nhiều loại dữ liệu inputType. Các bạn xóa chữ textPassword đi và lại sử dụng tổ hợp phím kỳ diệu Ctrl+space nhé

c. TableLayout
- Là dạng bảng, cho phép các view sắp xếp theo dạng lưới(dòng và cột)
***Chú ý: TableLayout sẽ xem dòng nào có số lượng view nhiều nhất để xác định rằng nó có bao nhiêu cột. Có nghĩa là nó sẽ lấy dòng có số View nhiều nhất là số cột chuẩn
TableLayout
Theo hình trên thì TableLayout sẽ có 3 dòng và 4 cột. Các bạn cần phải chú ý điểm này khi code giao diện với TableLayout nhé.

<TableLayout 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:stretchColumns="*">
  
    <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Username:"
            android:textSize="20sp"
            android:textColor="#008000"/>
        <EditText
            android:id="@+id/edtName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="5"
            android:layout_span="2"/>
    </TableRow>
  
   <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Password:"
            android:textSize="20sp"
            android:textColor="#008000"/>
        <EditText
            android:id="@+id/edtPass"
            android:inputType="textPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="5"
            android:layout_span="2"/>
    </TableRow>

   <TableRow android:layout_width="fill_parent"
        android:layout_height="wrap_content">
       
       <Button
           android:id="@+id/btnOk"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="OK"/>
       <Button
           android:id="@+id/btnClear"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Clear"/>
       <Button
           android:id="@+id/btnCancel"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Cancel"/>
      
   </TableRow>
  
</TableLayout>
Kết quả:
TableLayout

Các bạn chú ý một vài câu lệnh sau:
+ android:stretchColumns="*" dùng để dãn đều các cột và các view.
+ android:layout_span="2"  trộn số cột với nhau, ở đây là trộn 2 cột. Các bạn thử xóa dòng này đi trong Editext, sẽ thấy nó ngắn lại, chỉ dài đúng bằng kết thúc của nút Clear. Không tin hả, làm thử coi =))

Ngoài ra các bạn dùng layout_column để di chuyển vị trí các view đến một cột nào đó của dòng. Các bạn tự thực hành thêm về thuộc tính này nhé

d.Relative Layout:
- Cho phép sắp xếp các view theo một vị trí trương đối so với các view khác. Thường thì Relative Layout sẽ dựa vào các ID của các view để sắp xếp nên các bạn phải thật sự đặt cẩn thận các ID của layout. Nếu không giao diện sẽ bị xáo trộn hoàn toàn.


<?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"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Name" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:ems="10" >

        <requestFocus />
    </EditText>
    <Button android:id="@+id/btnOk"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editText1"
        android:layout_alignParentRight="true"
        android:text="OK"/>
</RelativeLayout>

Kết quả:
RelativeLayout

e. AbsoluteLayout:
-Cho phép thiết lập các giao diện các control tùy thích.

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

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Name"
        android:layout_x="150px"
        android:layout_y="50px"/>
</AbsoluteLayout>

Kết quả:
AbsoluteLayout

Thường thì chúng ta sẽ ít sử dụng Layout này bởi lẽ khi bạn đưa ra vị trí kiểu như vậy sẽ khó phù hợp với các loại màn hình với độ lớn và độ phân giải khác nhau

Qua bài học này, các bạn đã hiểu rõ về các loại Layout và cách sử dụng chúng. Mình mong rằng các bạn sẽ tự thực hành nhiều hơn, code nhiều hơn để có thể nhớ và nắm vững kiến thức. Lý thuyết thì khó nhớ nhưng chỉ cần các bạn tự code lại, thực hành lại thì sẽ hiểu ngay. Chớ nên copy code rồi debug ra màn hình emulator rồi tự khâm phục mình giỏi nhé ^^

Chúc các bạn may mắn. Hẹn gặp lại trong các bài tiếp theo

>>>Bài 6: Làm quen với một số kiểu lập trình sự kiện trong android

Thứ Bảy, 21 tháng 6, 2014

Bài 4: Vòng đời của một ứng dụng Android

     Trong phần này, mình và các bạn sẽ cùng đi tìm hiểu về các khái niệm vòng đời của một ứng dụng trong android. Chúng ta sẽ cùng nghiên cứu về các khái niệm sau:
     + Applications
     + Activities
     + Activity Stack
     + Task
     + Life Cycle

1. Applications là gì ?
     - Các bạn có thể hiểu một cách ngắn gọn rằng: Một Android project khi được biên dịch thành công sẽ được đóng gói thành một tệp .apk và tệp .apk này chính là một Application. Với tệp .apk này bạn có thể cài đặt trên emulator hoặc trên chính chiếc điện thoại thông minh của bạn.

2. Activities là gì ?
     - Nói chung một Application sẽ có một hoặc nhiều Activity (đại khái là màn hình tương tác của bạn với chương trình). Mỗi một Activity này sẽ có một vòng đời riêng độc lập với các Activity khác, cho nên, các bạn phải nắm chắc về vòng đời của các Activity. Chúng ta sẽ tìm hiểu trong phần sau.
     - Activity nếu muốn được gọi ra thì phải được khai báo trong file AndroidManifest.xml. Cái này thì bài tước mình cũng đề cập tới rồi.

3. Activity Stack là gì ?
     - Cũng giống với các ngôn ngữ lập trình khác, Activity Stack hoạt động dựa theo cơ chế LIFO(LAST IN FIRST OUT). Các bạn có thể hiểu Stack như là một ngăn xếp các quyển sách, với việc quyển đầu tiên được đặt dưới cùng ngăn xếp. Các quyển sách tiếp theo được đặt lên trên quyển sách đó và tương tự. Khi lấy ra thì phải lấy lần lượt từ trên xuống dưới, có nghĩa là quyển nào xếp vào sau cùng thì lấy ra trước. Đó chính là LIFO đó.
     - Vì vậy, mỗi một Android Activity khi được triệu gọi sẽ được mở bên trên Activity trước đó. Bạn có thể trể về với Activity cũ với nút Back của điện thoại hoặc code lệnh

     - Các bạn lưu ý có 2 kiểu mở Activity mới nhé:
          + Mở Activity mới che khuất toàn bộ Activity cũ => Sẽ xảy ra các sự kiện onPause rồi onStop với Activity cũ.
           + Mở Activity mới chỉ che khuất một phần của Activity cũ => Sảy ra sự kiện onPause đối với Activity cũ.
      - Khi muốn quay trở lại Activity cũ thì chúng ta phải gọi hàm onResume để phục hồi lại trạng thái ứng dụng. Nói chung vấn đề này sẽ được mình đề cập tới trong các bài tiếp theo. Các bạn hiện tại chỉ cần ghi nhớ vậy là được. Lý thuyết hơi nhọc một tí

4. Tasks là gì?
      - Tasks có thể hiểu nôm na là khả năng thực thi một công việc nào đó của ứng dụng, cụ thể là của các Activity.
      - Ví dụ như khi bạn muốn viết một ứng dụng gọi điện thoại, bạn cần phải triệu gọi tới Activity của ứng dụng danh bạ. Sau khi lấy xong sẽ trả về dữ liệu và quay về ứng dụng của bạn. Đó là một Task trong chương trình của bạn.

5. Life Cycle States (Trạng thái vòng đời )
     - Mỗi Activity thường vòng đời có 3 trạng thái (states) như sau:
          +Running (Đang chạy, đang kích hoạt)
          +Paused (tạm dừng)
          +Stopped (dừng - không phải Destroyed đâu nhé)

           - Bạn lưu ý khi Activity trong trạng thái Stopped Paused thì đều có khả năng bị Destroyed(hủy) khi bộ nhớ ưu tiên cần cho việc khác.

6.Visible Lifetime Foreground Lifetime
     - Visible Lifetime: Sẽ xảy ra từ sau khi onStart -> gọi onStop. Trong thời gian này, các bạn vẫn có thể thấy màn hình Activity (Nhưng chỉ tương tác được khi trong vòng Foreground Lifetime, sẽ không tương tác được nếu ở ngoài vòng này)
     - Foreground Lifetime: Sảy ra từ khi gọi onResume -> gọi onPause: Trong thời gian này, các bạn có thể tương tác thoải mái và Activity luôn ở trên cùng.

Về cơ bản thì lý thuyết là vậy, các bạn cố gắng nhớ những điều này vì sau này sẽ áp dụng vào việc code của bạn. Hẹn gặp lại các bạn ở bài tập sau

>>>Bài 5: Các loại layout trong Android

Giải quyết vấn đề với Fragment Layout

     Trong phiên bản mới ( từ phiên bản 22.6.x) các bạn sẽ gặp phải một điều khó chịu khi tạo ra một android project mới. Đó là việc tạo ra thêm một fragment Layout và một folder appcompat_v7. Điều này sẽ làm rắc rối cho chúng ta trong quá trình học tập và thường sẽ gây rối loạn phần code. Sau đây mình xin hướng dẫn cách khắc phục vấn đề này và các bạn sẽ sử dụng xuyên xuốt trong quá trình ghé thăm blog của mình.



- Sau khi tạo một project mới, bạn xem trong Package Explorer, mở phần res / layout. Mở file activity_main.xml và file fragment_main.xml. Ở file fragment_main.xml, các bạn chuyển qua tab fragment_main.xml ở dưới cùng nhé. Copy toàn bộ code ở trong file này và copy vào phần code của file activity_main.xml rồi save lại
- Sau đó chuột phải vào file fragment_main.xml rồi chọn delete. Xóa hẳn file này đi sẽ có báo lỗi ở file MainActivity.java. Không cần lo lắng mở file MainActivity.java lên và xóa đi tất cả các hàm sau trong file này: onCreateOptionsMenu, onOptionsItemSelected, PlaceholderFragment. Trong hàm onCreate xóa toàn bộ khung if đi để lại 2 dòng:
-Như vậy, các bạn đã sửa xong project của mình. Sau này khi muốn code giao diện thì bạn mở file activity_main.xml. Muốn viết các thực thi chương trình thì vào phần MainActivity.java



Bài 3: Hướng dẫn tạo project trong android. Tìm hiểu cấu trúc các thành phần của một project android.



      Ở bài trước, các bạn đã tìm hiểu cách tạo và sử dụng máy ảo android và DDMS. Trong bài này, chúng ta sẽ cùng tìm hiểu cách tạo ra một project android và xem các thành phần bên trong của nó.

      1.Cách tạo project mới: Các bạn mở eclipse. Chọn Menu File / New / Android Application Project. Một cửa sổ mới hiện lên cho phép chúng ta lập một project mới.


Hướng dẫn tạo project trong android

      - Các bạn lưu ý rằng khi tạo ra một Anrdroid  Project mới thì nó sẽ xuất hiện ở khung Package Explorer bên tay trái. Nếu eclipse của bạn không hiện khung này thì các bạn có thể mở ra bằng cách: “Vào menu Windows / Show View / chọn Package Explorer
       - Các thông số như hình trên đã nhập gồm có:
            + Application Name: Tên ứng dụng do bạn nhập vào
            + Project Name: Mặc định giống với tên Application Name. Bạn cũng không cần thiết phải đổi
            + Package Name: Tên gói (Tự sinh ra khi nhập tên)
            + Minimum Required SDK: Bạn chọn API thấp nhất mà ứng dụng của bạn có thể cài đặt
            + Target SDK: Chọn API phù hợp nhất (Thường là chọn mới nhất)
      Nói chung, bạn có thể hiểu Minimum Required SDK là yêu cầu thấp nhất có thể khởi chạy chương trình của bạn. Rõ rang máy điện thoại có API thấp hơn  (cùi mía hơn) sẽ không thể chạy vì không đảm bảo yêu cầu tối thiểu của chương trình. Target SDK là API tương thích tốt nhất cho chương trình của bạn. Sau này có thể có API mới hơn do Google đưa ra nhưng tất nhiên là nó cũng support cho các API cũ rồi. Bạn cũng không phải suy nghĩ nhiều về vấn đề này. Cứ để anh Google giúp bạn.
      -Tiếp theo, bạn cứ bấm Next hết và finish nhé. Những cái này chưa cần thiết phải quan tâm đến vào lúc đầu. Để sau này quay lại tìm hiểu sau cũng chưa muộn.
Vậy là các bạn đã tạo ra được một Android Project rồi đấy. Tiếp theo chúng ta cùng tìm hiểu về các thành phần của một project

      2. Cấu trúc các thành phần bên trong của một Android Project:
Hướng dẫn tạo project trong android

      -Với bộ SDK mới của Google, việc tạo mới một Android Project sẽ sinh ra thêm một folder appcompat_v7. Bạn có thể quan sát trong  Package Explorer của mình. Các bạn cần nắm rõ về cấu trúc project để giúp bạn lập trình dễ dàng.
      -Khi một ứng dụng mới được tạo ra, thì sẽ có một Activity để khởi chạy ứng dụng. Các bạn hiểu nôm na một activity như một nền giao diện của chương trình mà bạn thao tác và thực hiện các công việc. Ở đây sẽ sinh ra 3 file: MainActivity.java , activity_main.xmlfragment_main.xml. File MainActivity.java sẽ chính là class chứa toàn bộ source code thực hiện một hay nhiều công việc nào đó mà bạn muốn. 2 file xml còn lại chính là giúp thiết kế giao diện cho chương trình của bạn. Thực ra với bản mới này, việc tạo ra fragment_main.xml sẽ gây khó chịu tới người lập trình. Ở bài sau mình sẽ hướng dẫn các bạn xóa file này đi.
      -Bất kỳ một Activity nào của ứng dụng muốn được triệu gọi ra thì phải được khai báo trong tập tin Android Manifest.xml. Nếu không khai báo thì đơn giản là lỗi chương trình thôi, không xài được.
      -Dưới đây là một cấu trúc của file AndroidManifest.xml. Click đúp vào file AndroidManifest.xml trong Package Exlorer và chọn tab AndroidManifest.xml ở màn hình soạn thảo như sau
Hướng dẫn tạo project trong android

      -Tiếp theo, bạn mở file activity_main.xmlđể xem xét
Hướng dẫn tạo project trong android
      +Bạn có thể thấy một khung hình chương trình hiện ra với một chuỗi ký tự  “HelloWorld” mặc định trong project.
      +Bên tay trái là bảng Palette. Đây là bảng chứa đầy đủ các View để thiết kế chương trình. Bạn có thể kéo thả từng View này vào trong khung chương trình để thử xem cho vui. Sau này khi code bạn phải học cách tự code cho nó chuyên nghiệp, vì không ai dùng kéo thả đâu.
      +Bên tay phải là Properties thuộc tính của từng View. Hiện tại đang hiển thị là thuộc tính của container(FrameLayout). Chỗ này giúp bạn tinh chỉnh các thuộc tính như dài rộng, màu chữ, font…
      -Tiếp theo bạn mở thư mục gen trong Package Explorer và mở tập tin R.java lên để coi xem ra sao. Cứ thoải mái mà làm tới đi bạn, sợ gì đâu. Nhỡ có làm gì sai thì xóa project đi tạo project khác ^^
Hướng dẫn tạo project trong android

      Phù, mới tạo Project và ngồi coi thôi mà đã có một đống thứ thế này. Nhìn cũng hoa cả mắt. Nhưng các bạn cứ yên tâm đi. Đây là code tự sinh ra thôi, và các bạn không cần phải sửa chữa cái gì của nó. Thư gen này do Android tự động tạo ra , và dù bạn có xóa thì nó cũng lại tạo ra. Tất cả nhũng gì bạn thiết lập giao diện, kéo thả….. đủ các thể loại đều được sinh ra và chứa trong file R.java này. File này về sau giúp bạn truy suất các đối tượng trong code.
      -Còn một vài file khác, các bạn tự tìm hiểu thêm, để tăng tính tự lập cho chính mình nhé. Tìm hiểu thêm cách build một chương trình android như thế nào.
      Hẹn gặp lại các bạn ở trong bài tập tiếp theo nhé !

 >>>Bài 4: Vòng đời của một ứng dụng Android

Bài đăng phổ biến