Bài tập 12: Ví dụ tổng hợp TextView, EditText, CheckBox, Button và ImageButton trong Android


Trong bài tập 10 và bài tập 11 bạn đã làm quen được với các control này. Trong bài tập 12 Tôi sẽ làm một ví dụ tổng hợp + kết hợp với ArrayList để bạn củng cố thêm kiến thức về các control đã học.

– Viết chương trình thanh toán tiền bán sách (bạn đừng quan tâm là chương trình này nó có được ứng dụng thực tế hay không, hãy quan tâm cách viết code để hiểu thêm về các control):

12_th_0

–  Mô tả yêu cầu:

  • Khi bấm nút Tính Thành Tiền (Tính TT) chương trình sẽ tính thành tiền biết rằng mỗi cuốn sách có đơn giá là 20000, nếu là khách hàng VIP thì giảm 10%
  • Khi bấm nút Tiếp, chương trình sẽ lưu thông tin hóa đơn vừa tính Thành Tiền vào danh sách, đồng thời xóa trắng dữ liệu trong hóa đơn và cho focus tới EditText Tên khách hàng
  • Khi bấm nút Thống kê, chương trình sẽ hiển thị thông tin vào mục Thông tin thống kê: tổng số KH, tổng số KH VIP và tổng doanh thu
  • Khi bấm vào nút thoát (dùng ImageButton): hiển thị AlertDialog hỏi xem người sử dụng có chắc chắn muốn thoát hay không?
  • Dùng ScrollView để chương trình có thể làm việc tốt hơn khi sử dụng các thiết bị có màn hình nhỏ.

– Bạn tham khảo Outline để cho dễ thiết kế:

12_th_1

– Vì có thể bạn sẽ “bực bội” khi nhìn thấy Outline ở trên vì vậy Tôi cung cấp luôn XML của Outline này, bạn chỉ việc copy paste vào nếu “làm biếng”:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/ScrollView1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".MainActivity" >

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

<TextView
 android:id="@+id/textView1"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="#008080"
 android:gravity="center"
 android:text="Chương trình tính tiền bán sách online"
 android:textColor="#FFFFFF"
 android:textSize="15sp"
 android:textStyle="bold" />

<TextView
 android:id="@+id/textView2"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="#FFFF00"
 android:text="Thông tin hóa đơn:"
 android:textSize="15sp" />

<TableLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:stretchColumns="1" >

<TableRow
 android:id="@+id/tableRow1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView3"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Tên Khách Hàng:" />

<EditText
 android:id="@+id/edittenkh"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:ems="10"
 android:text="Đoàn Ái Nương" >

<requestFocus />
 </EditText>
 </TableRow>

<TableRow
 android:id="@+id/tableRow2"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView4"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Số lượng sách:" />

<EditText
 android:id="@+id/editsoluongsach"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:ems="10"
 android:inputType="number"
 android:text="113" />
 </TableRow>

<TableRow
 android:id="@+id/tableRow3"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<CheckBox
 android:id="@+id/chklavip"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_column="1"
 android:checked="true"
 android:text="Khách hàng là VIP" />
 </TableRow>

<TableRow
 android:id="@+id/tableRow4"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView5"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Thành tiền:" />

<TextView
 android:id="@+id/txtthanhtien"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="#C0C0C0"
 android:gravity="center"
 android:text="2034000"
 android:textColor="#008000"
 android:textSize="20sp" />
 </TableRow>

<LinearLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<Button
 android:id="@+id/btntinhtt"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_weight="1"
 android:text="Tính TT" />

<Button
 android:id="@+id/btntiep"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_weight="1"
 android:text="Tiếp" />

<Button
 android:id="@+id/btnthongke"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_weight="1"
 android:text="Thống kê" />
 </LinearLayout>
 </TableLayout>

<TextView
 android:id="@+id/TextView01"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="#FFFF00"
 android:text="Thông tin thống kê:"
 android:textSize="15sp" />

<TableLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:stretchColumns="1" >

<TableRow
 android:id="@+id/tableRow5"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView6"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Tổng số KH:" />

<EditText
 android:id="@+id/edittongsokh"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:ems="10"
 android:inputType="number"
 android:text="3" />
 </TableRow>

