2017-02-22 7 views
2

Я работаю над приложением Android-калькулятора, не использующим встроенные таймерные классы на Android, но вместо этого использую Handlers и Threads для обновления пользовательского интерфейса. Я не уверен, есть ли проблема с моей логикой или нет, но по какой-то причине, когда я устанавливаю время и нажимаю кнопку «Пуск», на экране вообще ничего не происходит. Целевой TextView не уменьшается, как следует. Опять же, я, возможно, сделал простые ошибки (или несколько), но я отправляю свои java и xml-файлы для всех вас, чтобы посмотреть. Заранее спасибо за любые ответы.Проблема с кнопкой «Пуск» на Android-калькуляторе

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

Там в несколько вещей происходит в вашем коде. Я не буду пытаться обращаться к ним всем, кроме некоторых, чтобы заставить ваш код делать то, что ему нужно. Я скопировал &, попробовал ваш код &, это фактически меняет отображение для меня. Я пропустил ваши диалоги выбора времени & только что установил sec=20. Если вы не получаете какой-либо изменяющийся дисплей, отображается ли экран, исходящий из набора времени?

В любом случае, давайте поговорим об отладке. Один из способов сделать это - поставить логические операторы в свой код. Начало, помещая это в верхней части файла

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); 

Имея эти сообщения журнала могут помочь вам узнать, что ваша программа сделала &, что она hasn 't, плюс показать вам некоторые значения переменных. Вы также можете использовать отладчик, к которому я сейчас не подключаюсь.

Теперь для вашего кода. onStart() - метод жизненного цикла. Вы не должны называть это самим. Переименуйте свой метод (возможно, что-то вроде onStartButton()). Поскольку у вас есть это сейчас, у вас есть 2 экземпляра вашего потока, и ваш счетчик спускается дважды в секунду.

В handleMessage() у вас есть переменные (hrs, min, sec), которые вы используете для отслеживания времени, но у вас также есть zeroCheck, который вы читаете из текста на дисплее. Лучше всего было бы использовать переменные, которые вы уже сохраняете (if(sec > 0) { sec -= 1;...). Я не проверял вашу логику в остальных этих условиях. Как только дисплей будет обновлен, я оставлю это для вас.

Наконец, txtSeconds.setText(sec + ""); не является хорошим способом использования setText() (вероятно, это нормально для сообщений журнала, но лучше привыкнуть к использованию текста другими способами). Существует более одного хорошего способа отображения текста, но для этого экземпляра вам требуется специальное форматирование. То есть вы хотите, чтобы ваш дисплей показывал ведущее 0 для каждого номера «00:09:07», а не «0: 9: 7». Вы можете получить, что с

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

Таким образом, всегда дает дисплей 2 цифры от 0 до 59. Других полезных форматтеров являются «% 08X» для 32-битных шестнадцатеричных или «% .2f», который ограничивает дисплей 2 места мимо десятичной точки, например, для показа долларов и центов.

Таким образом, ни одна из этих проблем не устранит проблему в вашем сообщении, но они вернут ваш окончательный код ближе к тому, что ему нужно. Как я уже сказал, ваш код обновляет отображение, как и для меня (не используя таймеры).Вы можете начать с установки sec на фиксированное число, а затем нажать кнопку «Старт», чтобы узнать, что произойдет. Если в ваших сборщиках времени есть проблемы, вы можете использовать сообщения журнала для отслеживания ошибок & исправить их.

EDIT:

Так что происходит с таймер не запускается в том, что, в то время как вы изменить отображение в ваш номер сборщика, не установить основные переменные (sec и т.д.) Определите некоторые переменные использовать в качестве хранилища темп (temp_sec и т.д.), а затем установить это в onValueChange(),

temp_sec = newVal; 

Теперь в вашем positiveButton onClick(), вы будете иметь

sec = temp_sec; 
+0

Wow !! Спасибо! Я все еще привык к использованию сообщений журнала. Так что спасибо за советы и другие. Вернемся назад, чтобы применить их и дойти до корня проблемы. –

+0

О, еще одна вещь, вы сказали, что она обновила дисплей для вас, когда значение не было задано с помощью выбора числа, верно? –

+0

Это правильно. Я был ленив и не хотел иметь дело со сборщиками чисел, поэтому я просто помещал это в файл 'private int hrs = 0, min = 0, sec = 20;' – Gary99

Смежные вопросы