0

I'm writing a calculator app for android using android studio. I want to used 4 buttons for inputting values and functions. However the way I am currently doing it takes the input from the text written on the button. So for my button 1/2/3 when this is pressed 1/2/3 is passed to the textView.

Below is my MainActivity:

   package com.example.myfirstapp;

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


public class MainActivity extends ActionBarActivity  {
    private int[] operatorButtons = {R.id.operators};
    private int[] numericButtons = {R.id.onetwothree, R.id.fourfivesix, R.id.seveneightninezero};
    private boolean  lastNumeric, stateError;
    private TextView txtScreen;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Find the TextView
        this.txtScreen = (TextView) findViewById(R.id.txtScreen);
        // Find and set OnClickListener to numeric buttons
        setNumericOnClickListener();
        // Find and set OnClickListener to operator buttons, equal button and decimal point button
        setOperatorOnClickListener();
    }


    private void setNumericOnClickListener() {
        // Create a common OnClickListener
        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Just append/set the text of clicked button
                Button button = (Button) v;
                if (stateError) {
                    // If current state is Error, replace the error message
                    txtScreen.setText(button.getText());
                    stateError = false;
                } else {
                    // If not, already there is a valid expression so append to it
                    txtScreen.append(button.getText());
                }
                // Set the flag
                lastNumeric = true;
            }
        };
        // Assign the listener to all the numeric buttons
        for (int id : numericButtons) {
            findViewById(id).setOnClickListener(listener);
        }
    }

    private void setOperatorOnClickListener() {
        // Create a common OnClickListener for operators
        View.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // If the current state is Error do not append the operator
                // If the last input is number only, append the operator
                if (lastNumeric && !stateError) {
                    Button button = (Button) v;
                    txtScreen.append(button.getText());
                    lastNumeric = false;

                }
            }
        };
        // Assign the listener to all the operator buttons
        for (int id : operatorButtons) {
            findViewById(id).setOnClickListener(listener);
        }


        // Equal button
        /*findViewById(R.id.btnEqual).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onEqual();
            }
        });*/
    }
}

and my activity_main:

  <?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">

    <TextView
        android:id="@+id/txtScreen"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:gravity="right|center_vertical"
        android:maxLength="16"
        android:padding="10dp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="30sp"
        android:typeface="serif" />
   <!--<Button-->
        <!--android:id="@+id/equal1"-->
        <!--android:layout_width="match_parent"-->
        <!--android:layout_height="100dp"-->
        <!--android:text="="-->
         <!--/>-->

    <Button
        android:id="@+id/equal2"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="="
        android:layout_alignParentBottom="true"
         />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/txtScreen"
        android:orientation="vertical"
        android:layout_above="@id/equal2">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

            <Button
                android:id="@+id/onetwothree"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="1/2/3"/>

            <Button
                android:id="@+id/fourfivesix"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="4/5/6"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

            <Button
                android:id="@+id/seveneightninezero"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="7/8/9/0"/>

            <Button
                android:id="@+id/operators"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="+-*/"/>

        </LinearLayout>

    </LinearLayout>

</RelativeLayout>

Will it be possible for me to get the input of 1, 2 or 3 from my first button for example? So on 1 press you get 1, 2 press gives 2 etc.

Any suggestions/ ideas on how I can move forward with this are greatly appreciated.

Kind Regards, Ben

Amit Upadhyay
  • 7,179
  • 4
  • 43
  • 57
benjano
  • 369
  • 1
  • 5
  • 17

2 Answers2

1

You could use a timer or delay variable to detect single, double or triple taps. This post may be of interest. If the time interval is not a factor, you could just keep track of the last pressed button and if the same button is being pressed again, update the text accordingly.

If you follow approach one, the code for the click listener for button onetwothree may be something like this (I commented out setNumericOnClickListener() and setOperatorOnClickListener(); in mainActivity onCreate and added the following):

Button onetwothree = (Button) findViewById(R.id.onetwothree);
    onetwothree.setOnTouchListener(new View.OnTouchListener() {

        Handler handler = new Handler();

        int numberOfTaps = 0;
        long lastTapTimeMs = 0;
        long touchDownMs = 0;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touchDownMs = System.currentTimeMillis();
                    break;
                case MotionEvent.ACTION_UP:
                    handler.removeCallbacksAndMessages(null);
                    if ((System.currentTimeMillis() - touchDownMs) > ViewConfiguration.getTapTimeout()) {
                        //it was not a tap

                        numberOfTaps = 0;
                        lastTapTimeMs = 0;
                        break;
                    }

                    if (numberOfTaps > 0
                            && (System.currentTimeMillis() - lastTapTimeMs) < ViewConfiguration.getDoubleTapTimeout()) {
                        numberOfTaps += 1;
                    } else {
                        numberOfTaps = 1;
                    }
                    lastTapTimeMs = System.currentTimeMillis();

                    if (numberOfTaps == 1) {
                        handler.postDelayed(new Runnable() {

                            @Override
                            public void run() {
                                if (txtScreen.getText().toString() == "") {
                                    txtScreen.setText("1");
                                } else txtScreen.append("1");
                            }
                        }, ViewConfiguration.getDoubleTapTimeout());



                    }else if (numberOfTaps == 2) {
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                if (txtScreen.getText().toString() == "") {
                                    txtScreen.setText("2");
                                } else txtScreen.append("2");
                            }
                        }, ViewConfiguration.getDoubleTapTimeout());

                    } else if (numberOfTaps == 3) {
                                if (txtScreen.getText().toString() == "") {
                                    txtScreen.setText("3");
                                } else txtScreen.append("3");
                    }
            }

            return true;
        }
    });

Complete MainActivity:

