Hướng dẫn lập trình Android cho người mới bắt đầu - Các ví dụ cơ bản
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- Giới thiệu

Tài liệu được viết dựa trên:
  • Android Studio 1.4

Bạn đang xem loạt bài hướng dẫn lập trình Android, đây là bài hướng dẫn thứ 2, trong tài liệu này tôi sẽ hướng dẫn bạn từng bước xây dựng một ứng dụng Android, các kiến thức cơ bản sẽ được đề cập bao gồm:
  1. Gọi Activity từ một Activity khác.
  2. Sử lý sự kiện cơ bản.
  3. Xây dựng giao diện cơ bản, và làm việc với nguồn dữ liệu.
     
Trước khi bắt đầu với tài liệu này, hãy đảm bảo rằng bạn đã chạy thành công ví dụ "Hello Android" và hiểu về cấu trúc một dự án Android. Bạn có thể xem tại:

2- Tạo project Android

Nếu bạn đang làm việc với một project Android trên Android Studio, hãy đóng project này lại, chúng ta sẽ tạo mới một project khác.
Trên Android Studio chọn:
  • File/Close Project
Tạo mới một project:
Nhập vào:
  • Application name: AndroidBasic2
  • Company Domain: o7planning.org
Ứng dụng đang tạo sẽ được sử dụng cho Phone và Tablet, chọn Minimum SDK mặc định.

Chú ý: API 15, Android 4.0.3 hiện tại đang được sử dụng trên hầu hết các thiết bị Phone và Table (Khoảng 94%).

Tiếp theo Wizard sẽ hỏi bạn có muốn tạo một Activity nào không, chọn "Add No Activity", wizard sẽ sẽ chỉ tạo một project rỗng, không bao gồm một Activity nào cả.
Project của bạn đã được tạo ra.

3- Tạo MainActivity và các Activity con

Chúng ta sẽ tạo một Activity chính ( MainActivity), Activity này sẽ được gọi khi ứng dụng được chạy. Trên MainActivity sẽ có các button gọi tới các Activity khác.
Trên Android Studio chọn:
  • File/New/Activity/Empty Activity
MainActivity đã được tạo ra, gồm 2 file MainActivity.javamain_activity.xml, thông tin của Activity này cũng đã được đăng ký với AndroidManifest.xml.
Tương tự như vậy chúng ta tạo thêm 5 Activity khác.
  1. Example1Activity
  2. Example2Activity
  3. Example3Activity
  4. Example4Activity
  5. Example5Activity
Trên Android Studio chọn:
  • File/New/Activity/Empty Activity

Chú ý: Tất cả các Activity vừa tạo mới không phải là một Activity chính, nó được gọi từ MainActivity, vì vậy bạn không nên check vào "Launcher Activity".

OK, 5 Activity mới đã được tạo ra, và chúng đã được đăng ký với AndroidManifest.xml.

4- MainActivity - Thiết kế giao diện

Mở activity_main.xml để thiết kế giao diện cho MainActivity:
Màn hình thiết bị mặc định sử dụng RelativeLayout để sắp xếp các thực thể (widget) trên giao diện. Bạn cần xóa bỏ Layout này, và thay bởi một Layout khác, hoặc add một Layout khác như một thực thể con.

LinearLayout kiểu Vertical sắp xếp các thực thể  theo dòng (row), mỗi thực thể nằm trên một row.
  • LinearLayout (Vertical):
  • LinearLayout (Horizontal):
Trên màn hình thiết kế, kéo đối tượng LinearLayout (Vertical) vào như thực thể con của RelativeLayout.
Kéo thả 5 button vào màn hình giao diện, các button này sẽ sắp xếp trên 5 dòng liên tiếp của LinearLayout.
Kéo chiều rộng của các button cho đầy chiều rộng của LinearLayout.
Mỗi button bạn vừa kéo thả vào giao diện, code được tạo ra trên file xml, trên Java chúng có thể được truy cập thông qua ID. Chính vì vậy mỗi button bạn cần phải khai báo ID cho chúng. Nhấn kép chuột vào button:
Nhập vào:
  • Resource name: go_button1_title
  • Resource value: Go to Example1 Activity
  • Ở trên bạn đã khai báo một button có ID = go_button1, trên mã Java bạn có thể truy cập vào button này bởi hằng số R.id.go_button1 (Sẽ được đề cập trong bài viết này).
  • R là một java class được tự động tạo ra bởi công cụ biên dịch, tôi đã giải thích về class này trong hướng dẫn đầu tiên về Android (Hello Android).
