【问题标题】:Automatic Countdown Timer on Button Click按钮点击自动倒计时
【发布时间】:2015-10-17 01:02:39
【问题描述】:

所以我正在创建一个锻炼应用程序,在该应用程序中,我必须在一定时间后更改按钮上的文本以表示新设置。单击“开始”按钮后,我希望计时器自动运行,直到完成所有锻炼设置。如果按下“暂停”按钮,则当前计时器将停止,直到再次按下开始按钮。我想知道该怎么做。我尝试在 for 循环中执行此操作,每次都创建一个新计时器,但在运行一次后它就停止了。对此有什么想法吗?我虽然想使用 Handler 来做到这一点,但我不知道该怎么做。

package com.dwolford.workoutroutine;

import android.os.CountDownTimer;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;


public class Vertical extends ActionBarActivity {

Handler handler = new Handler();
Button jumpRope;
Button start;
Button pause;
Button back;
EditText timeLeft;
String[] verticalWorkouts = {"JUMP ROPE", "STRETCH", "JUMP ROPE", "STRETCH",
        "SLOW MOTION SQUATS", "STRETCH", "LATERAL JUMPS", "STRETCH", "ALTERNATING JUMP LUNGES", "STRETCH", "TUCK JUMPS", "STRETCH", "TOE RAISES", "STRETCH",
        "SLOW MOTION SQUATS", "STRETCH", "LATERAL JUMPS", "STRETCH", "ALTERNATING JUMP LUNGES", "STRETCH", "TUCK JUMPS", "STRETCH", "TOE RAISES", "STRETCH",
        "SLOW MOTION SQUATS", "STRETCH", "LATERAL JUMPS", "STRETCH", "ALTERNATING JUMP LUNGES", "STRETCH", "TUCK JUMPS", "STRETCH", "TOE RAISES", "STRETCH"};


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


    jumpRope = (Button)findViewById(R.id.jumpRope);
    jumpRope.setFocusableInTouchMode(true);
    jumpRope.requestFocus();


    timeLeft = (EditText)findViewById(R.id.time_left);
    start = (Button)findViewById(R.id.start);
    start.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            for(int i = 0; i < verticalWorkouts.length; i++)
            {
                final int iTemp = i;
                new CountDownTimer(2000, 1000) {

                    public void onTick(long millisUntilFinished) {
                        timeLeft.setText("secs: " + millisUntilFinished / 1000);
                    }

                    int temp = iTemp;
                    public void onFinish() {
                        timeLeft.setText("done!");

                        jumpRope.setText(verticalWorkouts[temp]);
                    }
                }.start();
            }
        }
    });

    pause = (Button)findViewById(R.id.pause);
    pause.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            jumpRope.setText(verticalWorkouts[2]);
        }
    });

    back = (Button)findViewById(R.id.back);
    back.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_vertical, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

这是 XML:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="WORKOUT: VERTICAL"
    android:id="@+id/title"
    android:height="50dp"
    android:textSize="22dp"
    android:gravity="center_horizontal"
    android:textStyle="bold"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Toe Raises"

    android:state_pressed="true"

    android:id="@+id/toeRaises"
    android:layout_below="@+id/tuckJumps"
    android:background="@drawable/button_gradient"
    android:layout_alignParentLeft="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Tuck Jumps"
    android:id="@+id/tuckJumps"
    android:layout_below="@+id/altJumpLunge"
    android:background="@drawable/button_gradient"
    android:layout_alignParentLeft="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Alternating jump lunges"
    android:id="@+id/altJumpLunge"
    android:layout_below="@+id/latJump"
    android:background="@drawable/button_gradient"
    android:layout_alignParentLeft="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Lateral jumps"
    android:id="@+id/latJump"
    android:layout_below="@+id/button7"
    android:background="@drawable/button_gradient"
    android:layout_alignParentLeft="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Slow motion squats"
    android:id="@+id/button7"
    android:layout_below="@+id/stretch"
    android:background="@drawable/button_gradient"
    android:layout_alignParentLeft="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Stretch"
    android:id="@+id/stretch"
    android:layout_below="@+id/jumpRope"
    android:background="@drawable/button_gradient"
    android:layout_alignParentLeft="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="JUMP ROPE"
    android:id="@+id/jumpRope"
    android:layout_below="@+id/title"
    android:layout_alignParentLeft="true"
    android:background="@drawable/button_gradient"
    android:layout_alignParentStart="true" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TIME:"
    android:id="@+id/time"
    android:height="50dp"
    android:textSize="22dp"
    android:gravity="center_horizontal"
    android:textStyle="bold"
    android:layout_alignBottom="@+id/jumpRope"
    android:layout_alignRight="@+id/title"
    android:layout_alignEnd="@+id/title" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Sets Left: "
    android:id="@+id/setsLeft"
    android:height="50dp"
    android:textSize="22dp"
    android:gravity="center_horizontal"
    android:textStyle="bold"
    android:layout_below="@+id/toeRaises"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Pause"
    android:id="@+id/pause"
    android:background="@drawable/button_gradient"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="start"
    android:id="@+id/start"
    android:layout_alignTop="@+id/pause"
    android:background="@drawable/button_gradient"
    android:layout_centerHorizontal="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="back"
    android:id="@+id/back"
    android:background="@drawable/button_gradient"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/editText2"
    android:layout_below="@+id/toeRaises"
    android:layout_toRightOf="@+id/toeRaises"
    android:layout_alignRight="@+id/latJump"
    android:layout_alignEnd="@+id/latJump" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/time_left"
    android:layout_below="@+id/time"
    android:layout_alignRight="@+id/back"
    android:layout_alignEnd="@+id/back"
    android:layout_alignLeft="@+id/time"
    android:layout_alignStart="@+id/time" />