package com.example.myfirstapp;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity  {
    private int[] operatorButtons = {R.id.operators};
    private int[] numericButtons = {R.id.onetwothree, R.id.fourfivesix, R.id.seveneightninezero};
    private boolean  lastNumeric, stateError;
    private TextView txtScreen;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // Find the TextView
    this.txtScreen = (TextView) findViewById(R.id.txtScreen);
    // Find and set OnClickListener to numeric buttons
//        setNumericOnClickListener();
        // Find and set OnClickListener to operator buttons, equal button and decimal point button
//        setOperatorOnClickListener();

    Button onetwothree = (Button) findViewById(R.id.onetwothree);
    onetwothree.setOnTouchListener(new View.OnTouchListener() {

        Handler handler = new Handler();

        int numberOfTaps = 0;
        long lastTapTimeMs = 0;
        long touchDownMs = 0;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touchDownMs = System.currentTimeMillis();
                    break;
                case MotionEvent.ACTION_UP:
                    handler.removeCallbacksAndMessages(null);
                    if ((System.currentTimeMillis() - touchDownMs) > ViewConfiguration.getTapTimeout()) {
                        //it was not a tap

                        numberOfTaps = 0;
                        lastTapTimeMs = 0;
                        break;
                    }

                    if (numberOfTaps > 0
                            && (System.currentTimeMillis() - lastTapTimeMs) < ViewConfiguration.getDoubleTapTimeout()) {
                        numberOfTaps += 1;
                    } else {
                        numberOfTaps = 1;
                    }
                    lastTapTimeMs = System.currentTimeMillis();

                    if (numberOfTaps == 1) {
                        handler.postDelayed(new Runnable() {

                            @Override
                            public void run() {
                                if (txtScreen.getText().toString() == "") {
                                    txtScreen.setText("1");
                                } else txtScreen.append("1");
                            }
                        }, ViewConfiguration.getDoubleTapTimeout());



                    }else if (numberOfTaps == 2) {
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                if (txtScreen.getText().toString() == "") {
                                    txtScreen.setText("2");
                                } else txtScreen.append("2");
                            }
                        }, ViewConfiguration.getDoubleTapTimeout());

                    } else if (numberOfTaps == 3) {
                                if (txtScreen.getText().toString() == "") {
                                    txtScreen.setText("3");
                                } else txtScreen.append("3");
                    }
            }

            return false;
        }
    });
}


private void setNumericOnClickListener() {
    // Create a common OnClickListener
    View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Just append/set the text of clicked button
            Button button = (Button) v;
            if (stateError) {
                // If current state is Error, replace the error message
                txtScreen.setText(button.getText());
                stateError = false;
            } else {
                // If not, already there is a valid expression so append to it
                txtScreen.append(button.getText());
            }
            // Set the flag
            lastNumeric = true;
        }
    };
    // Assign the listener to all the numeric buttons
    for (int id : numericButtons) {
        findViewById(id).setOnClickListener(listener);
    }
}

private void setOperatorOnClickListener() {
    // Create a common OnClickListener for operators
    View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // If the current state is Error do not append the operator
            // If the last input is number only, append the operator
            if (lastNumeric && !stateError) {
                Button button = (Button) v;
                txtScreen.append(button.getText());
                lastNumeric = false;

            }
        }
    };
    // Assign the listener to all the operator buttons
    for (int id : operatorButtons) {
        findViewById(id).setOnClickListener(listener);
    }


}
}
Community
  • 1
  • 1
skbrhmn
  • 1,124
  • 1
  • 14
  • 36
  • Changed the answer slightly and added an example code for single, double and triple tap. – skbrhmn Feb 07 '17 at 19:34
  • Hi, looking at that code it looks like it will do exactly what I want. When trying to use it in my code I get errors regarding viewConfiguration and setOnTouch listener and event etc. I know this is a dumb question but do I need to import something to use these? I'm new to android studio and android development. Thanks for the help – benjano Feb 07 '17 at 20:08
  • Hi, I added the mainActivity with all the imports to my answer for further clarification. You could also turn on Auto Imports in Android Studio. Preferences>Editor>General>Auto Imports and then check the boxes including `Add unambiguous imports on the fly`. – skbrhmn Feb 07 '17 at 20:18
  • Also, what sort of errors are you getting? It would be easier if you can mention the errors from the logcat. Let me know if the imports solve the problem :) – skbrhmn Feb 07 '17 at 20:36
  • HI, thanks for the tip on the auto imports! That will save me a lot of grief. The solution works perfectly and I will now be able to implement the other buttons. – benjano Feb 08 '17 at 00:22
  • Hi, I've got all my buttons working now which is awesome... I'm attempting to edit the code so there is a longer time allowed between presses, I've tried adding an int TAP_TIMEOUT to replace where getTapTimeout, getDoubleTapTimeout are used. I'm also trying this because two of my buttons contain four things. Is using a TAP_TIMEOUT the correct method for this? – benjano Feb 08 '17 at 16:56
  • instead of `ViewConfiguration.getDoubleTapTimeout()`, just input a different int value, the conventional value is 300, you can input a different value. For four taps, don't forget to add handlers for each tap except the one. – skbrhmn Feb 08 '17 at 17:13
0

You can take all numbers when doing some operation

(Button) plusBtn = (Button) findViewById(R.id.plusBtn);
plusBtn.setOnClickListener(new OnClickListener(){
@Override
public voidonClick(View v){
number1 = Integer.parseInt(txtScreen.getText().toString());
});

Where number1 is global int. But I don't know how it can help you and if it is a good approach. You could find a better solution, just remember how to parse the String from your TextView to Integer for your calculation.

Sebastianb
  • 2,020
  • 22
  • 31
H.Taras
  • 753
  • 4
  • 15