Tương tự bạn sét đặt ID và tiêu đề cho các button khác như hình minh họa dưới đây:
Bạn có thể chuyển sang Tab "Text" để thấy mã XML đã được tạo ra.
  • activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="org.o7planning.androidbasic2.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/go_button1_title"
            android:id="@+id/go_button1"
            android:layout_gravity="center_horizontal" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/go_button2_title"
            android:id="@+id/go_button2"
            android:layout_gravity="center_horizontal" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/go_button3_title"
            android:id="@+id/go_button3"
            android:layout_gravity="center_horizontal" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/go_button4_title"
            android:id="@+id/go_button4"
            android:layout_gravity="center_horizontal" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/go_button5_title"
            android:id="@+id/go_button5"
            android:layout_gravity="center_horizontal" />
    </LinearLayout>

</RelativeLayout>
Mở file string.xml bạn sẽ thấy mã XML cũng được tự động sinh ra. 
Chạy thử ứng dụng:

5- Gọi một Activity từ một Activity

Ở đây chúng ta sẽ sử lý các sự kiện click vào các Button, chúng sẽ gọi đến các Example1Activity, .. Example5Activity tương ứng.
Các Activity nói chuyện với nhau thông qua một đối tượng Intent. Ví dụ Activity1 muốn gọi Activity2 chạy, nó đóng gói những gì cần nói, và lời yêu cầu vào một đối tượng Intent và gửi đối tượng Intent này tới Activity2. Bạn có thể xem hình minh họa dưới đây.
Mở class MainActivity, trên code Java bạn có thể lấy được đối tượng Button thông qua ID của chúng.
// Lấy ra button theo ID
Button button1 = (Button) this.findViewById(R.id.go_button1);

// Sét đặt sự kiện Click vào Button1.
button1.setOnClickListener(new Button.OnClickListener() {

  @Override
  public void onClick(View v) {

      // Tạo một Intent:
      // (Mang nội dung sẽ gửi tới Example1Activity).
      Intent myIntent = new Intent(MainActivity.this, Example1Activity.class);

      // Các tham số gắn trên Intent (Không bắt buộc).
      myIntent.putExtra("text1", "This is text");
      myIntent.putExtra("text2", "This is long text");

      // Yêu cầu chạy Example1Activity.
      MainActivity.this.startActivity(myIntent);
  }
});
Code đầy đủ của MainActivity.java:
  • MainActivity.java
