mirror of
https://gitee.com/51danju/workclock.git
synced 2025-07-16 13:57:29 +08:00
增加 计时、倒计时,时间变更动画和几个指针样式
This commit is contained in:
parent
6e9ddaa968
commit
45a2ab6701
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<AbstractClock> {
|
||||
@ -35,4 +42,35 @@ public class ClockAnimator extends AbstractAnimator<AbstractClock> {
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -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<MagicLineAnimator.MagicLine, MagicLineAnimator.CorrdinateData> {
|
||||
|
||||
|
||||
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<CorrdinateData> 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<SawtoothAnimator.Sawtooth> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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<WaterAnimator.Water> {
|
||||
|
||||
@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<Wave> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
/**
|
||||
* 绘制时钟的圆形和刻度
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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++;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.clockanimator.pointer;
|
||||
|
||||
public class DefaultPointer extends AbstractPointer {
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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<Integer, AbstractCharAnimator> 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;i<textLength;i++){
|
||||
String c=String.valueOf(textToDraw.charAt(i));
|
||||
if(i<5){
|
||||
@ -160,7 +195,24 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView {
|
||||
startX+=flagCharwidth;
|
||||
}else{
|
||||
int charWidth= getCharWidth(c,mTextPaint);
|
||||
canvas.drawText(c, startX+(baseCharWidth-charWidth)/2, startY+baseLineDown, mTextPaint);
|
||||
if(currentCharAnimatorType!= CharAnimatorEnum.NOSETUP) {
|
||||
charAnimator = charAnimatorHashMap.get(i);
|
||||
if (charAnimator != null && !charAnimator.isCharAnimatorRuning()) {
|
||||
charAnimatorHashMap.remove(i);
|
||||
charAnimator=null;
|
||||
}
|
||||
if (charAnimator == null&&preString != null&&preString.length()==textToDraw.length() && textToDraw.charAt(i) != preString.charAt(i)) {
|
||||
charAnimator=createCharAnimator(String.valueOf(preString.charAt(i)), c, currentCharAnimatorType);
|
||||
charAnimatorHashMap.put(i, charAnimator);
|
||||
}
|
||||
if (charAnimator != null) {
|
||||
charAnimator.drawCharAnimator(canvas, startX + (baseCharWidth - charWidth) / 2, startY + baseLineDown, mTextPaint);
|
||||
Log.d(Tag,"charAnimator index i:"+i+"\tanimator percent:");
|
||||
invalidate();
|
||||
}else
|
||||
drawChar(canvas, c, startX + (baseCharWidth - charWidth) / 2, startY + baseLineDown, mTextPaint);
|
||||
}else
|
||||
drawChar(canvas, c, startX + (baseCharWidth - charWidth) / 2, startY + baseLineDown, mTextPaint);
|
||||
startX+=baseCharWidth;
|
||||
}
|
||||
}else if(i==5) {
|
||||
@ -168,11 +220,54 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView {
|
||||
} else {
|
||||
float centerY=(getHeight()+smallTextHight)/2;
|
||||
centerY=centerY+(startY-centerY)/2+smallCharPaint.getFontMetrics().descent;
|
||||
canvas.drawText(c, startX, centerY+baseLineDown, smallCharPaint);
|
||||
drawChar(canvas,c, startX, centerY+baseLineDown, smallCharPaint);
|
||||
startX+=smallCharWidth;
|
||||
//Log.d(Tag,"view hight:"+getHeight()+"\t startY:"+startY+"\t text hight:"+textHight+"small text hight:"+smallTextHight);
|
||||
}
|
||||
}
|
||||
preString=textToDraw;
|
||||
}
|
||||
|
||||
private void drawChar(Canvas canvas,String c,float startX,float startY,Paint mTextPaint){
|
||||
if(isReflectedAble)
|
||||
drawCharReflected(canvas,c, startX, startY, mTextPaint);
|
||||
canvas.drawText(c, startX, startY, mTextPaint);
|
||||
}
|
||||
|
||||
|
||||
private void drawCharReflected(Canvas canvas,String c,float startX,float startY,Paint mTextPaint){
|
||||
canvas.save();
|
||||
Paint paint = new Paint(mTextPaint);
|
||||
LinearGradient shader = new LinearGradient(startX,
|
||||
-startY, startX,
|
||||
-startY-textHight*6/5,
|
||||
Color.BLACK, 0x00ffffff, Shader.TileMode.MIRROR);// 创建线性渐变LinearGradient对象
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.preScale(1, -1); // 实现图片的反转
|
||||
paint.setShader(shader); // 绘制
|
||||
paint.setAlpha(50);
|
||||
canvas.setMatrix(matrix);
|
||||
canvas.drawText(c, startX, -startY, paint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
private AbstractCharAnimator createCharAnimator(String preString, String currentString, CharAnimatorEnum type){
|
||||
AbstractCharAnimator charAnimator=null;
|
||||
switch (type){
|
||||
case DOWN2UP:
|
||||
charAnimator= new Down2UpCharAnimator(preString,currentString);
|
||||
break;
|
||||
case UP2DOWN:
|
||||
charAnimator= new Up2DownCharAnimator(preString,currentString);
|
||||
break;
|
||||
case Marquee3D_Up:
|
||||
charAnimator=new Marquee3DCharAnimator(preString,currentString,Marquee3DCharAnimator.D2U);
|
||||
break;
|
||||
case Marquee3D_Down:
|
||||
charAnimator=new Marquee3DCharAnimator(preString,currentString,Marquee3DCharAnimator.U2D);
|
||||
break;
|
||||
}
|
||||
return charAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,38 @@
|
||||
package clock.socoolby.com.clock.widget.textview.charanimator;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
public abstract class AbstractCharAnimator {
|
||||
protected boolean charAnimatorRuning;
|
||||
protected float charAnimatorPercent;
|
||||
|
||||
protected String preString,currentString;
|
||||
|
||||
public AbstractCharAnimator(String preString, String currentString) {
|
||||
this.preString = preString;
|
||||
this.currentString = currentString;
|
||||
charAnimatorRuning=true;
|
||||
charAnimatorPercent=0f;
|
||||
}
|
||||
|
||||
public void drawCharAnimator(Canvas canvas, float startX, float startY, Paint mTextPaint){
|
||||
drawCharPre(canvas, preString, startX, startY, mTextPaint,charAnimatorPercent);
|
||||
drawCharCurrent(canvas, currentString, startX, startY, mTextPaint,charAnimatorPercent);
|
||||
move();
|
||||
}
|
||||
|
||||
public abstract void drawCharPre(Canvas canvas,String strToDraw, float startX, float startY, Paint mTextPaint,final float percent);
|
||||
|
||||
public abstract void drawCharCurrent(Canvas canvas,String strToDraw, float startX, float startY, Paint mTextPaint,final float percent);
|
||||
|
||||
public void move(){
|
||||
charAnimatorPercent+=0.05f;
|
||||
if(charAnimatorPercent>1)
|
||||
charAnimatorRuning=false;
|
||||
}
|
||||
|
||||
public boolean isCharAnimatorRuning() {
|
||||
return charAnimatorRuning;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package clock.socoolby.com.clock.widget.textview.charanimator;
|
||||
|
||||
public enum CharAnimatorEnum{
|
||||
NOSETUP,UP2DOWN,DOWN2UP,Marquee3D_Up,Marquee3D_Down;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
18
app/src/main/res/drawable/ic_alarm_clock.xml
Normal file
18
app/src/main/res/drawable/ic_alarm_clock.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M3.7526,0.8136c-0.6062,0.1332 -0.7349,0.2251 -1.9243,1.4054c-0.6521,0.6475 -1.1666,1.194 -1.2538,1.3411c-0.078,0.1332 -0.1884,0.4042 -0.2388,0.6017c-0.2206,0.859 -0.101,1.1666 0.7992,2.0806c0.3262,0.3353 0.6154,0.6108 0.643,0.6108c0.0643,-0 4.5744,-4.5101 4.5744,-4.5744c0,-0.0734 -1.0426,-1.0747 -1.295,-1.2492c-0.4183,-0.2849 -0.7399,-0.3401 -1.3046,-0.216Z"
|
||||
android:fillColor="#FFF"/>
|
||||
<path
|
||||
android:pathData="M19.2895,0.8321c-0.1241,0.0504 -0.2986,0.1469 -0.3905,0.2158c-0.2388,0.179 -1.2492,1.1758 -1.2492,1.2355c0,0.0643 4.5101,4.5696 4.5742,4.5696c0.0276,-0 0.3168,-0.2755 0.6475,-0.6108c0.8957,-0.9139 1.0104,-1.2262 0.7946,-2.076c-0.0504,-0.1975 -0.1469,-0.4546 -0.2112,-0.5695c-0.1517,-0.2573 -2.1677,-2.3009 -2.4526,-2.4847c-0.4958,-0.312 -1.2996,-0.4452 -1.7129,-0.2798Z"
|
||||
android:fillColor="#FFF"/>
|
||||
<path
|
||||
android:pathData="M10.5084,2.3981c-2.1494,0.3307 -4.014,1.2446 -5.5618,2.7235c-2.7326,2.6086 -3.7937,6.4663 -2.7924,10.1268c0.2388,0.8726 0.7118,1.9428 1.2079,2.7418c0.0506,0.0826 -0.0458,0.3262 -0.7716,1.9702l-0.8314,1.8739l0,0.7073l0,0.7073l0.7118,-0l0.7118,-0l1.4698,-1.1712c0.8083,-0.643 1.4789,-1.1712 1.4926,-1.1712c0.0091,-0 0.179,0.1056 0.3766,0.2342c0.473,0.3122 1.5293,0.822 2.1079,1.0195c1.1393,0.395 2.1175,0.5558 3.3713,0.5558c0.9691,-0 1.5799,-0.0689 2.4341,-0.2803c0.9967,-0.2388 2.0988,-0.7073 2.9578,-1.2446c0.2479,-0.1562 0.4594,-0.2849 0.4685,-0.2849c0.0091,-0 0.6797,0.5282 1.488,1.1712l1.4698,1.1712l0.7118,-0l0.7118,-0l0,-0.7073l0,-0.7027l-0.8311,-1.8785l-0.8316,-1.878l0.0826,-0.1378c0.9552,-1.6075 1.4146,-3.0449 1.5341,-4.7626c0.2479,-3.6511 -1.4789,-7.1232 -4.579,-9.2129c-0.9185,-0.6199 -2.2366,-1.1803 -3.3571,-1.4282c-1.1251,-0.2527 -2.6638,-0.3079 -3.7522,-0.1426ZM12.6946,4.8782c1.8691,0.193 3.3938,0.9139 4.7074,2.2229c1.3502,1.3502 2.0666,2.9026 2.232,4.836c0.115,1.3457 -0.1195,2.5949 -0.7255,3.8717c-1.0517,2.2044 -3.0494,3.743 -5.4883,4.2346c-0.7531,0.1469 -2.0806,0.1469 -2.8337,-0c-3.2239,-0.6478 -5.6443,-3.1416 -6.1634,-6.3473c-0.2434,-1.511 0.0322,-3.2378 0.7394,-4.6433c0.7164,-1.4376 2.0851,-2.7739 3.5364,-3.4582c1.2538,-0.5971 2.6683,-0.8496 3.9958,-0.7164Z"
|
||||
android:fillColor="#FFF"/>
|
||||
<path
|
||||
android:pathData="M11.4499,5.8886c-3.0221,0.2479 -5.447,2.489 -6.0026,5.5342c-0.101,0.5556 -0.101,1.6534 0,2.2138c0.2525,1.3824 0.8635,2.549 1.8691,3.5549c0.9691,0.9691 2.0345,1.5478 3.3986,1.837c0.6384,0.1378 1.8324,0.1471 2.4571,0.023c2.448,-0.4822 4.3675,-2.154 5.1391,-4.4825c0.2342,-0.7073 0.3168,-1.2401 0.3168,-2.0438c0,-1.6258 -0.5098,-3.0403 -1.5614,-4.3034c-1.3502,-1.6212 -3.4812,-2.5078 -5.6167,-2.333ZM12.5062,9.7006l0,2.8015l0.2525,-0l0.2527,-0l0,0.2527l0,0.2525l0.2525,-0l0.2525,-0l0,0.2527l0,0.2527l0.2527,-0l0.2479,-0l0.0137,0.2618l0.0137,0.2664l0.2664,0.0137l0.2618,0.0139l0,0.2474l0,0.2525l0.2525,-0l0.2527,-0l0,0.5052l0,0.5052l-0.505,-0l-0.5052,-0l0,-0.2525l0,-0.2479l-0.2618,-0.0137l-0.2664,-0.0137l-0.0137,-0.2388l-0.0137,-0.2388l-0.2388,-0.0139l-0.2388,-0.0137l-0.0137,-0.2388l-0.0137,-0.2388l-0.239,-0.0139l-0.2388,-0.0137l-0.0137,-0.2664l-0.0137,-0.2618l-0.2479,-0l-0.2525,-0l0,-0.2527l0,-0.2527l-0.2525,-0l-0.2525,-0l0,-3.054l0,-3.054l0.5052,-0l0.5052,-0l0,2.8015Z"
|
||||
android:fillColor="#FFF"/>
|
||||
</vector>
|
@ -1,5 +1,5 @@
|
||||
<vector android:height="32dp" android:viewportHeight="1000"
|
||||
android:viewportWidth="1000" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<vector android:height="24dp" android:viewportHeight="1000"
|
||||
android:viewportWidth="1000" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFF" android:pathData="M377.54,13.12c-15.63,8.11 -17.8,16.82 -18,66.87c0,41.74 1.58,50.45 10.29,59.74c8.11,8.31 18.6,10.48 52.03,10.48l26.71,-0l0,15.83l0,15.63l-7.32,1.19c-32.84,5.54 -64.49,13.85 -89.02,23.54c-6.92,2.77 -12.86,3.96 -13.65,2.97c-2.57,-4.35 -14.84,-8.31 -39.96,-12.86c-32.64,-5.74 -45.7,-5.94 -60.54,-0.79c-16.42,5.54 -21.96,9.5 -52.23,36.8c-35.61,32.25 -45.11,45.3 -50.05,67.66c-2.57,12.86 2.37,70.23 6.92,79.13c3.17,6.13 3.17,6.53 -6.53,25.52c-28.29,56.57 -41.74,114.93 -41.74,180.61c0,138.68 68.65,264.5 185.96,340.86c45.9,29.67 98.72,50.05 157.27,60.14c27.7,4.75 96.94,4.75 124.63,-0c44.71,-7.72 80.52,-19.39 118.7,-38.38c89.02,-44.51 157.87,-119.09 195.85,-211.87c18.79,-46.29 28.69,-98.13 28.69,-151.74c0,-64.89 -13.45,-123.05 -41.74,-179.63c-9.69,-18.99 -9.69,-19.39 -6.53,-25.52c2.18,-4.15 4.16,-17.41 6.13,-38.77c2.77,-31.65 2.57,-33.04 -1.19,-46.09c-2.37,-7.32 -7.52,-18.2 -11.47,-24.13c-7.52,-11.28 -58.16,-58.95 -70.63,-66.47c-11.27,-7.12 -28.69,-12.07 -41.54,-12.07c-24.73,-0 -73.2,11.08 -77.15,17.61c-0.59,0.99 -8.9,-1.19 -18.4,-4.75c-21.76,-8.11 -49.85,-15.83 -72.41,-19.78c-9.69,-1.58 -18.4,-3.36 -19.39,-4.15c-0.99,-0.59 -1.78,-7.52 -1.78,-15.63l0,-14.64l7.12,-1.39c3.96,-0.79 13.06,-0.79 20.58,-0.4c7.32,0.59 20.77,0.4 29.67,-0.4c14.64,-1.19 16.62,-1.98 22.75,-7.91c9.69,-9.5 11.28,-19.98 10.48,-67.85c-0.59,-43.92 -1.78,-48.47 -14.04,-57.57c-5.54,-4.15 -7.12,-4.15 -123.64,-4.75c-109.4,-0.41 -118.69,-0.21 -124.83,2.96ZM555.99,308.28c26.11,5.54 46.09,12.46 69.24,24.14c27.1,13.45 46.69,27.3 69.44,49.26c25.92,25.12 42.14,47.08 57.57,78.14c20.76,41.94 29.27,78.54 29.27,125.62c0,43.92 -8.7,82.1 -27.3,121.47c-17.41,36.8 -52.42,79.53 -84.87,103.47c-38.18,28.29 -85.07,47.68 -131.36,54.2c-21.56,2.97 -75.57,1.19 -95.16,-3.16c-114.54,-25.52 -200.01,-113.95 -220.98,-228.49c-4.55,-25.32 -4.55,-72.01 0,-95.95c10.88,-57.57 35.02,-105.25 74.19,-146c46.29,-48.47 104.85,-78.34 168.75,-86.45c22.76,-2.78 68.85,-1 91.21,3.75Z"/>
|
||||
<path android:fillColor="#FFF" android:pathData="M651.34,411.35c-3.76,1.19 -32.64,28.69 -82.5,78.54l-76.76,76.76l-53.41,-53.82c-57.17,-57.57 -57.96,-58.16 -74.19,-55.2c-7.91,1.58 -19.58,10.88 -23.94,19.19c-3.56,7.12 -3.56,20.18 0,27.1c5.14,9.5 136.11,138.48 142.24,140.06c8.51,1.98 22.35,-0.2 27.5,-4.55c2.57,-2.18 44.91,-44.51 94.37,-93.97l89.81,-90.21l-0.99,-11.87c-0.59,-9.1 -2.18,-13.65 -6.33,-18.99c-8.7,-11.46 -23.34,-16.8 -35.8,-13.04Z"/>
|
||||
</vector>
|
||||
|
@ -24,6 +24,14 @@
|
||||
android:background="#00FFFFFF"
|
||||
/>
|
||||
|
||||
<clock.socoolby.com.clock.widget.textview.DigitTextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:textColor="#fff"
|
||||
/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rel_main"
|
||||
android:layout_width="match_parent"
|
||||
@ -91,10 +99,11 @@
|
||||
android:layout_below="@+id/tv_weather"
|
||||
android:layout_marginLeft="100dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:src="@drawable/ic_handup" />
|
||||
android:src="@drawable/ic_alarm_clock" />
|
||||
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/tv_hours_system"
|
||||
android:id="@+id/tv_break"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#00FFFFFF"
|
||||
@ -102,8 +111,7 @@
|
||||
android:layout_below="@+id/tv_weather"
|
||||
android:layout_marginLeft="25dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:src="@drawable/ic_am"
|
||||
android:visibility="gone"
|
||||
android:src="@drawable/ic_handup"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
@ -111,7 +119,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#00FFFFFF"
|
||||
android:layout_toRightOf="@+id/tv_hours_system"
|
||||
android:layout_toRightOf="@+id/tv_break"
|
||||
android:layout_below="@+id/tv_weather"
|
||||
android:layout_marginLeft="40dp"
|
||||
android:layout_marginTop="10dp"
|
||||
@ -171,6 +179,19 @@
|
||||
android:textSize="26sp" />
|
||||
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/tv_hours_system"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#00FFFFFF"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginLeft="40dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:src="@drawable/ic_am"
|
||||
/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -215,15 +236,6 @@
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<clock.socoolby.com.clock.widget.textview.DigitTextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:textColor="#fff"
|
||||
/>
|
||||
|
||||
|
||||
<clock.socoolby.com.clock.widget.animatorview.AnimatorView
|
||||
android:id="@+id/tv_foreground_animatorview"
|
||||
android:layout_width="match_parent"
|
||||
|
Loading…
x
Reference in New Issue
Block a user