본문 바로가기
Android

안드로이드 스튜디오,java] 간단한 계산기 앱 만들기

by 김마리님 2020. 7. 14.

출력 결과 : 

 

안드로이드 스튜디오를 접한 사람이라면 먼저 자바나 코틀린을 접했을 것이다.

자바의 간단한 계산기는 eval함수를 이용하여 문자열을 계산해준다. 그 함수는 javax 함수 위에 있는데, 안드로이드는 없기 때문에 이것도 생각해본다.

 

먼저, 디자인 xml을 생성한다.

여러가지 레이아웃으로 만들어도 관계 없지만, 여기서는 테이블 레이아웃을 이용했다.

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingRight="10dp"
    android:paddingLeft="10dp"
    android:paddingTop="200dp"
    android:stretchColumns="*"
    tools:context=".MainActivity">

    <TableRow>
        <EditText
            android:layout_span="4"
            android:id="@+id/et_result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="textPersonName"
            android:hint="숫자를 입력하세요." />

    </TableRow>


    <!-- 첫번째 버튼 줄-->
    <TableRow>
        <Button
            android:id="@+id/num_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1" />

        <Button
            android:id="@+id/num_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="2" />

        <Button
            android:id="@+id/num_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="3" />

        <Button
            android:id="@+id/btn_plus"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="+" />
    </TableRow>
    <!--첫 번째 버튼 줄 종료-->

    <!-- 두 번째 버튼 줄 -->
    <TableRow>
        <Button
            android:id="@+id/num_4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="4" />

        <Button
            android:id="@+id/num_5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="5" />

        <Button
            android:id="@+id/num_6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="6" />

        <Button
            android:id="@+id/btn_minus"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="-" />
    </TableRow>
    <!-- 두 번째 버튼 줄 종료-->

    <!--세 번째 버튼 줄 시작-->
    <TableRow>
        <Button
            android:id="@+id/num_7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="7" />

        <Button
            android:id="@+id/num_8"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="8" />

        <Button
            android:id="@+id/num_9"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="9" />

        <Button
            android:id="@+id/btn_multiple"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="*" />
    </TableRow>
    <!-- 세 번째 버튼 줄 종료-->

    <!-- 네 번째 버튼 줄 시작-->
    <TableRow>
        <Button
            android:id="@+id/num_0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0" />

        <Button
            android:id="@+id/btn_clear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="C" />

        <Button
            android:id="@+id/btn_slush"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="/" />

        <Button
            android:id="@+id/btn_result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="=" />
    </TableRow>
    <!-- 네번째 줄 종료-->

</TableLayout>

안드로이드의 테이블은 html과 다르게 따로 td등을 만들 필요 없이 한 줄이 <tablerow> 인데, 여기 내부에 들어있는 요소의 양이 제일 많은대로 열이 된다. 즉, 첫 번째 줄에 요소 3개, 두 번째 줄에 요소 4개 세 번째 줄의 요소가 5개라면, 5X3의 테이블 레이아웃이 완성된다.

 

EditText는 한 줄에 크게 차지하기 때문에 span 속성을 통해 4칸을 차지하도록 속성을 주었다.

레이아웃의 stretchColumns 속성은 테이블의 모양이 균일하게 요소 내부를 채워준다. 만일, 단일 테이블 요소의 크기를 조절하고 싶다면, stretchColunms 속성에 *가 아닌, 열의 숫자를 지정해주면 된다.

 

이제 코드이다.