package org.o7planning.androidbasic2;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

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

       // Lấy ra button theo ID
       Button button1 = (Button) this.findViewById(R.id.go_button1);

       // Sét đặt sự kiện Click vào Button1.
       button1.setOnClickListener(new Button.OnClickListener() {

           @Override
           public void onClick(View v) {

               // Tạo một Intent:
               // (Mang nội dung sẽ gửi tới Example1Activity).
               Intent myIntent = new Intent(MainActivity.this, Example1Activity.class);

               // Các tham số gắn trên Intent (Không bắt buộc).
               myIntent.putExtra("text1", "This is text");
               myIntent.putExtra("text2", "This is long text");

               // Yêu cầu chạy Example1Activity.
               MainActivity.this.startActivity(myIntent);
           }
       });


       // Lấy ra button theo ID
       Button button2 = (Button) this.findViewById(R.id.go_button2);

       // Sét đặt sự kiện Click vào Button2.
       button2.setOnClickListener(new Button.OnClickListener() {

           @Override
           public void onClick(View v) {

               // Tạo một Intent:
               // (Mang nội dung sẽ gửi tới Example2Activity).
               Intent myIntent = new Intent(MainActivity.this, Example2Activity.class);

               // Yêu cầu chạy Example2Activity.
               MainActivity.this.startActivity(myIntent);
           }
       });


       // Lấy ra button theo ID
       Button button3 = (Button) this.findViewById(R.id.go_button3);

       // Sét đặt sự kiện Click vào Button3.
       button3.setOnClickListener(new Button.OnClickListener() {

           @Override
           public void onClick(View v) {

               // Tạo một Intent:
               // (Mang nội dung sẽ gửi tới Example3Activity).
               Intent myIntent = new Intent(MainActivity.this, Example3Activity.class);

               // Yêu cầu chạy Example3Activity.
               MainActivity.this.startActivity(myIntent);
           }
       });



       // Lấy ra button theo ID
       Button button4 = (Button) this.findViewById(R.id.go_button4);

       // Sét đặt sự kiện Click vào Button4.
       button4.setOnClickListener(new Button.OnClickListener() {

           @Override
           public void onClick(View v) {

               // Tạo một Intent:
               // (Mang nội dung sẽ gửi tới Example2Activity).
               Intent myIntent = new Intent(MainActivity.this, Example4Activity.class);

               // Yêu cầu chạy Example4Activity.
               MainActivity.this.startActivity(myIntent);
           }
       });



       // Lấy ra button theo ID
       Button button5 = (Button) this.findViewById(R.id.go_button5);

       // Sét đặt sự kiện Click vào Button5.
       button5.setOnClickListener(new Button.OnClickListener() {

           @Override
           public void onClick(View v) {

               // Tạo một Intent:
               // (Mang nội dung sẽ gửi tới Example5Activity).
               Intent myIntent = new Intent(MainActivity.this, Example5Activity.class);

               // Yêu cầu chạy Example5Activity.
               MainActivity.this.startActivity(myIntent);
           }
       });
   }
}

6- Example1Activity - Ví dụ nhận Intent và sử lý sự kiện

Tiếp theo mở activity_example1.xml chúng ta sẽ thiết kế giao diện cho Example1Activity
Kéo thả các đối tượng Large Text, Medium TextButton vào màn hình giao diện.
Nhấn kép chuột vào đối tượng Large Text để sét đặt ID cho nó, ở đây tôi đặt ID là my_text1
Tương tự sét đặt ID cho đối tượng Medium Textmy_text2
Sét tiêu đề cho Button là "Click me" và ID là my_button1
Example1Activity được gọi từ MainActivity, nó nhận được đối tượng Intent truyền sang từ MainActivity, phương thức onCreate() của Example1Activity sẽ được gọi, tại đây bạn cần phân tích các dữ liệu trong Intent.
Sửa code class Example1Activity:
  • Example1Activity.java
package org.o7planning.androidbasic2;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


public class Example1Activity extends AppCompatActivity {

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

       Intent intent = getIntent();

       // Tham số trong Intent truyền sang từ MainActivity
       String value1 = intent.getStringExtra("text1");


       // Tham số trong Intent truyền sang từ MainActivity
       String value2 = intent.getStringExtra("text2");

       // Lấy ra đối tượng trên giao diện bởi ID của nó.
       final TextView text1 = (TextView)this.findViewById(R.id.my_text1);

       // Lấy ra đối tượng trên giao diện bởi ID của nó.
       final TextView text2 = (TextView)this.findViewById(R.id.my_text2);

       text1.setText(value1);
       text2.setText(value2);

       Button button = (Button)this.findViewById(R.id.my_button1);

       // Sử lý sự kiện khi click vào Button.
       button.setOnClickListener(new Button.OnClickListener() {

           @Override
           public void onClick(View v) {
               text1.setText("You click button");
           }
       });

       // Sử lý sự kiện khi click vào Button và giữ lâu.
       button.setOnLongClickListener(new Button.OnLongClickListener() {


           // return true if the callback consumed the long click, false otherwise.
           @Override
           public boolean onLongClick(View v) {
               text2.setText("You long click button");
               return true;
           }
       });

   }
}
Chạy lại ứng dụng của bạn (Xem Slider):

7- Example2Activity - Ví dụ với các sự kiện cử chỉ (Gesture)

Trong ví dụ này tôi sẽ hướng dẫn sử lý các sự kiện liên quan tới cử chỉ. Android có xây dựng sẵn class GestureDetector (Tạm dịch: bộ dò cử chỉ), class này có 3 interface Listener:
  • GestureDetector.OnGestureListener
  • GestureDetector.OnDoubleTapListener
  • GestureDetector.OnContextClickListener