<TableRow
 android:id="@+id/tableRow6"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView7"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Tổng số KH là VIP:" />

<EditText
 android:id="@+id/edittongsokhlavip"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:ems="10"
 android:inputType="number"
 android:text="1" />
 </TableRow>

<TableRow
 android:id="@+id/tableRow7"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView8"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Tổng doanh thu:" />

<EditText
 android:id="@+id/edittongdt"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:ems="10"
 android:inputType="numberDecimal"
 android:text="2184000" />
 </TableRow>
 </TableLayout>

<TextView
 android:id="@+id/textView9"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="#008080" />

<ImageButton
 android:id="@+id/imgbtnthoat"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="right"
 android:src="@drawable/exit" />
 </LinearLayout>

</ScrollView>

Bạn cần chú ý là ở cuối XML có ImageButton, nhìn vào thuộc tính android:src=“@drawable/exit” . Ở đây bạn tạo một hình có tên exit.png rồi kéo vào thư mục drawable (bạn có thể tự tạo 1 thư mục mới tên là drawable vào trong ứng dụng của bạn).

– Bạn xem cấu trúc tập tin src của ứng dụng này:

12_th_2– Ở trên có MainActivity.java (là màn hình chính của ứng dụng mà bạn thấy ở phần giới thiệu)

– class KhachHang dùng để lưu thông tin của khách hàng: Tên khách hàng, số lượng mua, thành tiền, là VIP hay không

– class DanhSachKhachHang dùng để lưu trữ các khách hàng mua sách, đồng thời cung cấp một số hàm như: tính tổng tiền, tính tổng số khách hàng, tính tổng số khách hàng VIP….

Dưới đây là chi tiết cho từng class:

class KhachHang:

package tranduythanh.com;

public class KhachHang {

private String tenKh;

private int slmua;

private boolean isVip;

public static final int GIA=20000;

public KhachHang()

{

}

public KhachHang(String tenKh,int slmua,boolean isVip)

{

this.tenKh=tenKh;

this.slmua=slmua;

this.isVip=isVip;

}

public String getTenKh() {

return tenKh;

}

public void setTenKh(String tenKh) {

this.tenKh = tenKh;

}

public int getSlmua() {

return slmua;

}

public void setSlmua(int slmua) {

this.slmua = slmua;

}

public boolean isVip() {

return isVip;

}

public void setVip(boolean isVip) {

this.isVip = isVip;

}

public double tinhThanhTien()

{

return (!isVip?slmua*GIA:slmua*GIA*0.9);

}

}

Class DanhSachKhachHang:

package tranduythanh.com;

import java.util.ArrayList;

public class DanhSachKhachHang {

ArrayList<KhachHang>listKH=new ArrayList<KhachHang>();

public void addKhachHang(KhachHang kh)

{

listKH.add(kh);

}

public double tongDoanhThu()

{

double tien=0.0;

for(KhachHang kh:listKH)

{

tien+=kh.tinhThanhTien();

}

return tien;

}

public int tongKhachHang()

{

return listKH.size();

}

public int tongKhachHangVip()

{

int s=0;

for(KhachHang kh:listKH)

{

if(kh.isVip())

s++;

}

return s;

}

}

class MainActivity:

– Dùng để triệu gọi 2 class trên và thực thi các nghiệp vụ:

package tranduythanh.com;

import android.os.Bundle;

import android.app.Activity;

import android.app.AlertDialog;

import android.content.DialogInterface;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.CheckBox;

import android.widget.EditText;

import android.widget.ImageButton;

import android.widget.TextView;

public class MainActivity extends Activity {

Button btnTT,btnTiep,btnTK;

ImageButton btnThoat;

EditText editTen,editSl,editTongKh,editTongKhVip,ediTongTT;

TextView txtTT;

CheckBox chkVip;

DanhSachKhachHang danhsach=new DanhSachKhachHang();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

getControls();

addEvents();

}

private void getControls()

