Android计算器上的“开始”按钮问题

时间:2017-02-22 22:17:59

标签: java android xml

我正在开发一款Android计算器应用,不使用Android中的任何内置基于计时器的类,而是使用处理程序和线程来更新UI。我不确定我的逻辑是否存在问题,但无论出于何种原因,当我设置时间并点击“开始”按钮时,屏幕上根本没有任何问题。目标TextView不会减少。再说一次,我可能犯了一个简单的错误(或者一些错误),但是我发布了我的java和xml文件供大家查看。提前感谢任何回复。

TimerActivity.java

package com.example.stins.intentsandtimer;


import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.NumberPicker;
import android.widget.TextView;
import android.os.Handler;
import android.os.Message;
import android.content.Context;
import android.os.Vibrator;



public class TimerActivity extends AppCompatActivity implements View.OnClickListener {
    TextView hours, minutes, seconds;
    Button numberPicker;
    private int hrs, min, sec;
    private boolean start;

    Handler timerHandler = new Handler(){

        /**
         * Handler for the timer class. It receives the onStart runnable to allow the textviews
         * to be updated. It checks to see if all textviews are empty and only updates them if
         * they follow the conditions of a traditional timer.  Including moving from 1 hour to 59 minutes.
         * The handler also sends the Vibrator function once the timer is complete.
         * @param msg
         */
        @Override
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            TextView txtSeconds = (TextView) findViewById(R.id.textview_seconds);
            TextView txtMinutes = (TextView) findViewById(R.id.textview_minutes);
            TextView txtHours = (TextView) findViewById(R.id.textview_hours);
            int zeroCheck = Integer.parseInt(txtSeconds.getText().toString());

            if (zeroCheck > 0) {
                sec -= 1;
                txtSeconds.setText(sec + "");
            } else if (min > 0 && sec == 0) {
                min -= 1;
                txtMinutes.setText(min + "");
                sec = 59;
                txtSeconds.setText(sec + "");
            } else if (hrs > 0 && min == 0 && sec == 0) {
                hrs -= 1;
                txtHours.setText(hrs + "");
                min = 59;
                txtMinutes.setText(min + "");
                sec = 59;
                txtSeconds.setText(sec + "");
            } else {
                Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                v.vibrate(1000);
            }
        }

    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_timer);
        this.setTitle("Timer");

        Button btnStart = (Button) findViewById(R.id.start_button);
        Button btnStop = (Button) findViewById(R.id.stop_button);
        Button btnReset = (Button) findViewById(R.id.reset_button);


        hours = (TextView) findViewById(R.id.textview_hours);
        numberPicker = (Button) findViewById(R.id.btn_set_hours);
        numberPicker.setOnClickListener(this);

        minutes = (TextView) findViewById(R.id.textview_minutes);
        numberPicker = (Button) findViewById(R.id.btn_set_minutes);
        numberPicker.setOnClickListener(this);

        seconds = (TextView) findViewById(R.id.textview_seconds);
        numberPicker = (Button) findViewById(R.id.btn_set_seconds);
        numberPicker.setOnClickListener(this);


        btnReset.setOnClickListener(new Button.OnClickListener() {
                                        public void onClick(View view) {
                                            TextView txtSeconds = (TextView) findViewById(R.id.textview_seconds);
                                            TextView txtMinutes = (TextView) findViewById(R.id.textview_minutes);
                                            TextView txtHours = (TextView) findViewById(R.id.textview_hours);
                                            sec = 0;
                                            min = 0;
                                            hrs = 0;
                                            txtSeconds.setText(sec+"");
                                            txtMinutes.setText(min+"");
                                            txtHours.setText(hrs+"");

                                        }
                                    }
        );

        btnStart.setOnClickListener(new Button.OnClickListener() {
                                        public void onClick(View view) {
                                            start = true;
                                            onStart();
                                        }
                                    }
        );

        btnStop.setOnClickListener(new Button.OnClickListener() {
                                       public void onClick(View view) {
                                           start = false;
                                       }
                                   }
        );


    }

    protected void onStart(){
        super.onStart();
        final Thread myThread = new Thread(new Runnable(){

            @Override
            public void run() {

                while (sec > 0 || min > 0 || hrs > 0) {
                    if(start) {
                        try {

                            Thread.sleep(1000);
                            timerHandler.sendMessage(timerHandler.obtainMessage());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    else{

                    }
                }

            }

        });
        myThread.start();
    }




    public void onClick (View v){
        switch (v.getId()) {

            case R.id.btn_set_hours:
                hourPickerDialog();
                break;

            case R.id.btn_set_minutes:
                minutePickerDialog();
                break;

            case R.id.btn_set_seconds:
                secondPickerDialog();
                break;

            default:
                break;
        }


    }



    private void hourPickerDialog(){
        NumberPicker myNumberPicker = new NumberPicker(this);
        myNumberPicker.setMaxValue(99);
        myNumberPicker.setMinValue(0);
        NumberPicker.OnValueChangeListener myValChangedListener = new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                hours.setText(""+newVal);
            }
        };
        myNumberPicker.setOnValueChangedListener(myValChangedListener);
        AlertDialog.Builder builder =  new AlertDialog.Builder(this).setView(myNumberPicker);
        builder.setTitle("Set Hours");
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        builder.show();


    }

    private void minutePickerDialog(){
        NumberPicker myNumberPicker = new NumberPicker(this);
        myNumberPicker.setMaxValue(59);
        myNumberPicker.setMinValue(0);
        NumberPicker.OnValueChangeListener myValChangedListener = new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                minutes.setText(""+newVal);
            }
        };
        myNumberPicker.setOnValueChangedListener(myValChangedListener);
        AlertDialog.Builder builder =  new AlertDialog.Builder(this).setView(myNumberPicker);
        builder.setTitle("Set Minutes");
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        builder.show();


    }

    private void secondPickerDialog(){
        NumberPicker myNumberPicker = new NumberPicker(this);
        myNumberPicker.setMaxValue(59);
        myNumberPicker.setMinValue(0);
        NumberPicker.OnValueChangeListener myValChangedListener = new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                seconds.setText(""+newVal);
            }
        };
        myNumberPicker.setOnValueChangedListener(myValChangedListener);
        AlertDialog.Builder builder =  new AlertDialog.Builder(this).setView(myNumberPicker);
        builder.setTitle("Set Seconds");
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        builder.show();


    }


}