GestureDetector.SimpleOnGestureListener is class that implements 3 interfaces above, with the implementation methods do nothing.
Interface lắng nghe Mô tả
GestureDetector.OnGestureListener Bộ lắng nghe (Listener) này được sử dụng để thông báo khi có một cử chỉ khi xảy ra. Nếu bạn muốn nghe cho tất cả những cử chỉ khác nhau hãy thi hành interface này. Nếu bạn chỉ muốn nghe cho một tập hợp con các cử chỉ bạn có thể viết class mở rộng class GestureDetector.SimpleOnGestureListener.
GestureDetector.OnDoubleTapListener Bộ lắng nghe (Listener) này được sử dụng để thông báo khi có một cú chạm kép (double-tap) hoặc một cú chạm đơn (single-tap) xẩy ra.
GestureDetector.OnContextClickListener Bộ lắng nghe (listener) được sử dụng để thông báo khi một bối cảnh nhấp chuột (context-click) xảy ra. Khi nghe một bối cảnh nhấp chuột đảm bảo rằng bạn gọi onGenericMotionEvent (MotionEvent) trong View.onGenericMotionEvent (MotionEvent).
Các phương thức:
OnGestureListener
boolean onDown(MotionEvent e); Thông báo khi một cú chạm xuống xảy ra, MotionEvent kích hoạt nó. Nó sẽ được kích hoạt ngay lập tức cho mỗi sự kiện xuống. Tất cả các sự kiện khác sẽ xẩy ra trước điều này.
  • @param e Các sự kiện chuyển động xuống.
void onShowPress(MotionEvent e);

 
Người dùng đã thực hiện một thao tác xuống (down), MotionEvent, và không được thực hiện một động thái hay lên (up). Sự kiện này thường được sử dụng để cung cấp thông tin phản hồi trực quan cho người sử dụng để cho họ biết rằng hành động của họ đã được biết tới tức là làm nổi bật một phần tử (element) (Phần tử bị tác động).
  • @param e Sự kiện xuống chuyển động...
boolean onSingleTapUp(MotionEvent e);

 
Thông báo khi một cú chạm lên xảy ra, MotionEvent kích hoạt nó.
  • @param e Các sự kiện chuyển động lên hoàn thành cú chạm đầu tiên
  • @return true nếu sự kiện này được tiêu thụ (consumed), ngược lại trả về false.
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);

 
Thông báo khi có sự kiện cuộn, ban đầu là hành động chạm xuống sau đó là di chuyển (quẹt) Các khoảng cách x và y cũng được cung cấp đầy đủ.
 
  • @param e1 sự kiện lần đầu chạm xuống, bắt đầu của cuộn.
  • @param e2 sự kiện di chuyển được bẫy bởi onScroll hiện tại.
  • @param distanceX khoảng cách dọc theo trục X đã cuộn từ lần gọi cuối của onScroll. Nó không phải là khoảng cách giữa e1 và e2.
  • @param distanceY khoảng cách dọc theo trục Y đã cuộn từ lần gọi cuối của onScroll. Nó không phải là khoảng cách giữa e1 và e2.
  • @return true nếu sự kiện này được tiêu thụ (consumed), ngược lại trả về false.
void onLongPress(MotionEvent e);

 
Thông báo khi có một cú nhấn lâu (long press) xẩy ra, khởi tạo ban đầu là cú chạm xuống bị bắt bởi  MotionEvent.
  • @param e Cú chạm xuống đầu tiên, bắt đầu cho sự kiến nhấn lâu.
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);

 
Thông báo về một sự kiện liệng (fling) khi nó xảy ra với ban đầu là cú chạm xuống, quẹt và đi lên. Vận tốc tính toán được cung cấp dọc theo trục x và y theo số pixel trên mỗi giây.
  • @param e1 sự kiện chuyển động xuống đầu tiên bắt đầu quăng ra.
  • @param e2 sự kiện chuyển động di chuyển mà gây ra sự onFling hiện hành.
  • @param velocityX Vận tốc của fling này đo bằng pixel mỗi giây dọc theo trục x.
  • @param velocityY Vận tốc của fling này đo bằng pixel mỗi giây dọc theo trục y.
  • @return true nếu sự kiện này được tiêu thụ (consumed), ngược lại trả về false.
