Imported Alarm countdown text

This commit is contained in:
Phillip Hsu 2016-06-07 13:16:53 -07:00
parent dca0a258f8
commit 9f151fa9cc
6 changed files with 171 additions and 7 deletions

View File

@ -0,0 +1,26 @@
package com.philliphsu.clock2;
import android.support.annotation.NonNull;
/**
* Created by Phillip Hsu on 4/30/2016.
*/
public interface DurationDisplayer {
/**
* Callback interface to be implemented by a parent/host of this displayer.
* The host should use this to tell its displayer to update its duration text
* via showAsText(long).
*/
/*public*/ interface OnTickListener {
// Listeners implement this to be notified of when
// they should update this displayer's text
void onTick();
}
/** Hosts of this displayer use this to attach themselves */
void setOnTickListener(@NonNull OnTickListener listener);
void startTicking(boolean resume);
void stopTicking();
void forceTick();
void showAsText(long duration);
}

View File

@ -0,0 +1,71 @@
package com.philliphsu.clock2;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import com.philliphsu.clock2.DurationDisplayer.OnTickListener;
import static com.philliphsu.clock2.util.Preconditions.checkNotNull;
/**
* Created by Phillip Hsu on 4/18/2016.
*/
public class TickHandler extends Handler {
private static final int MSG_TICK = 0;
private static final int MSG_FORCE_TICK = 1;
@NonNull private final OnTickListener mOnTickListener;
private final long mTickInterval;
public TickHandler(@NonNull OnTickListener listener, long tickInterval) {
super(Looper.getMainLooper());
mOnTickListener = checkNotNull(listener);
mTickInterval = tickInterval;
}
@Override
public void handleMessage(Message msg) {
// Account for the time showDuration() takes to execute
// and subtract that off from the countdown interval
// (so the countdown doesn't get postponed by however long
// showDuration() takes)
long startOnTick = SystemClock.elapsedRealtime();
mOnTickListener.onTick();
long countdownRemainder = mTickInterval -
(SystemClock.elapsedRealtime() - startOnTick);
// special case: onTick took longer than countdown
// interval to complete, skip to next interval
while (countdownRemainder < 0)
countdownRemainder += mTickInterval;
if (msg.what == MSG_TICK) { // as opposed to MSG_FORCE_TICK
sendMessageDelayed(obtainMessage(MSG_TICK), mTickInterval);
}
}
public void startTicking(boolean resume) {
if (hasMessages(MSG_TICK))
return;
if (resume) {
sendMessage(obtainMessage(MSG_TICK));
} else {
sendMessageDelayed(obtainMessage(MSG_TICK), mTickInterval);
}
}
public void stopTicking() {
removeMessages(MSG_TICK);
}
/**
* Forces a single call to {@link OnTickListener#onTick() onTick()}
* without scheduling looped messages on this handler.
*/
public void forceTick() {
sendMessage(obtainMessage(MSG_FORCE_TICK));
}
}

View File