【问题讨论】:

  • 如果您的问题得到回答,请确保将回复标记为答案。

标签: android countdowntimer android-handler


【解决方案1】:

在我的应用程序中,我实现了一个处理程序。这是一段未经测试的摘录:

private TextView time;
private boolean isPause;
private long startTime;
private long millis;
private long elapsedTime;
private final int MAXTIME = 10000;
private Handler timeHandler = new Handler();
private Runnable timeRunnable = new Runnable(){
    @Override
    public synchronized void run(){
        if(!isPause){
            millis = System.currentTimeMillis() - startTime;
            updateMyTextView();
            checkEnd();
        }
        //here you can add other stuff...
        timeHandler.postDelayed(this, 500); 
}};

@Override
protected void onCreate(Bundle savedInstanceState) {

    //...

    isPause = false;
    startTime = System.currentTimeMillis();
    time = (TextView) findViewById(R.id.timerTextView);
    time.setText("Time: " + String.valueOf(MAXTIME/1000)); //MAXTIME -> how many milliseconds your timer should work overall
    elapsedTime = 0; //buffer for pause

    timeHandler.postDelayed(timeRunnable, 0);        
}

private void updateMyTextView(){
    timerTextView.setText("Time: " + String.valueOf((MAXTIME-millis)/1000));
}

private synchronized void checkEnd(){
    if(millis >= MAXTIME){
        isPause = true;
        timerTextView.setText("Time: OUT OF TIME");
    }
}

private void startAgain(){
    startTime = System.currentTimeMillis();
    time.setText("Time: " + String.valueOf(MAXTIME/1000));
    elapsedTime = 0;
    isPause = false;
}

@Override
public synchronized void onClick(View v) {
    if(v == pause){
        if (isPause) {
            isPause = false;
            SoundManager.getInstance().resume();
            pause.setImageResource(R.drawable.pause);
            startTime = System.currentTimeMillis() - elapsedTime ;
        } else {
            isPause = true;
            SoundManager.getInstance().pause();
            pause.setImageResource(R.drawable.start);
            elapsedTime = System.currentTimeMillis() - startTime;
        }
    }
    //... here you can add buttons for restart
}

@Override
public synchronized void onPause() {
    elapsedTime = System.currentTimeMillis() - startTime;           
    super.onPause();
}

@Override
public synchronized void onResume(){
    super.onResume();
    startTime = System.currentTimeMillis() - elapsedTime ;
}

在 Runnable 中,我正在更新一个称为毫秒的时间变量。有一个按钮用于开始/暂停倒计时。如果按钮被按下,变量 elapsedTime 有助于在暂停后恢复正确的时间。如果要重新启动,可以调用方法 startAgain()。运行时由常量 MAXTIME 指定。

【讨论】:

    【解决方案2】:

    我能想到的另一种方法是让计时器在单独的线程上运行。

    long lastPauseTimelong currentTimelong elapsedTimeboolean isPaused 声明为字段变量。每当按下暂停按钮时切换isPaused。并在一个线程中实现这个伪代码:

    while countdownTime > 0: 
    
        if isPaused:
            lastPauseTime = currentTime
        else: 
            elapsedTime = elapsedTime + (currentTime - lastPauseTime)
    
        countdownTime = timeLimit - elapsedTime 
        TextView --> display countdownTime
    

    然后通过开始、停止、锻炼类型等功能增强这些功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-06
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多