OnDoubleTapListener
boolean onSingleTapConfirmed(MotionEvent e); Không giống như OnGestureListener.onSingleTapUp(MotionEvent), điều này sẽ chỉ được gọi sau khi phát hiện chắc chắn rằng chú chạm đầu tiên của người dùng không được theo sau bởi một chú chạm thứ hai dẫn đến một cử chỉ nhấp đúp (double-tap).
  • @param e Các sự kiện chuyển động xuống các đơn tap.
  • @return true nếu sự kiện này được tiêu thụ, ngược lại trả về false.
boolean onDoubleTap(MotionEvent e);

 
Notified when a double-tap occurs.
  • @param e The down motion event of the first tap of the double-tap.
  • @return true if the event is consumed, else false
Thông báo khi có một cú chạm kép (double-tap) xảy ra.
  • @ param e Các sự kiện chuyển động xuống của cú chạm đầu tiên của cú chạm kép.
  •  @return true nếu sự kiện này được tiêu thụ, ngược lại trả về false
boolean onDoubleTapEvent(MotionEvent e);

 
Thông báo khi có một sự kiện chạm kép (double-tap) xảy ra, bao gồm cả xuống, di chuyển, và đi lên.
  • @param e Các sự kiện chuyển động xảy ra trong cử chỉ chạm kép (double-tap).
  • @return true nếu sự kiện này được tiêu thụ, ngược lại trả về false.
OnContextClickListener
boolean onContextClick(MotionEvent e); Thông báo khi có một bối cảnh nhấp chuột (context click) xảy ra.
  • @param e Các sự kiện chuyển động đã xảy ra trong bối cảnh nhấp chuột.
  • @return true nếu sự kiện này được tiêu thụ, ngược lại trả về false
Mở file activity_example2.xml:
Sét đặt ID cho 2 đối tượng Large Text lần lượt là my_text_evt1 my_text_evt2
Sử lý các sự kiện hành vi của người dùng trên Example2Acivity.
  • Example2Activity.java
package org.o7planning.androidbasic2;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

//@TargetApi(Build.VERSION_CODES.M)
public class Example2Activity extends AppCompatActivity  {

   private  TextView textEvt1;
   private  TextView textEvt2;

   private static final String TAG = "TestGesture";


   // Bộ dò cử chỉ của người dùng.
   private GestureDetector gestureDetector;

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

       this.textEvt1 = (TextView)this.findViewById(R.id.my_text_evt1);

       this.textEvt2 = (TextView)this.findViewById(R.id.my_text_evt2);

       GestureDetector.OnGestureListener gestureListener = new MyOnGestureListener();
       GestureDetector.OnDoubleTapListener doubleTapListener = new MyOnDoubleTapListener();


       // GestureDetectorCompat(Context context, OnGestureListener listener)
       this.gestureDetector= new GestureDetector(this, gestureListener);

       this.gestureDetector.setOnDoubleTapListener(doubleTapListener);


       // Lấy ra đối tượng View gốc (Toàn bộ màn hình điện thoại).
       View rootView = this.findViewById(android.R.id.content).getRootView();

       // Sét bộ lắng nghe cho các sự kiện chạm vào bề mặt điện thoại.
       rootView.setOnTouchListener(new View.OnTouchListener() {
           public boolean onTouch(View v, MotionEvent me) {
               return gestureDetector.onTouchEvent(me);
           }
       });

