diff --git a/app/src/main/java/clock/socoolby/com/clock/MainActivity.java b/app/src/main/java/clock/socoolby/com/clock/MainActivity.java index d0377db..096e138 100755 --- a/app/src/main/java/clock/socoolby/com/clock/MainActivity.java +++ b/app/src/main/java/clock/socoolby/com/clock/MainActivity.java @@ -12,8 +12,6 @@ import android.os.PowerManager; import android.os.Bundle; import android.provider.Settings; import android.support.v4.app.ActivityCompat; -import android.text.Spannable; -import android.text.SpannableString; import android.util.Log; import android.view.GestureDetector; import android.view.KeyEvent; @@ -40,6 +38,7 @@ import com.luck.picture.lib.entity.LocalMedia; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Timer; import java.util.TimerTask; @@ -63,13 +62,14 @@ import clock.socoolby.com.clock.widget.animatorview.animator.BubbleWhirlPoolAnim import clock.socoolby.com.clock.widget.animatorview.animator.CarrouselAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.ClockAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.DotsLineAnimator; +import clock.socoolby.com.clock.widget.animatorview.animator.MagicLineAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.PhaserBallAnimator; +import clock.socoolby.com.clock.widget.animatorview.animator.SawtoothAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.Wave3DAnimator; -import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.AbstractClock; import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.CircleClock; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.CircleTwoClock; import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.HelixClock; import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.HexagonalClock; -import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.OctagonalClock; import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.OvalClock; import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.SquareClock; import clock.socoolby.com.clock.widget.animatorview.animator.textanimator.EZLedAnimator; @@ -77,7 +77,6 @@ import clock.socoolby.com.clock.widget.animatorview.animator.FireAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.FireworkAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.FluorescenceAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.RainAnimator; -import clock.socoolby.com.clock.widget.animatorview.animator.RippleAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.SkyAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.SnowAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.StarFallAnimator; @@ -85,7 +84,6 @@ import clock.socoolby.com.clock.widget.animatorview.animator.VorolayAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.WaterAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.WindmillAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.textanimator.EvaporateTextAnimator; -import clock.socoolby.com.clock.widget.animatorview.animator.textanimator.PathEffectTextAnimator; import clock.socoolby.com.clock.widget.textview.AutoScrollTextView; import clock.socoolby.com.clock.widget.textview.DigitTextView; @@ -311,6 +309,14 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC private Integer foregroundColor; private FrameLayout mainBackground; + private ImageButton tv_break; + private Date countingDateTimeBase =null; + + private ShowTimeType showTimeType=ShowTimeType.TIME; + + public enum ShowTimeType{ + TIME,COUNTING_DOWN,COUNTING; + } public void setWeather(WeatherResponse weather) { @@ -378,6 +384,21 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC } }); + tv_break=findViewById(R.id.tv_break); + tv_break.setOnClickListener(this); + tv_break.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if(handUpAbla){ + if(showTimeType==ShowTimeType.COUNTING_DOWN) + setCurrentShowTimeType(ShowTimeType.TIME); + else + setCurrentShowTimeType(ShowTimeType.COUNTING_DOWN); + } + return true; + } + }); + tv_handup=findViewById(R.id.tv_hand); tv_handup.setOnClickListener(this); tv_handup.setOnLongClickListener(new View.OnLongClickListener() { @@ -702,6 +723,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC tv_hand_time.setTextColor(color); tv_hours_system.setColorFilter(color); tv_background_image_hand.setColorFilter(color); + + tv_break.setColorFilter(color); } protected void setBackGroundColor(Integer color){ @@ -765,6 +788,13 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC } screenLock(!screenLock); break; + case R.id.tv_break: + if(showTimeType!=ShowTimeType.COUNTING){ + setCurrentShowTimeType(ShowTimeType.COUNTING); + }else{ + setCurrentShowTimeType(ShowTimeType.TIME); + } + break; case R.id.tv_descript: setDiscript(SettingActivity.roundAutoQuotes()); break; @@ -799,6 +829,14 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC } } + public void setCurrentShowTimeType(ShowTimeType type){ + switch (type){ + case COUNTING: + countingDateTimeBase =new Date(); + } + showTimeType=type; + } + public void screenLock(boolean locked){ screenLock=locked; @@ -879,6 +917,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC tv_foreground_color.setVisibility(View.GONE); tv_foreground_color1.setVisibility(View.GONE); tv_background_image_hand.setVisibility(View.GONE); + + tv_break.setVisibility(View.GONE); }else{ if(clockView.isRunning()) { //clockView.setAnimator(null); @@ -893,6 +933,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC tv_handup_image.setVisibility(View.VISIBLE); tv_handup.setVisibility(View.VISIBLE); + tv_break.setVisibility(View.VISIBLE); if(prevMode==MODE_HANDUP) switchMode(MODE_NORMAL); @@ -914,7 +955,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC DotsLineAnimator dotsLineAnimator; WaterAnimator waterAnimator; FireAnimator fireAnimator; - RippleAnimator rippleAnimator; + SawtoothAnimator sawtoothAnimator; WindmillAnimator windmillAnimator; VorolayAnimator vorolayAnimator; EZLedAnimator eZLedAnimator; @@ -922,6 +963,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC PhaserBallAnimator phaserBallAnimator; CarrouselAnimator carrouselAnimator; Wave3DAnimator wave3DAnimator; + MagicLineAnimator magicLineAnimator; public void changeBackGroundAnimator(int index){ switch(index){ case 0: @@ -942,7 +984,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC backGroundAnimator= phaserBallAnimator; backGroundAnimator.setRandColor(true); break; - case 3: + case 20: if(rainAnimator==null) { rainAnimator = new RainAnimator(); rainAnimator.init(animatorView.getContext(),animatorView); @@ -1095,7 +1137,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC backGroundAnimator= dotsLineAnimator; backGroundAnimator.setRandColor(true); break; - case 20: + case 3: if(waterAnimator ==null) { waterAnimator = new WaterAnimator(); waterAnimator.init(animatorView.getContext(),animatorView); @@ -1123,12 +1165,12 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC backGroundAnimator.setRandColor(false); break; case 23: - if(rippleAnimator ==null) { - rippleAnimator = new RippleAnimator(); - rippleAnimator.init(animatorView.getContext(),animatorView); - rippleAnimator.setColor(foregroundColor); + if(sawtoothAnimator ==null) { + sawtoothAnimator = new SawtoothAnimator(); + sawtoothAnimator.init(animatorView.getContext(),animatorView); + sawtoothAnimator.setColor(foregroundColor); } - backGroundAnimator= rippleAnimator; + backGroundAnimator= sawtoothAnimator; backGroundAnimator.setRandColor(true); break; case 24: @@ -1158,7 +1200,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC backGroundAnimator= carrouselAnimator; backGroundAnimator.setRandColor(true); break; - case 1: + case 27: if(wave3DAnimator ==null) { wave3DAnimator = new Wave3DAnimator(); wave3DAnimator.init(animatorView.getContext(),animatorView); @@ -1167,6 +1209,24 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC backGroundAnimator= wave3DAnimator; backGroundAnimator.setRandColor(true); break; + case 28: + if(magicLineAnimator ==null) { + magicLineAnimator = new MagicLineAnimator(); + magicLineAnimator.init(animatorView.getContext(),animatorView); + magicLineAnimator.setColor(foregroundColor); + } + backGroundAnimator= magicLineAnimator; + backGroundAnimator.setRandColor(true); + break; + case 1: + if(magicLineAnimator ==null) { + magicLineAnimator = new MagicLineAnimator(); + magicLineAnimator.init(animatorView.getContext(),animatorView); + magicLineAnimator.setColor(foregroundColor); + } + backGroundAnimator= magicLineAnimator; + backGroundAnimator.setRandColor(false); + break; case 60: if(evaporateTextAnimator ==null) { @@ -1205,7 +1265,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC clockAnimator = new ClockAnimator(); clockAnimator.init(clockView.getContext(),clockView); clockAnimator.setColor(foregroundColor); - if(index>4) + if(index>5) currentClockAnimatorIndex=index=0; switch (index) { @@ -1218,13 +1278,13 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC case 1: clockAnimator.setClock(new SquareClock()); break; - //case 3: - // clockAnimator.setClock(new OctagonalClock()); - // break; case 3: - clockAnimator.setClock(new HexagonalClock()); + clockAnimator.setClock(new CircleTwoClock()); break; case 4: + clockAnimator.setClock(new HexagonalClock()); + break; + case 5: clockAnimator.setClock(new HelixClock()); break; default: @@ -1245,6 +1305,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC }else{ this.tv_handup.setColorFilter(R.color.colorPrimaryDark); this.tv_hand_time.setVisibility(View.GONE); + if(showTimeType==ShowTimeType.COUNTING_DOWN) + setCurrentShowTimeType(ShowTimeType.TIME); } } @@ -1354,6 +1416,9 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC handUPDialy--; if(handUPDialy==0) { switchMode(MODE_NORMAL); + if(!isArtificialHiddle&&showTimeType==ShowTimeType.TIME){ + setCurrentShowTimeType(ShowTimeType.COUNTING); + } }else Player.getInstance().playHandUp(this); return; @@ -1387,7 +1452,19 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC private void updateTime() { heartbeat=!heartbeat; DateModel date = new DateModel(); - String timeString = model.isDisplaySecond() ? date.getTimeString(model.isHourSystem12()) : date.getShortTimeString(heartbeat,model.isHourSystem12()); + String timeString=null; + switch (showTimeType){ + case COUNTING: + DateModel temp=new DateModel(countingDateTimeBase); + timeString=temp.getTimeString(false); + break; + case COUNTING_DOWN: + timeString=DateModel.getTimeFull(handUpTime); + break; + default: + timeString = model.isDisplaySecond() ? date.getTimeString(model.isHourSystem12()) : date.getShortTimeString(heartbeat,model.isHourSystem12()); + break; + } setCurrentTimeToView(timeString); reportTime(date); updateDay(date); @@ -1607,6 +1684,9 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC if(!isArtificialHiddle) { tv_time.setLinearGradientRandom(!tv_time.isLinearGradientAble()); return true; + }else if(clockAnimator!=null){ + clockAnimator.randPointer(); + return true; } return false; } diff --git a/app/src/main/java/clock/socoolby/com/clock/model/DateModel.java b/app/src/main/java/clock/socoolby/com/clock/model/DateModel.java index 64f70cb..dc51c61 100755 --- a/app/src/main/java/clock/socoolby/com/clock/model/DateModel.java +++ b/app/src/main/java/clock/socoolby/com/clock/model/DateModel.java @@ -19,7 +19,14 @@ public class DateModel implements Serializable { private int second = 0; public DateModel() { - setDataString(getNowWithTime()); + Calendar c1 = Calendar.getInstance(); //当前日期 + year=c1.get(Calendar.YEAR); + month=c1.get(Calendar.MONTH)+1; + day=c1.get(Calendar.DAY_OF_MONTH); + hour=c1.get(Calendar.HOUR_OF_DAY); + minute=c1.get(Calendar.MINUTE); + second=c1.get(Calendar.SECOND); + //setDataString(getNowWithTime()); } public DateModel(int year, int month, int day) { @@ -28,6 +35,15 @@ public class DateModel implements Serializable { this.day = day; } + public DateModel(Date base) { + Date date=new Date(); + int between = new Long(date.getTime() - base.getTime()).intValue(); + day = between / (24 * 60 * 60 * 1000); + hour = (between / (60 * 60 * 1000) - day * 24); + minute = ((between / (60 * 1000)) - day * 24 * 60 - hour * 60); + second = (between / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); + } + /** * @param timeString 12:00 || 12:00:00 */ @@ -144,6 +160,14 @@ public class DateModel implements Serializable { return String.format("%02d:%02d:%02d", hours, minutes, second); } + public static String getTimeFull(int second){ + long hours = second / 3600;//转换小时数 + second = second % 3600;//剩余秒数 + long minutes = second / 60;//转换分钟 + second = second % 60;//剩余秒数 + return String.format("%02d:%02d:%02d", hours, minutes, second); + } + public int minusTime(DateModel strEnd) { SimpleDateFormat df = new SimpleDateFormat("HH:mm"); Date d1 = null; @@ -155,7 +179,6 @@ public class DateModel implements Serializable { e.printStackTrace(); } return (int) ((d2.getTime() - d1.getTime()) / DateUtils.SECOND_IN_MILLIS); - } diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/ClockAnimator.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/ClockAnimator.java index 0926d96..86b8da8 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/ClockAnimator.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/ClockAnimator.java @@ -3,6 +3,13 @@ package clock.socoolby.com.clock.widget.animatorview.animator; import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator; import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.AbstractClock; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.DefaultPointer; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.LeafPointer; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.LeafTwoPointer; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.SecondTailPointer; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.SwordPointer; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.TrianglePointer; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.TwoStepPointer; // 参考自:https://github.com/ifadai/ClockDemo public class ClockAnimator extends AbstractAnimator { @@ -35,4 +42,35 @@ public class ClockAnimator extends AbstractAnimator { clock.init(width,height,width/2,height/2,minHigh/2,color,textColor); list.add(clock); } + + int randPointerIndex=1; + public void randPointer(){ + if(clock==null) + return; + if(randPointerIndex>6) + randPointerIndex=0; + switch (randPointerIndex){ + case 1: + clock.setPointer(new SecondTailPointer()); + break; + case 2: + clock.setPointer(new TrianglePointer()); + break; + case 3: + clock.setPointer(new SwordPointer()); + break; + case 4: + clock.setPointer(new TwoStepPointer()); + break; + case 5: + clock.setPointer(new LeafPointer()); + break; + case 6: + clock.setPointer(new LeafTwoPointer()); + break; + default: + clock.setPointer(new DefaultPointer()); + } + randPointerIndex++; + } } diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/MagicLineAnimator.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/MagicLineAnimator.java new file mode 100644 index 0000000..84761a4 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/MagicLineAnimator.java @@ -0,0 +1,156 @@ +package clock.socoolby.com.clock.widget.animatorview.animator; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; + +import java.util.ArrayList; +import java.util.List; + +import clock.socoolby.com.clock.widget.animatorview.AbstractCacheDifferenceAnimator; +import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry; + + +//引用自:https://github.com/zhangyuChen1991/MagicLine +public class MagicLineAnimator extends AbstractCacheDifferenceAnimator { + + + public MagicLineAnimator() { + super(1); + } + + @Override + public MagicLine createNewEntry() { + return new MagicLine(width,height); + } + + public static float[][] demos={{400,400,0.05f,200,200,0.35f}, + {450,450,0.5f,450,450,0.15f}, + {450,450,1.0f,150,150,0.15f}, + {320,320,0.025f,320,80,0.06f}, + {450,450,1.0f,150,150,0.15f}, + {90, 90,0.5f, 450, 450, 0.15f}, + {200, 200, 0.55f, 450, 450, 0.15f}, + {450, 150, 0.15f, 150, 450, 0.05f}, + {200, 500, 0.4f, 500, 200, 0.4f} + }; + + public class MagicLine implements I_AnimatorEntry { + + //起点在x、y移动范围 + private float p1XLength = 400, p1YLength = 20, speedP1 = 0.15f; + private float p2XLength = 20, p2YLength = 400, speedP2 = 0.05f; + private double angleP1 = 0, angleP2 = 0; + private int viewWidth, viewHeight; + private Paint paint; + //记录移动过的所有点的数据 + private List corrDatas; + //动画绘制的时间 + private int animDuration = 600; + + public MagicLine(int viewWidth, int viewHeight) { + this.viewWidth = viewWidth; + this.viewHeight = viewHeight; + init(); + } + + @Override + public void move(int maxWidth, int maxHight) { + calculate(); + animDuration--; + if(animDuration==0) { + animDuration = 600; + reStartDraw(); + } + } + + @Override + public void onDraw(Canvas canvas, Paint mPaint) { + for (int i = 0; i < corrDatas.size(); i++) { + CorrdinateData cd = corrDatas.get(i); + paint.setColor(cd.color); + canvas.drawLine(cd.p1X, cd.p1Y, cd.p2X, cd.p2Y, paint); + } + } + + private void init() { + paint = new Paint(); + paint.setAntiAlias(true); + paint.setStrokeWidth(2); + paint.setStyle(Paint.Style.FILL); + //paint.setColor(Color.WHITE); + paint.setAlpha(50); +// Shader shader = new LinearGradient(cd.p1X, cd.p1Y, cd.p2X, cd.p2Y, colors, null, Shader.TileMode.MIRROR); +// paint.setShader(shader); + corrDatas = new ArrayList<>(); + } + + /** + * 开始绘制 + */ + public void reStartDraw() { + moveToTrashCache(corrDatas); + corrDatas.clear(); + + int demoIndex=rand.nextInt(demos.length); + p1XLength = demos[demoIndex][0]; + p1YLength = demos[demoIndex][1]; + speedP1 = demos[demoIndex][2]; + p2XLength = demos[demoIndex][3]; + p2YLength = demos[demoIndex][4]; + speedP2 = demos[demoIndex][5]; + + } + + /** + * 计算坐标值 + */ + private void calculate() { + angleP1 = angleP1 + speedP1; + angleP2 = angleP2 + speedP2; + + //两个点的位置更新 + float nowP1X = (float) (p1XLength * Math.cos(angleP1) + viewWidth / 2f); + float nowP1Y = (float) (p1YLength * Math.sin(angleP1) + viewHeight / 2f); + float nowP2X = (float) (p2XLength * Math.cos(angleP2) + viewWidth / 2f); + float nowP2Y = (float) (p2YLength * Math.sin(angleP2) + viewHeight / 2f); + + CorrdinateData corrdinataData =revectForTrashCache(); + randomColorIfAble(); + if(corrdinataData!=null) + corrdinataData.init(nowP1X, nowP1Y, nowP2X, nowP2Y,color); + else + corrdinataData=new CorrdinateData(nowP1X, nowP1Y, nowP2X, nowP2Y,color); + corrDatas.add(corrdinataData); + } + + /** + * 设置参数 + */ + public void setParam(float p1XLength, float p1YLength, float p2XLength, float p2YLength, float speedP1, float speedP2) { + this.p1XLength = p1XLength; + this.p1YLength = p1YLength; + this.p2XLength = p2XLength; + this.p2YLength = p2YLength; + this.speedP1 = speedP1; + this.speedP2 = speedP2; + } + } + + public class CorrdinateData { + float p1X, p1Y, p2X, p2Y; + int color; + + CorrdinateData(float p1X, float p1Y, float p2X, float p2Y,int color) { + init(p1X,p1Y,p2X,p2Y,color); + } + + public void init(float p1X, float p1Y, float p2X, float p2Y,int color) { + this.p1X = p1X; + this.p1Y = p1Y; + this.p2X = p2X; + this.p2Y = p2Y; + this.color=color; + } + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/SawtoothAnimator.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/SawtoothAnimator.java new file mode 100644 index 0000000..49bbaa8 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/SawtoothAnimator.java @@ -0,0 +1,314 @@ +package clock.socoolby.com.clock.widget.animatorview.animator; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; + +import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator; +import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry; + +//参考自:http://refactor.cn/2016/12/26/GearMachine-Canvas绘制漂亮的齿轮装置/ +public class SawtoothAnimator extends AbstractAnimator { + + public SawtoothAnimator() { + super(1); + } + + @Override + public Sawtooth createNewEntry() { + return new Sawtooth(width,height); + } + + + @Override + public int dialyTime() { + return 20; + } + + public class Sawtooth implements I_AnimatorEntry { + private static final int X = 0; + private static final int Y = 1; + + private float mTopCircleRadius; + private float mBottomBigCircleRadius; + private Paint mRedPaint, mDarkRedPaint, mStrokePaint, mBeltPaint; + + private Paint mTransitionPaint, mTransitionDarkPaint; + private Path mBigSawtoothPath, mSmallSawtoothPath; + private Path mLeftTopTrianglePath, mRightTopTrianglePath, mBarPath, mSmallBarPath; + + private float mCurProgress; + private RectF mShadeRectF; + private PorterDuffXfermode mClearXfermode; + + private int width,hight; + + public Sawtooth(int width, int hight) { + this.width = width; + this.hight = hight; + init(); + mCurProgress=0f; + } + + /** + * 确定四个点 + * 1. 左上齿轮中心 宽占完整宽度的比例0.237 高占完整宽度的比例 0.102 + * 2. 右上齿轮中心 宽占完整宽度的比例0.763 高占完整宽度的比例 0.102 + * 3. 中上齿轮中心 宽占完整宽度的比例0.5 高占完整宽度的比例 0.311 + * 4. 中下齿轮中心 宽占完整宽度的比例0.5 高占完整宽度的比例 0.597 + */ + private float[] mLeftTopCentre, mRightTopCentre, mTopCentre, mBottomCentre; + + + private void init() { + mLeftTopCentre = new float[2]; + mRightTopCentre = new float[2]; + mTopCentre = new float[2]; + mBottomCentre = new float[2]; + + mRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mRedPaint.setStrokeJoin(Paint.Join.ROUND); + mRedPaint.setStrokeCap(Paint.Cap.ROUND); + mRedPaint.setColor(Color.RED); + + mDarkRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mDarkRedPaint.setStrokeJoin(Paint.Join.ROUND); + mDarkRedPaint.setStrokeCap(Paint.Cap.ROUND); + mDarkRedPaint.setStyle(Paint.Style.FILL); + mDarkRedPaint.setColor(color); + + mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mStrokePaint.setStrokeJoin(Paint.Join.ROUND); + mStrokePaint.setStrokeCap(Paint.Cap.ROUND); + mStrokePaint.setStyle(Paint.Style.STROKE); + mStrokePaint.setColor(Color.RED); + + mTransitionPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTransitionPaint.setStrokeJoin(Paint.Join.ROUND); + mTransitionPaint.setStrokeCap(Paint.Cap.ROUND); + mTransitionPaint.setStyle(Paint.Style.FILL); + mTransitionPaint.setColor(color); + + mTransitionDarkPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTransitionDarkPaint.setStrokeJoin(Paint.Join.ROUND); + mTransitionDarkPaint.setStrokeCap(Paint.Cap.ROUND); + mTransitionDarkPaint.setStyle(Paint.Style.FILL); + mTransitionDarkPaint.setColor(Color.DKGRAY); + + mBeltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBeltPaint.setStrokeJoin(Paint.Join.ROUND); + mBeltPaint.setStrokeCap(Paint.Cap.ROUND); + mBeltPaint.setStyle(Paint.Style.FILL); + mBeltPaint.setColor(Color.RED); + + mClearXfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR); + + int paddingLeft = 0; + int paddingRight = 0; + int paddingTop = 0; + int paddingBottom = 0; + + + // 横向有效宽度 + int validWidth = width - paddingLeft - paddingRight; + // 纵向有效高度 + int validHeight = height - paddingTop - paddingBottom; + + // 左上齿轮中心 + mLeftTopCentre[X] = (float) (paddingLeft + validWidth * 0.237); + mLeftTopCentre[Y] = (float) (paddingTop + validHeight * 0.102); + + // 右上齿轮中心 + mRightTopCentre[X] = (float) (paddingLeft + validWidth * 0.763); + mRightTopCentre[Y] = (float) (paddingTop + validHeight * 0.102); + + // 中上齿轮中心 + mTopCentre[X] = (float) (paddingLeft + validWidth * 0.5); + mTopCentre[Y] = (float) (paddingTop + validHeight * 0.311); + + // 中下齿轮中心 + mBottomCentre[X] = (float) (paddingLeft + validWidth * 0.5); + mBottomCentre[Y] = (float) (paddingTop + validHeight * 0.597); + + // 上部两个齿轮的半径 + mTopCircleRadius = (float) (validWidth * 0.102); + + // 最大的齿轮stroke size + mBottomBigCircleRadius = validWidth / 2 - mTopCircleRadius / 4 * 5; + mStrokePaint.setStrokeWidth(mTopCircleRadius / 4 * 5); + + // 传送带stroke size + mBeltPaint.setStrokeWidth((float) (validWidth * 0.0077)); + + // 大齿轮Path + mBigSawtoothPath = new Path(); + mBigSawtoothPath.moveTo((float) (mBottomCentre[X] - validWidth * 0.03), (float) (mBottomCentre[Y] - mBottomBigCircleRadius - mStrokePaint.getStrokeWidth() / 2 * 0.9)); // 此处的0.9表示未被绘制上的偏移量 + mBigSawtoothPath.lineTo((float) (mBottomCentre[X] - validWidth * 0.025), (float) (mBottomCentre[Y] - (mBottomBigCircleRadius + mStrokePaint.getStrokeWidth() / 3 * 2.4))); // 此处的mStrokePaint.getStrokeWidth() / 3 * 2.4 代表最大锯齿的高度 + mBigSawtoothPath.lineTo((float) (mBottomCentre[X] + validWidth * 0.025), (float) (mBottomCentre[Y] - (mBottomBigCircleRadius + mStrokePaint.getStrokeWidth() / 3 * 2.4))); + mBigSawtoothPath.lineTo((float) (mBottomCentre[X] + validWidth * 0.03), (float) (mBottomCentre[Y] - mBottomBigCircleRadius - mStrokePaint.getStrokeWidth() / 2 * 0.9)); + mBigSawtoothPath.close(); + mBigSawtoothPath.close(); + + // 小齿轮Path + mSmallSawtoothPath = new Path(); + mSmallSawtoothPath.moveTo((float) (mBottomCentre[X] - validWidth * 0.01), (float) (mBottomCentre[Y] - (mTopCircleRadius / 2 * 2.8))); // 此处的12 代表梯形底边的一半 + mSmallSawtoothPath.lineTo((float) (mBottomCentre[X] - validWidth * 0.013), (float) (mBottomCentre[Y] - (mTopCircleRadius / 2 * 3.2))); // 此处的10 代表梯形顶边的一半 + mSmallSawtoothPath.lineTo((float) (mBottomCentre[X] + validWidth * 0.013), (float) (mBottomCentre[Y] - (mTopCircleRadius / 2 * 3.2))); // 此处的10 代表梯形顶边的一半 + mSmallSawtoothPath.lineTo((float) (mBottomCentre[X] + validWidth * 0.01), (float) (mBottomCentre[Y] - (mTopCircleRadius / 2 * 2.8))); + mSmallSawtoothPath.close(); + + // 左上角三角齿轮 + mLeftTopTrianglePath = new Path(); + mLeftTopTrianglePath.moveTo((float) (mLeftTopCentre[X] - validWidth * 0.0082), mLeftTopCentre[Y] - (mTopCircleRadius / 4 * 2)); + mLeftTopTrianglePath.lineTo(mLeftTopCentre[X] , (float) (mLeftTopCentre[Y] - (mTopCircleRadius / 4 * 2.6))); // 此处的10 是三角形底边的一半 + mLeftTopTrianglePath.lineTo((float) (mLeftTopCentre[X] + validWidth * 0.0082), mLeftTopCentre[Y] - (mTopCircleRadius / 4 * 2)); + mLeftTopTrianglePath.close(); + + // 右上角三角齿轮 + mRightTopTrianglePath = new Path(); + mRightTopTrianglePath.moveTo((float) (mRightTopCentre[X] - validWidth * 0.0082), mRightTopCentre[Y] - (mTopCircleRadius / 4 * 2)); + mRightTopTrianglePath.lineTo(mRightTopCentre[X] , (float) (mRightTopCentre[Y] - (mTopCircleRadius / 4 * 2.6))); // 此处的10 是三角形底边的一半 + mRightTopTrianglePath.lineTo((float) (mRightTopCentre[X] + validWidth * 0.0082), mRightTopCentre[Y] - (mTopCircleRadius / 4 * 2)); + mRightTopTrianglePath.close(); + + // 上方斜杆 + mBarPath = new Path(); + mBarPath.moveTo(mTopCentre[X] - mTopCircleRadius, mTopCentre[Y]); + mBarPath.lineTo(mRightTopCentre[X] - mTopCircleRadius, mRightTopCentre[Y]); + mBarPath.lineTo(mRightTopCentre[X] + mTopCircleRadius, mRightTopCentre[Y]); + mBarPath.lineTo(mTopCentre[X] + mTopCircleRadius, mTopCentre[Y]); + mBarPath.close(); + + mSmallBarPath = new Path(); + mSmallBarPath.moveTo((float) (mTopCentre[X] - mTopCircleRadius * 0.3), mTopCentre[Y]); + mSmallBarPath.lineTo((float) (mRightTopCentre[X] - mTopCircleRadius * 0.3), mRightTopCentre[Y]); + mSmallBarPath.lineTo((float) (mRightTopCentre[X] + mTopCircleRadius * 0.3), mRightTopCentre[Y]); + mSmallBarPath.lineTo((float) (mTopCentre[X] + mTopCircleRadius * 0.3), mTopCentre[Y]); + mSmallBarPath.close(); + + mShadeRectF = new RectF(0, mBottomCentre[Y] - width / 2, width, mBottomCentre[Y] + width / 2); + } + + + @Override + public void onDraw(Canvas canvas, Paint mPaint) { + + // 中下最大的齿轮 + canvas.drawCircle(mBottomCentre[X], mBottomCentre[Y], mBottomBigCircleRadius, mStrokePaint); + + canvas.save(); + canvas.rotate(mCurProgress * 180, mBottomCentre[X], mBottomCentre[Y]); + for (int i = 0; i < 18; i ++) { + // 中心齿轮最外围的齿轮上的锯齿 梯形 + canvas.drawPath(mBigSawtoothPath, mRedPaint); + canvas.rotate(20.0f, mBottomCentre[X], mBottomCentre[Y]); + } + canvas.restore(); + + // 大齿轮扇形遮罩 + mDarkRedPaint.setXfermode(mClearXfermode); + canvas.drawArc(mShadeRectF, 180, 130, true, mDarkRedPaint); + mDarkRedPaint.setXfermode(null); + + // 上方两个齿轮底下的斜向连杆 + canvas.drawPath(mBarPath, mTransitionPaint); + canvas.drawPath(mSmallBarPath, mTransitionDarkPaint); + + // 上方两个齿轮底下的横向连杆 + canvas.drawRect(mLeftTopCentre[X], mLeftTopCentre[Y] - mTopCircleRadius / 4 * 3, mRightTopCentre[X], mRightTopCentre[Y] + mTopCircleRadius / 4 * 3, mRedPaint); + + // 左上齿轮 + canvas.drawCircle(mLeftTopCentre[X], mLeftTopCentre[Y], mTopCircleRadius, mRedPaint); + canvas.drawCircle(mLeftTopCentre[X], mLeftTopCentre[Y], mTopCircleRadius / 4 * 3, mDarkRedPaint); + canvas.save(); + canvas.rotate(mCurProgress * 360, mLeftTopCentre[X], mLeftTopCentre[Y]); + for (int i = 0; i < 24; i ++) { + // 齿轮的三角 path + canvas.drawPath(mLeftTopTrianglePath, mRedPaint); + canvas.rotate(15.0f, mLeftTopCentre[X], mLeftTopCentre[Y]); + } + canvas.restore(); + canvas.drawCircle(mLeftTopCentre[X], mLeftTopCentre[Y], mTopCircleRadius / 2, mRedPaint); + canvas.drawCircle(mLeftTopCentre[X], mLeftTopCentre[Y], mTopCircleRadius / 5 * 2, mDarkRedPaint); + canvas.drawCircle(mLeftTopCentre[X], mLeftTopCentre[Y], mTopCircleRadius / 4, mRedPaint); + + // 右上齿轮 + canvas.drawCircle(mRightTopCentre[X], mRightTopCentre[Y], mTopCircleRadius, mRedPaint); + canvas.drawCircle(mRightTopCentre[X], mRightTopCentre[Y], mTopCircleRadius / 4 * 3, mDarkRedPaint); + canvas.save(); + canvas.rotate(-mCurProgress * 360, mRightTopCentre[X], mRightTopCentre[Y]); + for (int i = 0; i < 24; i ++) { + // 齿轮的三角 path + canvas.drawPath(mRightTopTrianglePath, mRedPaint); + canvas.rotate(15.0f, mRightTopCentre[X], mRightTopCentre[Y]); + } + canvas.restore(); + canvas.drawCircle(mRightTopCentre[X], mRightTopCentre[Y], mTopCircleRadius / 2, mRedPaint); + canvas.drawCircle(mRightTopCentre[X], mRightTopCentre[Y], mTopCircleRadius / 5 * 2, mDarkRedPaint); + canvas.drawCircle(mRightTopCentre[X], mRightTopCentre[Y], mTopCircleRadius / 4, mRedPaint); + + // 中上齿轮 + canvas.drawCircle(mTopCentre[X], mTopCentre[Y], mTopCircleRadius, mRedPaint); + canvas.drawCircle(mTopCentre[X], mTopCentre[Y], mTopCircleRadius / 4 * 3, mDarkRedPaint); + canvas.drawCircle(mTopCentre[X], mTopCentre[Y], mTopCircleRadius / 4, mRedPaint); + canvas.save(); + canvas.rotate(mCurProgress * 225, mTopCentre[X], mTopCentre[Y]); + for (int i = 0; i < 8; i ++) { + // 圆盘上的小圆点 + canvas.drawCircle(mTopCentre[X], mTopCentre[Y] - (mTopCircleRadius / 4 * 2), (float) (mTopCircleRadius * 0.0625), mRedPaint); // 此处的(mTopCircleRadius * 0.125) 表示小圆球的半径 + canvas.rotate(45.0f, mTopCentre[X], mTopCentre[Y]); + } + canvas.restore(); + + // 中下齿轮 + canvas.save(); + canvas.rotate(-mCurProgress * 216, mBottomCentre[X], mBottomCentre[Y]); + for (int i = 0; i < 15; i ++) { + // 中心齿轮最外围的齿轮上的锯齿 梯形 + canvas.drawPath(mSmallSawtoothPath, mDarkRedPaint); + canvas.rotate(24.0f, mBottomCentre[X], mBottomCentre[Y]); + } + canvas.restore(); + + canvas.drawCircle(mBottomCentre[X], mBottomCentre[Y], mTopCircleRadius / 2 * 3, mDarkRedPaint); + canvas.drawCircle(mBottomCentre[X], mBottomCentre[Y], mTopCircleRadius / 16 * 17, mRedPaint); + // 投影 + mRedPaint.setShadowLayer(10.0f, 0f, 6.0f, Color.LTGRAY); + canvas.drawCircle(mBottomCentre[X], mBottomCentre[Y], mTopCircleRadius / 80 * 55, mRedPaint); + mRedPaint.setShadowLayer(0f, 0f, 0f, Color.LTGRAY); + canvas.drawCircle(mBottomCentre[X], mBottomCentre[Y], mTopCircleRadius / 80 * 40, mDarkRedPaint); + + canvas.save(); + canvas.rotate(mCurProgress * 180, mBottomCentre[X], mBottomCentre[Y]); + for (int i = 0; i < 8; i ++) { + // 圆盘上的小圆点 + canvas.drawCircle(mBottomCentre[X], (float) (mBottomCentre[Y] - (mTopCircleRadius / 4 * 1.2)), (float) (mTopCircleRadius * 0.05), mRedPaint); + canvas.rotate(45.0f, mBottomCentre[X], mBottomCentre[Y]); + } + canvas.restore(); + canvas.drawCircle(mBottomCentre[X], mBottomCentre[Y], mTopCircleRadius / 8, mRedPaint); + + // 左侧传送带 + canvas.drawLine(mTopCentre[X] - mTopCircleRadius * 0.85f, mTopCentre[Y], + mBottomCentre[X] - mTopCircleRadius * 0.6f, mBottomCentre[Y], + mBeltPaint); + + // 右侧传送带 + canvas.drawLine(mTopCentre[X] + mTopCircleRadius * 0.85f, mTopCentre[Y], + mBottomCentre[X] + mTopCircleRadius * 0.6f, mBottomCentre[Y], + mBeltPaint); + } + + @Override + public void move(int maxWidth, int maxHight) { + mCurProgress +=0.1f; + if(mCurProgress>1) + mCurProgress=0; + } + + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/WaterAnimator.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/WaterAnimator.java index c0f3acc..1571547 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/WaterAnimator.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/WaterAnimator.java @@ -2,16 +2,10 @@ package clock.socoolby.com.clock.widget.animatorview.animator; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.LinearGradient; -import android.graphics.Matrix; +import android.graphics.DrawFilter; import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; import android.graphics.Path; -import android.graphics.Shader; - -import java.util.ArrayList; -import java.util.List; - -import static java.lang.Float.parseFloat; import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator; import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry; @@ -30,254 +24,93 @@ public class WaterAnimator extends AbstractAnimator { @Override public Water createNewEntry() { - int startColor=Color.parseColor("#00FFFFFF"); - int waveColor=color; - randomColorIfAble(); - return new Water(width,height,waveColor,startColor,color); + //randomColorIfAble(); + return new Water(0,0,width,height,height*3/4); } class Water implements I_AnimatorEntry { + private Path mAbovePath, mBelowWavePath; + private Paint mAboveWavePaint, mBelowWavePaint; - private Paint mPaint = new Paint(); - private Matrix mMatrix = new Matrix(); - private List mltWave = new ArrayList<>(); - private int mWaveHeight; - private int mStartColor; - private int mCloseColor; - private int mGradientAngle; - private float mVelocity; - private float mColorAlpha; - private float mProgress; - private long mLastTime = 0; - private String tag; + private DrawFilter mDrawFilter; - public Water(int w,int h,int color,int mStartColor,int mCloseColor) { - mPaint.setAntiAlias(true); - mPaint.setColor(color); - mWaveHeight = Util.dipToPX(context,50); - this.mStartColor = mStartColor; - this.mCloseColor = mCloseColor; - mColorAlpha = 0.45f; - mProgress = 1f; - mVelocity = 1f; - mGradientAngle = 45; - tag="70,25,1.4,1.4,-26\n" + - "100,5,1.4,1.2,15\n" + - "420,0,1.15,1,-10\n" + - "520,10,1.7,1.5,20\n" + - "220,0,1,1,-15"; + private float φ; + private double ω; + private float y, y2; - updateWavePath(w, h); - updateLinearGradient(w, h); + private int width,higth,left,top; + + public Water(int left,int top,int width, int higth,int y2) { + this.width = width; + this.higth = higth; + this.left=left; + this.top=top; + this.y2=y2; + init(); } - public void runWave() { + protected void init() { + + //初始化路径 + mAbovePath = new Path(); + mBelowWavePath = new Path(); + //初始化画笔 + //上方波浪 + mAboveWavePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mAboveWavePaint.setAntiAlias(true); + mAboveWavePaint.setStyle(Paint.Style.FILL); + mAboveWavePaint.setColor(Color.BLUE); + //下方波浪 + mBelowWavePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBelowWavePaint.setAntiAlias(true); + mBelowWavePaint.setStyle(Paint.Style.FILL); + mBelowWavePaint.setColor(Color.BLUE); + mBelowWavePaint.setAlpha(60); + //画布抗锯齿 + mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); } - private void updateLinearGradient(int width, int height) { - //int startColor = Util.getColorWithAlpha(mStartColor, mColorAlpha*255); - //int closeColor = Util.getColorWithAlpha(mCloseColor, mColorAlpha*255); - //noinspection UnnecessaryLocalVariable - //double w = width; - //double h = height * mProgress; - //double r = Math.sqrt(w * w + h * h) / 2; - //double y = r * Math.sin(2 * Math.PI * mGradientAngle / 360); - //double x = r * Math.cos(2 * Math.PI * mGradientAngle / 360); - //mPaint.setShader(new LinearGradient((int)(w/2-x), (int)(h/2-y), (int)(w/2+x), (int)(h/2+y), startColor, closeColor, Shader.TileMode.CLAMP)); - - } - - private void updateWavePath(int w, int h) { - mltWave.clear(); - if (tag instanceof String) { - String[] waves = tag.toString().split("\\s+"); - if ("-1".equals(tag)) { - waves = "70,25,1.4,1.4,-26\n100,5,1.4,1.2,15\n420,0,1.15,1,-10\n520,10,1.7,1.5,20\n220,0,1,1,-15".split("\\s+"); - } else if ("-2".equals(tag)) { - waves = "0,0,1,0.5,90\n90,0,1,0.5,90".split("\\s+"); - } - for (String wave : waves) { - String[] args = wave.split ("\\s*,\\s*"); - if (args.length == 5) { - mltWave.add(new Wave(Util.dipToPX(context,parseFloat(args[0])), Util.dipToPX(context,parseFloat(args[1])), Util.dipToPX(context,parseFloat(args[4])), parseFloat(args[2]), parseFloat(args[3]), w, h, mWaveHeight/2)); - } - } - } else { - mltWave.add(new Wave(Util.dipToPX(context,50), Util.dipToPX(context,0), Util.dipToPX(context,5), 1.7f, 2f, w, h, mWaveHeight/2)); - } - - } @Override public void move(int maxWidth, int maxHight) { - runWave(); + φ -= 0.1f; + ω = 2 * Math.PI / width; } @Override - public void onDraw(Canvas canvas, Paint paint) { - if (mltWave.size() > 0 && mPaint != null) { - long thisTime = System.currentTimeMillis(); - for (Wave wave : mltWave) { - mMatrix.reset(); - canvas.save(); - if (mLastTime > 0 && wave.velocity != 0) { - float offsetX = (wave.offsetX - (wave.velocity * mVelocity * (thisTime - mLastTime) / 1000f)); - if (-wave.velocity > 0) { - offsetX %= wave.width / 2; - } else { - while (offsetX < 0) { - offsetX += (wave.width / 2); - } - } - wave.offsetX = offsetX; - mMatrix.setTranslate(offsetX, (1 - mProgress) * height); - canvas.translate(-offsetX, -wave.offsetY - (1 - mProgress) * height); - } else{ - mMatrix.setTranslate(wave.offsetX, (1 - mProgress) * height); - canvas.translate(-wave.offsetX, -wave.offsetY - (1 - mProgress) * height); - } - //mPaint.getShader().setLocalMatrix(mMatrix); - canvas.drawPath(wave.path, mPaint); - canvas.restore(); + public void onDraw(Canvas canvas, Paint mPaint) { + canvas.setDrawFilter(mDrawFilter); + + mAbovePath.reset(); + mBelowWavePath.reset(); + + mAbovePath.moveTo(left, higth); +// mBelowWavePath.moveTo(getLeft(), getBottom() + 15); + for (float x = 0; x <= width; x++) { + /** + * y=Asin(ωx+φ)+k + * A—振幅越大,波形在y轴上最大与最小值的差值越大 + * ω—角速度, 控制正弦周期(单位角度内震动的次数) + * φ—初相,反映在坐标系上则为图像的左右移动。这里通过不断改变φ,达到波浪移动效果 + * k—偏距,反映在坐标系上则为图像的上移或下移。 + */ + y = (float) (30 * Math.cos(ω * x + φ) + 30)+y2; +// y2 = (float) (30 * Math.sin(ω * x + φ) + 30); + mAbovePath.lineTo(x, y); +// mBelowWavePath.lineTo(x, y2); + if (x == width / 2) { + mPaint.setColor(color); + canvas.drawCircle(x, y-40, 20, mPaint); + //mWaveAnimationListener.OnWaveAnimation(y); } - mLastTime = thisTime; } - } - } - - /** - * 水波对象 - * Created by SCWANG on 2017/12/11. - */ - class Wave { - - Path path; //水波路径 - int width; //画布宽度(2倍波长) - int wave; //波幅(振幅) - float offsetX; //水波的水平偏移量 - float offsetY; //水波的竖直偏移量 - float velocity; //水波移动速度(像素/秒) - private float scaleX; //水平拉伸比例 - private float scaleY; //竖直拉伸比例 - - - /** - * 通过参数构造一个水波对象 - * - * @param offsetX 水平偏移量 - * @param offsetY 竖直偏移量 - * @param velocity 移动速度(像素/秒) - * @param scaleX 水平拉伸量 - * @param scaleY 竖直拉伸量 - * @param w 波长 - * @param h 画布高度 - * @param wave 波幅(波宽度) - */ - - public Wave(int offsetX, int offsetY, int velocity, float scaleX, float scaleY, int w, int h, int wave) { - - this.width = (int) (2 * scaleX * w); //画布宽度(2倍波长) - this.wave = wave; //波幅(波宽) - this.scaleX = scaleX; //水平拉伸量 - this.scaleY = scaleY; //竖直拉伸量 - this.offsetX = offsetX; //水平偏移量 - this.offsetY = offsetY; //竖直偏移量 - this.velocity = velocity; //移动速度(像素/秒) - this.path = buildWavePath(width, h); - } - - - /* - * 根据 波长度、中轴线高度、波幅 绘制水波路径 - */ - - public void updateWavePath(int w, int h, int waveHeight) { - this.wave = (wave > 0) ? wave : waveHeight / 2; - this.width = (int) (2 * scaleX * w); //画布宽度(2倍波长) - this.path = buildWavePath(width, h); - } - - - private Path buildWavePath(int width, int height) { - int DP = Util.dipToPX(context, 1);//一个dp在当前设备表示的像素量(水波的绘制精度设为一个dp单位) - if (DP < 1) { - DP = 1; - } - - int wave = (int) (scaleY * this.wave);//计算拉伸之后的波幅 - - Path path = new Path(); - //path.moveTo(0, 0); - //path.lineTo(0, height - wave); - path.moveTo(0, height); - path.lineTo(0, height - wave); - - for (int x = DP; x < width; x += DP) { - path.lineTo(x, height - wave - wave * (float) Math.sin(4.0 * Math.PI * x / width)); - } - - path.lineTo(width, height - wave); - //path.lineTo(width, 0); - path.lineTo(width, height); - path.close(); - return path; - } - } - - - /** - * 绘制外层的刻度 - * - * @param canvas - protected void drawOutArc(Canvas canvas) { - canvas.save(); - for (int i = 0; i < 100; i++) { - if (i < mPercent) { - mOutProgressPaint.setColor(mProgressColor); - } else { - mOutProgressPaint.setColor(mOutBaseColor); - } - canvas.rotate(3.6f, width / 2, height / 2); - canvas.drawLine(width / 2, 0, height / 2, mDefaultLineLen, mOutProgressPaint); - - } - canvas.restore(); - } - */ - - /** - * 根据 最高点,获取贝塞尔曲线的 控制点 - * - * @param startPointF 开始点 - * @param endPointF 结束点 - * @param bezierPointF 最高点 - * @return 控制点 - */ - public static Point getControlPointF(Point startPointF, Point endPointF, Point bezierPointF) { - //B(t)=(1-t)^2P0+2t(1-t)P1+t^2P2; - Point controlPointF = new Point(0l, 0l); - float tmp = 0.5F; - float t = 0.5F; - controlPointF.setX((bezierPointF.x - tmp * tmp * startPointF.y - t * t * endPointF.y) / (2 * t * tmp)); - controlPointF.setY((bezierPointF.y- tmp * tmp * startPointF.y - t * t * endPointF.y) / (2 * t * tmp)); - return controlPointF; - } - - public static class Point{ - public float x,y; - public Point(float x,float y){ - this.x=x; - this.y=y; - } - - public void setX(float x){ - this.x=x; - } - - public void setY(float y){ - this.y=y; + //回调 把y坐标的值传出去(在activity里面接收让小机器人随波浪一起摇摆) + mAbovePath.lineTo(width, higth); +// mBelowWavePath.lineTo(getRight(), getBottom() + 15); + canvas.drawPath(mAbovePath, mAboveWavePaint); +// canvas.drawPath(mBelowWavePath, mBelowWavePaint); } } diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/AbstractClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/AbstractClock.java index b0c4304..ff69399 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/AbstractClock.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/AbstractClock.java @@ -6,32 +6,31 @@ import android.graphics.Paint; import java.util.Calendar; import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry; +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer.DefaultPointer; public abstract class AbstractClock implements I_AnimatorEntry { protected int width,hight; protected int mCenterX, mCenterY; - // 默认刻度画笔、指针画笔、文字画笔; - protected Paint mDefaultPaint, mPointerPaint, mTextPaint; + // 默认刻度画笔、文字画笔; + protected Paint mDefaultPaint, mTextPaint; - // 时钟半径、中心点半径、默认刻度长度、默认刻度宽度、特殊刻度长度、特殊刻度宽度、 - // 时指针长度、时钟指针宽度、分钟指针长度、分钟指针宽度、秒钟指针长度、秒钟指针宽度 - protected float mRadius, mPointRadius, + // 时钟半径、中心点半径、默认刻度长度、默认刻度宽度、特殊刻度长度、特殊刻度宽度 + protected float mRadius, mDefaultScaleLength, mDefaultScaleWidth, - mParticularlyScaleLength, mParticularlyScaleWidth, - mHourPointerLength, mHourPointerWidth, - mMinutePointerLength, mMinutePointerWidth, - mSecondPointerLength, mSecondPointerWidth; + mParticularlyScaleLength, mParticularlyScaleWidth; // 当前时、分、秒 protected int mH, mM, mS; - // 时钟颜色、默认刻度颜色、时刻度颜色、时针颜色、分针颜色、秒针颜色 - protected int mClockColor, mColorDefaultScale, mColorParticularyScale, mColorHourPointer, - mColorMinutePointer, mColorSecondPointer,textColor; + // 时钟颜色、默认刻度颜色、时刻度颜色 + protected int mClockColor, mColorDefaultScale, mColorParticularyScale,textColor; + + I_Pointer pointer; public AbstractClock() { + } public void init(int width,int hight,int mCenterX, int mCenterY, float mRadius, int mClockColor,int textColor){ @@ -42,35 +41,51 @@ public abstract class AbstractClock implements I_AnimatorEntry { this.mRadius = mRadius; this.mClockColor = mClockColor; this.textColor=textColor; + initScaleLength(); init(); + setPointer(new DefaultPointer()); } private void init() { mColorDefaultScale = mClockColor; mColorParticularyScale = mClockColor; - mColorHourPointer = mClockColor; - mColorMinutePointer = mClockColor; - mColorSecondPointer = mClockColor; - mDefaultPaint = new Paint(); mDefaultPaint.setAntiAlias(true); mDefaultPaint.setStyle(Paint.Style.STROKE); - mPointerPaint = new Paint(); - mPointerPaint.setAntiAlias(true); - mPointerPaint.setStyle(Paint.Style.FILL_AND_STROKE); - mPointerPaint.setTextSize(14); - mPointerPaint.setStrokeCap(Paint.Cap.ROUND); - mTextPaint = new Paint(); - mPointerPaint.setAntiAlias(true); - mPointerPaint.setStyle(Paint.Style.FILL); - mPointerPaint.setColor(mClockColor); - initClockPointerLength(); + mTextPaint.setStrokeWidth(mDefaultScaleWidth / 2); + mTextPaint.setTextSize(mParticularlyScaleWidth * 4); + mTextPaint.setTextAlign(Paint.Align.CENTER); + mTextPaint.setColor(textColor); } + protected void initScaleLength(){ + /* + * 默认时钟刻度长=半径/10; + * 默认时钟刻度宽=长/6; + * + * */ + mDefaultScaleLength = mRadius / 10; + mDefaultScaleWidth = mDefaultScaleLength / 6; + + /* + * 特殊时钟刻度长=半径/5; + * 特殊时钟刻度宽=长/6; + * + * */ + mParticularlyScaleLength = mRadius / 5; + mParticularlyScaleWidth = mParticularlyScaleLength / 6; + } + + + public void setPointer(I_Pointer pointer){ + this.pointer=pointer; + pointer.init(mRadius,mClockColor); + } + /** * 获取当前系统时间 */ @@ -95,21 +110,14 @@ public abstract class AbstractClock implements I_AnimatorEntry { mS = s; } - /** - * 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径 - */ - protected abstract void initClockPointerLength(); public void onDraw(Canvas canvas, Paint mPaint) { - - setTextPaint(); drawBorder(canvas); drawOrnament(canvas); // 坐标原点移动到View 中心 canvas.translate(mCenterX, mCenterY); drawText(canvas); - drawPointer(canvas); - + pointer.drawPointer(canvas,mH,mM,mS,mPaint); } /** @@ -204,83 +212,6 @@ public abstract class AbstractClock implements I_AnimatorEntry { canvas.drawText(h, y, 0 + offsetY, mTextPaint); } - protected void setTextPaint() { - mTextPaint.setStrokeWidth(mDefaultScaleWidth / 2); - mTextPaint.setTextSize(mParticularlyScaleWidth * 4); - mTextPaint.setTextAlign(Paint.Align.CENTER); - mTextPaint.setColor(textColor); - } - - /** - * 绘制指针 - */ - protected void drawPointer(Canvas canvas) { - drawHourPointer(canvas); - drawMinutePointer(canvas); - drawSecondPointer(canvas); - - mPointerPaint.setColor(mClockColor); - // 绘制中心原点,需要在指针绘制完成后才能绘制 - canvas.drawCircle(0, 0, mPointRadius, mPointerPaint); - } - - /** - * 绘制时针 - */ - protected void drawHourPointer(Canvas canvas) { - - mPointerPaint.setStrokeWidth(mHourPointerWidth); - mPointerPaint.setColor(mColorHourPointer); - - // 当前时间的总秒数 - float s = mH * 60 * 60 + mM * 60 + mS; - // 百分比 - float percentage = s / (12 * 60 * 60); - // 通过角度计算弧度值,因为时钟的角度起线是y轴负方向,而View角度的起线是x轴正方向,所以要加270度 - float angle = 270 + 360 * percentage; - - float x = (float) (mHourPointerLength * Math.cos(Math.PI * 2 / 360 * angle)); - float y = (float) (mHourPointerLength * Math.sin(Math.PI * 2 / 360 * angle)); - - canvas.drawLine(0, 0, x, y, mPointerPaint); - } - - /** - * 绘制分针 - */ - protected void drawMinutePointer(Canvas canvas) { - - mPointerPaint.setStrokeWidth(mMinutePointerWidth); - mPointerPaint.setColor(mColorMinutePointer); - - float s = mM * 60 + mS; - float percentage = s / (60 * 60); - float angle = 270 + 360 * percentage; - - float x = (float) (mMinutePointerLength * Math.cos(Math.PI * 2 / 360 * angle)); - float y = (float) (mMinutePointerLength * Math.sin(Math.PI * 2 / 360 * angle)); - - canvas.drawLine(0, 0, x, y, mPointerPaint); - } - - /** - * 绘制秒针 - */ - protected void drawSecondPointer(Canvas canvas) { - - mPointerPaint.setStrokeWidth(mSecondPointerWidth); - mPointerPaint.setColor(mColorSecondPointer); - - float s = mS; - float percentage = s / 60; - float angle = 270 + 360 * percentage; - - float x = (float) (mSecondPointerLength * Math.cos(Math.PI * 2 / 360 * angle)); - float y = (float) (mSecondPointerLength * Math.sin(Math.PI * 2 / 360 * angle)); - - canvas.drawLine(0, 0, x, y, mPointerPaint); - } - @Override public void move(int maxWidth, int maxHight) { getTime(); diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/CircleClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/CircleClock.java index 81228ae..7b0ffab 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/CircleClock.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/CircleClock.java @@ -6,53 +6,7 @@ import android.graphics.Paint; public class CircleClock extends AbstractClock { - /** - * 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径 - */ - protected void initClockPointerLength() { - /* - * 默认时钟刻度长=半径/10; - * 默认时钟刻度宽=长/6; - * - * */ - mDefaultScaleLength = mRadius / 10; - mDefaultScaleWidth = mDefaultScaleLength / 6; - /* - * 特殊时钟刻度长=半径/5; - * 特殊时钟刻度宽=长/6; - * - * */ - mParticularlyScaleLength = mRadius / 5; - mParticularlyScaleWidth = mParticularlyScaleLength / 6; - - /* - * 时针长=半径/3; - * 时针宽=特殊时钟刻度宽; - * - * */ - mHourPointerLength = mRadius / 3; - mHourPointerWidth = mParticularlyScaleWidth; - - /* - * 分针长=半径/2; - * 分针宽=特殊时钟刻度宽; - * - * */ - mMinutePointerLength = mRadius / 2; - mMinutePointerWidth = mParticularlyScaleWidth; - - /* - * 秒针长=半径/3*2; - * 秒针宽=默认时钟刻度宽; - * - * */ - mSecondPointerLength = mRadius / 3 * 2; - mSecondPointerWidth = mDefaultScaleWidth; - - // 中心点半径=(默认刻度宽+特殊刻度宽)/2 - mPointRadius = (mDefaultScaleWidth + mParticularlyScaleWidth) / 2; - } /** * 绘制时钟的圆形和刻度 */ @@ -69,14 +23,14 @@ public class CircleClock extends AbstractClock { mDefaultPaint.setStrokeWidth(mParticularlyScaleWidth); mDefaultPaint.setColor(mColorParticularyScale); - + mDefaultPaint.setAlpha(255); canvas.drawLine(0, -mRadius, 0, -mRadius + mParticularlyScaleLength, mDefaultPaint); } else { // 一般时刻 mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); mDefaultPaint.setColor(mColorDefaultScale); - + mDefaultPaint.setAlpha(100); canvas.drawLine(0, -mRadius, 0, -mRadius + mDefaultScaleLength, mDefaultPaint); } diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/CircleTwoClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/CircleTwoClock.java new file mode 100644 index 0000000..8858e37 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/CircleTwoClock.java @@ -0,0 +1,43 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator; + +import android.graphics.Canvas; + +public class CircleTwoClock extends AbstractClock { + + + + /** + * 绘制时钟的圆形和刻度 + */ + protected void drawBorder(Canvas canvas) { + canvas.save(); + canvas.translate(mCenterX, mCenterY); + mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); + mDefaultPaint.setColor(mClockColor); + + canvas.drawCircle(0, 0, mRadius, mDefaultPaint); + + for (int i = 0; i < 60; i++) { + if (i % 5 == 0) { // 特殊时刻 + mDefaultPaint.setStrokeWidth(mParticularlyScaleWidth); + mDefaultPaint.setColor(mColorParticularyScale); + mDefaultPaint.setAlpha(255); + canvas.drawLine(0, -mRadius+mDefaultScaleWidth*1.2f, 0, -mRadius + mDefaultScaleLength+mDefaultScaleWidth*1.3f, mDefaultPaint); + } else { // 一般时刻 + mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); + mDefaultPaint.setColor(mColorDefaultScale); + mDefaultPaint.setAlpha(100); + canvas.drawLine(0, -mRadius+mDefaultScaleWidth, 0, -mRadius + mDefaultScaleLength, mDefaultPaint); + } + canvas.rotate(6); + } + + mDefaultPaint.setStrokeWidth(mDefaultScaleWidth/2); + mDefaultPaint.setAlpha(100); + canvas.drawCircle(0, 0, mRadius-mDefaultScaleLength*1.5f, mDefaultPaint); + + canvas.restore(); + } + + +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HelixClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HelixClock.java index 0ed29a8..7367b96 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HelixClock.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HelixClock.java @@ -7,53 +7,6 @@ import android.graphics.Paint; public class HelixClock extends AbstractClock { - /** - * 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径 - */ - protected void initClockPointerLength() { - /* - * 默认时钟刻度长=半径/10; - * 默认时钟刻度宽=长/6; - * - * */ - mDefaultScaleLength = mRadius / 10; - mDefaultScaleWidth = mDefaultScaleLength / 6; - - /* - * 特殊时钟刻度长=半径/5; - * 特殊时钟刻度宽=长/6; - * - * */ - mParticularlyScaleLength = mRadius / 5; - mParticularlyScaleWidth = mParticularlyScaleLength / 6; - - /* - * 时针长=半径/3; - * 时针宽=特殊时钟刻度宽; - * - * */ - mHourPointerLength = mRadius / 3; - mHourPointerWidth = mParticularlyScaleWidth; - - /* - * 分针长=半径/2; - * 分针宽=特殊时钟刻度宽; - * - * */ - mMinutePointerLength = mRadius / 2; - mMinutePointerWidth = mParticularlyScaleWidth; - - /* - * 秒针长=半径/3*2; - * 秒针宽=默认时钟刻度宽; - * - * */ - mSecondPointerLength = mRadius / 3 * 2; - mSecondPointerWidth = mDefaultScaleWidth; - - // 中心点半径=(默认刻度宽+特殊刻度宽)/2 - mPointRadius = (mDefaultScaleWidth + mParticularlyScaleWidth) / 2; - } /** * 绘制时钟的圆形和刻度 */ diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HexagonalClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HexagonalClock.java index 3046fd4..ddd3eca 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HexagonalClock.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/HexagonalClock.java @@ -6,53 +6,7 @@ import android.graphics.Paint; //六角形 public class HexagonalClock extends AbstractClock { - /** - * 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径 - */ - protected void initClockPointerLength() { - /* - * 默认时钟刻度长=半径/10; - * 默认时钟刻度宽=长/6; - * - * */ - mDefaultScaleLength = mRadius / 10; - mDefaultScaleWidth = mDefaultScaleLength / 6; - /* - * 特殊时钟刻度长=半径/5; - * 特殊时钟刻度宽=长/6; - * - * */ - mParticularlyScaleLength = mRadius / 5; - mParticularlyScaleWidth = mParticularlyScaleLength / 6; - - /* - * 时针长=半径/3; - * 时针宽=特殊时钟刻度宽; - * - * */ - mHourPointerLength = mRadius / 3; - mHourPointerWidth = mParticularlyScaleWidth; - - /* - * 分针长=半径/2; - * 分针宽=特殊时钟刻度宽; - * - * */ - mMinutePointerLength = mRadius / 2; - mMinutePointerWidth = mParticularlyScaleWidth; - - /* - * 秒针长=半径/3*2; - * 秒针宽=默认时钟刻度宽; - * - * */ - mSecondPointerLength = mRadius / 3 * 2; - mSecondPointerWidth = mDefaultScaleWidth; - - // 中心点半径=(默认刻度宽+特殊刻度宽)/2 - mPointRadius = (mDefaultScaleWidth + mParticularlyScaleWidth) / 2; - } /** * 绘制时钟的圆形和刻度 */ @@ -89,10 +43,12 @@ public class HexagonalClock extends AbstractClock { if (j % 5 == 0) { // 特殊时刻 mDefaultPaint.setStrokeWidth(mParticularlyScaleWidth); mDefaultPaint.setColor(mColorParticularyScale); + mDefaultPaint.setAlpha(255); scaleLength = mParticularlyScaleLength; } else { // 一般时刻 mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); mDefaultPaint.setColor(mColorDefaultScale); + mDefaultPaint.setAlpha(100); scaleLength = mDefaultScaleLength; } floatLength = radianTanValue * scaleLength; diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/I_Pointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/I_Pointer.java new file mode 100644 index 0000000..93bcb7a --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/I_Pointer.java @@ -0,0 +1,12 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator; + +import android.graphics.Canvas; +import android.graphics.Paint; + +public interface I_Pointer { + + void init(float mRadius,int mClockColor); + + void drawPointer(Canvas canvas, int mH,int mM,int mS, Paint mPointerPaint); + +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OctagonalClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OctagonalClock.java index dd07be3..64af727 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OctagonalClock.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OctagonalClock.java @@ -6,54 +6,6 @@ import android.graphics.Paint; //八边形 public class OctagonalClock extends AbstractClock { - /** - * 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径 - */ - protected void initClockPointerLength() { - /* - * 默认时钟刻度长=半径/10; - * 默认时钟刻度宽=长/6; - * - * */ - mDefaultScaleLength = mRadius / 10; - mDefaultScaleWidth = mDefaultScaleLength / 6; - - /* - * 特殊时钟刻度长=半径/5; - * 特殊时钟刻度宽=长/6; - * - * */ - mParticularlyScaleLength = mRadius / 5; - mParticularlyScaleWidth = mParticularlyScaleLength / 6; - - /* - * 时针长=半径/3; - * 时针宽=特殊时钟刻度宽; - * - * */ - mHourPointerLength = mRadius / 3; - mHourPointerWidth = mParticularlyScaleWidth; - - /* - * 分针长=半径/2; - * 分针宽=特殊时钟刻度宽; - * - * */ - mMinutePointerLength = mRadius / 2; - mMinutePointerWidth = mParticularlyScaleWidth; - - /* - * 秒针长=半径/3*2; - * 秒针宽=默认时钟刻度宽; - * - * */ - mSecondPointerLength = mRadius / 3 * 2; - mSecondPointerWidth = mDefaultScaleWidth; - - // 中心点半径=(默认刻度宽+特殊刻度宽)/2 - mPointRadius = (mDefaultScaleWidth + mParticularlyScaleWidth) / 2; - } - /** * 绘制时钟的圆形和刻度 * 分三段 @@ -95,10 +47,12 @@ public class OctagonalClock extends AbstractClock { if (k % 5 == 0) { // 特殊时刻 mDefaultPaint.setStrokeWidth(mParticularlyScaleWidth); mDefaultPaint.setColor(mColorParticularyScale); + mDefaultPaint.setAlpha(255); scaleLength=mParticularlyScaleLength; } else { // 一般时刻 mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); mDefaultPaint.setColor(mColorDefaultScale); + mDefaultPaint.setAlpha(100); scaleLength=mDefaultScaleLength; } floatLength=radianTanValue*scaleLength; diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OvalClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OvalClock.java index ff342cd..6e42ef4 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OvalClock.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/OvalClock.java @@ -6,54 +6,6 @@ import android.graphics.Paint; //(假)椭圆 public class OvalClock extends AbstractClock { - - /** - * 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径 - */ - protected void initClockPointerLength() { - /* - * 默认时钟刻度长=半径/10; - * 默认时钟刻度宽=长/6; - * - * */ - mDefaultScaleLength = mRadius / 10; - mDefaultScaleWidth = mDefaultScaleLength / 6; - - /* - * 特殊时钟刻度长=半径/5; - * 特殊时钟刻度宽=长/6; - * - * */ - mParticularlyScaleLength = mRadius / 5; - mParticularlyScaleWidth = mParticularlyScaleLength / 6; - - /* - * 时针长=半径/3; - * 时针宽=特殊时钟刻度宽; - * - * */ - mHourPointerLength = mRadius / 3; - mHourPointerWidth = mParticularlyScaleWidth; - - /* - * 分针长=半径/2; - * 分针宽=特殊时钟刻度宽; - * - * */ - mMinutePointerLength = mRadius / 2; - mMinutePointerWidth = mParticularlyScaleWidth; - - /* - * 秒针长=半径/3*2; - * 秒针宽=默认时钟刻度宽; - * - * */ - mSecondPointerLength = mRadius / 3 * 2; - mSecondPointerWidth = mDefaultScaleWidth; - - // 中心点半径=(默认刻度宽+特殊刻度宽)/2 - mPointRadius = (mDefaultScaleWidth + mParticularlyScaleWidth) / 2; - } /** * 绘制时钟的圆形和刻度 */ @@ -70,14 +22,14 @@ public class OvalClock extends AbstractClock { mDefaultPaint.setStrokeWidth(mParticularlyScaleWidth); mDefaultPaint.setColor(mColorParticularyScale); - + mDefaultPaint.setAlpha(255); canvas.drawLine(0, -mRadius, 0, -mRadius + mParticularlyScaleLength, mDefaultPaint); } else { // 一般时刻 mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); mDefaultPaint.setColor(mColorDefaultScale); - + mDefaultPaint.setAlpha(100); canvas.drawLine(0, -mRadius, 0, -mRadius + mDefaultScaleLength, mDefaultPaint); } diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/SquareClock.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/SquareClock.java index 44bf5f7..3716060 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/SquareClock.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/SquareClock.java @@ -6,54 +6,6 @@ import android.graphics.Paint; //方型 public class SquareClock extends AbstractClock { - /** - * 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径 - */ - protected void initClockPointerLength() { - /* - * 默认时钟刻度长=半径/10; - * 默认时钟刻度宽=长/6; - * - * */ - mDefaultScaleLength = mRadius / 10; - mDefaultScaleWidth = mDefaultScaleLength / 6; - - /* - * 特殊时钟刻度长=半径/5; - * 特殊时钟刻度宽=长/6; - * - * */ - mParticularlyScaleLength = mRadius / 5; - mParticularlyScaleWidth = mParticularlyScaleLength / 6; - - /* - * 时针长=半径/3; - * 时针宽=特殊时钟刻度宽; - * - * */ - mHourPointerLength = mRadius / 3; - mHourPointerWidth = mParticularlyScaleWidth; - - /* - * 分针长=半径/2; - * 分针宽=特殊时钟刻度宽; - * - * */ - mMinutePointerLength = mRadius / 2; - mMinutePointerWidth = mParticularlyScaleWidth; - - /* - * 秒针长=半径/3*2; - * 秒针宽=默认时钟刻度宽; - * - * */ - mSecondPointerLength = mRadius / 3 * 2; - mSecondPointerWidth = mDefaultScaleWidth; - - // 中心点半径=(默认刻度宽+特殊刻度宽)/2 - mPointRadius = (mDefaultScaleWidth + mParticularlyScaleWidth) / 2; - } - /** * 绘制时钟的外型形和刻度 */ @@ -82,10 +34,12 @@ public class SquareClock extends AbstractClock { if (j % 5 == 0) { // 特殊时刻 mDefaultPaint.setStrokeWidth(mParticularlyScaleWidth); mDefaultPaint.setColor(mColorParticularyScale); + mDefaultPaint.setAlpha(255); scaleLength=mParticularlyScaleLength; } else { // 一般时刻 mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); mDefaultPaint.setColor(mColorDefaultScale); + mDefaultPaint.setAlpha(100); scaleLength=mDefaultScaleLength; } floatLength=radianTanValue*scaleLength; @@ -113,10 +67,12 @@ public class SquareClock extends AbstractClock { if (j % 5 == 0) { // 特殊时刻 mDefaultPaint.setStrokeWidth(mParticularlyScaleWidth); mDefaultPaint.setColor(mColorParticularyScale); + mDefaultPaint.setAlpha(255); scaleLength=mParticularlyScaleLength; } else { // 一般时刻 mDefaultPaint.setStrokeWidth(mDefaultScaleWidth); mDefaultPaint.setColor(mColorDefaultScale); + mDefaultPaint.setAlpha(100); scaleLength=mDefaultScaleLength; } floatLength=radianTanValue*scaleLength; @@ -127,7 +83,6 @@ public class SquareClock extends AbstractClock { canvas.drawLine(width,startY-stepLeng, width - scaleLength,startY-stepLeng+floatLength, mDefaultPaint); j++; } - //} } diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/AbstractPointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/AbstractPointer.java new file mode 100644 index 0000000..fb86cbe --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/AbstractPointer.java @@ -0,0 +1,177 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.I_Pointer; + +public abstract class AbstractPointer implements I_Pointer { + + protected Paint mPointerPaint; + + protected float mRadius, mPointRadius, + mHourPointerLength, mHourPointerWidth, + mMinutePointerLength, mMinutePointerWidth, + mSecondPointerLength, mSecondPointerWidth; + + + protected int mClockColor, mColorHourPointer,mColorMinutePointer, mColorSecondPointer; + + // 当前时、分、秒 + protected int mH, mM, mS; + + @Override + public void init(float mRadius,int mClockColor) { + this.mRadius = mRadius; + this.mClockColor = mClockColor; + mColorHourPointer=mColorMinutePointer=mColorSecondPointer=mClockColor; + initPaint(); + initPointerLength(mRadius); + } + + + public void initPaint(){ + mPointerPaint = new Paint(); + mPointerPaint.setAntiAlias(true); + mPointerPaint.setStyle(Paint.Style.FILL_AND_STROKE); + mPointerPaint.setStrokeCap(Paint.Cap.ROUND); + mPointerPaint.setColor(mClockColor); + } + + + + + public void initPointerLength(float mRadius){ + /* + * 默认时钟刻度长=半径/10; + * 默认时钟刻度宽=长/6; + * + * */ + float mDefaultScaleLength = mRadius / 10; + float mDefaultScaleWidth = mDefaultScaleLength / 6; + + /* + * 特殊时钟刻度长=半径/5; + * 特殊时钟刻度宽=长/6; + * + * */ + float mParticularlyScaleLength = mRadius / 5; + float mParticularlyScaleWidth = mParticularlyScaleLength / 6; + + /* + * 时针长=半径/3; + * 时针宽=特殊时钟刻度宽; + * + * */ + mHourPointerLength = mRadius / 3; + mHourPointerWidth = mParticularlyScaleWidth; + + /* + * 分针长=半径/2; + * 分针宽=特殊时钟刻度宽; + * + * */ + mMinutePointerLength = mRadius / 2; + mMinutePointerWidth = mParticularlyScaleWidth; + + /* + * 秒针长=半径/3*2; + * 秒针宽=默认时钟刻度宽; + * + * */ + mSecondPointerLength = mRadius / 3 * 2; + mSecondPointerWidth = mDefaultScaleWidth; + + // 中心点半径=(默认刻度宽+特殊刻度宽)/2 + mPointRadius = (mDefaultScaleWidth + mParticularlyScaleWidth) / 2; + } + + /** + * 绘制指针 + */ + public void drawPointer(Canvas canvas, int mH,int mM,int mS, Paint paint) { + this.mH=mH; + this.mM=mM; + this.mS=mS; + + drawHourPointer(canvas); + drawMinutePointer(canvas); + drawSecondPointer(canvas); + + drawCenterCircle(canvas); + } + + // 绘制中心原点,需要在指针绘制完成后才能绘制 + protected void drawCenterCircle(Canvas canvas){ + canvas.drawCircle(0, 0, mPointRadius, mPointerPaint); + } + + /** + * 绘制时针 + */ + protected void drawHourPointer(Canvas canvas) { + + mPointerPaint.setStrokeWidth(mHourPointerWidth); + mPointerPaint.setColor(mColorHourPointer); + + // 当前时间的总秒数 + float s = mH * 60 * 60 + mM * 60 + mS; + // 百分比 + float percentage = s / (12 * 60 * 60); + // 通过角度计算弧度值,因为时钟的角度起线是y轴负方向,而View角度的起线是x轴正方向,所以要加270度 + float angle = calcAngle(percentage); + + float x = calcX(mHourPointerLength , angle); + float y = calcY(mHourPointerLength , angle); + + canvas.drawLine(0, 0, x, y, mPointerPaint); + } + + /** + * 绘制分针 + */ + protected void drawMinutePointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mMinutePointerWidth); + mPointerPaint.setColor(mColorMinutePointer); + + float s = mM * 60 + mS; + float percentage = s / (60 * 60); + float angle = calcAngle(percentage); + + float x = calcX(mMinutePointerLength , angle); + float y = calcY(mMinutePointerLength , angle); + + canvas.drawLine(0, 0, x, y, mPointerPaint); + } + + /** + * 绘制秒针 + */ + protected void drawSecondPointer(Canvas canvas) { + + mPointerPaint.setStrokeWidth(mSecondPointerWidth); + mPointerPaint.setColor(mColorSecondPointer); + + float s = mS; + float percentage = s / 60; + float angle = calcAngle(percentage); + + float x = calcX(mSecondPointerLength , angle); + float y = calcY(mSecondPointerLength , angle); + + canvas.drawLine(0, 0, x, y, mPointerPaint); + } + + protected float calcAngle(float percentage){ + return 270 + 360 * percentage; + } + + protected float calcX(float baseLength,float angle){ + return (float)(baseLength * Math.cos(Math.PI * 2 / 360 * angle)); + } + + protected float calcY(float baseLength,float angle){ + return (float) (baseLength * Math.sin(Math.PI * 2 / 360 * angle)); + } + +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/DefaultPointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/DefaultPointer.java new file mode 100644 index 0000000..725e550 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/DefaultPointer.java @@ -0,0 +1,5 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +public class DefaultPointer extends AbstractPointer { + +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/LeafPointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/LeafPointer.java new file mode 100644 index 0000000..1b58213 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/LeafPointer.java @@ -0,0 +1,73 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +import android.graphics.Canvas; +import android.graphics.Path; + +public class LeafPointer extends SecondTailPointer { + + + @Override + public void initPointerLength(float mRadius) { + super.initPointerLength(mRadius); + mMinutePointerWidth=mMinutePointerWidth/3; + } + + @Override + protected void drawHourPointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mHourPointerWidth); + mPointerPaint.setColor(mColorHourPointer); + + // 当前时间的总秒数 + float s = mH * 60 * 60 + mM * 60 + mS; + // 百分比 + float percentage = s / (12 * 60 * 60); + // 通过角度计算弧度值,因为时钟的角度起线是y轴负方向,而View角度的起线是x轴正方向,所以要加270度 + float angle = calcAngle(percentage); + + float x = calcX(mHourPointerLength, angle); + float y = calcY(mHourPointerLength, angle); + + float minLength = mHourPointerLength / 2; + + float x1 = calcX(minLength, angle + 20); + float y1 = calcY(minLength, angle + 20); + + float x2 = calcX(minLength, angle - 20); + float y2 = calcY(minLength, angle - 20); + + + Path path = new Path(); + path.cubicTo(0, 0, x1, y1, x, y); + path.cubicTo(x, y, x2, y2, 0, 0); + + canvas.drawPath(path, mPointerPaint); + } + + @Override + protected void drawMinutePointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mMinutePointerWidth); + mPointerPaint.setColor(mColorMinutePointer); + + float s = mM * 60 + mS; + float percentage = s / (60 * 60); + float angle = calcAngle(percentage); + + float x = calcX(mMinutePointerLength, angle); + float y = calcY(mMinutePointerLength, angle); + + float minLength = mMinutePointerLength / 2; + + float x1 = calcX(minLength, angle + 10); + float y1 = calcY(minLength, angle + 10); + + float x2 = calcX(minLength, angle - 10); + float y2 = calcY(minLength, angle - 10); + + + Path path = new Path(); + path.cubicTo(0, 0, x1, y1, x, y); + path.cubicTo(x, y, x2, y2, 0, 0); + + canvas.drawPath(path, mPointerPaint); + } +} \ No newline at end of file diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/LeafTwoPointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/LeafTwoPointer.java new file mode 100644 index 0000000..43608d7 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/LeafTwoPointer.java @@ -0,0 +1,72 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +import android.graphics.Canvas; +import android.graphics.Path; + +public class LeafTwoPointer extends SecondTailPointer { + + @Override + public void initPointerLength(float mRadius) { + super.initPointerLength(mRadius); + mMinutePointerWidth=mMinutePointerWidth/3; + } + + @Override + protected void drawHourPointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mHourPointerWidth); + mPointerPaint.setColor(mColorHourPointer); + + // 当前时间的总秒数 + float s = mH * 60 * 60 + mM * 60 + mS; + // 百分比 + float percentage = s / (12 * 60 * 60); + // 通过角度计算弧度值,因为时钟的角度起线是y轴负方向,而View角度的起线是x轴正方向,所以要加270度 + float angle = calcAngle(percentage); + + float x = calcX(mHourPointerLength, angle); + float y = calcY(mHourPointerLength, angle); + + float minLength = mHourPointerLength / 2; + + float x1 = calcX(minLength, angle + 20); + float y1 = calcY(minLength, angle + 20); + + float x2 = calcX(minLength, angle - 20); + float y2 = calcY(minLength, angle - 20); + + + Path path = new Path(); + path.cubicTo(0, 0, x1, y1, x, y); + path.cubicTo(0, 0, x2, y2,x, y ); + + canvas.drawPath(path, mPointerPaint); + } + + @Override + protected void drawMinutePointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mMinutePointerWidth); + mPointerPaint.setColor(mColorMinutePointer); + + float s = mM * 60 + mS; + float percentage = s / (60 * 60); + float angle = calcAngle(percentage); + + float x = calcX(mMinutePointerLength, angle); + float y = calcY(mMinutePointerLength, angle); + + float minLength = mMinutePointerLength / 2; + + float x1 = calcX(minLength, angle + 10); + float y1 = calcY(minLength, angle + 10); + + float x2 = calcX(minLength, angle - 10); + float y2 = calcY(minLength, angle - 10); + + + Path path = new Path(); + path.cubicTo(0, 0, x1, y1, x, y); + path.cubicTo(0, 0,x2, y2, x, y); + + canvas.drawPath(path, mPointerPaint); + } +} \ No newline at end of file diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/SecondTailPointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/SecondTailPointer.java new file mode 100644 index 0000000..846ed2b --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/SecondTailPointer.java @@ -0,0 +1,40 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +import android.graphics.Canvas; +import android.graphics.Color; + +public class SecondTailPointer extends AbstractPointer{ + + @Override + public void initPointerLength(float mRadius) { + super.initPointerLength(mRadius); + mHourPointerLength = mRadius / 8*4.5f; + mMinutePointerLength = mRadius / 8*6; + mSecondPointerLength = mRadius / 8 * 7; + } + + @Override + protected void drawCenterCircle(Canvas canvas) { + super.drawCenterCircle(canvas); + mPointerPaint.setColor(Color.BLACK); + canvas.drawCircle(0, 0, mPointRadius/2, mPointerPaint); + } + + @Override + protected void drawSecondPointer(Canvas canvas) { + super.drawSecondPointer(canvas); + + mPointerPaint.setStrokeWidth(mSecondPointerWidth*1.5f); + + float s = mS; + float percentage = s / 60; + float angle = calcAngle(percentage)+180; + + float x = calcX(mSecondPointerLength/5 , angle); + float y = calcY(mSecondPointerLength/5 , angle); + + canvas.drawLine(0, 0, x, y, mPointerPaint); + + canvas.drawCircle(0,0,mSecondPointerWidth*2,mPointerPaint); + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/SwordPointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/SwordPointer.java new file mode 100644 index 0000000..046d069 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/SwordPointer.java @@ -0,0 +1,99 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +import android.graphics.Canvas; +import android.graphics.Path; + +public class SwordPointer extends SecondTailPointer{ + + @Override + public void initPointerLength(float mRadius) { + super.initPointerLength(mRadius); + mHourPointerWidth=mHourPointerWidth/4; + mMinutePointerWidth=mMinutePointerWidth/4; + } + + @Override + protected void drawHourPointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mHourPointerWidth); + mPointerPaint.setColor(mColorHourPointer); + + // 当前时间的总秒数 + float s = mH * 60 * 60 + mM * 60 + mS; + // 百分比 + float percentage = s / (12 * 60 * 60); + // 通过角度计算弧度值,因为时钟的角度起线是y轴负方向,而View角度的起线是x轴正方向,所以要加270度 + float angle = calcAngle(percentage); + + float x = calcX(mHourPointerLength , angle); + float y = calcY(mHourPointerLength , angle); + + float minLength=mHourPointerLength*4/5; + + float x3 = calcX(minLength , angle+10); + float y3 = calcY(minLength , angle+10); + + float x4 = calcX(minLength , angle-10); + float y4 = calcY(minLength , angle-10); + + minLength=mHourPointerLength/5; + + float x1=calcX(minLength , angle+180+20); + float y1 = calcY(minLength , angle+180+20); + + float x2=calcX(minLength, angle+180-20); + float y2 = calcY(minLength , angle+180-20); + + + Path path=new Path(); + path.lineTo(x1,y1); + path.lineTo(x2,y2); + path.lineTo(0,0); + path.lineTo(x3,y3); + path.lineTo(x,y); + path.lineTo(x4,y4); + path.lineTo(0,0); + + canvas.drawPath(path,mPointerPaint); + } + + @Override + protected void drawMinutePointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mMinutePointerWidth); + mPointerPaint.setColor(mColorMinutePointer); + + float s = mM * 60 + mS; + float percentage = s / (60 * 60); + float angle = calcAngle(percentage); + + float x = calcX(mMinutePointerLength , angle); + float y = calcY(mMinutePointerLength , angle); + + float minLength=mMinutePointerLength*4/5; + + float x3 = calcX(minLength , angle+6); + float y3 = calcY(minLength , angle+6); + + float x4 = calcX(minLength , angle-6); + float y4 = calcY(minLength , angle-6); + + minLength=mMinutePointerLength/5; + + float x1=calcX(minLength , angle+180+10); + float y1 = calcY(minLength , angle+180+10); + + float x2=calcX(minLength, angle+180-10); + float y2 = calcY(minLength , angle+180-10); + + + Path path=new Path(); + path.lineTo(x1,y1); + path.lineTo(x2,y2); + path.lineTo(0,0); + path.lineTo(x3,y3); + path.lineTo(x,y); + path.lineTo(x4,y4); + path.lineTo(0,0); + + canvas.drawPath(path,mPointerPaint); + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/TrianglePointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/TrianglePointer.java new file mode 100644 index 0000000..413fd1c --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/TrianglePointer.java @@ -0,0 +1,71 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +import android.graphics.Canvas; +import android.graphics.Path; + +public class TrianglePointer extends SecondTailPointer{ + + + @Override + protected void drawHourPointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mHourPointerWidth); + mPointerPaint.setColor(mColorHourPointer); + + // 当前时间的总秒数 + float s = mH * 60 * 60 + mM * 60 + mS; + // 百分比 + float percentage = s / (12 * 60 * 60); + // 通过角度计算弧度值,因为时钟的角度起线是y轴负方向,而View角度的起线是x轴正方向,所以要加270度 + float angle = calcAngle(percentage); + + float x = calcX(mHourPointerLength , angle); + float y = calcY(mHourPointerLength , angle); + + float minLength=mHourPointerLength/5; + + float x1=calcX(minLength , angle+180+20); + float y1 = calcY(minLength , angle+180+20); + + float x2=calcX(minLength, angle+180-20); + float y2 = calcY(minLength , angle+180-20); + + + Path path=new Path(); + path.moveTo(x1,y1); + path.lineTo(x2,y2); + path.lineTo(x,y); + path.lineTo(x1,y1); + + canvas.drawPath(path,mPointerPaint); + } + + @Override + protected void drawMinutePointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mMinutePointerWidth); + mPointerPaint.setColor(mColorMinutePointer); + + float s = mM * 60 + mS; + float percentage = s / (60 * 60); + float angle = calcAngle(percentage); + + float x = calcX(mMinutePointerLength , angle); + float y = calcY(mMinutePointerLength , angle); + + float minLength=mMinutePointerLength/5; + + float x1=calcX(minLength , angle+180+20); + float y1 = calcY(minLength , angle+180+20); + + float x2=calcX(minLength, angle+180-20); + float y2 = calcY(minLength , angle+180-20); + + + Path path=new Path(); + path.moveTo(x1,y1); + path.lineTo(x2,y2); + path.lineTo(x,y); + path.lineTo(x1,y1); + + canvas.drawPath(path,mPointerPaint); + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/TwoStepPointer.java b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/TwoStepPointer.java new file mode 100644 index 0000000..78dcc69 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/animatorview/animator/clockanimator/pointer/TwoStepPointer.java @@ -0,0 +1,56 @@ +package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer; + +import android.graphics.Canvas; + +public class TwoStepPointer extends SecondTailPointer{ + + /** + * 绘制时针 + */ + protected void drawHourPointer(Canvas canvas) { + + mPointerPaint.setStrokeWidth(mHourPointerWidth*2); + mPointerPaint.setColor(mColorHourPointer); + + // 当前时间的总秒数 + float s = mH * 60 * 60 + mM * 60 + mS; + // 百分比 + float percentage = s / (12 * 60 * 60); + // 通过角度计算弧度值,因为时钟的角度起线是y轴负方向,而View角度的起线是x轴正方向,所以要加270度 + float angle = calcAngle(percentage); + + float x = calcX(mHourPointerLength , angle); + float y = calcY(mHourPointerLength , angle); + + float x1 = calcX(mHourPointerLength/4 , angle); + float y1 = calcY(mHourPointerLength/4 , angle); + + canvas.drawLine(x1, y1, x, y, mPointerPaint); + + mPointerPaint.setStrokeWidth(mHourPointerWidth/4); + canvas.drawLine(0,0,x1, y1, mPointerPaint); + } + + /** + * 绘制分针 + */ + protected void drawMinutePointer(Canvas canvas) { + mPointerPaint.setStrokeWidth(mMinutePointerWidth*2); + mPointerPaint.setColor(mColorMinutePointer); + + float s = mM * 60 + mS; + float percentage = s / (60 * 60); + float angle = calcAngle(percentage); + + float x = calcX(mMinutePointerLength , angle); + float y = calcY(mMinutePointerLength , angle); + + float x1 = calcX(mMinutePointerLength/4 , angle); + float y1 = calcY(mMinutePointerLength/4 , angle); + + canvas.drawLine(x1, y1, x, y, mPointerPaint); + + mPointerPaint.setStrokeWidth(mMinutePointerWidth/4); + canvas.drawLine(0,0,x1, y1, mPointerPaint); + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/textview/DigitTextView.java b/app/src/main/java/clock/socoolby/com/clock/widget/textview/DigitTextView.java index 6bf03a8..9eb6bcd 100644 --- a/app/src/main/java/clock/socoolby/com/clock/widget/textview/DigitTextView.java +++ b/app/src/main/java/clock/socoolby/com/clock/widget/textview/DigitTextView.java @@ -4,6 +4,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Shader; import android.text.TextPaint; @@ -12,8 +13,15 @@ import android.util.AttributeSet; import android.util.Log; import androidx.annotation.Nullable; +import java.util.HashMap; import java.util.Random; +import clock.socoolby.com.clock.widget.textview.charanimator.AbstractCharAnimator; +import clock.socoolby.com.clock.widget.textview.charanimator.CharAnimatorEnum; +import clock.socoolby.com.clock.widget.textview.charanimator.Down2UpCharAnimator; +import clock.socoolby.com.clock.widget.textview.charanimator.Marquee3DCharAnimator; +import clock.socoolby.com.clock.widget.textview.charanimator.Up2DownCharAnimator; + public class DigitTextView extends android.support.v7.widget.AppCompatTextView { public static final String Tag=DigitTextView.class.getSimpleName(); @@ -29,6 +37,8 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { int textWidth=0; + private CharSequence preString=null; + public DigitTextView(Context context) { super(context); } @@ -49,10 +59,13 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { boolean isLinearGradientPosAble=false; + boolean isReflectedAble=false; + public void setLinearGradientRandom(boolean able){ if(able){ linearGradientColors= new int[]{roundColor(), roundColor(), roundColor(), roundColor(), roundColor(), roundColor(), roundColor()}; isLinearGradientPosAble=rand.nextBoolean(); + isReflectedAble=rand.nextBoolean(); } setLinearGradientAble(able); setShadowType(rand.nextInt(3)); @@ -83,8 +96,9 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { case 1://阴影效果 setShadowLayer(4, 10, 10, Color.BLACK); break; - case 2://浮雕效果 - setShadowLayer(1, 0.5f, 0.5f, Color.argb(200,204,204,204)); + case 2: + //setShadowLayer(1, 0.5f, 0.5f, Color.argb(200,204,204,204));//浮雕效果 + setShadowLayer(10, 0, 0, Color.parseColor("#FF4141"));//边缘模糊 break; default: setShadowLayer(0,0,0,getPaint().getColor()); @@ -115,6 +129,25 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { this.linearGradientColors = linearGradientColors; } + public CharAnimatorEnum getCurrentCharAnimatorType() { + return currentCharAnimatorType; + } + + public void setCurrentCharAnimatorType(CharAnimatorEnum currentCharAnimatorType) { + this.currentCharAnimatorType = currentCharAnimatorType; + } + + private int textHight; + private int baseCharWidth; + private int flagCharwidth; + private int smallTextHight; + private int smallCharWidth; + private int textLength; + private int textSmallSpan; + private HashMap charAnimatorHashMap=new HashMap<>(); + + private CharAnimatorEnum currentCharAnimatorType= CharAnimatorEnum.Marquee3D_Up; + protected void onDraw(Canvas canvas) { int color = getCurrentTextColor(); @@ -126,15 +159,15 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { Paint.FontMetricsInt fm=mTextPaint.getFontMetricsInt(); - int baseCharWidth= getCharWidth("8",mTextPaint); - int flagCharwidth=getCharWidth(":",mTextPaint); - int textHight=-fm.descent - fm.ascent; - int smallTextHight=0; - int smallCharWidth=0; + baseCharWidth= getCharWidth("8",mTextPaint); + flagCharwidth=getCharWidth(":",mTextPaint); + textHight=-fm.descent - fm.ascent; + smallTextHight=0; + smallCharWidth=0; Paint smallCharPaint=null; - int textLength=textToDraw.length(); - int textSmallSpan=0; + textLength=textToDraw.length(); + textSmallSpan=0; if(textLength>4){ textWidth=baseCharWidth*4+flagCharwidth; @@ -152,6 +185,8 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { float startX=(getWidth()-textWidth-textSmallSpan)/2; float startY=(getHeight()+textHight)/2; + AbstractCharAnimator charAnimator; + for(int i=0;i1) + charAnimatorRuning=false; + } + + public boolean isCharAnimatorRuning() { + return charAnimatorRuning; + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/CharAnimatorEnum.java b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/CharAnimatorEnum.java new file mode 100644 index 0000000..2621b08 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/CharAnimatorEnum.java @@ -0,0 +1,5 @@ +package clock.socoolby.com.clock.widget.textview.charanimator; + +public enum CharAnimatorEnum{ + NOSETUP,UP2DOWN,DOWN2UP,Marquee3D_Up,Marquee3D_Down; +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Down2UpCharAnimator.java b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Down2UpCharAnimator.java new file mode 100644 index 0000000..ba121e3 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Down2UpCharAnimator.java @@ -0,0 +1,21 @@ +package clock.socoolby.com.clock.widget.textview.charanimator; + +import android.graphics.Canvas; +import android.graphics.Paint; + +public class Down2UpCharAnimator extends AbstractCharAnimator { + public Down2UpCharAnimator(String preString, String currentString) { + super(preString, currentString); + } + + @Override + public void drawCharPre(Canvas canvas, String strToDraw, float startX, float startY, Paint mTextPaint, float percent) { + canvas.drawText(strToDraw, startX, startY-startY*percent, mTextPaint); + } + + @Override + public void drawCharCurrent(Canvas canvas, String strToDraw, float startX, float startY, Paint mTextPaint, float percent) { + canvas.drawText(strToDraw, startX, 2*startY-startY*percent, mTextPaint); + } + +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Marquee3DCharAnimator.java b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Marquee3DCharAnimator.java new file mode 100644 index 0000000..09a4d87 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Marquee3DCharAnimator.java @@ -0,0 +1,113 @@ +package clock.socoolby.com.clock.widget.textview.charanimator; + +import android.graphics.Camera; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; + +//参考:https://github.com/xiangcman/Marquee3DView +public class Marquee3DCharAnimator extends AbstractCharAnimator { + + //从下到上进行旋转滚动 + public static final int D2U = 1; + //从上到下进行旋转滚动 + public static final int U2D = 2; + + //负责围绕那个轴进行旋转 + private Camera camera; + //负责控制旋转点 + private Matrix matrix; + + private float changeRotate; + + private float translateY; + + private int direction; + + public Marquee3DCharAnimator(String preString, String currentString,int direction) { + super(preString, currentString); + this.direction=direction; + initialize(); + } + + private void initialize() { + camera = new Camera(); + matrix = new Matrix(); + } + + @Override + public void move() { + super.move(); + changeRotate = 90*charAnimatorPercent; + } + + @Override + public void drawCharPre(Canvas canvas, String strToDraw, float startX, float startY, Paint mTextPaint, float percent) { + //从0到height的一个过程 + translateY = startY *charAnimatorPercent; + + int alpha = (int) (255 - percent * 255); + mTextPaint.setAlpha(alpha); + + float width=startX; + float height=startY; + + canvas.save(); + camera.save(); + if (direction == D2U) { + //当前的item是往里面转动的,因此角度是增大的 + camera.rotateX(changeRotate);//0到90度的过程 + } else { + camera.rotateX(-changeRotate); + } + camera.getMatrix(matrix); + camera.restore(); + if (direction == D2U) { + matrix.preTranslate(-width / 2, -height); + matrix.postTranslate(width / 2, height - translateY);//最后跑到0的位置了 + } else { + matrix.preTranslate(-width / 2, 0); + matrix.postTranslate(width / 2, translateY); + } + canvas.setMatrix(matrix); + canvas.drawText(strToDraw, startX, startY, mTextPaint); + canvas.restore(); + } + + @Override + public void drawCharCurrent(Canvas canvas, String strToDraw, float startX, float startY, Paint mTextPaint, float percent) { + + translateY = startY *charAnimatorPercent; + + float width=startX; + float height=startY; + + int alpha = (int) (percent * 255); + mTextPaint.setAlpha(alpha); + + canvas.save(); + camera.save(); + if (direction == D2U) { + //从-90度到0度的过程 + camera.rotateX(-90 + changeRotate); + } else { + //从上到下是90度到0度的过程 + camera.rotateX(90 - changeRotate); + } + camera.getMatrix(matrix); + camera.restore(); + + if (direction == D2U) { + matrix.preTranslate(-width / 2, 0); + matrix.postTranslate(width / 2, height + (-translateY)); + } else { + matrix.preTranslate(-width / 2, -height); + matrix.postTranslate(width / 2, translateY); + } + + canvas.setMatrix(matrix); + + canvas.drawText(strToDraw, startX, startY, mTextPaint); + canvas.restore(); + } +} diff --git a/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Up2DownCharAnimator.java b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Up2DownCharAnimator.java new file mode 100644 index 0000000..2ded6f3 --- /dev/null +++ b/app/src/main/java/clock/socoolby/com/clock/widget/textview/charanimator/Up2DownCharAnimator.java @@ -0,0 +1,21 @@ +package clock.socoolby.com.clock.widget.textview.charanimator; + +import android.graphics.Canvas; +import android.graphics.Paint; + +public class Up2DownCharAnimator extends AbstractCharAnimator { + public Up2DownCharAnimator(String preString, String currentString) { + super(preString, currentString); + } + + @Override + public void drawCharPre(Canvas canvas, String strToDraw, float startX, float startY, Paint mTextPaint, float percent) { + canvas.drawText(strToDraw, startX, startY+startY*percent, mTextPaint); + } + + @Override + public void drawCharCurrent(Canvas canvas, String strToDraw, float startX, float startY, Paint mTextPaint, float percent) { + canvas.drawText(strToDraw, startX, startY*percent, mTextPaint); + } + +} diff --git a/app/src/main/res/drawable/ic_alarm_clock.xml b/app/src/main/res/drawable/ic_alarm_clock.xml new file mode 100644 index 0000000..03ee783 --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm_clock.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_handup.xml b/app/src/main/res/drawable/ic_handup.xml index a13422b..6625921 100644 --- a/app/src/main/res/drawable/ic_handup.xml +++ b/app/src/main/res/drawable/ic_handup.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7b566c2..2090a57 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -24,6 +24,14 @@ android:background="#00FFFFFF" /> + + + android:src="@drawable/ic_alarm_clock" /> + + + + - - -