Lập trình Android – Bài 6: Thực hành xây dựng ứng dụng Calculator

Chào các bạn, trong 2 bài trước chúng ta đã tập thiết kế giao diện tương đối nhiều rồi. Để bớt sự căng thẳng và đổi gió chút thì bài này sẽ hướng dẫn các bạn làm một ứng dụng Calculator hoàn chỉnh.

[qads]

Chúng ta sẽ sử dụng code giao diện hôm trước đã thiết kế.

calculator-layout-ok-2

Ah quên, nhắc với các bạn là để làm ứng dụng này có thể tính toán nhanh chóng và không mất nhiều công sức, chúng ta sẽ dùng thư viện Balan mà mình đã xây dựng. Các bạn download file balan.jar tại đây. Tiếp theo mở chế độ Project và copy file balan.jar vào thư mục app/libs như hình

android-add-libs

Sau đó Click chuột phải vào file balan.jar chọn Add as Library… ở gần cuối menu, hệ thống hỏi bạn có muốn add vào modul app khôgn thì cứ ok. Đợi một chút hệ thống đồng bộ là xong.

Bây giờ các bạn mở file ActivityMain.java trong thư mục app/src/main/java/{tên package} ra. Hiện tại hàm setContentViewdrrdf của chúng ta vẫn là R.layout.activity_main, các bạn thay đổi nó thành R.layout.layout_calculator để kết nối đến file giao diện của Calculator mà bạn đã thiết kế hôm trước.

package com.nguyenvanquan7826.tut5linearlayout;

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

public class MainActivity extends AppCompatActivity {

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

Rồi ok, giờ mới thực sự bắt đầu nhé.
Trước tiên, để có thể thao tác với máy tính, chúng ta cần kết nối các phần tử trong giao diện với code java thông qua các biến tương ứng.

package com.nguyenvanquan7826.tut5linearlayout;

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tvMath;
    private TextView tvResult;

    private int[] idButton = {
            R.id.btn0,
            R.id.btn1, R.id.btn2, R.id.btn3,
            R.id.btn4, R.id.btn5, R.id.btn6,
            R.id.btn7, R.id.btn8, R.id.btn9,
            R.id.btnDot, R.id.btnResult,
            R.id.btnPlus, R.id.btnSub, R.id.btnMul, R.id.btnDiv,
            R.id.btnC, R.id.btnOpen, R.id.btnClose
    };

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

        connectView();
    }

    private void connectView() {
        tvMath = (TextView) findViewById(R.id.tvMath);
        tvResult = (TextView) findViewById(R.id.tvResult);

        for (int i = 0; i < idButton.length; i++) {
            findViewById(idButton[i]).setOnClickListener(this);
        }
    }

    @Override
    public void onClick(View view) {
        
    }
}

Các bạn chú ý trong code trên việc kết nối TextView Math và Result là bình thường, riêng kết nối các Button là không bình thường. Lý do là mình nhận thấy có rất nhiều button cần kết nối và chúng đều cần bắt sự kiện cả. Do vậy ý nghĩ hiện lên là liệu có thể cho vào vòng lặp để lặp đi lặp lại công việc giống nhau đó? Vì vậy mình đã cho các id của chúng vào một mảng idButton. Id của mỗi View thực chất được chuyển thành kiểu nguyên trong hệ thống, vì vậy mảng này có kiểu là int. Ngoài ra việc kết nối và bắt sự kiện cho mỗi button trong vòng for cũng có sự khác biệt. Chúng ta không ép kiểu về button mà vừa kết nối vừa bắt sự kiện ngay qua chuỗi lệnh findViewById(idButton[i]).setOnClickListener(this);
Lý do là hàm findViewById sẽ trả về cho chúng ta một View (và từ đó thông thường chúng ta ép về kiểu đúng của nó như Button, TextView,…) mà mỗi View đều có thể bắt sự kiện Click (kể cả TextView, EditText,…) nên chúng ta gọi ngay được setOnClickListener sau đó mà không cần ép kiểu về Button.

Bây giờ công việc tiếp theo là xử lý sự kiện click button. Tại đây chúng ta phân ra làm 3 loại button: Button số, Button phép toán và Button Xử lý phép toán.
Button số và button phép toán thì khi click vào button nào, chúng ta cứ thêm text tương ứng vào biểu thức. Còn button xử lý (button C và button = ) thì thực hiện công việc tính toán hoặc xóa màn hình. Khi click Button bằng, chúng ta gọi hàm valueMath của đối tượng Balan trong thư viện Balan mà chúng ta đã thêm vào ban đầu, nó sẽ tính cho chúng ta kết quả.

package com.nguyenvanquan7826.tut5linearlayout;

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

import cachhoc.net.Balan;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tvMath;
    private TextView tvResult;

    private int[] idButton = {
            R.id.btn0,
            R.id.btn1, R.id.btn2, R.id.btn3,
            R.id.btn4, R.id.btn5, R.id.btn6,
            R.id.btn7, R.id.btn8, R.id.btn9,
            R.id.btnDot,
            R.id.btnPlus, R.id.btnSub, R.id.btnMul, R.id.btnDiv,
            R.id.btnOpen, R.id.btnClose,
            R.id.btnC, R.id.btnResult
    };

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

        connectView();
    }

    private void connectView() {
        tvMath = (TextView) findViewById(R.id.tvMath);
        tvResult = (TextView) findViewById(R.id.tvResult);

        for (int i = 0; i < idButton.length; i++) {
            findViewById(idButton[i]).setOnClickListener(this);
        }
        init();
    }

    private void init() {
        tvMath.setText("|");
        tvResult.setText("0");
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();

        // check button number and button operator
        for (int i = 0; i < idButton.length - 2; i++) {
            if (id == idButton[i]) {
                String text = ((Button) findViewById(id)).getText().toString();

                // clear char | on top
                if (tvMath.getText().toString().trim().equals("|")) {
                    tvMath.setText("");
                }

                tvMath.append(text);
                return;
            }
        }

        // clear screen
        if (id == R.id.btnC) {
            init();
            return;
        }

        // calculation
        if (id == R.id.btnResult) {
            cal();
        }
    }

    private void cal() {
        String math = tvMath.getText().toString().trim();
        if (math.length() > 0) {
            Balan balan = new Balan();
            String result = balan.valueMath(math) + "";
            String error = balan.getError();

            // check error
            if (error != null) {
                tvResult.setText(error);
            } else { // show result
                tvResult.setText(result);
            }
        }
    }
}

Vậy là xong, kết quả của chúng ta đây nhé.
calculator-result