       Log.e(TAG,"Running...");
   }


   class MyOnGestureListener implements GestureDetector.OnGestureListener  {

       @Override
       public boolean onDown(MotionEvent e) {
           textEvt1.setText("onDown");
           textEvt2.setText(e.getX()+":"+ e.getY());
           Log.e(TAG, "onDown");
           return true;
       }

       @Override
       public void onShowPress(MotionEvent e) {
           textEvt1.setText("onShowPress");
           textEvt2.setText(e.getX()+":"+ e.getY());
           Log.e(TAG, "onShowPress");
       }

       @Override
       public boolean onSingleTapUp(MotionEvent e) {
           textEvt1.setText("onSingleTapUp");
           textEvt2.setText(e.getX()+":"+ e.getY());
           Log.e(TAG, "onSingleTapUp");
           return true;
       }

       @Override
       public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
           textEvt1.setText("Scroll");
           textEvt2.setText(e1.getX()+":"+ e1.getY() +"  "+ e2.getX()+":"+ e2.getY());
           Log.e(TAG, "onScroll");
           return true;
       }

       @Override
       public void onLongPress(MotionEvent e) {
           textEvt1.setText("onLongPress");
           textEvt2.setText(e.getX()+":"+ e.getY());
           Log.e(TAG, "onLongPress");
       }

       @Override
       public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
           textEvt1.setText("onFling");
           textEvt2.setText(e1.getX() + ":" + e1.getY() + "  " + e2.getX() + ":" + e2.getY());
           Log.e(TAG, "onFling");
           return true;
       }


   }

   class MyOnDoubleTapListener implements GestureDetector.OnDoubleTapListener {

       @Override
       public boolean onSingleTapConfirmed(MotionEvent e) {
           textEvt1.setText("onSingleTapConfirmed");
           textEvt2.setText(e.getX()+":"+ e.getY());
           Log.e(TAG, "onSingleTapConfirmed");
           return true;
       }

       @Override
       public boolean onDoubleTap(MotionEvent e) {
           textEvt1.setText("onDoubleTap");
           textEvt2.setText(e.getX()+":"+ e.getY());
           Log.e(TAG, "onDoubleTap");
           return true;
       }

       @Override
       public boolean onDoubleTapEvent(MotionEvent e) {
           textEvt1.setText("onDoubleTapEvent");
           textEvt2.setText(e.getX() + ":" + e.getY());
           Log.e(TAG, "onDoubleTapEvent");
           return true;
       }
   }


}
Chạy lại ứng dụng của bạn (Xem Slider):

8- Example3Activity - Sử dụng fragment

Để thiết kế một giao diện, bạn có thể thiết kế nhiều mảnh (fragment) và ghép lại với nhau. Trong ví dụ này tôi sẽ hướng dẫn bạn làm việc với fragment.
Và sử lý sự kiện tương tác giữa 2 fragment.
Chuẩn bị một file ảnh, chẳng hạn andrea.jpg.
  • andrea.jpg
Copy và paste file andrea.jpg vào thư mục mipmap của project.
Android Studio sẽ bắt bạn chọn chất lượng ảnh sẽ được tạo ra. Chọn mipmap-mdpi đây là các ảnh với chất lượng trung bình.
Tiếp theo chúng ta tạo file activity_example3_top.xml:
Trên Android Studio chọn:
  • File/New/Layout resource file
Nhập vào:
  • File name: activity_example3_top.xml
  • Root element: RelativeLayout
  • Directory name: layout
Tương tự tạo file activity_example3_bottom.xml

Thiết kế giao diện trên activity_example3_top.xml

Thay đổi các thuộc tính cho EditText bạn vừa kéo thả vào màn hình.
  • layout:width: match_parent
  • layout:margin
    • left: 10dp
    • top: 15dp
    • right: 10dp
  • layout:centerInParent: horizontal
Tương tự kéo thả một đối tượng EditText khác vào màn hình.
Kéo thả một Button vào màn hình.
Sét đặt ID cho các đối tượng bạn vừa kéo thả vào màn hình.
  • input_top_image_text
  • input_bottom_image_text
  • button_apply
  • activity_example3_top.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">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/input_top_image_text"
        android:layout_alignParentTop="true"
        android:layout_marginTop="15dp"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/input_bottom_image_text"
        android:layout_below="@+id/input_top_image_text"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="15dp"
        android:layout_marginRight="10dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Apply"
        android:id="@+id/button_apply"
        android:layout_below="@+id/input_bottom_image_text"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

Thiết kế giao diện trên activity_example3_bottom.xml

Chọn background:
Kéo thả tiếp 2 đối tượng Large Text vào phía trên và phía dưới của màn hình.
Thay đổi các thuộc tính cho 2 đối tượng Text:
  • layout:width: match_parent
  • gravity
    • center_horizontal: checked
  • textColor: #fff