{

btnTT=(Button) findViewById(R.id.btntinhtt);

btnTiep=(Button) findViewById(R.id.btntiep);

btnTK=(Button) findViewById(R.id.btnthongke);

btnThoat=(ImageButton) findViewById(R.id.imgbtnthoat);

editTen=(EditText) findViewById(R.id.edittenkh);

editSl=(EditText) findViewById(R.id.editsoluongsach);

editTongKh=(EditText) findViewById(R.id.edittongsokh);

editTongKhVip=(EditText) findViewById(R.id.edittongsokhlavip);

ediTongTT=(EditText) findViewById(R.id.edittongdt);

txtTT=(TextView) findViewById(R.id.txtthanhtien);

chkVip =(CheckBox) findViewById(R.id.chklavip);

}

private void addEvents()

{

btnTT.setOnClickListener(new ProcessMyEvent());

btnTiep.setOnClickListener(new ProcessMyEvent());

btnTK.setOnClickListener(new ProcessMyEvent());

btnThoat.setOnClickListener(new ProcessMyEvent());

}

private void doTinhTien()

{

KhachHang kh=new KhachHang();

kh.setTenKh(editTen.getText()+”");

kh.setSlmua(Integer.parseInt(editSl.getText()+”"));

kh.setVip(chkVip.isChecked());

txtTT.setText(kh.tinhThanhTien()+”");

danhsach.addKhachHang(kh);

}

private void doTiep()

{

editTen.setText(“”);

editSl.setText(“”);

txtTT.setText(“”);

editTen.requestFocus();

}

private void doThongKe()

{

editTongKh.setText(danhsach.tongKhachHang()+”");

editTongKhVip.setText(danhsach.tongKhachHangVip()+”");

ediTongTT.setText(danhsach.tongDoanhThu()+”");

}

private void doThoat()

{

AlertDialog.Builder builder=new AlertDialog.Builder(this);

builder.setTitle(“hỏi thoát chương trình”);

builder.setMessage(“Muốn thoát chương trình này hả?”);

builder.setNegativeButton(“Không”, new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which) {

dialog.cancel();

}

});

builder.setPositiveButton(“Có”, new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which) {

finish();

}

});

builder.create().show();

}

private class ProcessMyEvent implements OnClickListener

{

@Override

public void onClick(View arg0) {

switch(arg0.getId())

{

case R.id.btntinhtt:

doTinhTien();

break;

case R.id.btntiep:

doTiep();

break;

case R.id.btnthongke:

doThongKe();

break;

case R.id.imgbtnthoat:

doThoat();

break;

}

}

}

}

– Trong MainActivity Tôi cố tình tách các nghiệp vụ ra thành các hàm riêng biệt như vậy để bạn dễ dàng xử lý. Chúng ta nên tập viết như vậy để Coding được sạch sẽ, khi có lỗi sảy ra cũng giúp các bạn dễ Fixed bug, sai hàm nào thì sửa hàm đó mà nó không bị ảnh hưởng tới các nghiệp vụ khác.

– Bạn có thể load đầy đủ coding mẫu  trong link này: http://www.mediafire.com/?lgq5g2l28xb222c

– Bạn phải hiểu cách làm bài tập này để ứng dụng cho các phần sau.

– Hãy thực hành bài này nhiều lần cho tới khi thực sự hiểu logic của nó.

– Bài tập tiếp theo bạn sẽ được học về các control nâng cao trong Android, và ta sẽ thực hành thật kỹ từng control cụ thể, đầu tiên là ListView (control rất thường xuyên được sử dụng trong một chương trình Android nào đó).

– Chúc các bạn thành công

33 responses

  1. thay huong dan chi tiet qua. em cam on !!

  2. Em cảm ơn thầy! Bài hướng dẫn rất chi tiết và bổ ích!

  3. thầy ơi cho e hỏi cái hàm này .return (!isVip ? slmua * GIA : slmua * GIA * 0.9); có nghĩa là gì ạ,mong thầy giải thích hộ e nhé

    1. đại khái mình hiểu là : nếu không phải vip (!isVip) thì return (slmua * GIA) và ngược lại là Vip thì return (slmua * GIA* 0.9) – vip giảm 10% mà bạn
      hjx

  4. cám ơn thầy bài viết rất hữu ích

  5. Thầy dạy rất hay, mong có nhiều bài hướng dẫn hơn nữa, cảm ơn thầy nhiều

  6. Cam on thay nhieu lam

  7. thầy ơi sao em không thấy thuộc tính layout_column và layout_span trong table_layout nhỉ?

  8. sao hàm isVip không đếm dc số người Vip, mà ai cũng là vip cả khi ko checked thầy ạ?

    1. Cái này bạn phải nhấn vào TinhTT sau đó nhấn Thống kê thì mới làm việc nhé

    2. public int tongKhachHangVip(){
      int s =0;
      for(KhachHang kh:ListKH){
      if(kh.isVip())
      s++;
      }
      return s;
      kiểm tra lại đoạn này xem bạn có thừa dấu ” ; ” ko.

  9. Vũ Thị Thanh Thảo | Reply

    thầy cho e hỏi, e sử dụng btnimage.setEnabled(false); mà imagebutton ko ẩn đi. còn cách nào khác không ạ? và làm s để khi cài đặt để chế độ xoay màn hình. câu lệnh nào giúp auto khi xoay ạ?

  10. thầy cho em hỏi chỗ code này :

    private void addEvents()

    {

    btnTT.setOnClickListener(new ProcessMyEvent());

    btnTiep.setOnClickListener(new ProcessMyEvent());

    btnTK.setOnClickListener(new ProcessMyEvent());

    btnThoat.setOnClickListener(new ProcessMyEvent());

    }

    em không hiểu ProcessMyEvent() là cái gì. khi em code giống thế thì báo lỗi ạ. ctrl + 1 thì nó hướng dẫn tạo 1 class mới… thầy giải thích giúp em với được ko ạ…

    1. Em đọc kỹ hướng dẫn có nói phần tạo sự kiện như thế này.

    2. Thầy cho em hỏi là em có khai báo :

      ImageButton ibtnThoat;
      ibtnThoat = (ImageButton) findViewById(R.id.ibtnThoat);

      thì AndroidStudio báo lỗi khi runtime, còn em set nút ImageButton đó về dạng Button như:

      Button ibtnThoat;
      ibtnThoat = (Button) findViewById(R.id.ibtnThoat);

      thì không gặp lỗi gì, chương trình vẫn chạy tốt mặc dù đó là Button hình ảnh ? Em thắc mắc tại sao ?

      1. Bạn thử clean project và build lại lần nữa xem

  11. Cái vòng for(KhachHang kh:listKH) là như thế nào vậy thầy?

    1. Tấn Cường | Reply

      theo mình hiểu thì tạo mới 1 khách hàng: “KhacHang kh”,rồi chạy vòng for đến khi nào vẫn còn khách hàng trong listKH thì vẫn làm việc,nếu hết thì ngưng

      1. đây là vòng lặp foreach nó chạy từ đầu đến cuối mảng mà không cần biết trước số lượng phần tử có trong mảng

  12. em cảm ơn thầy ạ

  13. versus_b123@yahoo.com.vn | Reply

    ai giải thích hộ mình với , trong class khachhang lại có 1 pt
    public KhachHang() { } , tại sao lại phải có nó ?????

    1. versus_b123@yahoo.com.vn | Reply

      à pt khởi tạo ^^!

      1. Tự hỏi tự trả lời , thánh :V

  14. Cảm ơn thầy rất nhiều về bài hướng dẫn này

  15. Cám ơn thầy mới học mà được thầy giảng chi tiết quá :D. Thầy cho e hỏi chút là mình thiết kế thế nào để layout hiển thị lên màn hình ko bị lấp thầy nhỉ? Ví dụ như hình trên nút thoát của thầy bị lấp 1 nửa.

    1. Dùng Scollview để cuộn bạn ạ 😀

  16. Thầy ơi, cho em hỏi là tại sao project không có lỗi gì nhưng khi chạy trên AVD thì bị lỗi unforturately,.. has stopped ạ. Em cảm ơn thầy.

  17. Mình vẫn không hiểu chỗ vòng for, bạn nào giải thích hộ mình với

  18. Thầy dạy rất hay,rất dễ hiểu. Em là em bái phục thầy đấy ạ 🙂

  19. Thank thầy, rất hay và ý nghĩa

  20. Các bài tập rất tổng quát, tuy đơn giản nhưng lại làm theo cách tổng quát giúp học sinh dễ tiếp thu, cảm ơn thầy!
    Sinh viên BKHN.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s