Android Open Source - XStopwatch Stopwatch Text






From Project

Back to project page XStopwatch.

License

The source code is released under:

GNU General Public License

If you think the Android project XStopwatch listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * XStopwatch / XTimer/*from  www .  jav  a  2s .  c  o  m*/
 * Copyright (C) 2014 by Dan Wallach
 * Home page: http://www.cs.rice.edu/~dwallach/xstopwatch/
 * Licensing: http://www.cs.rice.edu/~dwallach/xstopwatch/licensing.html
 */
package org.dwallach.xstopwatch;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;

import java.util.Observable;
import java.util.Observer;

/**
 * This class acts something like android.widget.Chronometer, but that class only knows
 * how to count up, and we need to be able to go up (for a stopwatch) and down (for a timer).
 *
 * When running, the text is updated once a second, with text derived from the SharedState
 * (which might be either StopwatchState or TimerState).
 */
public class StopwatchText extends View implements Observer {
    private final static String TAG = "StopwatchText";

    private boolean visible = true;
    private SharedState state;
    private String shortName;
    Paint textPaint;

    public StopwatchText(Context context, AttributeSet attrs) {
        super(context, attrs);

        setWillNotDraw(false);

        textPaint = new Paint(Paint.SUBPIXEL_TEXT_FLAG | Paint.HINTING_ON);
        textPaint.setAntiAlias(true);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setColor(Color.WHITE);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTypeface(Typeface.MONOSPACE);
    }

    public StopwatchText(Context context) {
        super(context);
    }

    static final int MSG_UPDATE_TIME = 0;

    /** Handler to update the time once a second in interactive mode. */
    private final Handler updateTimeHandler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case MSG_UPDATE_TIME:
                    invalidate();
                    if (visible && state.isRunning()) {
                        long timeMs = System.currentTimeMillis();
                        long delayMs = 1000 - (timeMs % 1000);
                        updateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
                    } else {
                        Log.v(TAG, shortName + "time handler complete");
                    }
                    break;
            }
        }
    };


    public void setSharedState(SharedState sharedState) {
        this.state = sharedState;
        this.shortName = sharedState.getShortName();
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        visible = (visibility == VISIBLE);

        Log.v(TAG, shortName + "visible: " + visible);

        if(state != null)
            state.setVisible(visible);

        if(visible) {
            updateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME); // now, rather than later
        } else {
            updateTimeHandler.removeMessages(MSG_UPDATE_TIME);
        }
    }

    private float textX, textY;

    @Override
    protected void onSizeChanged (int w, int h, int oldw, int oldh) {
        Log.v(TAG, shortName + "size change: " + w + ", " + h);
        this.width = w;
        this.height = h;
        int textSize = (h*3)/5;

        Log.v(TAG, shortName + "new text size: " + textSize);

        textPaint.setTextSize(textSize);
        //
        // note: metrics.ascent is a *negative* number while metrics.descent is a *positive* number
        //
        Paint.FontMetrics metrics = textPaint.getFontMetrics();
        textY = -metrics.ascent;
        textX = w/2;

        //
        // In some weird cases, we get an onSizeChanged but not an onVisibilityChanged
        // event, even though visibility did change; Lovely.
        //
        onVisibilityChanged(null, VISIBLE);
    }

    private int width, height;


    @Override
    public void onDraw(Canvas canvas) {
//        Log.v(TAG, shortName + "onDraw -- visible: " + visible + ", running: " + state.isRunning());

        if(state == null) {
            Log.e(TAG, shortName + "onDraw: no state yet");
            return;
        }

        String result = state.toString();

//        Log.v(TAG, "update text to: " + result);

        if(width == 0 || height == 0) {
            Log.e(TAG, shortName + "zero-width or zero-height, can't draw yet");
            return;
        }

        // clear the screen: complicated because uggh.
        // http://stackoverflow.com/questions/4650755/clearing-canvas-with-canvas-drawcolor
//        Paint paint = new Paint();
//        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
//        canvas.drawPaint(paint);
//        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));

        // let's see if this works again, because it might do better with the ripple effects than the above
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

        canvas.drawText(result, textX, textY, textPaint);
    }


    @Override
    public void update(Observable observable, Object data) {
        // something changed in the StopwatchState...
        Log.v(TAG, shortName + "update: invalidating text");
        updateTimeHandler.removeMessages(MSG_UPDATE_TIME);
        updateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME); // now, rather than later
    }
}




Java Source Code List

org.dwallach.xstopwatch.Constants.java
org.dwallach.xstopwatch.NotificationHelper.java
org.dwallach.xstopwatch.NotificationService.java
org.dwallach.xstopwatch.PreferencesHelper.java
org.dwallach.xstopwatch.Receiver.java
org.dwallach.xstopwatch.SharedState.java
org.dwallach.xstopwatch.StopwatchActivity.java
org.dwallach.xstopwatch.StopwatchState.java
org.dwallach.xstopwatch.StopwatchText.java
org.dwallach.xstopwatch.TimerActivity.java
org.dwallach.xstopwatch.TimerState.java