activity_timer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_margin="16dp"
              android:gravity="center_horizontal"
              android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:orientation="horizontal"
        android:gravity="center">

        <TextView
            android:id="@+id/textview_hours"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="00"
            android:textSize="70sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text=":"
            android:textSize="70sp"/>

        <TextView
            android:id="@+id/textview_minutes"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="00"
            android:textSize="70sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text=":"
            android:textSize="70sp"/>

        <TextView
            android:id="@+id/textview_seconds"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="00"
            android:textSize="70sp" />


    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center">

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

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

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



    </LinearLayout>

    <Button
        android:id="@+id/start_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="16dp"
        android:background="?selectableItemBackgroundBorderless"
        android:text="@string/timer_start"
        style="@style/MyButton"
        />

    <Button
        android:id="@+id/stop_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="16dp"
        android:background="?selectableItemBackgroundBorderless"
        android:text="@string/timer_stop"
        style="@style/MyButton"/>

    <Button
        android:id="@+id/reset_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:background="?selectableItemBackgroundBorderless"
        android:text="@string/timer_reset"
        style="@style/MyButton"/>

</LinearLayout>

1 个答案:

答案 0 :(得分:1)

您的代码中发生了一些事情。我不会试图解决所有这些问题,只是为了让你的代码能够做到应有的事情。我复制了&amp;试过你的代码&amp;它实际上改变了我的显示。我跳过你的时间选择器对话框&amp;只需设置sec=20即可开始。如果您没有获得任何更改显示,那么显示器最初是从时间选择器设置的吗?

无论如何,第一个让我们谈谈调试。一种方法是将Log语句放在代码中。首先将其放在文件的顶部

private final static String TAG = "TimerActivity";

然后在代码中有这样的事情:

// put this in the start button click listener
Log.d(TAG, "Start clicked");

// or this in handleMessage
Log.d(TAG, "handleMessage(), seconds = " + sec);

拥有这些日志消息可以帮助您了解您的计划已完成的工作&amp;什么没有,加上向你展示一些变量值。你也可以使用我现在不会进入的调试器。

现在为你的代码。 onStart()是一种生命周期方法。你不应该自己打电话。重命名您的方法(可能类似于onStartButton())。正如你现在所做的那样,你有2个线程运行实例,你的计数器每秒都会下降两次。

handleMessage()中,您有用于跟踪时间的变量(小时,分钟,秒),但您还可以从显示屏上的文本中读取zeroCheck。最好的办法是使用你已经保留的变量(if(sec > 0) { sec -= 1;...)。在其余的这些条件下,我没有验证你的逻辑。一旦显示更新,我会留给你。

最后,txtSeconds.setText(sec + "");不是使用setText()的好方法(对于日志消息可能没问题,但最好习惯于以其他方式使用文本)。显示文本的方法不止一种,但对于此实例,您需要特殊的格式。那就是你希望你的显示器显示每个数字“00:09:07”而不是“0:9:7”的前导0。你可以用

来搞定
txtSeconds.setText(String.format("%02d", sec));

这种方式总是给出一个2位数的显示,从0到59.其他有用的格式化器是32位十六进制的“%08x”或“%。2f”,它将显示限制在小数点后的2位,如显示美元和美分。

所以,这些都不会解决你的帖子中的问题,但是它们会使你的最终代码更接近它所需要的。正如我所说,你的代码更新了我的显示(不使用时间选择器)。您可以先将sec设置为固定数字,然后点击“开始”按钮查看会发生什么。如果你的时间选择器有问题,你可以使用日志消息来追踪错误和解决它们。

修改

所以你的计时器没有启动会发生什么,当你更改数字选择器中的显示时,你没有设置基础变量(sec等)。定义一些变量用作临时存储( temp_sec等)然后在onValueChange()

中设置此项
temp_sec = newVal;

现在在您的positiveButton onClick()中,您将拥有

sec = temp_sec;