@ -0,0 +1,53 @@
package com.philliphsu.clock2.alarms;
import android.content.Context;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.widget.TextView;
import com.philliphsu.clock2.DurationDisplayer;
import com.philliphsu.clock2.TickHandler;
import com.philliphsu.clock2.util.DurationUtils;
/**
* Created by Phillip Hsu on 4/30/2016.
*/
public class AlarmCountdown extends TextView implements DurationDisplayer {
private static final String TAG = "NextAlarmText";
private static final int TICK_INTERVAL = 60000; // per minute
private TickHandler mHandler;
public AlarmCountdown(Context context) {
super(context);
}
public AlarmCountdown(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setOnTickListener(@NonNull OnTickListener listener) {
mHandler = new TickHandler(listener, TICK_INTERVAL);
}
@Override
public void showAsText(long duration) {
setText(DurationUtils.toString(getContext(), duration, true));
}
@Override
public void startTicking(boolean resume) {
mHandler.startTicking(resume);
}
@Override
public void stopTicking() {
mHandler.stopTicking();
}
@Override
public void forceTick() {
mHandler.forceTick();
}
}

View File

@ -31,18 +31,19 @@ import static com.philliphsu.clock2.util.DateFormatUtils.formatTime;
/** /**
* Created by Phillip Hsu on 5/31/2016. * Created by Phillip Hsu on 5/31/2016.
*/ */
public class AlarmViewHolder extends BaseViewHolder<Alarm> { public class AlarmViewHolder extends BaseViewHolder<Alarm> implements AlarmCountdown.OnTickListener {
private static final RelativeSizeSpan AMPM_SIZE_SPAN = new RelativeSizeSpan(0.5f); private static final RelativeSizeSpan AMPM_SIZE_SPAN = new RelativeSizeSpan(0.5f);
@Bind(R.id.time) TextView mTime; @Bind(R.id.time) TextView mTime;
@Bind(R.id.on_off_switch) SwitchCompat mSwitch; @Bind(R.id.on_off_switch) SwitchCompat mSwitch;
@Bind(R.id.label) TextView mLabel; @Bind(R.id.label) TextView mLabel;
@Bind(R.id.countdown) TextView mCountdown; // TODO: Change type to NextAlarmText, once you move that class to this project @Bind(R.id.countdown) AlarmCountdown mCountdown;
@Bind(R.id.recurring_days) TextView mDays; @Bind(R.id.recurring_days) TextView mDays;
@Bind(R.id.dismiss) Button mDismissButton; @Bind(R.id.dismiss) Button mDismissButton;
public AlarmViewHolder(ViewGroup parent, OnListItemInteractionListener<Alarm> listener) { public AlarmViewHolder(ViewGroup parent, OnListItemInteractionListener<Alarm> listener) {
super(parent, R.layout.item_alarm, listener); super(parent, R.layout.item_alarm, listener);
mCountdown.setOnTickListener(this);
} }
@Override @Override
@ -88,9 +89,14 @@ public class AlarmViewHolder extends BaseViewHolder<Alarm> {
bindDays(num > 0, text); bindDays(num > 0, text);
} }
@Override
public void onTick() {
mCountdown.showAsText(getAlarm().ringsIn());
}
@OnClick(R.id.dismiss) @OnClick(R.id.dismiss)
void onClick() { void onClick() {
AlarmUtils.cancelAlarm(getContext(), getItem()); AlarmUtils.cancelAlarm(getContext(), getAlarm());
bindDismissButton(false, ""); // Will be set to correct text the next time we bind. bindDismissButton(false, ""); // Will be set to correct text the next time we bind.
// TODO: Check if alarm has no recurrence, then turn it off. // TODO: Check if alarm has no recurrence, then turn it off.
} }
@ -113,11 +119,11 @@ public class AlarmViewHolder extends BaseViewHolder<Alarm> {
private void bindCountdown(boolean enabled, long remainingTime) { private void bindCountdown(boolean enabled, long remainingTime) {
if (enabled) { if (enabled) {
//TODO:mCountdown.showAsText(remainingTime); mCountdown.showAsText(remainingTime);
//TODO:mCountdown.getTickHandler().startTicking(true) mCountdown.startTicking(true);
mCountdown.setVisibility(VISIBLE); mCountdown.setVisibility(VISIBLE);
} else { } else {
//TODO:mCountdown.getTickHandler().stopTicking(); mCountdown.stopTicking();
mCountdown.setVisibility(GONE); mCountdown.setVisibility(GONE);
} }
} }
@ -140,4 +146,8 @@ public class AlarmViewHolder extends BaseViewHolder<Alarm> {
private void setVisibility(@NonNull View view, boolean visible) { private void setVisibility(@NonNull View view, boolean visible) {
view.setVisibility(visible ? VISIBLE : GONE); view.setVisibility(visible ? VISIBLE : GONE);
} }
private Alarm getAlarm() {
return getItem();
}
} }

View File

@ -12,6 +12,10 @@ import java.util.concurrent.TimeUnit;
* Created by Phillip Hsu on 6/6/2016. * Created by Phillip Hsu on 6/6/2016.
*/ */
public class DurationUtils { public class DurationUtils {
public static final int HOURS = 0;
public static final int MINUTES = 1;
public static final int SECONDS = 2;
public static final int MILLIS = 3;
/** Return a string representing the duration, formatted in hours and minutes. /** Return a string representing the duration, formatted in hours and minutes.
* TODO: Need to adapt this to represent all time fields eventually */ * TODO: Need to adapt this to represent all time fields eventually */

View File

@ -42,7 +42,7 @@
android:layout_below="@id/time_layout" android:layout_below="@id/time_layout"
android:layout_marginBottom="@dimen/item_margin_between_elements"/> android:layout_marginBottom="@dimen/item_margin_between_elements"/>
<TextView <com.philliphsu.clock2.alarms.AlarmCountdown
android:id="@+id/countdown" android:id="@+id/countdown"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"