package com.mary.countingapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Main_Activity";

    private EditText ptResult;
    private Button btn[]=new Button[16];
    private int i=0;

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

        init();
        initListener();
    }

    private void init(){
        btn[0]=findViewById(R.id.num_0);
        btn[1]=findViewById(R.id.num_1);
        btn[2]=findViewById(R.id.num_2);
        btn[3]=findViewById(R.id.num_3);
        btn[4]=findViewById(R.id.num_4);
        btn[5]=findViewById(R.id.num_5);
        btn[6]=findViewById(R.id.num_6);
        btn[7]=findViewById(R.id.num_7);
        btn[8]=findViewById(R.id.num_8);
        btn[9]=findViewById(R.id.num_9);

        btn[10]=findViewById(R.id.btn_plus);
        btn[11]=findViewById(R.id.btn_minus);
        btn[12]=findViewById(R.id.btn_multiple);
        btn[13]=findViewById(R.id.btn_slush);
        btn[14]=findViewById(R.id.btn_clear);
        btn[15]=findViewById(R.id.btn_result);
        ptResult=findViewById(R.id.et_result);

    }

    private void initListener(){
        for (int i=0; i<14;i++){
            btn[i].setOnClickListener((View view)-> {
                Button btn = (Button) view;
                ptResult.append(btn.getText().toString());
            });
        }
        btn[14].setOnClickListener((View view)-> {
           ptResult.setText("");
        });
        btn[15].setOnClickListener((View view)-> {
            String result=ptResult.getText().toString();
            ptResult.setText(Eval.cal(result));
        });
    }
}

버튼이 16개나 된다.

그러니까, 이 버튼의 변수를 일일히 지정하는 것보다, 배열로 지정하면 변수의 이름을 일일히 지정해줄 필요도 없고 이벤트 리스너를 만들 때 일일히 지정할 필요 없이 같은 역할을 하는 버튼을 for문을 돌려 이벤트 리스너를 지정한다.

 

배열의 크기를 지정하고, 각 배열의 위치에 findView 속성을 통해 버튼을 호출해 배열 속에 넣는다.

여기서 역할이 좀 중요한데, clear과 =는 텍스트에디터 위에 나타나는 값이 아니다. 나머지는 텍스트 에디터 위에 나타나는 값이다. 그렇기 때문에 clear과 = 버튼은 뒤로 지정하고, 나머지를 배열의 앞에 넣어 for문을 돌린다.

 

for문을 돌리는 방식은 간단하다. 내가 textEditor 위에 호출할 값들까지만 for문을 돌리며, for문 내부 함수는 버튼 속의 text값을 getText로 가져와 문자열로 파싱 후 append 하면 된다.

즉, 1을 누르면 "1", 2를 누르면 "1"+"2"가 되니 3이 아니라 12가 되는 셈이다.

 

clear 버튼이야.. 그냥 텍스트 에디터 위의 값을 다 날리면 되니 setText("")로 공백을 만든다.

 

마지막 result를 위해서 먼저 자바스크립트 라이브러리를 참조하게 해 줄 라이브러리를 찾는다. 여기서는 Rinor for Android를 이용했다.

https://mvnrepository.com/artifact/io.apisense/rhino-android/1.0

 

Maven Repository: io.apisense » rhino-android » 1.0

Give access to RhinoScriptEngine from the JSR223 interfaces on Android JRE. Note: There is a new version for this artifact io.apisense rhino-android 1.0 // https://mvnrepository.com/artifact/io.apisense/rhino-android compile group: 'io.apisense', name: 'rh

mvnrepository.com

이제 이 라이브러리를 의존성을 부여하자.

앱 수준의 build.gradle로 이동해서 implement한다.

implementation 'io.apisense:rhino-android:1.0'

이제, 자바스크립트를 참조할 수 있으니, eval 함수를 만들자.

 

새 자바 클래스를 생성한다.

package com.mary.countingapp;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Eval {
    public static String cal(String result){
        ScriptEngineManager manager=new ScriptEngineManager();
        ScriptEngine engine=manager.getEngineByName("js");
        try{
            return engine.eval(result).toString();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

먼저 스크립트 매니저를 호출하고, 이후에 엔진을 호출한다. 엔진은 내가 어떤 스크립트를 사용할건지 선택하게 하는데, 나는 자바스크립트를 만들테니 확장자 js를 호출한다. 이러면 자바스크립트 내부의 함수(eval)을 이용할 수 있다.

이 함수를 결과값 이벤트 리스너에서 호출한다.

반응형