I am creating a custom analog clock with images for hour, second, minute hands. The clock works fine but only problem is the anchoring of the hands. Below is an image of the clock attached. The hour, minute hands are anchored at the center which makes the clock look bad. All the hands should be anchored at the edges so that it looks more realistic and readable. Can someone suggest something. My custom view is attached here.
package com.example.submission_customclock;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews.RemoteView;
import java.util.TimeZone;
/**
* This widget display an analogic clock with two hands for hours and
* minutes.
*
* #attr ref android.R.styleable#AnalogClock_dial
* #attr ref android.R.styleable#AnalogClock_hand_hour
* #attr ref android.R.styleable#AnalogClock_hand_minute
*/
#RemoteView
public class AnalogClock extends View {
private Time mCalendar;
private static final String DEBUGTAG = "FA";
private Drawable mHourHand;
private Drawable mMinuteHand;
private Drawable mSecondHand;
private Drawable mDial;
private Drawable mDial_frame;
private int mDialWidth;
private int mDialHeight;
private boolean mAttached;
private final Handler mHandler = new Handler();
private float mMinutes;
private float mHour;
private boolean mChanged;
public AnalogClock(Context context) {
this(context, null);
}
public AnalogClock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
Context mContext;
public AnalogClock(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
Resources r = context.getResources();
mContext=context;
Log.d(AnalogClock.DEBUGTAG,"Analog clock started");
mDial = r.getDrawable(R.drawable.clock4);
mDial_frame = r.getDrawable(R.drawable.clock_frame);
mHourHand = r.getDrawable(R.drawable.hour_hand);
mMinuteHand = r.getDrawable(R.drawable.minute_hand);
mSecondHand = r.getDrawable(R.drawable.second_hand);
mCalendar = new Time();
mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mAttached) {
mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
// in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time
mCalendar = new Time();
// Make sure we update to the current time
onTimeChanged();
counter.start();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
counter.cancel();
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
float hScale = 1.0f;
float vScale = 1.0f;
if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
hScale = (float) widthSize / (float) mDialWidth;
}
if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
vScale = (float )heightSize / (float) mDialHeight;
}
float scale = Math.min(hScale, vScale);
Log.d(AnalogClock.DEBUGTAG,"onMeasure params: " + widthSize + " "
+ heightSize + " " + hScale + " " + vScale + " " + scale);
try {
setMeasuredDimension(resolveSizeAndState((int) (mDialWidth * scale), widthMeasureSpec, 0),
resolveSizeAndState((int) (mDialHeight * scale), heightMeasureSpec, 0));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mChanged = true;
}
boolean mSeconds=false;
float mSecond=0;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean changed = mChanged;
if (changed) {
mChanged = false;
}
boolean seconds = mSeconds;
if (seconds ) {
mSeconds = false;
}
int availableWidth = this.getMeasuredWidth();
int availableHeight = this.getMeasuredHeight();
int x = availableWidth / 2;
int y = availableHeight / 2;
final Drawable dial = mDial;
final Drawable dial_frame = mDial_frame;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
// Log.d(AnalogClock.DEBUGTAG,"onDraw params: " + availableWidth +" "+ availableHeight + " " +
// x + " " + y + " " + w + " "+ h + " " + changed);
if (availableWidth < w || availableHeight < h) {
scaled = true;
//float scale = Math.min((float) availableWidth / (float) w,
// (float) availableHeight / (float) h);
canvas.save();
float scale1 = (float) 0.6;
float scale2 = (float) 0.8;
// Log.d(AnalogClock.DEBUGTAG,"scale params: " + scale1 + " " + scale2);
canvas.scale(scale1, scale2, x, y);
}
if (changed) {
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - (w / 2)) + " " + (y - (h / 2)) + " " + ( x + (w / 2)) + " " + (y + (h / 2)));
dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
//dial_frame.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - (w / 2 + w/10)) + " " + (y - (h / 2 + h/10)) + " " + ( x + (w / 2 + w/10)) + " " +
// (y + (h / 2 + h/10)));
dial_frame.setBounds(x - (w/2 + w/10), y - (h/2 + h/10), x + (w/2 + w/10), y + (h/2 + h/10));
}
dial.draw(canvas);
dial_frame.draw(canvas);
canvas.save();
canvas.rotate(mHour / 12.0f * 180.0f, x, y);
final Drawable hourHand = mHourHand;
if (changed) {
w = hourHand.getIntrinsicWidth();
h = hourHand.getIntrinsicHeight();
hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
hourHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mMinutes / 60.0f * 180.0f, x, y);
final Drawable minuteHand = mMinuteHand;
if (changed) {
w = minuteHand.getIntrinsicWidth();
h = minuteHand.getIntrinsicHeight();
minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
minuteHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mSecond, x, y);
if (seconds) {
w = mSecondHand.getIntrinsicWidth();
h = mSecondHand.getIntrinsicHeight();
mSecondHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
mSecondHand.draw(canvas);
canvas.restore();
if (scaled) {
canvas.restore();
}
}
MyCount counter = new MyCount(10000, 1000);
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
counter.start();
}
#Override
public void onTick(long millisUntilFinished) {
mCalendar.setToNow();
int second = mCalendar.second;
mSecond=6.0f*second;
mSeconds=true;
//mChanged = true;
AnalogClock.this.invalidate();
}
}
private void onTimeChanged() {
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
}
onTimeChanged();
invalidate();
}
};
}
your problem is with specific dimensions for clock_frame ,minute_hand,hour_hand and second_hand in drawable folder.for example if you take 240 x 240 clockframe the you should takeminute_hand,hour_hand and second_hand as 19 x 240 and these hands should start from top and end with exactly center position of clock_frame with comparition.if u want more fashionable you can end up with slightly distance from exactly center position of clock_frame
Simplest way is to set hands bitmaps the same size as dial and rotate to 12 o clock.
Related
first this is my textureView class
public abstract class ScalableTextureView extends TextureView{
private static final boolean SHOW_LOGS = false;
private static final String TAG = ScalableTextureView.class.getSimpleName();
private Integer mContentWidth;
private Integer mContentHeight;
private float mPivotPointX = 0f;
private float mPivotPointY = 0f;
private float mContentScaleX = 1f;
private float mContentScaleY = 1f;
private float mContentRotation = 0f;
private float mContentScaleMultiplier = 1f;
private int mContentX = 0;
private int mContentY = 0;
private final Matrix mTransformMatrix = new Matrix();
private ScaleType mScaleType;
public enum ScaleType {
CENTER_CROP, TOP, BOTTOM, FILL,FITX
}
public ScalableTextureView(Context context) {
super(context);
}
public ScalableTextureView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScalableTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ScalableTextureView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setScaleType(ScaleType scaleType) {
mScaleType = scaleType;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (SHOW_LOGS) Logger.v(TAG, "onMeasure, mContentoWidth " + mContentWidth + ", mContentHeight " + mContentHeight);
if (mContentWidth != null && mContentHeight != null) {
updateTextureViewSize();
}
}
public void updateTextureViewSize() {
if (SHOW_LOGS) Logger.d(TAG, ">> updateTextureViewSize");
if (mContentWidth == null || mContentHeight == null) {
throw new RuntimeException("null content size");
}
float viewWidth = getMeasuredWidth();
float viewHeight = getMeasuredHeight();
float contentWidth = mContentWidth;
float contentHeight = mContentHeight;
if (SHOW_LOGS) {
Logger.v(TAG, "updateTextureViewSize, mContentWidth " + mContentWidth + ", mContentHeight " + mContentHeight + ", mScaleType " + mScaleType);
Logger.v(TAG, "updateTextureViewSize, viewWidth " + viewWidth + ", viewHeight " + viewHeight);
}
float scaleX = 1.0f;
float scaleY = 1.0f;
switch (mScaleType) {
case FILL:
if (viewWidth > viewHeight) { // device in landscape
scaleX = (viewHeight * contentWidth) / (viewWidth * contentHeight);
} else {
scaleY = (viewWidth * contentHeight) / (viewHeight * contentWidth);
}
break;
case BOTTOM:
case CENTER_CROP:
case FITX:
case TOP:
if (contentWidth > viewWidth && contentHeight > viewHeight) {
scaleX = contentWidth / viewWidth;
scaleY = contentHeight / viewHeight;
} else if (contentWidth < viewWidth && contentHeight < viewHeight) {
scaleY = viewWidth / contentWidth;
scaleX = viewHeight / contentHeight;
} else if (viewWidth > contentWidth) {
scaleY = (viewWidth / contentWidth) / (viewHeight / contentHeight);
} else if (viewHeight > contentHeight) {
scaleX = (viewHeight / contentHeight) / (viewWidth / contentWidth);
}
break;
}
if (SHOW_LOGS) {
Logger.v(TAG, "updateTextureViewSize, scaleX " + scaleX + ", scaleY " + scaleY);
}
// Calculate pivot points, in our case crop from center
float pivotPointX;
float pivotPointY;
switch (mScaleType) {
case TOP:
pivotPointX = 0;
pivotPointY = 0;
break;
case BOTTOM:
pivotPointX = viewWidth;
pivotPointY = viewHeight;
break;
case CENTER_CROP:
pivotPointX = viewWidth / 2;
pivotPointY = viewHeight / 2;
break;
case FITX:
pivotPointX = viewWidth ;
pivotPointY = viewHeight ;
break;
case FILL:
pivotPointX = mPivotPointX;
pivotPointY = mPivotPointY;
break;
default:
throw new IllegalStateException("pivotPointX, pivotPointY for ScaleType " + mScaleType + " are not defined");
}
if (SHOW_LOGS)
Logger.v(TAG, "updateTextureViewSize, pivotPointX " + pivotPointX + ", pivotPointY " + pivotPointY);
float fitCoef = 1;
switch (mScaleType) {
case FILL:
break;
case BOTTOM:
case CENTER_CROP:
case TOP:
if (mContentHeight > mContentWidth) { //Portrait video
fitCoef = viewWidth / (viewWidth * scaleX);
} else { //Landscape video
fitCoef = viewHeight / (viewHeight * scaleY);
}
break;
}
mContentScaleX = fitCoef * scaleX;
mContentScaleY = fitCoef * scaleY;
mPivotPointX = pivotPointX;
mPivotPointY = pivotPointY;
updateMatrixScaleRotate();
if (SHOW_LOGS) Logger.d(TAG, "<< updateTextureViewSize");
}
private void updateMatrixScaleRotate() {
if (SHOW_LOGS) Logger.d(TAG, ">> updateMatrixScaleRotate, mContentRotation " + mContentRotation + ", mContentScaleMultiplier " + mContentScaleMultiplier + ", mPivotPointX " + mPivotPointX + ", mPivotPointY " + mPivotPointY);
mTransformMatrix.reset();
mTransformMatrix.setScale(mContentScaleX * mContentScaleMultiplier, mContentScaleY * mContentScaleMultiplier, mPivotPointX, mPivotPointY);
mTransformMatrix.postRotate(mContentRotation, mPivotPointX, mPivotPointY);
setTransform(mTransformMatrix);
if (SHOW_LOGS) Logger.d(TAG, "<< updateMatrixScaleRotate, mContentRotation " + mContentRotation + ", mContentScaleMultiplier " + mContentScaleMultiplier + ", mPivotPointX " + mPivotPointX + ", mPivotPointY " + mPivotPointY);
}
private void updateMatrixTranslate() {
if (SHOW_LOGS) {
Logger.d(TAG, "updateMatrixTranslate, mContentX " + mContentX + ", mContentY " + mContentY);
}
float scaleX = mContentScaleX * mContentScaleMultiplier;
float scaleY = mContentScaleY * mContentScaleMultiplier;
mTransformMatrix.reset();
mTransformMatrix.setScale(scaleX, scaleY, mPivotPointX, mPivotPointY);
mTransformMatrix.postTranslate(mContentX, mContentY);
setTransform(mTransformMatrix);
}
#Override
public void setRotation(float degrees) {
if (SHOW_LOGS)
Logger.d(TAG, "setRotation, degrees " + degrees + ", mPivotPointX " + mPivotPointX + ", mPivotPointY " + mPivotPointY);
mContentRotation = degrees;
updateMatrixScaleRotate();
}
#Override
public float getRotation() {
return mContentRotation;
}
#Override
public void setPivotX(float pivotX) {
if (SHOW_LOGS) Logger.d(TAG, "setPivotX, pivotX " + pivotX);
mPivotPointX = pivotX;
}
#Override
public void setPivotY(float pivotY) {
if (SHOW_LOGS) Logger.d(TAG, "setPivotY, pivotY " + pivotY);
mPivotPointY = pivotY;
}
#Override
public float getPivotX() {
return mPivotPointX;
}
#Override
public float getPivotY() {
return mPivotPointY;
}
public float getContentAspectRatio() {
return mContentWidth != null && mContentHeight != null
? (float) mContentWidth / (float) mContentHeight
: 0;
}
/**
* Use it to animate TextureView content x position
* #param x
*/
public final void setContentX(float x) {
mContentX = (int) x - (getMeasuredWidth() - getScaledContentWidth()) / 2;
updateMatrixTranslate();
}
/**
* Use it to animate TextureView content x position
* #param y
*/
public final void setContentY(float y) {
mContentY = (int) y - (getMeasuredHeight() - getScaledContentHeight()) / 2;
updateMatrixTranslate();
}
protected final float getContentX() {
return mContentX;
}
protected final float getContentY() {
return mContentY;
}
/**
* Use it to set content of a TextureView in the center of TextureView
*/
public void centralizeContent() {
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
int scaledContentWidth = getScaledContentWidth();
int scaledContentHeight = getScaledContentHeight();
if (SHOW_LOGS) Logger.d(TAG, "centralizeContent, measuredWidth " + measuredWidth + ", measuredHeight " + measuredHeight + ", scaledContentWidth " + scaledContentWidth + ", scaledContentHeight " + scaledContentHeight);
mContentX = 0;
mContentY = 0;
if (SHOW_LOGS) Logger.d(TAG, "centerVideo, mContentX " + mContentX + ", mContentY " + mContentY);
updateMatrixScaleRotate();
}
public Integer getScaledContentWidth() {
return (int) (mContentScaleX * mContentScaleMultiplier * getMeasuredWidth());
}
public Integer getScaledContentHeight() {
return (int) (mContentScaleY * mContentScaleMultiplier * getMeasuredHeight());
}
public float getContentScale() {
return mContentScaleMultiplier;
}
public void setContentScale(float contentScale) {
if (SHOW_LOGS) Logger.d(TAG, "setContentScale, contentScale " + contentScale);
mContentScaleMultiplier = contentScale;
updateMatrixScaleRotate();
}
protected final void setContentHeight(int height) {
mContentHeight = height;
}
protected final Integer getContentHeight() {
return mContentHeight;
}
protected final void setContentWidth(int width) {
mContentWidth = width;
}
protected final Integer getContentWidth() {
return mContentWidth;
}
}
now all the scale type fill , top , bottom ... not shown all video size its crop part from Video when i play it i just try to add scale type FITX for show all video no cropping
i try this for crop in Fit X
case FITX:
double aspectRatio = (double) viewHeight / viewWidth;
float newWidth, newHeight;
if (viewHeight > (int) (viewWidth* aspectRatio)) {
newWidth = viewWidth;
newHeight = (int) (viewWidth* aspectRatio);
} else {
// limited by short height; restrict width
newWidth = (int) (viewHeight/ aspectRatio);
newHeight = viewHeight;
}
pivotPointX = newWidth ;
pivotPointY = newHeight ;
break;
but its like scale BOTTOM or TOP i don't know how to solve it complicated to me
NOTE ** FITX added by me in code
I want to move the seconds hand smoothly and swiftly as I have watched many watches moving their seconds hand swiftly with out making tick tick movements .
I have tried this code from open source and it is working fine
public class AnalogClock1 extends View {
public AnalogClock1(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
private Time mCalendar;
private Drawable mHourHand;
private Drawable mMinuteHand;
private Drawable mSecondHand;
private Drawable mDial;
private int mDialWidth;
private int mDialHeight;
private boolean mAttached;
private final Handler mHandler = new Handler();
private float mMinutes;
private float mHour;
private float mMillisec;
private boolean mChanged;
Context mContext;
public AnalogClock1(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AnalogClock1(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
Resources r = context.getResources();
TypedArray a =
context.obtainStyledAttributes(
attrs, R.styleable.AnalogClock, defStyle, 0);
mContext=context;
// mDial = a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);
// if (mDial == null) {
mDial = r.getDrawable(R.drawable.clock_dial);
// }
// mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);
// if (mHourHand == null) {
mHourHand = r.getDrawable(R.drawable.clock_hour);
// }
// mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);
// if (mMinuteHand == null) {
mMinuteHand = r.getDrawable(R.drawable.clock_minute);
mSecondHand = r.getDrawable(R.drawable.clockgoog_minute);
// }
mCalendar = new Time();
mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mAttached) {
mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
// in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time
mCalendar = new Time();
// Make sure we update to the current time
onTimeChanged();
counter.start();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
counter.cancel();
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
float hScale = 1.0f;
float vScale = 1.0f;
if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
hScale = (float) widthSize / (float) mDialWidth;
}
if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
vScale = (float )heightSize / (float) mDialHeight;
}
float scale = Math.min(hScale, vScale);
setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),
resolveSize((int) (mDialHeight * scale), heightMeasureSpec));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mChanged = true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean changed = mChanged;
if (changed) {
mChanged = false;
}
boolean seconds = mSeconds;
if (seconds ) {
mSeconds = false;
}
int availableWidth = 200;
int availableHeight = 200;
int x = availableWidth / 2;
int y = availableHeight / 2;
final Drawable dial = mDial;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
if (availableWidth < w || availableHeight < h) {
scaled = true;
float scale = Math.min((float) availableWidth / (float) w,
(float) availableHeight / (float) h);
canvas.save();
canvas.scale(scale, scale, x, y);
}
if (changed) {
dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
dial.draw(canvas);
canvas.save();
canvas.rotate(mHour / 12.0f * 360.0f, x, y);
final Drawable hourHand = mHourHand;
if (changed) {
w = hourHand.getIntrinsicWidth();
h = hourHand.getIntrinsicHeight();
hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
hourHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);
//canvas.rotate(mSecond, x, y);
final Drawable minuteHand = mMinuteHand;
if (changed) {
w = minuteHand.getIntrinsicWidth();
h = minuteHand.getIntrinsicHeight();
minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
minuteHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mSecond, x, y);
//minuteHand = mMinuteHand;
if (seconds) {
w = mSecondHand.getIntrinsicWidth();
h = mSecondHand.getIntrinsicHeight();
mSecondHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
mSecondHand.draw(canvas);
canvas.restore();
if (scaled) {
canvas.restore();
}
}
MyCount counter = new MyCount(10000, 1000);
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
counter.start();
}
#Override
public void onTick(long millisUntilFinished) {
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mSecond=6.0f*second;
mSeconds=true;
//mChanged = true;
AnalogClock1.this.invalidate();
//Toast.makeText(mContext, "text", Toast.LENGTH_LONG).show();
}
}
boolean mSeconds=false;
float mSecond=0;
private void onTimeChanged() {
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
}
onTimeChanged();
invalidate();
}
};
}
Please help me out.
I think that you got to change the values that you are assigning to the Counter class.
in the particular case I think that you should really need to change the values in the Following line inside your code.
MyCount counter = new MyCount(10000, 1000);
please rate if this works.
I have created a circle in custom view. I want to add 6 colors to it based on a condition. The 6 regions will keep changing based on the condition. For eg, each region can vary from 30 degrees to 90 degrees to 120 degrees.
My question is
1) How do I add 6 colors to the circle. Please note that I cannot divide the circle into 6 equal regions, thats not how it is supposed to be.
2) How do I assign the starting and ending points of the regions. For example if I want to add green color from 45degrees to 90 degrees. How do I do this?
The end product is supposed to look as below
package com.example.submission_customclock;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews.RemoteView;
import java.util.TimeZone;
/**
* This widget display an analogic clock with two hands for hours and
* minutes.
*
* #attr ref android.R.styleable#AnalogClock_dial
* #attr ref android.R.styleable#AnalogClock_hand_hour
* #attr ref android.R.styleable#AnalogClock_hand_minute
*/
#RemoteView
public class AnalogClock extends View {
private Time mCalendar;
private static final String DEBUGTAG = "FA";
private Drawable mHourHand;
private Drawable mMinuteHand;
private Drawable mSecondHand;
private Drawable mDial;
private Drawable mDial_frame;
private Drawable mDial_center;
private int mDialWidth;
private int mDialHeight;
private boolean mAttached;
private final Handler mHandler = new Handler();
private float mMinutes;
private float mHour;
private boolean mChanged;
public AnalogClock(Context context) {
this(context, null);
}
public AnalogClock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
Context mContext;
public AnalogClock(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
Resources r = context.getResources();
mContext=context;
Log.d(AnalogClock.DEBUGTAG,"Analog clock started");
mDial = r.getDrawable(R.drawable.clock4);
mDial_frame = r.getDrawable(R.drawable.clock_frame);
mDial_center = r.getDrawable(R.drawable.clock_dot);
mHourHand = r.getDrawable(R.drawable.hour_hand);
mMinuteHand = r.getDrawable(R.drawable.minute_hand);
mSecondHand = r.getDrawable(R.drawable.second_hand);
mCalendar = new Time();
mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mAttached) {
mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
// in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time
mCalendar = new Time();
// Make sure we update to the current time
onTimeChanged();
counter.start();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
counter.cancel();
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
float hScale = 1.0f;
float vScale = 1.0f;
if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
hScale = (float) widthSize / (float) mDialWidth;
}
if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
vScale = (float )heightSize / (float) mDialHeight;
}
float scale = Math.min(hScale, vScale);
Log.d(AnalogClock.DEBUGTAG,"onMeasure params: " + widthSize + " "
+ heightSize + " " + hScale + " " + vScale + " " + scale);
try {
setMeasuredDimension(resolveSizeAndState((int) (mDialWidth * scale), widthMeasureSpec, 0),
resolveSizeAndState((int) (mDialHeight * scale), heightMeasureSpec, 0));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mChanged = true;
}
boolean mSeconds=false;
float mSecond=0;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean changed = mChanged;
if (changed) {
mChanged = false;
}
boolean seconds = mSeconds;
if (seconds ) {
mSeconds = false;
}
int availableWidth = this.getMeasuredWidth();
int availableHeight = this.getMeasuredHeight();
int x = availableWidth / 2;
int y = availableHeight / 2;
final Drawable dial = mDial;
final Drawable dial_frame = mDial_frame;
final Drawable dial_dot = mDial_center;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
// Log.d(AnalogClock.DEBUGTAG,"onDraw params: " + availableWidth +" "+ availableHeight + " " +
// x + " " + y + " " + w + " "+ h + " " + changed);
if (availableWidth < w || availableHeight < h) {
scaled = true;
//float scale = Math.min((float) availableWidth / (float) w,
// (float) availableHeight / (float) h);
canvas.save();
float scale1 = (float) 0.6;
float scale2 = (float) 0.8;
// Log.d(AnalogClock.DEBUGTAG,"scale params: " + scale1 + " " + scale2);
canvas.scale(scale1, scale2, x, y);
}
if (changed) {
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - (w / 2)) + " " + (y - (h / 2)) + " " + ( x + (w / 2)) + " " + (y + (h / 2)));
dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
//dial_frame.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - (w / 2 + w/10)) + " " + (y - (h / 2 + h/10)) + " " + ( x + (w / 2 + w/10)) + " " +
// (y + (h / 2 + h/10)));
dial_frame.setBounds(x - (w/2 + w/10), y - (h/2 + h/10), x + (w/2 + w/10), y + (h/2 + h/10));
dial_dot.setBounds(x -30 , y -20 , x + 30, y + 20);
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x ) + " " + (y) + " " + ( x + (w / 2 )) + " " +
// (y + (h / 2)));
}
int radius = 0;
if(x>y)
radius=y-10;
else
radius=x-10;
Paint circlepaint;
circlepaint = new Paint();
circlepaint.
dial.draw(canvas);
dial_frame.draw(canvas);
// canvas.drawCircle(x, y, radius, circlepaint);
canvas.save();
canvas.rotate(mHour / 12.0f * 180.0f, x - 10, y - 10);
final Drawable hourHand = mHourHand;
if (changed) {
w = hourHand.getIntrinsicWidth();
h = hourHand.getIntrinsicHeight();
hourHand.setBounds(x -w/2, y - h/2 - h/4 , x + w/6, y + h/6);
}
hourHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mMinutes / 60.0f * 360.0f, x - 10, y - 10);
final Drawable minuteHand = mMinuteHand;
if (changed) {
w = minuteHand.getIntrinsicWidth();
h = minuteHand.getIntrinsicHeight();
//minuteHand.setBounds(x, y, x + (w / 2 + w/10), y + (h / 2 + w/10));
minuteHand.setBounds(x - w, y - h/2, x + w/6, y + h/6);
// Log.d(AnalogClock.DEBUGTAG,"Bounds params:x " + (x) + " y " + (y) + " w " + ( w ) + " h " +
// (h));
// Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - w) + " " + (y - h/2) + " " + ( x ) + " " +
// (y));
}
minuteHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mSecond, x, y);
if (seconds) {
w = mSecondHand.getIntrinsicWidth();
h = mSecondHand.getIntrinsicHeight();
// mSecondHand.setBounds(x, y, x + (w / 2 + w/10), y + (h / 2 + w/10));
mSecondHand.setBounds(x-w/6, y-h/6, x + w,y + h/2);
Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x ) + " " + (y) + " " + ( w) + " " +
(h));
}
mSecondHand.draw(canvas);
canvas.restore();
canvas.save();
dial_dot.draw(canvas);
if (scaled) {
canvas.restore();
}
}
MyCount counter = new MyCount(10000, 1000);
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
counter.start();
}
#Override
public void onTick(long millisUntilFinished) {
mCalendar.setToNow();
int second = mCalendar.second;
mSecond=6.0f*second;
mSeconds=true;
//mChanged = true;
AnalogClock.this.invalidate();
}
}
private void onTimeChanged() {
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
}
onTimeChanged();
invalidate();
}
};
}
In my android application, i want to apply image warp effect provided in Photo Warp and Photo Deformer application. For that i used BitmapMesh. The problem is that, it's not saving warped image. Whenever i touch image, it refresh the image and doesn't save my previously warped image.I want to save that image whenever user perform warp operation. Here i am posting my code. Here i am using "BitmapMesh" activity to perform warp effect on image.
Please help me to solve this problem.
Thanks.
Code:
BitmapMesh Activity:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
public class BitmapMesh extends GraphicsActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private static final int WIDTH = 20;
private static final int HEIGHT = 20;
private static final int COUNT = (WIDTH + 1) * (HEIGHT + 1);
private final Bitmap mBitmap;
private final float[] mVerts = new float[COUNT * 2];
private final float[] mOrig = new float[COUNT * 2];
private final Matrix mMatrix = new Matrix();
private final Matrix mInverse = new Matrix();
private static void setXY(float[] array, int index, float x, float y) {
array[index * 2 + 0] = x;
array[index * 2 + 1] = y;
}
public SampleView(Context context) {
super(context);
setFocusable(true);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.image1);
float w = mBitmap.getWidth();
float h = mBitmap.getHeight();
// construct our mesh
int index = 0;
for (int y = 0; y <= HEIGHT; y++) {
float fy = h * y / HEIGHT;
for (int x = 0; x <= WIDTH; x++) {
float fx = w * x / WIDTH;
setXY(mVerts, index, fx, fy);
setXY(mOrig, index, fx, fy);
index += 1;
}
}
mMatrix.setTranslate(10, 10);
mMatrix.invert(mInverse);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
canvas.concat(mMatrix);
canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0, null, 0,
null);
}
private void warp(float cx, float cy) {
final float K = 10000;
float[] src = mOrig;
float[] dst = mVerts;
for (int i = 0; i < COUNT * 2; i += 2) {
float x = src[i + 0];
float y = src[i + 1];
float dx = cx - x;
float dy = cy - y;
float dd = dx * dx + dy * dy;
float d = FloatMath.sqrt(dd);
float pull = K / (dd + 0.000001f);
pull /= (d + 0.000001f);
// android.util.Log.d("skia", "index " + i + " dist=" + d +
// " pull=" + pull);
if (pull >= 1) {
dst[i + 0] = cx;
dst[i + 1] = cy;
} else {
dst[i + 0] = x + dx * pull;
dst[i + 1] = y + dy * pull;
}
}
}
private int mLastWarpX = -9999; // don't match a touch coordinate
private int mLastWarpY;
#Override
public boolean onTouchEvent(MotionEvent event) {
float[] pt = { event.getX(), event.getY() };
mInverse.mapPoints(pt);
int x = (int) pt[0];
int y = (int) pt[1];
if (mLastWarpX != x || mLastWarpY != y) {
mLastWarpX = x;
mLastWarpY = y;
warp(pt[0], pt[1]);
invalidate();
}
return true;
}
}
}
Graphics Activity:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
class GraphicsActivity extends Activity {
// set to true to test Picture
private static final boolean TEST_PICTURE = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void setContentView(View view) {
if (TEST_PICTURE) {
ViewGroup vg = new PictureLayout(this);
vg.addView(view);
view = vg;
}
super.setContentView(view);
}
}
PictureLayout.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
class PictureLayout extends ViewGroup {
private final Picture mPicture = new Picture();
public PictureLayout(Context context) {
super(context);
}
public PictureLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void addView(View child) {
if (getChildCount() > 1) {
throw new IllegalStateException(
"PictureLayout can host only one direct child");
}
super.addView(child);
}
#Override
public void addView(View child, int index) {
if (getChildCount() > 1) {
throw new IllegalStateException(
"PictureLayout can host only one direct child");
}
super.addView(child, index);
}
#Override
public void addView(View child, LayoutParams params) {
if (getChildCount() > 1) {
throw new IllegalStateException(
"PictureLayout can host only one direct child");
}
super.addView(child, params);
}
#Override
public void addView(View child, int index, LayoutParams params) {
if (getChildCount() > 1) {
throw new IllegalStateException(
"PictureLayout can host only one direct child");
}
super.addView(child, index, params);
}
#Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int count = getChildCount();
int maxHeight = 0;
int maxWidth = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
maxWidth += getPaddingLeft() + getPaddingRight();
maxHeight += getPaddingTop() + getPaddingBottom();
Drawable drawable = getBackground();
if (drawable != null) {
maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
}
setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
resolveSize(maxHeight, heightMeasureSpec));
}
private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx,
float sy) {
canvas.save();
canvas.translate(x, y);
canvas.clipRect(0, 0, w, h);
canvas.scale(0.5f, 0.5f);
canvas.scale(sx, sy, w, h);
canvas.drawPicture(mPicture);
canvas.restore();
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
mPicture.endRecording();
int x = getWidth() / 2;
int y = getHeight() / 2;
if (false) {
canvas.drawPicture(mPicture);
} else {
drawPict(canvas, 0, 0, x, y, 1, 1);
drawPict(canvas, x, 0, x, y, -1, 1);
drawPict(canvas, 0, y, x, y, 1, -1);
drawPict(canvas, x, y, x, y, -1, -1);
}
}
#Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
location[0] = getLeft();
location[1] = getTop();
dirty.set(0, 0, getWidth(), getHeight());
return getParent();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = super.getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final int childLeft = getPaddingLeft();
final int childTop = getPaddingTop();
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(),
childTop + child.getMeasuredHeight());
}
}
}
}
//Little changes in this piece of code
float[] dst; //Global
public SampleView(Context context) {
super(context);
setFocusable(true);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.image1);
float w = mBitmap.getWidth();
float h = mBitmap.getHeight();
// construct our mesh
int index = 0;
for (int y = 0; y <= HEIGHT; y++) {
float fy = h * y / HEIGHT;
for (int x = 0; x <= WIDTH; x++) {
float fx = w * x / WIDTH;
setXY(mVerts, index, fx, fy);
setXY(mOrig, index, fx, fy);
index += 1;
dst=mVerts;//Assign dst here just once
}
}
mMatrix.setTranslate(10, 10);
mMatrix.invert(mInverse);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
canvas.concat(mMatrix);
canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0, null, 0,
null);
}
private void warp(float cx, float cy) {
final float K = 10000;
float[] src = dst; //now you are applying wrap effect on the last effected pixels
for (int i = 0; i < COUNT * 2; i += 2) {
float x = src[i + 0];
float y = src[i + 1];
float dx = cx - x;
float dy = cy - y;
float dd = dx * dx + dy * dy;
float d = FloatMath.sqrt(dd);
float pull = K / (dd + 0.000001f);
pull /= (d + 0.000001f);
// android.util.Log.d("skia", "index " + i + " dist=" + d +
// " pull=" + pull);
if (pull >= 1) {
dst[i + 0] = cx;
dst[i + 1] = cy;
} else {
dst[i + 0] = x + dx * pull;
dst[i + 1] = y + dy * pull;
}
}
}
I work at world analog clock I used android analog clock, it's work at activity but I can't use it at widget,I tired googled it is there any one have idea ?
You can use the following widget classes in Home Screen Widget:
* AnalogClock
* Button
* Chronometer
* ImageButton
* ImageView
* ProgressBar
* TextView
Descendants of these classes are not supported
see an example how we use an AnalogClock widget in Home Screen widget here
You have to create your own widget based on ImageView and create background service to create bitmaps and periodically push them to widget.
/**
*
* This widget display an analogic clock with two hands for hours and
*
* minutes.
*/
#RemoteView
public class AnalogClock2 extends View {
public AnalogClock2(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
private Time mCalendar;
private Drawable mHourHand;
private Drawable mMinuteHand;
private Drawable mSecondHand;
private Drawable mDial;
private int mDialWidth;
private int mDialHeight;
private boolean mAttached;
private final Handler mHandler = new Handler();
private float mMinutes;
private float mHour;
private boolean mChanged;
Context mContext;
public static String mtimezone="Asia/Calcutta";
public AnalogClock2(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AnalogClock2(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
Resources r = context.getResources();
// TypedArray a =
// context.obtainStyledAttributes(
// attrs, R.styleable.AnalogClock, defStyle, 0);
mContext = context;
// mDial =
// a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);
// if (mDial == null) {
mDial = r.getDrawable(R.drawable.widgetdial);
// }
// mHourHand =
// a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);
// if (mHourHand == null) {
mHourHand = r.getDrawable(R.drawable.widgethour);
// }
// mMinuteHand =
// a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);
// if (mMinuteHand == null) {
mMinuteHand = r.getDrawable(R.drawable.widgetminute);
mSecondHand = r.getDrawable(R.drawable.widgetminute);
// }
mCalendar = new Time();
mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight();
}
public static void timezone(String timezone){
mtimezone=timezone;
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mAttached) {
mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
}
// NOTE: It's safe to do these after registering the receiver since the
// receiver always runs
// in the main thread, therefore the receiver can't run before this
// method returns.
// The time zone may have changed while the receiver wasn't registered,
// so update the Time
//mCalendar = new Time();
mCalendar = new Time(mtimezone);
// Make sure we update to the current time
onTimeChanged();
counter.start();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
counter.cancel();
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
float hScale = 1.0f;
float vScale = 1.0f;
if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
hScale = (float) widthSize / (float) mDialWidth;
}
if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
vScale = (float) heightSize / (float) mDialHeight;
}
System.out.println("***********************HAI****************");
float scale = Math.min(hScale, vScale);
setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),
resolveSize((int) (mDialHeight * scale), heightMeasureSpec));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mChanged = true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// // here changes on every tick//////
// / ////
// / //
// //////
// // ///
// //
boolean changed = mChanged;
if (changed) {
mChanged = false;
}
boolean seconds = mSeconds;
if (seconds) {
mSeconds = false;
}
int availableWidth = 100;
int availableHeight = 200;
int x = availableWidth / 2;
int y = availableHeight / 2;
final Drawable dial = mDial;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
if (availableWidth < w || availableHeight < h) {
scaled = true;
float scale = Math.min((float) availableWidth / (float) w,
(float) availableHeight / (float) h);
canvas.save();
canvas.scale(scale, scale, x, y);
}
if (changed) {
dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
dial.draw(canvas);
canvas.save();
canvas.rotate(mHour / 12.0f * 360.0f, x, y);
final Drawable hourHand = mHourHand;
if (changed) {
w = hourHand.getIntrinsicWidth();
h = hourHand.getIntrinsicHeight();
hourHand.setBounds(x - (w / 2), y - (h / 3), x + (w / 2), y + (h / 3));
}
hourHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);
// canvas.rotate(mSecond, x, y);
final Drawable minuteHand = mMinuteHand;
if (changed) {
w = minuteHand.getIntrinsicWidth();
h = minuteHand.getIntrinsicHeight();
minuteHand.setBounds(x - (w / 2), y - (h / 3), x + (w / 2), y + (h / 3));
}
minuteHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mSecond, x, y);
// minuteHand = mMinuteHand;
if (seconds) {
w = mSecondHand.getIntrinsicWidth();
h = mSecondHand.getIntrinsicHeight();
mSecondHand.setBounds(x - (w / 2), y - (h / 3), x + (w / 2), y + (h / 3));
}
mSecondHand.draw(canvas);
canvas.restore();
if (scaled) {
canvas.restore();
}
}
MyCount counter = new MyCount(10000, 1000);
public class MyCount extends CountDownTimer {
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
counter.start();
}
#Override
public void onTick(long millisUntilFinished) {
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mSecond = 6.0f * second;
mSeconds = true;
// mChanged = true;
AnalogClock2.this.invalidate();
// Toast.makeText(mContext, "text", Toast.LENGTH_LONG).show();
}
}
boolean mSeconds = false;
float mSecond = 0;
private void onTimeChanged() {
mCalendar.setToNow();
int hour = mCalendar.hour+4;
int minute = mCalendar.minute+15;
int second = mCalendar.second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
}
mCalendar = new Time(mtimezone);
onTimeChanged();
invalidate();
}
};
}