Sét ID cho 2 đối tượng text:
  • top_image_text
  • bottom_image_text
  • activity_example3_bottom.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"
    android:background="@mipmap/andrea">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/top_image_text"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal"
        android:textColor="#fff" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/bottom_image_text"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:textColor="#fff"
        android:gravity="center_horizontal" />

</RelativeLayout>
Mỗi Fragment sẽ tương ứng với một Java class. Class này mở rộng từ class Fragment.
Tạo 2 class Example3TopFragmentExample3BottomFragment và sửa code của nó.
  • Example3TopFragment.java
package org.o7planning.androidbasic2;
 
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Example3TopFragment extends Fragment {
 
    private Example3Activity example3Activity;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // Đọc file xml tạo ra đối tượng View.

        // inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
         
        View view= inflater.inflate(R.layout.activity_example3_top, container, false);
        return view;
    }

}
  • Example3BottomFragment.java
package org.o7planning.androidbasic2;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Example3BottomFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // Đọc file xml tạo ra đối tượng View.
        // inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
        View view= inflater.inflate(R.layout.activity_example3_bottom, container, false);
        return view;
    }

}
Và bây giờ, bạn cần bố trí các fragment trên giao diện chính của Activity. Mở file activity_example3.xml
Chọn Example3TopFragment:
Tiếp theo kéo thả Example3BottomFragment vào màn hình chính.
Kéo để thay đổi kích thước Example3BottomFragment.
Thay đổi ID cho các fragment.
  • example3_top_fragment
  • example3_bottom_fragment
OK, bây giờ bạn cần phải sửa đổi code của 3 class Example3Activity, Example3TopFragment, Example3BottomFragment để sử lý các sự kiện
  • Example3Activity.java
package org.o7planning.androidbasic2;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class Example3Activity extends AppCompatActivity {

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

    }


    public void showText(String topImageText, String bottomImageText)  {
         Example3BottomFragment bottomFragment
                 = (Example3BottomFragment) this.getSupportFragmentManager()
                          .findFragmentById(R.id.example3_bottom_fragment);
        bottomFragment.showText(topImageText, bottomImageText);
    }
}
  • Example3TopFragment.java
package org.o7planning.androidbasic2;


import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

public class Example3TopFragment extends Fragment {

   private EditText inputTopImageText;
   private EditText inputBottomImageText;

   private Example3Activity example3Activity;


   @Nullable
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

       // Đọc file xml tạo ra đối tượng View.
       // inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
       View view= inflater.inflate(R.layout.activity_example3_top, container, false);

       inputTopImageText = (EditText)view.findViewById(R.id.input_top_image_text);
       inputBottomImageText = (EditText)view.findViewById(R.id.input_bottom_image_text);

       Button applyButton = (Button) view.findViewById(R.id.button_apply);

       applyButton.setOnClickListener(new View.OnClickListener() {

           @Override
           public void onClick(View v) {
               applyText();
           }
       });

       return view;
   }

   // Phương thức này được gọi sau khi Fragment được
   // ghép vào Activity.
   @Override
   public void onAttach(Context context) {
       super.onAttach(context);

       if(context instanceof Example3Activity)  {
           this.example3Activity= (Example3Activity) context;
       }
   }


   private void applyText()  {
       String topText = this.inputTopImageText.getText().toString();
       String bottomText = this.inputBottomImageText.getText().toString();

       this.example3Activity.showText(topText, bottomText);
   }
}
  • Example3BottomFragment.java
package org.o7planning.androidbasic2;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class Example3BottomFragment extends Fragment {

   private TextView topText;
   private TextView bottomText;

   @Nullable
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

       // Đọc file xml tạo ra đối tượng View.
       // inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
       View view= inflater.inflate(R.layout.activity_example3_bottom, container, false);

       topText = (TextView) view.findViewById(R.id.top_image_text);
       bottomText = (TextView) view.findViewById(R.id.bottom_image_text);

       return view;
   }


   public void showText(String topImageText, String bottomImageText)  {
       topText.setText(topImageText);
       bottomText.setText(bottomImageText);
   }
}
Chạy ứng dụng (Xem Slider):

9- Example4Activity - Sử dụng Menu

Trong ví dụ này tôi sẽ hướng dẫn bạn làm việc với Menu, và sử lý các sự kiện khi bạn click vào 1 MenuItem. Một ví dụ đơn giản Menu gồm 3 MenuItem (Red, Green, Blue) khi bạn click vào các MenuItem màn hình sẽ đổi mầu nền tương ứng.
Nhấn phải chuột vào res chọn
  • New/Android resource file
Nhập vào:
  • File name: activity_example4_menu
  • Resource type: Menu
OK, file resource đã được tạo ra. File này là nơi bạn khai báo Menu sẽ hiển trên activity. Hiện tại nó chưa được chỉ định sẽ hiển thị trên Activity nào.

Nhấn vào biểu tượng Menu trên màn hình Preview, chọn "Associate with other activity" để liên hợp Menu này với một Activity.
Code XML đã được tự động tạo ra.
Thật đáng tiếc Android Studio phiên bản 1.4 không hỗ trợ bạn thiết kế Menu một cách trực quan, vì vậy bạn cần phải viết code.
  • activity_example4_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   tools:context=".Example4Activity">



   <group android:checkableBehavior="single">

       <item
           android:id="@+id/menu_red"
           android:orderInCategory ="1"
           app:showAsAction="never"
           android:title="@string/menu_red_string" />

       <item
           android:id="@+id/menu_green"
           android:orderInCategory ="1"
           app:showAsAction="never"
           android:title="@string/menu_green_string" />

       <item
           android:id="@+id/menu_blue"
           android:orderInCategory ="1"
           app:showAsAction="never"
           android:title="@string/menu_blue_string" />

   </group>
</menu>
Có một vài thông báo lỗi xuất hiện trên code XML của activity_example4_menu.xml, nguyên nhân là bạn sử dụng một số string không có trong resource strings.xml.
Bạn cần đặt chuột vào các dòng chữ bị bôi đỏ để làm xuất hiện biểu tượng gợi ý sửa lỗi.
 
Bây giờ file XML đã không còn thông báo lỗi. Bạn cũng có thể nhìn thấy biểu tượng Menu xuất hiện trên màn hình điện thoại:
Mở file activity_example4.xml, nhấn kép chuột vào màn hình điện thoại, để sét đặt ID cho RelativeLayout.
Bạn cần viết mã trên class Example4Activity để sử lý các sự kiện liên quan tới Menu.
Bạn cần ghi đè 2 phương thức onCreateOptionsMenu(Menu)onOptionsItemSelected(MenuItem)
  • Example4Activity.java
package org.o7planning.androidbasic2;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RelativeLayout;

public class Example4Activity extends AppCompatActivity {

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

   @Override
  public boolean onCreateOptionsMenu(Menu menu) {
       // Read XML file to add MenuItem to menu.
       // Đọc file XML để thêm các MenuItem vào menu.
       this.getMenuInflater().inflate(R.menu.activity_example4_menu, menu);
       return true;
  }

   // Method này sử lý sự kiện khi MenuItem được chọn.
   @Override
   public boolean onOptionsItemSelected(MenuItem item)  {

       RelativeLayout rootView = (RelativeLayout)this.findViewById(R.id.root_view);
       int itemId = item.getItemId();

       switch(itemId)  {
           case R.id.menu_green :
               if(item.isChecked()) {
                   item.setChecked(false);
               }else {
                   item.setChecked(true);
               }
               rootView.setBackgroundColor(Color.GREEN);

               return true;
           case R.id.menu_red :
               if(item.isChecked()) {
                   item.setChecked(false);
               }else {
                   item.setChecked(true);
               }
               rootView.setBackgroundColor(Color.RED);

               return true;
           case R.id.menu_blue :
               if(item.isChecked()) {
                   item.setChecked(false);
               }else {
                   item.setChecked(true);
               }
               rootView.setBackgroundColor(Color.BLUE);

               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
   }
}
Và bây giờ bạn có thể chạy lại ứng dụng (Xem Slider):
  • SLIDER:

10- Hướng dẫn lập trình Android - Tiếp theo

OK, bạn có thể tiếp tục với tài liệu: