mirror of
https://gitee.com/51danju/workclock.git
synced 2025-10-25 19:31:26 +08:00
修改走秒样式,增加12/24小时模式切换,可以进入全屏精简及相关动画
This commit is contained in:
@@ -12,6 +12,9 @@ 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.text.SpannableStringBuilder;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.KeyEvent;
|
||||
@@ -25,8 +28,11 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.blankj.utilcode.util.PermissionUtils;
|
||||
import com.fadai.particlesmasher.ParticleSmasher;
|
||||
import com.fadai.particlesmasher.SmashAnimator;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
@@ -43,19 +49,26 @@ import clock.socoolby.com.clock.utils.Player;
|
||||
import clock.socoolby.com.clock.utils.ScreenManager;
|
||||
import clock.socoolby.com.clock.model.SharePerferenceModel;
|
||||
import clock.socoolby.com.clock.pop.TimeSetupPopup;
|
||||
import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
|
||||
import clock.socoolby.com.clock.widget.animatorview.AnimatorView;
|
||||
import clock.socoolby.com.clock.widget.animatorview.I_Animator;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.BubbleAnimator;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.BubbleCollisionAnimator;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.BubbleWhirlPoolAnimator;
|
||||
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.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;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.WaterAnimator;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.WindmillAnimator;
|
||||
import clock.socoolby.com.clock.widget.textview.AutoScrollTextView;
|
||||
import clock.socoolby.com.clock.widget.textview.DigitTextView;
|
||||
|
||||
|
||||
public class MainActivity extends Activity implements Handler.Callback, View.OnClickListener, android.view.GestureDetector.OnGestureListener {
|
||||
@@ -65,6 +78,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
public final static int MODE_NORMAL = 200;
|
||||
public final static int MODE_SETTING_OTHER = 202;
|
||||
public final static int MODE_HANDUP=203;
|
||||
public final static int MODE_FULLSCREEN=204;
|
||||
|
||||
clock.socoolby.com.clock.widget.animatorview.AnimatorView view;
|
||||
|
||||
public final static String[] FONT_NAME_ARRAY={
|
||||
@@ -94,27 +109,27 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
public final static Map<String,Integer> FONT_SIZE_MAP=new HashMap<>();
|
||||
|
||||
static {
|
||||
FONT_SIZE_MAP.put("cherif",100);
|
||||
FONT_SIZE_MAP.put("cherif",80);
|
||||
FONT_SIZE_MAP.put("Cigar Box Guitar",120);
|
||||
FONT_SIZE_MAP.put("Ciung Wanara Sejati",130);
|
||||
FONT_SIZE_MAP.put("Ciung Wanara Sejati",110);
|
||||
FONT_SIZE_MAP.put("crystallightning",150);
|
||||
FONT_SIZE_MAP.put("DK Bergelmir",120);
|
||||
|
||||
FONT_SIZE_MAP.put("ds_digi",140);
|
||||
FONT_SIZE_MAP.put("Granite Rock St",120);
|
||||
FONT_SIZE_MAP.put("Granite Rock St",110);
|
||||
FONT_SIZE_MAP.put("GROOT",120);
|
||||
FONT_SIZE_MAP.put("LCD-U",130);
|
||||
FONT_SIZE_MAP.put("MILKDROP",120);
|
||||
FONT_SIZE_MAP.put("MILKDROP",110);
|
||||
|
||||
FONT_SIZE_MAP.put("Pro Display tfb",120);
|
||||
FONT_SIZE_MAP.put("SailingJunco",130);
|
||||
FONT_SIZE_MAP.put("scoreboard",120);
|
||||
FONT_SIZE_MAP.put("SFWasabi-Bold",120);
|
||||
FONT_SIZE_MAP.put("SFWasabi-Bold",110);
|
||||
FONT_SIZE_MAP.put("the_vandor_spot",140);
|
||||
|
||||
FONT_SIZE_MAP.put("WarioLand4CHMC",120);
|
||||
FONT_SIZE_MAP.put("Woodplank",120);
|
||||
FONT_SIZE_MAP.put("Xtra Power",110);
|
||||
FONT_SIZE_MAP.put("Xtra Power",100);
|
||||
}
|
||||
|
||||
private TextView tv_time;
|
||||
@@ -126,6 +141,9 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
private ImageButton tv_handup;
|
||||
private TextView tv_handup_image;
|
||||
|
||||
private TextView tv_hand_time;
|
||||
private boolean hand_time_visable=true;
|
||||
|
||||
private Timer timer;
|
||||
private Handler handler;
|
||||
private final static int UPDATE_TIME = 100;
|
||||
@@ -137,6 +155,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
|
||||
private int currectAnimatorIndex=0;
|
||||
|
||||
|
||||
private ImageButton tv_hours_system;
|
||||
//颜色相关
|
||||
private ImageButton tv_background_color;
|
||||
private ImageButton tv_foreground_color;
|
||||
@@ -194,9 +214,26 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
animatorView=findViewById(R.id.tv_background_animatorview);
|
||||
|
||||
tv_time = findViewById(R.id.tv_time);
|
||||
//tv_time.setOnClickListener(this);
|
||||
|
||||
tv_date = findViewById(R.id.tv_date);
|
||||
tv_day = findViewById(R.id.tv_day);
|
||||
tv_date.setOnClickListener(this);
|
||||
|
||||
|
||||
tv_day = findViewById(R.id.tv_day);
|
||||
tv_day.setOnClickListener(this);
|
||||
tv_day.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if(screenLock)
|
||||
return true;
|
||||
model.setHourSystem12(!model.isHourSystem12());
|
||||
model.save();
|
||||
updateHourSystem();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tv_weather = findViewById(R.id.tv_weather);
|
||||
tv_weather.setOnClickListener(this);
|
||||
tv_descript = findViewById(R.id.tv_descript);
|
||||
@@ -206,10 +243,24 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
tv_handup.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
if(screenLock)
|
||||
return true;
|
||||
setupHandUpTime();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
tv_hand_time=findViewById(R.id.tv_hand_time);
|
||||
tv_hand_time.setOnClickListener(this);
|
||||
tv_hand_time.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
hand_time_visable=false;
|
||||
tv_hand_time.setVisibility(View.GONE);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tv_hours_system=findViewById(R.id.tv_hours_system);
|
||||
|
||||
tv_background_color=findViewById(R.id.tv_background_color);
|
||||
tv_background_color.setOnClickListener(this);
|
||||
@@ -219,12 +270,15 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
tv_foreground_color.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if(screenLock)
|
||||
return true;
|
||||
if (colorPickerDialog == null)
|
||||
colorPickerDialog = new ColorPickerPop(MainActivity.this);
|
||||
|
||||
colorPickerDialog.setOnColorChangeListenter(new ColorPickerPop.OnColorListener() {
|
||||
@Override
|
||||
public void onEnsure(int color) {
|
||||
|
||||
model.setForegroundColor(color);
|
||||
model.save();
|
||||
setForegroundColor(color);
|
||||
@@ -245,6 +299,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
tv_foreground_color1.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if(screenLock)
|
||||
return true;
|
||||
if (colorPickerDialog == null)
|
||||
colorPickerDialog = new ColorPickerPop(MainActivity.this);
|
||||
|
||||
@@ -274,12 +330,20 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
handler = new Handler(this);
|
||||
tv_setting = (ImageButton) findViewById(R.id.tv_setting);
|
||||
tv_setting.setOnClickListener(this);
|
||||
//tv_time.setOnClickListener(this);
|
||||
|
||||
//RelativeLayout rel_main = (RelativeLayout) findViewById(R.id.rel_main);
|
||||
//rel_main.setOnClickListener(this);
|
||||
|
||||
tv_screen_lock = (ImageButton) findViewById(R.id.tv_screen_lock);
|
||||
tv_screen_lock.setOnClickListener(this);
|
||||
tv_screen_lock.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
screenLock(true);
|
||||
switchMode(MODE_FULLSCREEN);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if(PermissionUtils.isGranted("android.permission.WAKE_LOCK","android.permission.DEVICE_POWER")) {
|
||||
@@ -359,9 +423,10 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
fontIndex =model.getFontIndex()==null?4:model.getFontIndex();
|
||||
brightness=getSystemBrightness();
|
||||
handUpAbla=model.isHandUpAble();
|
||||
resetColorFromModel();
|
||||
upHandStatic();
|
||||
resetHandUpTime();
|
||||
resetColorFromModel();
|
||||
updateHourSystem();
|
||||
}
|
||||
|
||||
private void resetColorFromModel(){
|
||||
@@ -372,6 +437,14 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
animatorView.setColor(model.getForegroundColor1());
|
||||
}
|
||||
|
||||
|
||||
private void updateHourSystem(){
|
||||
if(model.isHourSystem12())
|
||||
tv_hours_system.setVisibility(View.VISIBLE);
|
||||
else
|
||||
tv_hours_system.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//将该Activity上的触碰事件交给GestureDetector处理
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent me)
|
||||
@@ -425,10 +498,14 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
}
|
||||
|
||||
protected void setFont(int index){
|
||||
String timeString=tv_time.getText().toString();
|
||||
tv_time.setText("", TextView.BufferType.NORMAL);
|
||||
Log.d(TAG,"befor setFont text:"+timeString+"\t witch:"+tv_time.getWidth()+"\t height:"+tv_time.getHeight());
|
||||
Log.d(TAG,"setFont index:"+index+"/t name:"+FONT_NAME_ARRAY[index]+".ttf/t size:"+FONT_SIZE_MAP.get(FONT_NAME_ARRAY[index]));
|
||||
FontUtils.getInstance().replaceFontFromAsset(tv_time,"fonts/"+FONT_NAME_ARRAY[index]+".ttf");
|
||||
tv_time.setTextSize(FONT_SIZE_MAP.get(FONT_NAME_ARRAY[index]));
|
||||
FontUtils.getInstance().replaceFontFromAsset(tv_date,"fonts/"+FONT_NAME_ARRAY[index]+".ttf");
|
||||
tv_time.setTextSize(FONT_SIZE_MAP.get(FONT_NAME_ARRAY[index]));
|
||||
Log.d(TAG,"after setFont text:"+tv_time.getText()+"\t witch:"+tv_time.getWidth()+"\t height:"+tv_time.getHeight());
|
||||
}
|
||||
|
||||
protected void setForegroundColor(Integer color){
|
||||
@@ -446,6 +523,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
tv_screen_lock.setColorFilter(color);
|
||||
tv_setting.setColorFilter(color);
|
||||
tv_background_color.setColorFilter(color);
|
||||
tv_hand_time.setTextColor(color);
|
||||
tv_hours_system.setColorFilter(color);
|
||||
}
|
||||
|
||||
protected void setBackGroundColor(Integer color){
|
||||
@@ -458,11 +537,13 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
|
||||
CalendarPopup calendarPopup;
|
||||
WeatherPopup weatherPopup;
|
||||
ParticleSmasher particleSmasher;
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if(screenLock&&view.getId()!=R.id.tv_screen_lock&&view.getId()!=R.id.tv_handup_image)
|
||||
if(screenLock&&view.getId()!=R.id.tv_screen_lock&&view.getId()!=R.id.tv_handup_image) {
|
||||
return;
|
||||
}
|
||||
switch (view.getId()) {
|
||||
case R.id.tv_setting:
|
||||
setup();
|
||||
@@ -478,9 +559,16 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
switchMode(MODE_NORMAL);
|
||||
}
|
||||
break;
|
||||
case R.id.tv_hand_time:
|
||||
setupTempHandUpTime();
|
||||
break;
|
||||
case R.id.tv_handup_image:
|
||||
switchMode(MODE_NORMAL);
|
||||
break;
|
||||
case R.id.tv_day:
|
||||
model.setDisplaySecond(!model.isDisplaySecond());
|
||||
model.save();
|
||||
break;
|
||||
case R.id.tv_date:
|
||||
if( calendarPopup ==null)
|
||||
calendarPopup =new CalendarPopup(this);
|
||||
@@ -494,9 +582,9 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
weatherPopup.showPopupWindow();
|
||||
break;
|
||||
case R.id.tv_screen_lock:
|
||||
screenLock=!screenLock;
|
||||
tv_screen_lock.setImageResource(screenLock?R.drawable.ic_screen_lock:R.drawable.ic_screen_unlock);
|
||||
setUpProximityService();
|
||||
if(isFullScreen)
|
||||
fullScreen(false);
|
||||
screenLock(!screenLock);
|
||||
break;
|
||||
case R.id.tv_descript:
|
||||
setDiscript(SettingActivity.roundAutoQuotes());
|
||||
@@ -529,16 +617,34 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
}
|
||||
|
||||
|
||||
public void screenLock(boolean locked){
|
||||
screenLock=locked;
|
||||
tv_screen_lock.setImageResource(screenLock?R.drawable.ic_screen_lock:R.drawable.ic_screen_unlock);
|
||||
setUpProximityService();
|
||||
}
|
||||
|
||||
private int prevMode=MODE_NORMAL;
|
||||
private boolean isArtificialHiddle=false;
|
||||
private boolean isFullScreen=false;
|
||||
private void switchMode(int mode) {
|
||||
Log.d(TAG,"switch mode to:"+mode);
|
||||
switch (mode) {
|
||||
case MODE_FULLSCREEN:
|
||||
fullScreen(true);
|
||||
break;
|
||||
case MODE_NORMAL:
|
||||
tv_time.setVisibility(View.VISIBLE);
|
||||
tv_handup_image.setVisibility(View.GONE);
|
||||
tv_setting.setVisibility(View.GONE);
|
||||
tv_background_color.setVisibility(View.GONE);
|
||||
tv_foreground_color.setVisibility(View.GONE);
|
||||
tv_foreground_color1.setVisibility(View.GONE);
|
||||
if(isFullScreen){
|
||||
if(!isArtificialHiddle)
|
||||
tv_time.setVisibility(View.VISIBLE);
|
||||
tv_handup_image.setVisibility(View.GONE);
|
||||
}else {
|
||||
tv_time.setVisibility(View.VISIBLE);
|
||||
tv_handup_image.setVisibility(View.GONE);
|
||||
tv_setting.setVisibility(View.GONE);
|
||||
tv_background_color.setVisibility(View.GONE);
|
||||
tv_foreground_color.setVisibility(View.GONE);
|
||||
tv_foreground_color1.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
case MODE_SETTING_OTHER:
|
||||
tv_time.setVisibility(View.VISIBLE);
|
||||
@@ -549,17 +655,60 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
tv_foreground_color1.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case MODE_HANDUP:
|
||||
tv_time.setVisibility(View.GONE);
|
||||
tv_handup_image.setVisibility(View.VISIBLE);
|
||||
tv_setting.setVisibility(View.GONE);
|
||||
tv_background_color.setVisibility(View.GONE);
|
||||
tv_foreground_color.setVisibility(View.GONE);
|
||||
tv_foreground_color1.setVisibility(View.GONE);
|
||||
setDiscriptForModel();
|
||||
if(isFullScreen){
|
||||
tv_time.setVisibility(View.GONE);
|
||||
tv_handup_image.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
tv_time.setVisibility(View.GONE);
|
||||
tv_handup_image.setVisibility(View.VISIBLE);
|
||||
tv_setting.setVisibility(View.GONE);
|
||||
tv_background_color.setVisibility(View.GONE);
|
||||
tv_foreground_color.setVisibility(View.GONE);
|
||||
tv_foreground_color1.setVisibility(View.GONE);
|
||||
setDiscriptForModel();
|
||||
}
|
||||
}
|
||||
prevMode=mMode;
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
private void fullScreen(boolean fullable){
|
||||
isFullScreen=fullable;
|
||||
if(fullable) {
|
||||
// @tudo 可对其时行位置移动
|
||||
//tv_time.setVisibility(View.GONE);
|
||||
tv_date.setVisibility(View.GONE);
|
||||
tv_day.setVisibility(View.GONE);
|
||||
tv_weather.setVisibility(View.GONE);
|
||||
tv_descript.setVisibility(View.GONE);
|
||||
tv_handup_image.setVisibility(View.GONE);
|
||||
|
||||
tv_handup.setVisibility(View.GONE);
|
||||
|
||||
tv_setting.setVisibility(View.GONE);
|
||||
tv_background_color.setVisibility(View.GONE);
|
||||
//tv_hand_time.setTextColor(color);
|
||||
|
||||
tv_background_color.setVisibility(View.GONE);
|
||||
tv_foreground_color.setVisibility(View.GONE);
|
||||
tv_foreground_color1.setVisibility(View.GONE);
|
||||
}else{
|
||||
tv_time.setVisibility(View.VISIBLE);
|
||||
tv_date.setVisibility(View.VISIBLE);
|
||||
tv_day.setVisibility(View.VISIBLE);
|
||||
tv_weather.setVisibility(View.VISIBLE);
|
||||
tv_descript.setVisibility(View.VISIBLE);
|
||||
tv_handup_image.setVisibility(View.VISIBLE);
|
||||
|
||||
tv_handup.setVisibility(View.VISIBLE);
|
||||
|
||||
if(prevMode==MODE_HANDUP)
|
||||
switchMode(MODE_NORMAL);
|
||||
else
|
||||
switchMode(prevMode);
|
||||
}
|
||||
}
|
||||
|
||||
StarFallAnimator starAnimator;
|
||||
SkyAnimator skyAnimator;
|
||||
RainAnimator rainAnimator;
|
||||
@@ -570,6 +719,11 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
BubbleCollisionAnimator bubbleCollisionAnimator;
|
||||
FireworkAnimator fireworkAnimator;
|
||||
DotsLineAnimator dotsLineAnimator;
|
||||
WaterAnimator waterAnimator;
|
||||
FireAnimator fireAnimator;
|
||||
ClockAnimator clockAnimator;
|
||||
RippleAnimator rippleAnimator;
|
||||
WindmillAnimator windmillAnimator;
|
||||
public void changeBackGroundAnimator(int index){
|
||||
switch(index){
|
||||
case 0:
|
||||
@@ -582,13 +736,13 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
backGroundAnimator.setRandColor(false);
|
||||
break;
|
||||
case 2:
|
||||
if(skyAnimator==null) {
|
||||
skyAnimator = new SkyAnimator();
|
||||
skyAnimator.init(animatorView.getContext(),animatorView);
|
||||
skyAnimator.setColor(foregroundColor);
|
||||
if(clockAnimator ==null) {
|
||||
clockAnimator = new ClockAnimator();
|
||||
clockAnimator.init(animatorView.getContext(),animatorView);
|
||||
clockAnimator.setColor(foregroundColor);
|
||||
}
|
||||
backGroundAnimator=skyAnimator;
|
||||
backGroundAnimator.setRandColor(false);
|
||||
backGroundAnimator= clockAnimator;
|
||||
//backGroundAnimator.setRandColor(true);
|
||||
break;
|
||||
case 3:
|
||||
if(rainAnimator==null) {
|
||||
@@ -734,7 +888,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
backGroundAnimator= dotsLineAnimator;
|
||||
backGroundAnimator.setRandColor(false);
|
||||
break;
|
||||
case 1:
|
||||
case 19:
|
||||
if(dotsLineAnimator ==null) {
|
||||
dotsLineAnimator = new DotsLineAnimator();
|
||||
dotsLineAnimator.init(animatorView.getContext(),animatorView);
|
||||
@@ -743,6 +897,52 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
backGroundAnimator= dotsLineAnimator;
|
||||
backGroundAnimator.setRandColor(true);
|
||||
break;
|
||||
case 20:
|
||||
if(waterAnimator ==null) {
|
||||
waterAnimator = new WaterAnimator();
|
||||
waterAnimator.init(animatorView.getContext(),animatorView);
|
||||
waterAnimator.setColor(foregroundColor);
|
||||
}
|
||||
backGroundAnimator= waterAnimator;
|
||||
backGroundAnimator.setRandColor(true);
|
||||
break;
|
||||
case 21:
|
||||
if(fireAnimator ==null) {
|
||||
fireAnimator = new FireAnimator();
|
||||
fireAnimator.init(animatorView.getContext(),animatorView);
|
||||
fireAnimator.setColor(foregroundColor);
|
||||
}
|
||||
backGroundAnimator= fireAnimator;
|
||||
//backGroundAnimator.setRandColor(true);
|
||||
break;
|
||||
case 22:
|
||||
if(skyAnimator==null) {
|
||||
skyAnimator = new SkyAnimator();
|
||||
skyAnimator.init(animatorView.getContext(),animatorView);
|
||||
skyAnimator.setColor(foregroundColor);
|
||||
}
|
||||
backGroundAnimator=skyAnimator;
|
||||
backGroundAnimator.setRandColor(false);
|
||||
break;
|
||||
case 23:
|
||||
if(rippleAnimator ==null) {
|
||||
rippleAnimator = new RippleAnimator();
|
||||
rippleAnimator.init(animatorView.getContext(),animatorView);
|
||||
rippleAnimator.setColor(foregroundColor);
|
||||
}
|
||||
backGroundAnimator= rippleAnimator;
|
||||
backGroundAnimator.setRandColor(true);
|
||||
break;
|
||||
case 1:
|
||||
if(windmillAnimator ==null) {
|
||||
windmillAnimator = new WindmillAnimator();
|
||||
windmillAnimator.init(animatorView.getContext(),animatorView);
|
||||
windmillAnimator.setColor(foregroundColor);
|
||||
}
|
||||
backGroundAnimator= windmillAnimator;
|
||||
backGroundAnimator.setRandColor(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
currectAnimatorIndex=0;
|
||||
backGroundAnimator=null;
|
||||
@@ -752,9 +952,13 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
|
||||
private void upHandStatic(){
|
||||
if(handUpAbla) {
|
||||
this.tv_handup.setColorFilter(0x000);
|
||||
this.tv_handup.setColorFilter(foregroundColor);
|
||||
//if(hand_time_visable)
|
||||
hand_time_visable=true;
|
||||
this.tv_hand_time.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
this.tv_handup.setColorFilter(R.color.colorPrimaryDark);
|
||||
this.tv_hand_time.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,6 +999,26 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
handUpTimePopup.showPopupWindow();
|
||||
}
|
||||
|
||||
private void setupTempHandUpTime(){
|
||||
handUpAbla=false;
|
||||
int hour=0;
|
||||
int minute=0;
|
||||
if(handUpTimePopup==null) {
|
||||
handUpTimePopup = new TimeSetupPopup(this);
|
||||
handUpTimePopup.setOnSeekBarChangeListener(new TimeSetupPopup.OnTimeChangeListener() {
|
||||
@Override
|
||||
public void onChanged(int hour, int minute) {
|
||||
handUpTime=hour*60+minute;
|
||||
}
|
||||
});
|
||||
}
|
||||
hour=handUpTime/60;
|
||||
minute=handUpTime-hour*60;
|
||||
handUpTimePopup.init(hour,minute);
|
||||
handUpTimePopup.showPopupWindow();
|
||||
handUpAbla=true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if(screenLock)
|
||||
@@ -842,8 +1066,9 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
private int handUPDialy=60;
|
||||
|
||||
private void checkHandUp(){
|
||||
if(!handUpAbla)
|
||||
if(!handUpAbla) {
|
||||
return;
|
||||
}
|
||||
//Log.d(TAG,"checkHandUp..\thandUPDialy:"+handUPDialy+" \thandUpTime:"+handUpTime+"\thandUpAble:"+handUpAbla);
|
||||
if(mMode==MODE_HANDUP) {
|
||||
tv_handup_image.setText("hand up:"+handUPDialy);
|
||||
@@ -855,6 +1080,8 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
return;
|
||||
}
|
||||
handUpTime--;
|
||||
if(hand_time_visable)
|
||||
tv_hand_time.setText(DateModel.getTime(handUpTime));
|
||||
if (handUpTime <= 10&&handUpTime > 0)
|
||||
setDiscript("提醒时间倒计时: " + handUpTime);
|
||||
if (handUpTime == 0) {
|
||||
@@ -864,17 +1091,45 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
DigitTextView.DigitSpan digitSpan,digitSpan1;
|
||||
DigitTextView.DigitSmallSpan digitSpan2;
|
||||
SpannableString spannable;
|
||||
DigitTextView.DigitFlagSpan digitFlagSpan;
|
||||
private void setCurrentTimeToView(String timeString){
|
||||
spannable = new SpannableString(timeString);
|
||||
if(digitSpan==null) {
|
||||
digitSpan = new DigitTextView.DigitSpan();
|
||||
digitSpan1 = new DigitTextView.DigitSpan();
|
||||
digitSpan2 = new DigitTextView.DigitSmallSpan();
|
||||
digitFlagSpan=new DigitTextView.DigitFlagSpan();
|
||||
}
|
||||
spannable.setSpan(digitSpan,0,2,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
spannable.setSpan(digitFlagSpan,2,3,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
spannable.setSpan(digitSpan1,3,5,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
if(timeString.length()>5)
|
||||
spannable.setSpan(digitSpan2,5,8,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
//tv_time.setText(spannable, TextView.BufferType.SPANNABLE);
|
||||
tv_time.setText(spannable, TextView.BufferType.NORMAL);
|
||||
//tv_time.setText(timeString);
|
||||
}
|
||||
|
||||
boolean heartbeat=false;
|
||||
private void updateTime() {
|
||||
heartbeat=!heartbeat;
|
||||
DateModel date = new DateModel();
|
||||
String timeString = model.isDisplaySecond() ? date.getTimeString() : date.getShortTimeString();
|
||||
//timeString=timeString.replace("1", " 1");
|
||||
if(timeString.startsWith(" "))
|
||||
timeString=timeString.substring(1,timeString.length());
|
||||
tv_time.setText(timeString);
|
||||
//tv_date.setText(dateString.replace("1", " 1"));
|
||||
String timeString = model.isDisplaySecond() ? date.getTimeString(model.isHourSystem12()) : date.getShortTimeString(heartbeat,model.isHourSystem12());
|
||||
setCurrentTimeToView(timeString);
|
||||
reportTime(date);
|
||||
updateDay(date);
|
||||
updateHourSytemStyle(date);
|
||||
}
|
||||
|
||||
int beforeHourForUpdateSystem=-1;
|
||||
private void updateHourSytemStyle(DateModel date){
|
||||
if(model.isHourSystem12()&&beforeHourForUpdateSystem!=date.getHour()) {
|
||||
beforeHourForUpdateSystem=date.getHour();
|
||||
tv_hours_system.setImageResource(beforeHourForUpdateSystem>12?R.drawable.ic_pm:R.drawable.ic_am);
|
||||
}
|
||||
}
|
||||
|
||||
DateModel currentDate=null;
|
||||
@@ -960,6 +1215,7 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent motionEvent) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -981,6 +1237,31 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC
|
||||
|
||||
@Override
|
||||
public void onLongPress(MotionEvent motionEvent) {
|
||||
if(screenLock&&isFullScreen) {
|
||||
if(tv_time.getVisibility()==View.GONE) {
|
||||
tv_time.setVisibility(View.VISIBLE);
|
||||
isArtificialHiddle=false;
|
||||
return;
|
||||
}
|
||||
if(particleSmasher==null)
|
||||
particleSmasher=new ParticleSmasher(this);
|
||||
particleSmasher.with(tv_time).setDuration(1000).addAnimatorListener(new SmashAnimator.OnAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimatorStart() {
|
||||
super.onAnimatorStart();
|
||||
// 回调,动画开始
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimatorEnd() {
|
||||
super.onAnimatorEnd();
|
||||
// 回调,动画结束
|
||||
particleSmasher.reShowView(tv_time);
|
||||
tv_time.setVisibility(View.GONE);
|
||||
isArtificialHiddle=true;
|
||||
}
|
||||
}).startRandomAnimator();
|
||||
}
|
||||
if(screenLock)
|
||||
return;
|
||||
if(!isPowerManagerDisable())
|
||||
|
||||
@@ -90,8 +90,6 @@ public class DateModel implements Serializable {
|
||||
} else {
|
||||
setDataString(getNowWithTime());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -102,12 +100,30 @@ public class DateModel implements Serializable {
|
||||
return String.format("%04d-%02d-%02d ", year, month, day);
|
||||
}
|
||||
|
||||
|
||||
public String getShortTimeString() {
|
||||
return String.format("%02d:%02d", hour, minute);
|
||||
}
|
||||
|
||||
public String getTimeString() {
|
||||
return String.format("%02d:%02d:%02d", hour, minute, second);
|
||||
return String.format("%02d:%02d %02d", hour, minute, second);
|
||||
}
|
||||
|
||||
public String getShortTimeString(boolean heartbeat,boolean isHourSystem12) {
|
||||
if(heartbeat)
|
||||
if(isHourSystem12&&hour>12)
|
||||
return String.format("%02d %02d", hour-12, minute);
|
||||
else
|
||||
return String.format("%02d %02d", hour, minute);
|
||||
if(isHourSystem12&&hour>12)
|
||||
return String.format("%02d:%02d", hour-12, minute, second);
|
||||
return String.format("%02d:%02d", hour, minute);
|
||||
}
|
||||
|
||||
public String getTimeString(boolean isHourSystem12) {
|
||||
if(isHourSystem12&&hour>12)
|
||||
return String.format("%02d:%02d %02d", hour-12, minute, second);
|
||||
return String.format("%02d:%02d %02d", hour, minute, second);
|
||||
}
|
||||
|
||||
public static String getNowWithTime() {
|
||||
@@ -116,6 +132,18 @@ public class DateModel implements Serializable {
|
||||
return sdf.format(dt);
|
||||
}
|
||||
|
||||
|
||||
public static String getTime(int second){
|
||||
long hours = second / 3600;//转换小时数
|
||||
second = second % 3600;//剩余秒数
|
||||
long minutes = second / 60;//转换分钟
|
||||
second = second % 60;//剩余秒数
|
||||
if(minutes>0||hours>0){
|
||||
return String.format(" %02d:%02d", hours, minutes, second);
|
||||
}
|
||||
return String.format("%02d:%02d:%02d", hours, minutes, second);
|
||||
}
|
||||
|
||||
public int minusTime(DateModel strEnd) {
|
||||
SimpleDateFormat df = new SimpleDateFormat("HH:mm");
|
||||
Date d1 = null;
|
||||
|
||||
@@ -28,6 +28,9 @@ public class SharePerferenceModel implements Serializable {
|
||||
private boolean isTriggerScreen = true;
|
||||
private final static String KEY_IS_TRIGGER_SCREEN = "key_is_trigger_screen";
|
||||
|
||||
private boolean hourSystem12 = false;
|
||||
private final static String KEY_IS_HOUR_SYSTEM_12 = "key_is_hour_system_12";
|
||||
|
||||
|
||||
private final static String KEY_CITY = "key_city";
|
||||
private String mCity;
|
||||
@@ -193,6 +196,7 @@ public class SharePerferenceModel implements Serializable {
|
||||
backgroundColor=jsonObject.optInt(KEY_BACKGROUND_COLOR,Color.rgb(0, 0, 0));
|
||||
foregroundColor=jsonObject.optInt(KEY_FOREGROUND_COLOR,Color.rgb(255, 255, 255));
|
||||
foregroundColor1=jsonObject.optInt(KEY_FOREGROUND_COLOR1,Color.rgb(199,21,133));
|
||||
hourSystem12=jsonObject.optBoolean(KEY_IS_HOUR_SYSTEM_12,false);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -221,6 +225,7 @@ public class SharePerferenceModel implements Serializable {
|
||||
jsonObject.put(KEY_BACKGROUND_COLOR,backgroundColor);
|
||||
jsonObject.put(KEY_FOREGROUND_COLOR,foregroundColor);
|
||||
jsonObject.put(KEY_FOREGROUND_COLOR1,foregroundColor1);
|
||||
jsonObject.put(KEY_IS_HOUR_SYSTEM_12,hourSystem12);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -260,6 +265,7 @@ public class SharePerferenceModel implements Serializable {
|
||||
", backgroundColor="+backgroundColor+
|
||||
", foregroundColor="+foregroundColor+
|
||||
", foregroundColor1="+foregroundColor1+
|
||||
", hourSystem12="+hourSystem12+
|
||||
'}';
|
||||
}
|
||||
|
||||
@@ -311,4 +317,12 @@ public class SharePerferenceModel implements Serializable {
|
||||
public void setForegroundColor1(Integer foregroundColor1) {
|
||||
this.foregroundColor1 = foregroundColor1;
|
||||
}
|
||||
|
||||
public boolean isHourSystem12() {
|
||||
return hourSystem12;
|
||||
}
|
||||
|
||||
public void setHourSystem12(boolean hourSystem12) {
|
||||
this.hourSystem12 = hourSystem12;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
|
||||
|
||||
// 参考自:https://github.com/ifadai/ClockDemo
|
||||
public class ClockAnimator extends AbstractAnimator<ClockAnimator.Clock> {
|
||||
private final String TAG = getClass().getSimpleName();
|
||||
|
||||
@Override
|
||||
public boolean run() {
|
||||
for(Clock clock:list)
|
||||
clock.getTime();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
for(Clock clock:list)
|
||||
clock.onDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
int textColor=color;
|
||||
if(randColor)
|
||||
randomColor();
|
||||
int minHigh=Math.min(width,height);
|
||||
int r=rand.nextInt(minHigh);
|
||||
if(r<minHigh/2)
|
||||
r=minHigh/2;
|
||||
list.add(new Clock(width/2,height/2,r,color,textColor));
|
||||
}
|
||||
|
||||
public class Clock{
|
||||
private int mCenterX, mCenterY;
|
||||
|
||||
// 默认刻度画笔、指针画笔、文字画笔;
|
||||
private Paint mDefaultPaint, mPointerPaint, mTextPaint;
|
||||
|
||||
// 时钟半径、中心点半径、默认刻度长度、默认刻度宽度、特殊刻度长度、特殊刻度宽度、
|
||||
// 时指针长度、时钟指针宽度、分钟指针长度、分钟指针宽度、秒钟指针长度、秒钟指针宽度
|
||||
private float mRadius, mPointRadius,
|
||||
mDefaultScaleLength, mDefaultScaleWidth,
|
||||
mParticularlyScaleLength, mParticularlyScaleWidth,
|
||||
mHourPointerLength, mHourPointerWidth,
|
||||
mMinutePointerLength, mMinutePointerWidth,
|
||||
mSecondPointerLength, mSecondPointerWidth;
|
||||
|
||||
// 当前时、分、秒
|
||||
private int mH, mM, mS;
|
||||
|
||||
// 时钟颜色、默认刻度颜色、时刻度颜色、时针颜色、分针颜色、秒针颜色
|
||||
private int mClockColor, mColorDefaultScale, mColorParticularyScale, mColorHourPointer,
|
||||
mColorMinutePointer, mColorSecondPointer,textColor;
|
||||
|
||||
public Clock(int mCenterX, int mCenterY, float mRadius, int mClockColor,int textColor) {
|
||||
this.mCenterX = mCenterX;
|
||||
this.mCenterY = mCenterY;
|
||||
this.mRadius = mRadius;
|
||||
this.mClockColor = mClockColor;
|
||||
this.textColor=textColor;
|
||||
init();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前系统时间
|
||||
*/
|
||||
private void getTime() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
int hour = calendar.get(Calendar.HOUR);
|
||||
hour = hour % 12;
|
||||
int minute = calendar.get(Calendar.MINUTE);
|
||||
int second = calendar.get(Calendar.SECOND);
|
||||
|
||||
if (hour != mH || minute != mM || second != mS) {
|
||||
setTime(hour, minute, second);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置时间
|
||||
*/
|
||||
private void setTime(int h, int m, int s) {
|
||||
mH = h;
|
||||
mM = m;
|
||||
mS = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据控件的大小,初始化时钟刻度的长度和宽度、指针的长度和宽度、时钟中心点的半径
|
||||
*/
|
||||
private 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;
|
||||
}
|
||||
|
||||
protected void onDraw(Canvas canvas) {
|
||||
// 坐标原点移动到View 中心
|
||||
canvas.translate(mCenterX, mCenterY);
|
||||
drawCircle(canvas);
|
||||
drawText(canvas);
|
||||
drawPointer(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制时钟的圆形和刻度
|
||||
*/
|
||||
private void drawCircle(Canvas canvas) {
|
||||
|
||||
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);
|
||||
|
||||
canvas.drawLine(0, -mRadius, 0, -mRadius + mParticularlyScaleLength, mDefaultPaint);
|
||||
|
||||
} else { // 一般时刻
|
||||
|
||||
mDefaultPaint.setStrokeWidth(mDefaultScaleWidth);
|
||||
mDefaultPaint.setColor(mColorDefaultScale);
|
||||
|
||||
canvas.drawLine(0, -mRadius, 0, -mRadius + mDefaultScaleLength, mDefaultPaint);
|
||||
|
||||
}
|
||||
canvas.rotate(6);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制特殊时刻(12点、3点、6点、9点)的文字
|
||||
*/
|
||||
private void drawText(Canvas canvas) {
|
||||
|
||||
setTextPaint();
|
||||
|
||||
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
|
||||
|
||||
// 文字顶部与基线距离
|
||||
float ascent = Math.abs(fontMetrics.ascent);
|
||||
// 文字底部与基线距离
|
||||
float descent = Math.abs(fontMetrics.descent);
|
||||
// 文字高度
|
||||
float fontHeight = ascent + descent;
|
||||
// 文字竖直中心点距离基线的距离;
|
||||
float offsetY = fontHeight / 2 - Math.abs(fontMetrics.descent);
|
||||
// 文字宽度
|
||||
float fontWidth;
|
||||
|
||||
// drawText(@NonNull String text, float x, float y, @NonNull Paint paint) 参数:y,为基线的y坐标,并非文字左下角的坐标
|
||||
// 文字距离圆圈的距离为 特殊刻度长度+宽度
|
||||
|
||||
String h = "12";
|
||||
// y轴坐标为: -(半径-特殊刻度长度-特殊刻度宽度(作为间距)-文字顶部距离基线的距离)
|
||||
float y = -(mRadius - mParticularlyScaleLength - mParticularlyScaleWidth - ascent);
|
||||
canvas.drawText(h, 0, y, mTextPaint);
|
||||
|
||||
h = "3";
|
||||
fontWidth = mTextPaint.measureText(h);
|
||||
// y轴坐标为: 半径-特殊刻度长度-特殊刻度宽度(作为间距)-文字长度/2(绘制原点在文字横向中心)
|
||||
y = mRadius - mParticularlyScaleLength - mParticularlyScaleWidth - (fontWidth / 2);
|
||||
canvas.drawText(h, y, 0 + offsetY, mTextPaint);
|
||||
|
||||
h = "6";
|
||||
// y轴坐标为: 半径-特殊刻度长度-特殊刻度宽度(作为间距)-文字底部与基线的距离
|
||||
y = mRadius - mParticularlyScaleLength - mParticularlyScaleWidth - descent;
|
||||
canvas.drawText(h, 0, y, mTextPaint);
|
||||
|
||||
h = "9";
|
||||
fontWidth = mTextPaint.measureText(h);
|
||||
// y轴坐标为: -(半径-特殊刻度长度-特殊刻度宽度(作为间距)-文字长度/2(绘制原点在文字横向中心))
|
||||
y = -(mRadius - mParticularlyScaleLength - mParticularlyScaleWidth - (fontWidth / 2));
|
||||
canvas.drawText(h, y, 0 + offsetY, mTextPaint);
|
||||
}
|
||||
|
||||
private void setTextPaint() {
|
||||
mTextPaint.setStrokeWidth(mDefaultScaleWidth / 2);
|
||||
mTextPaint.setTextSize(mParticularlyScaleWidth * 4);
|
||||
mTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
mTextPaint.setColor(textColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制指针
|
||||
*/
|
||||
private void drawPointer(Canvas canvas) {
|
||||
|
||||
drawHourPointer(canvas);
|
||||
drawMinutePointer(canvas);
|
||||
drawSecondPointer(canvas);
|
||||
|
||||
mPointerPaint.setColor(mClockColor);
|
||||
// 绘制中心原点,需要在指针绘制完成后才能绘制
|
||||
canvas.drawCircle(0, 0, mPointRadius, mPointerPaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制时针
|
||||
*/
|
||||
private 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制分针
|
||||
*/
|
||||
private 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制秒针
|
||||
*/
|
||||
private 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
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;
|
||||
|
||||
//参考: https://www.jianshu.com/p/0d4ab16a6b7b
|
||||
public class FireAnimator extends AbstractCacheDifferenceAnimator<FireAnimator.ParticleSystem, FireAnimator.Particle> {
|
||||
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
addFires(1);
|
||||
}
|
||||
|
||||
int high=0;
|
||||
int fireWidth=0;
|
||||
int particlesCount;
|
||||
public void addFires(int quantity) {
|
||||
|
||||
for (int i = 0; i < quantity;i++) {
|
||||
high=rand.nextInt(height);
|
||||
if(high<=height/3)
|
||||
high=high+height/2;
|
||||
fireWidth=rand.nextInt(width/2);
|
||||
particlesCount=rand.nextInt(300);
|
||||
particlesCount=particlesCount>150?particlesCount:particlesCount+150;
|
||||
list.add(new ParticleSystem(width/2,height,high,fireWidth,particlesCount,rand.nextInt(30)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean run() {
|
||||
for(ParticleSystem fire:list)
|
||||
fire.update(WIND.NULL,0);
|
||||
//fire.update(rand.nextFloat()*0.18f);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
for(ParticleSystem fire:list)
|
||||
fire.onDraw(canvas);
|
||||
}
|
||||
|
||||
public class ParticleSystem {
|
||||
private List<Particle> particles = new ArrayList<>();
|
||||
private int fire_width = 20;
|
||||
private int particle_width=20;
|
||||
private Paint paint = new Paint();
|
||||
private int x,y,high;
|
||||
|
||||
|
||||
public ParticleSystem(int x,int y,int high,int fire_width,int particlesCount,int particle_width) {
|
||||
this.x=x;
|
||||
this.y=y;
|
||||
this.high=high;
|
||||
this.fire_width =fire_width;
|
||||
this.particle_width=particle_width;
|
||||
if(particle_width<10)
|
||||
this.particle_width=10;
|
||||
if(randColor) {
|
||||
randomColor();
|
||||
paint.setColor(color);
|
||||
}else
|
||||
paint.setColor(Color.RED);
|
||||
for (int i = 0; i < particlesCount; i++) {
|
||||
particles.add(newParticle());
|
||||
}
|
||||
}
|
||||
|
||||
public void onDraw(Canvas canvas) {
|
||||
for (int i = 0; i < particles.size(); i++) {
|
||||
Particle particle = particles.get(i);
|
||||
paint.setAlpha(particle.alpha);
|
||||
canvas.drawRect(particle.getX(), particle.getY(), particle.getX() + particle_width, particle.getY() + particle_width, paint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 粒子集合更新方法
|
||||
*
|
||||
* @param wind wind是风,volume 是风加速度 0时代表无风,粒子不偏移
|
||||
*/
|
||||
public void update(WIND wind,float volume) {
|
||||
for (int i = 0; i < particles.size(); i++) {
|
||||
Particle particle = particles.get(i);
|
||||
|
||||
if (particle.xv > 0) {
|
||||
//当初始加速度为正,就一直为正
|
||||
particle.xv += 0.01f + volume;
|
||||
} else {
|
||||
//当初始加速度为负,就一直为正
|
||||
particle.xv += -0.01f + volume;
|
||||
}
|
||||
particle.yv = particle.yv + 0.1f;
|
||||
switch (wind){
|
||||
case LEFT_TO_RIGHT:
|
||||
break;
|
||||
case RIGHT_TO_LEFT:
|
||||
break;
|
||||
}
|
||||
|
||||
particle.setX(particle.getX() + particle.xv);
|
||||
particle.setY(particle.getY() - particle.yv);
|
||||
//跟据上升高度 计算透明度
|
||||
particle.alpha = 255-(int) ((y-particle.y)*255/high);
|
||||
}
|
||||
List<Particle> list = new ArrayList<>();
|
||||
list.addAll(particles);
|
||||
for (Particle particle : list) {
|
||||
if (particle.getY() < y-high) {
|
||||
moveToTrashCache(particle);
|
||||
particles.remove(particle);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
particles.add(newParticle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Particle newParticle(){
|
||||
Particle particle =revectForTrashCache();
|
||||
if(particle==null)
|
||||
particle = new Particle();
|
||||
if(rand.nextBoolean())
|
||||
particle.x=x - rand.nextInt(fire_width /2);
|
||||
else
|
||||
particle.x=x + rand.nextInt(fire_width /2);
|
||||
particle.y=y;
|
||||
particle.xv = 0.5f - 1 * rand.nextFloat();
|
||||
particle.yv=1;
|
||||
particle.alpha=255;
|
||||
return particle;
|
||||
}
|
||||
}
|
||||
|
||||
//用于两边向中间靠拢
|
||||
public enum WIND{
|
||||
LEFT_TO_RIGHT,NULL,RIGHT_TO_LEFT,
|
||||
TORNADO;//龙卷风
|
||||
}
|
||||
|
||||
public class Particle {
|
||||
//火焰粒子坐标
|
||||
private float x;
|
||||
private float y;
|
||||
public float xv = 1;//x轴加速度
|
||||
public float yv = 1;//y轴加速度
|
||||
public int alpha;
|
||||
|
||||
public Particle(){
|
||||
}
|
||||
|
||||
public Particle(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(float y) {
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PointF;
|
||||
|
||||
//参考自:https://blog.csdn.net/guimianhao9833/article/details/75094010
|
||||
public class FishAnimator {
|
||||
|
||||
|
||||
private static final String TAG = "Jcs_Fishsss";
|
||||
private static final float HEAD_RADIUS = 50;
|
||||
protected static final float BODY_LENGHT = HEAD_RADIUS * 3.2f; //第一节身体长度
|
||||
private static final int BODY_ALPHA = 220;
|
||||
private static final int OTHER_ALPHA = 160;
|
||||
private static final int FINS_ALPHA = 100;
|
||||
private static final int FINS_LEFT = 1;//左鱼鳍
|
||||
private static final int FINS_RIGHT = -1;
|
||||
private static final float FINS_LENGTH = HEAD_RADIUS * 1.3f;
|
||||
public static final float TOTAL_LENGTH = 6.79f * HEAD_RADIUS;
|
||||
|
||||
public class Fish{
|
||||
private Paint mPaint;
|
||||
//控制区域
|
||||
private int currentValue = 0;//全局控制标志
|
||||
private float mainAngle = 90;//角度表示的角
|
||||
private float waveFrequence = 1;
|
||||
//鱼头点
|
||||
private PointF headPoint;
|
||||
//转弯更自然的中心点
|
||||
private PointF middlePoint;
|
||||
private float finsAngle = 0;
|
||||
private Paint bodyPaint;
|
||||
private Path mPath;
|
||||
|
||||
public Fish() {
|
||||
init();
|
||||
}
|
||||
|
||||
public void run(){
|
||||
//currentValue = (int) (animation.getAnimatedValue());
|
||||
//invalidateSelf();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
|
||||
//路径
|
||||
mPath = new Path();
|
||||
//画笔
|
||||
mPaint = new Paint();
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setDither(true);//防抖
|
||||
mPaint.setColor(Color.argb(OTHER_ALPHA, 244, 92, 71));
|
||||
//身体画笔
|
||||
bodyPaint = new Paint();
|
||||
bodyPaint.setAntiAlias(true);
|
||||
bodyPaint.setStyle(Paint.Style.FILL);
|
||||
bodyPaint.setDither(true);//防抖
|
||||
bodyPaint.setColor(Color.argb(OTHER_ALPHA + 5, 244, 92, 71));
|
||||
middlePoint = new PointF(4.18f * HEAD_RADIUS, 4.18f * HEAD_RADIUS);
|
||||
|
||||
//鱼鳍灵动动画
|
||||
//finsAnimator = ObjectAnimator.ofFloat(this, "finsAngle", 0f, 1f, 0f);
|
||||
//finsAnimator.setRepeatMode(ValueAnimator.REVERSE);
|
||||
//finsAnimator.setRepeatCount(new Random().nextInt(3));
|
||||
|
||||
//引擎部分
|
||||
//ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 540 * 100);
|
||||
//valueAnimator.setDuration(180 * 1000);
|
||||
//valueAnimator.setInterpolator(new LinearInterpolator());
|
||||
//valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
|
||||
//valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
|
||||
//valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
// @Override
|
||||
// public void onAnimationUpdate(ValueAnimator animation) {
|
||||
// currentValue = (int) (animation.getAnimatedValue());
|
||||
// invalidateSelf();
|
||||
// }
|
||||
//});
|
||||
//valueAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
// @Override
|
||||
// public void onAnimationRepeat(Animator animation) {
|
||||
// super.onAnimationRepeat(animation);
|
||||
// finsAnimator.start();
|
||||
// }
|
||||
//});
|
||||
//valueAnimator.start();
|
||||
|
||||
}
|
||||
|
||||
public PointF getHeadPoint() {
|
||||
return headPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置身体主轴线方向角度
|
||||
*
|
||||
* @param mainAngle
|
||||
*/
|
||||
public void setMainAngle(float mainAngle) {
|
||||
this.mainAngle = mainAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前角度
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public float getMainAngle() {
|
||||
return mainAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置头的位置
|
||||
*
|
||||
* @param headPoint
|
||||
*/
|
||||
public void setHeadPoint(PointF headPoint) {
|
||||
this.headPoint = headPoint;
|
||||
}
|
||||
|
||||
public void setMiddlePoint(PointF middlePoint) {
|
||||
this.middlePoint = middlePoint;
|
||||
}
|
||||
|
||||
public PointF getMiddlePoint() {
|
||||
return middlePoint;
|
||||
}
|
||||
|
||||
public float getTotalLength() {
|
||||
return TOTAL_LENGTH;
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas) {
|
||||
|
||||
//生成一个半透明图层,否则与背景白色形成干扰,尺寸必须与view的大小一致否则鱼显示不全
|
||||
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), 240, Canvas.ALL_SAVE_FLAG);
|
||||
makeBody(canvas, HEAD_RADIUS);
|
||||
canvas.restore();
|
||||
mPath.reset();
|
||||
mPaint.setColor(Color.argb(OTHER_ALPHA, 244, 92, 71));
|
||||
}
|
||||
|
||||
//画身子
|
||||
|
||||
/**
|
||||
* 主方向是头到尾的方向跟X轴正方向的夹角(顺时针为正)
|
||||
* 前进方向和主方向相差180度
|
||||
* R + 3.2R
|
||||
*
|
||||
* @param canvas
|
||||
* @param headRadius
|
||||
*/
|
||||
private void makeBody(Canvas canvas, float headRadius) {
|
||||
//sin参数为弧度值
|
||||
//现有角度=原始角度+ sin(域值[-1,1])*可摆动的角度 sin作用是控制周期摆动
|
||||
float angle = mainAngle + (float) Math.sin(Math.toRadians(currentValue * 1.2 * waveFrequence)) * 2;//中心轴线加偏移量和X轴顺时针方向夹角
|
||||
headPoint = calculatPoint(middlePoint, BODY_LENGHT / 2,mainAngle);
|
||||
//画头
|
||||
canvas.drawCircle(headPoint.x, headPoint.y, HEAD_RADIUS, mPaint);
|
||||
//右鳍 起点
|
||||
PointF pointFinsRight = calculatPoint(headPoint, headRadius * 0.9f, angle -110);
|
||||
makeFins(canvas, pointFinsRight, FINS_RIGHT, angle);
|
||||
//左鳍 起点
|
||||
PointF pointFinsLeft = calculatPoint(headPoint, headRadius * 0.9f, angle +110);
|
||||
makeFins(canvas, pointFinsLeft, FINS_LEFT, angle);
|
||||
|
||||
PointF endPoint = calculatPoint(headPoint, BODY_LENGHT, angle-180);
|
||||
//躯干2
|
||||
PointF mainPoint = new PointF(endPoint.x, endPoint.y);
|
||||
makeSegments(canvas, mainPoint, headRadius * 0.7f, 0.6f, angle);
|
||||
PointF point1, point2, point3, point4, contralLeft, contralRight;
|
||||
//point1和4的初始角度决定发髻线的高低值越大越低
|
||||
point1 = calculatPoint(headPoint, headRadius, angle-80);
|
||||
point2 = calculatPoint(endPoint, headRadius * 0.7f, angle-90);
|
||||
point3 = calculatPoint(endPoint, headRadius * 0.7f, angle +90);
|
||||
point4 = calculatPoint(headPoint, headRadius, angle +80);
|
||||
//决定胖瘦
|
||||
contralLeft = calculatPoint(headPoint, BODY_LENGHT * 0.56f, angle -130);
|
||||
contralRight = calculatPoint(headPoint, BODY_LENGHT * 0.56f, angle +130);
|
||||
mPath.reset();
|
||||
mPath.moveTo(point1.x, point1.y);
|
||||
mPath.quadTo(contralLeft.x, contralLeft.y, point2.x, point2.y);
|
||||
mPath.lineTo(point3.x, point3.y);
|
||||
mPath.quadTo(contralRight.x, contralRight.y, point4.x, point4.y);
|
||||
mPath.lineTo(point1.x, point1.y);
|
||||
|
||||
mPaint.setColor(Color.argb(BODY_ALPHA, 244, 92, 71));
|
||||
//画最大的身子
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* 第二节节肢
|
||||
* 0.7R * 0.6 =1.12R
|
||||
*
|
||||
* @param canvas
|
||||
* @param mainPoint
|
||||
* @param segmentRadius
|
||||
* @param MP 梯形上边下边长度比
|
||||
*/
|
||||
private void makeSegments(Canvas canvas, PointF mainPoint, float segmentRadius, float MP, float fatherAngle) {
|
||||
float angle = fatherAngle + (float) Math.cos(Math.toRadians(currentValue * 1.5 * waveFrequence)) * 15;//中心轴线和X轴顺时针方向夹角
|
||||
//身长
|
||||
float segementLenght = segmentRadius * (MP + 1);
|
||||
PointF endPoint = calculatPoint(mainPoint, segementLenght, angle-180);
|
||||
|
||||
PointF point1, point2, point3, point4;
|
||||
point1 = calculatPoint(mainPoint, segmentRadius, angle-90);
|
||||
point2 = calculatPoint(endPoint, segmentRadius * MP,angle-90);
|
||||
point3 = calculatPoint(endPoint, segmentRadius * MP, angle +90);
|
||||
point4 = calculatPoint(mainPoint, segmentRadius, angle+90);
|
||||
|
||||
canvas.drawCircle(mainPoint.x, mainPoint.y, segmentRadius, mPaint);
|
||||
canvas.drawCircle(endPoint.x, endPoint.y, segmentRadius * MP, mPaint);
|
||||
mPath.reset();
|
||||
mPath.moveTo(point1.x, point1.y);
|
||||
mPath.lineTo(point2.x, point2.y);
|
||||
mPath.lineTo(point3.x, point3.y);
|
||||
mPath.lineTo(point4.x, point4.y);
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
|
||||
//躯干2
|
||||
PointF mainPoint2 = new PointF(endPoint.x, endPoint.y);
|
||||
makeSegmentsLong(canvas, mainPoint2, segmentRadius * 0.6f, 0.4f, angle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三节节肢
|
||||
* 0.7R * 0.6 * (0.4 + 2.7) + 0.7R * 0.6 * 0.4=1.302R + 0.168R
|
||||
*
|
||||
* @param canvas
|
||||
* @param mainPoint
|
||||
* @param segmentRadius
|
||||
* @param MP 梯形上边下边长度比
|
||||
*/
|
||||
private void makeSegmentsLong(Canvas canvas, PointF mainPoint, float segmentRadius, float MP, float fatherAngle) {
|
||||
float angle = fatherAngle + (float) Math.sin(Math.toRadians(currentValue * 1.5 * waveFrequence)) * 35;//中心轴线和X轴顺时针方向夹角
|
||||
//身长
|
||||
float segementLenght = segmentRadius * (MP + 2.7f);
|
||||
PointF endPoint = calculatPoint(mainPoint, segementLenght, angle-180);
|
||||
|
||||
PointF point1, point2, point3, point4;
|
||||
point1 = calculatPoint(mainPoint, segmentRadius, angle -90 );
|
||||
point2 = calculatPoint(endPoint, segmentRadius * MP,angle -90 );
|
||||
point3 = calculatPoint(endPoint, segmentRadius * MP, angle +90);
|
||||
point4 = calculatPoint(mainPoint, segmentRadius, angle +90);
|
||||
|
||||
makeTail(canvas, mainPoint, segementLenght, segmentRadius, angle);
|
||||
|
||||
|
||||
canvas.drawCircle(endPoint.x, endPoint.y, segmentRadius * MP, mPaint);
|
||||
mPath.reset();
|
||||
mPath.moveTo(point1.x, point1.y);
|
||||
mPath.lineTo(point2.x, point2.y);
|
||||
mPath.lineTo(point3.x, point3.y);
|
||||
mPath.lineTo(point4.x, point4.y);
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* 鱼鳍
|
||||
*
|
||||
* @param canvas
|
||||
* @param startPoint
|
||||
* @param type
|
||||
*/
|
||||
private void makeFins(Canvas canvas, PointF startPoint, int type, float fatherAngle) {
|
||||
float contralAngle = 115;//鱼鳍三角控制角度
|
||||
mPath.reset();
|
||||
mPath.moveTo(startPoint.x, startPoint.y);
|
||||
PointF endPoint = calculatPoint(startPoint, FINS_LENGTH, type == FINS_RIGHT ? fatherAngle - finsAngle-180 : fatherAngle + finsAngle+180);
|
||||
PointF contralPoint = calculatPoint(startPoint, FINS_LENGTH * 1.8f, type == FINS_RIGHT ?
|
||||
fatherAngle - contralAngle - finsAngle : fatherAngle + contralAngle + finsAngle);
|
||||
mPath.quadTo(contralPoint.x, contralPoint.y, endPoint.x, endPoint.y);
|
||||
mPath.lineTo(startPoint.x, startPoint.y);
|
||||
mPaint.setColor(Color.argb(FINS_ALPHA, 244, 92, 71));
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
mPaint.setColor(Color.argb(OTHER_ALPHA, 244, 92, 71));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 鱼尾及鱼尾张合
|
||||
*
|
||||
* @param canvas
|
||||
* @param mainPoint
|
||||
* @param length
|
||||
* @param maxWidth
|
||||
*/
|
||||
private void makeTail(Canvas canvas, PointF mainPoint, float length, float maxWidth, float angle) {
|
||||
float newWidth = (float) Math.abs(Math.sin(Math.toRadians(currentValue * 1.7 * waveFrequence)) * maxWidth + HEAD_RADIUS/5*3);
|
||||
//endPoint为三角形底边中点
|
||||
PointF endPoint = calculatPoint(mainPoint, length, angle-180);
|
||||
PointF endPoint2 = calculatPoint(mainPoint, length - 10, angle-180);
|
||||
PointF point1, point2, point3, point4;
|
||||
point1 = calculatPoint(endPoint, newWidth, angle-90);
|
||||
point2 = calculatPoint(endPoint, newWidth, angle +90);
|
||||
point3 = calculatPoint(endPoint2, newWidth - 20, angle-90);
|
||||
point4 = calculatPoint(endPoint2, newWidth - 20, angle +90);
|
||||
//内
|
||||
mPath.reset();
|
||||
mPath.moveTo(mainPoint.x, mainPoint.y);
|
||||
mPath.lineTo(point3.x, point3.y);
|
||||
mPath.lineTo(point4.x, point4.y);
|
||||
mPath.lineTo(mainPoint.x, mainPoint.y);
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
//外
|
||||
mPath.reset();
|
||||
mPath.moveTo(mainPoint.x, mainPoint.y);
|
||||
mPath.lineTo(point1.x, point1.y);
|
||||
mPath.lineTo(point2.x, point2.y);
|
||||
mPath.lineTo(mainPoint.x, mainPoint.y);
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
|
||||
}
|
||||
|
||||
private void setFinsAngle(float currentValue) {
|
||||
finsAngle = 45 * currentValue;
|
||||
}
|
||||
|
||||
|
||||
public void setWaveFrequence(float waveFrequence) {
|
||||
this.waveFrequence = waveFrequence;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setAlpha(int alpha) {
|
||||
mPaint.setAlpha(alpha);
|
||||
}
|
||||
|
||||
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
mPaint.setColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高度要容得下两个鱼身长度
|
||||
* 8.36计算过程 身长6.79减去头顶到中部位置的长度2.6 再乘以2
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
public int getIntrinsicHeight() {
|
||||
return (int) (8.38f * HEAD_RADIUS);
|
||||
}
|
||||
|
||||
|
||||
public int getIntrinsicWidth() {
|
||||
return (int) (8.38f * HEAD_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 输入起点、长度、旋转角度计算终点
|
||||
* @param startPoint 起点
|
||||
* @param length 长度
|
||||
* @param angle 旋转角度
|
||||
* @return 计算结果点
|
||||
*/
|
||||
private static PointF calculatPoint(PointF startPoint, float length, float angle) {
|
||||
float deltaX = (float) Math.cos(Math.toRadians(angle)) * length;
|
||||
//符合Android坐标的y轴朝下的标准
|
||||
float deltaY = (float) Math.sin(Math.toRadians(angle-180)) * length;
|
||||
return new PointF(startPoint.x + deltaX, startPoint.y + deltaY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
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.AbstractAnimator;
|
||||
|
||||
//参考自:https://github.com/zhuwentao2150/RippleView
|
||||
public class RippleAnimator extends AbstractAnimator<RippleAnimator.Ripple> {
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
Style style;
|
||||
int ran=rand.nextInt(3);
|
||||
if(ran==2)
|
||||
style=Style.OUT;
|
||||
else if(ran==1)
|
||||
style=Style.BREATH;
|
||||
else
|
||||
style=Style.IN;
|
||||
list.add(new Ripple(width,height,Color.BLUE,style));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean run() {
|
||||
for(Ripple ripple:list)
|
||||
ripple.breath();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
for(Ripple ripple:list)
|
||||
ripple.onDraw(canvas);
|
||||
}
|
||||
|
||||
public enum Style{
|
||||
IN,OUT,BREATH;
|
||||
}
|
||||
|
||||
public class Ripple{
|
||||
// 画笔对象
|
||||
private Paint mPaint;
|
||||
|
||||
// View宽
|
||||
private float mWidth;
|
||||
|
||||
// View高
|
||||
private float mHeight;
|
||||
|
||||
// 声波的圆圈集合
|
||||
private List<Circle> mRipples;
|
||||
|
||||
private int sqrtNumber;
|
||||
|
||||
// 圆圈扩散的速度
|
||||
private int mSpeed;
|
||||
|
||||
// 圆圈之间的密度
|
||||
private int mDensity;
|
||||
|
||||
// 圆圈的颜色
|
||||
private int mColor;
|
||||
|
||||
// 圆圈是否为填充模式
|
||||
private boolean mIsFill;
|
||||
|
||||
// 圆圈是否为渐变模式
|
||||
private boolean mIsAlpha;
|
||||
|
||||
Style style;
|
||||
|
||||
|
||||
|
||||
public Ripple(float mWidth, float mHeight, int mColor,Style style) {
|
||||
this.mWidth = mWidth;
|
||||
this.mHeight = mHeight;
|
||||
this.mColor = mColor;
|
||||
this.style=style;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mSpeed = 1;
|
||||
mDensity = 10;
|
||||
mIsFill = true;
|
||||
mIsAlpha = true;
|
||||
|
||||
// 设置画笔样式
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(mColor);
|
||||
mPaint.setStrokeWidth(Util.dipToPX(context,1));
|
||||
if (mIsFill) {
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
} else {
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
}
|
||||
mPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
mPaint.setAntiAlias(true);
|
||||
|
||||
// 添加第一个圆圈
|
||||
mRipples = new ArrayList<>();
|
||||
addNewCircle();
|
||||
|
||||
mDensity = Util.dipToPX(context, mDensity);
|
||||
}
|
||||
|
||||
public void onDraw(Canvas canvas) {
|
||||
switch (style){
|
||||
case BREATH:
|
||||
//呼吸的
|
||||
drawBreath(canvas);
|
||||
break;
|
||||
case OUT:
|
||||
// 外切正方形
|
||||
drawOutCircle(canvas);
|
||||
break;
|
||||
default:
|
||||
// 内切正方形
|
||||
drawInCircle(canvas);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void addNewCircle(){
|
||||
Circle c = new Circle(0, 255);
|
||||
if(randColor) {
|
||||
randomColor();
|
||||
c.color=color;
|
||||
}else
|
||||
c.color=mColor;
|
||||
mRipples.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 圆到宽度
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawInCircle(Canvas canvas) {
|
||||
canvas.save();
|
||||
|
||||
// 处理每个圆的宽度和透明度
|
||||
for (int i = 0; i < mRipples.size(); i++) {
|
||||
Circle c = mRipples.get(i);
|
||||
mPaint.setAlpha(c.alpha);// (透明)0~255(不透明)
|
||||
canvas.drawCircle(mWidth / 2, height / 2, c.width - mPaint.getStrokeWidth(), mPaint);
|
||||
|
||||
// 当圆超出View的宽度后删除
|
||||
if (c.width > width / 2) {
|
||||
mRipples.remove(i);
|
||||
} else {
|
||||
// 计算不透明的数值,这里有个小知识,就是如果不加上double的话,255除以一个任意比它大的数都将是0
|
||||
if (mIsAlpha) {
|
||||
double alpha = 255 - c.width * (255 / ((double) mWidth / 2));
|
||||
c.alpha = (int) alpha;
|
||||
}
|
||||
// 修改这个值控制速度
|
||||
c.width += mSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 里面添加圆
|
||||
if (mRipples.size() > 0) {
|
||||
// 控制第二个圆出来的间距
|
||||
if (mRipples.get(mRipples.size() - 1).width > Util.dipToPX(context, mDensity)) {
|
||||
addNewCircle();
|
||||
}
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 圆到对角线
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawOutCircle(Canvas canvas) {
|
||||
canvas.save();
|
||||
|
||||
// 使用勾股定律求得一个外切正方形中心点离角的距离
|
||||
sqrtNumber = (int) (Math.sqrt(mWidth * mWidth + mHeight * mHeight) / 2);
|
||||
|
||||
// 变大
|
||||
for (int i = 0; i < mRipples.size(); i++) {
|
||||
|
||||
// 启动圆圈
|
||||
Circle c = mRipples.get(i);
|
||||
mPaint.setAlpha(c.alpha);// (透明)0~255(不透明)
|
||||
canvas.drawCircle(mWidth / 2, mHeight / 2, c.width - mPaint.getStrokeWidth(), mPaint);
|
||||
|
||||
// 当圆超出对角线后删掉
|
||||
if (c.width > sqrtNumber) {
|
||||
mRipples.remove(i);
|
||||
} else {
|
||||
// 计算不透明的度数
|
||||
double degree = 255 - c.width * (255 / (double) sqrtNumber);
|
||||
c.alpha = (int) degree;
|
||||
c.width += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 里面添加圆
|
||||
if (mRipples.size() > 0) {
|
||||
// 控制第二个圆出来的间距
|
||||
if (mRipples.get(mRipples.size() - 1).width == 50) {
|
||||
addNewCircle();
|
||||
}
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
private float breathDirection = 1;//呼吸方向(+1:变亮,-1:变暗)
|
||||
private float breathSpeed = 0.02f;//呼吸速度
|
||||
private boolean isBreathing = false;
|
||||
|
||||
private int a = 0;
|
||||
private float breath = 1f;//控制呼吸
|
||||
private int waveCount = 5;//波纹的总个数
|
||||
|
||||
public void drawBreath(Canvas canvas) {
|
||||
|
||||
int alphaSpeed;
|
||||
float radiusSpeed;
|
||||
float hw = mWidth/2f;
|
||||
|
||||
/**
|
||||
* 根据view的宽度计算半径和透明度的变化速度,(为了尽力保证半径和透明度同时达到最值:255是透明度的最大值)
|
||||
*/
|
||||
if(hw >255f){
|
||||
radiusSpeed = hw/255f;
|
||||
alphaSpeed = 1;
|
||||
}else {
|
||||
alphaSpeed = new Float(255f/hw).intValue();
|
||||
radiusSpeed = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 控制呼吸
|
||||
*/
|
||||
if(isBreathing){
|
||||
breath=breath+breathSpeed*breathDirection;
|
||||
if(breath>1 ){
|
||||
breathDirection *= -1;//呼吸反向
|
||||
if(beforBreathIsAwave){
|
||||
isBreathing = false;
|
||||
isStarting = true;
|
||||
breath = 1;
|
||||
}
|
||||
|
||||
}else if(breath <0.001){
|
||||
breathDirection *= -1;//呼吸反向
|
||||
if(!beforBreathIsAwave){
|
||||
isBreathing = false;
|
||||
isStarting = false;
|
||||
breath = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 当达到设定的波距或第一次运行时 添加一个新波
|
||||
*/
|
||||
if (++a>= (hw/waveCount) || mRipples.size()<1){
|
||||
a = 0;
|
||||
addNewCircle();
|
||||
}
|
||||
|
||||
for (int i= 0;i< mRipples.size();i++){
|
||||
Circle temp = mRipples.get(i);
|
||||
if(isStarting){
|
||||
temp.alpha=temp.alpha-alphaSpeed;//改变波的透明度
|
||||
if(temp.alpha <0){
|
||||
temp.alpha=0;
|
||||
}
|
||||
temp.width=temp.width + new Float(radiusSpeed).intValue();//增加波的半径
|
||||
}
|
||||
mPaint.setColor(temp.color);
|
||||
int tempAlpha = (int)(temp.alpha*breath);//乘以breath是为了通过改变透明度达到呼吸的效果
|
||||
mPaint.setAlpha(tempAlpha<0?0:tempAlpha);
|
||||
canvas.drawCircle(mWidth / 2, mHeight / 2, temp.width, mPaint);//绘制波
|
||||
|
||||
|
||||
/**
|
||||
* 当波的半径大于本控件的宽大时删除这个波
|
||||
*/
|
||||
if( temp.width >mWidth || temp.alpha <0){
|
||||
mRipples.remove(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean beforBreathIsAwave = true;
|
||||
private boolean isStarting = true;
|
||||
|
||||
private int sleep=0;
|
||||
|
||||
/**
|
||||
* 此方法调用一次波会呼吸一次
|
||||
*/
|
||||
public synchronized void breath(){
|
||||
sleep++;
|
||||
if(sleep<10)
|
||||
return;
|
||||
sleep=0;
|
||||
this.beforBreathIsAwave = isStarting;
|
||||
if(beforBreathIsAwave){
|
||||
breath = 1;
|
||||
breathDirection =-1;
|
||||
}
|
||||
else {
|
||||
breath = 0.01f;
|
||||
breathDirection = 1;
|
||||
}
|
||||
isBreathing = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Circle {
|
||||
Circle(int width, int alpha) {
|
||||
this.width = width;
|
||||
this.alpha = alpha;
|
||||
}
|
||||
|
||||
int width;
|
||||
|
||||
int alpha;
|
||||
|
||||
int color;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
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 clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
|
||||
|
||||
public class WaterAnimator extends AbstractAnimator<WaterAnimator.Water> {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean run() {
|
||||
for(Water water:list) {
|
||||
water.runWave();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
for(Water water:list) {
|
||||
water.drawWaterView(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
addWater(1);
|
||||
}
|
||||
|
||||
|
||||
Water water;
|
||||
|
||||
public void addWater(int quantity) {
|
||||
for (int i = 0; i < quantity;i++) {
|
||||
if(randColor)
|
||||
randomColor();
|
||||
Water water=new Water(color,50);
|
||||
list.add(water);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Water{
|
||||
private int mWaterWidth;//水波纹圆形的宽度
|
||||
private int mWaterHeight;//水波纹圆形的高度
|
||||
private int mWaveCount = 2;//水波纹的个数
|
||||
private int mStep = 0;//移步的步长
|
||||
private float mWaterRange = 30;//水波纹的高度
|
||||
|
||||
private int mProgressY;//水波纹的中心的Y轴
|
||||
|
||||
//private int mRadius;//水波纹圆的半径
|
||||
private int mWaveLength;//波纹的宽度
|
||||
private Path path;
|
||||
private int waterColor;//水波纹的颜色
|
||||
private Paint waterPaint;
|
||||
|
||||
private int mPercent = 0;//当前进度0-100,决定Y点位置
|
||||
|
||||
public Water(int waterColor,int mPercent) {
|
||||
this.waterColor = waterColor;
|
||||
this.mPercent=mPercent;
|
||||
initWaveRange();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化水波纹的振幅
|
||||
*/
|
||||
public void initWaveRange() {
|
||||
//mHeight = Math.min(width, height);
|
||||
mWaterWidth = Math.min(width, height);
|
||||
mWaterHeight = Math.min(width, height);
|
||||
|
||||
waterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
waterPaint.setAntiAlias(true);
|
||||
waterPaint.setColor(waterColor);
|
||||
waterPaint.setStrokeWidth(3);
|
||||
waterPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
|
||||
mStep=rand.nextInt(width);//移动步长
|
||||
|
||||
mWaterRange = rand.nextInt(200);//高度
|
||||
if(mWaterRange<10)
|
||||
mWaterRange=50;
|
||||
mWaveCount=1;//波浪数
|
||||
path = new Path();
|
||||
mWaveLength = mWaterWidth / mWaveCount;//每个波浪数长度
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制水波纹
|
||||
*
|
||||
* @param canvas
|
||||
*
|
||||
*/
|
||||
public void drawWaterView(Canvas canvas) {
|
||||
mProgressY = mWaterHeight - (mWaterHeight * mPercent / 100);
|
||||
|
||||
//从左到右
|
||||
canvas.drawPath(getPath(), waterPaint);
|
||||
|
||||
//从右到左
|
||||
|
||||
//确定贝塞尔曲线各个点的位置
|
||||
path.reset();
|
||||
path.moveTo(0 , mProgressY);
|
||||
//从左往右绘制
|
||||
Point point=null;
|
||||
//w为什么是mWaveCount*3,那是因为需要在不可见的区域多绘制几个曲线,这样就可以形成
|
||||
//波浪的效果,如果只有一个mWaveCount的话,那么就是一个简单的正选曲线
|
||||
for (int i = 1; i <= mWaveCount * 3; i++) {
|
||||
int x1 = mWaveLength * i - mWaveLength / 2 - mStep;
|
||||
|
||||
if (i % 2 != 0) {
|
||||
path.quadTo(x1,
|
||||
mProgressY - mWaterRange,
|
||||
mWaveLength * i - mStep,
|
||||
mProgressY);
|
||||
|
||||
//point=getControlPointF(new Point(x1,mProgressY - mWaterRange),new Point(mWaveLength * i - mStep,mProgressY),new Point(width / 2, mProgressY + mWaveLength * i - mWaveLength / 2));
|
||||
|
||||
} else {
|
||||
path.quadTo(
|
||||
x1,
|
||||
mProgressY + mWaterRange,
|
||||
mWaveLength * i - mStep,
|
||||
mProgressY);
|
||||
//point=getControlPointF(new Point(x1,mProgressY + mWaterRange),new Point(mWaveLength * i - mStep,mProgressY),new Point(width / 2, mProgressY + mWaveLength * i - mWaveLength / 2));
|
||||
|
||||
}
|
||||
//Paint temp=new Paint();
|
||||
//temp.setColor(Color.WHITE);
|
||||
//canvas.drawCircle(width / 2,point.y-100,30,temp);
|
||||
}
|
||||
|
||||
path.lineTo(mWaveCount * 2 * mWaveLength,mWaterHeight);
|
||||
|
||||
path.lineTo(0, mWaterHeight);
|
||||
|
||||
path.close();
|
||||
canvas.drawPath(path, waterPaint);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 核心代码,计算path
|
||||
* @return
|
||||
*/
|
||||
private Path getPath(){
|
||||
int itemWidth = mWaterWidth/2;//半个波长
|
||||
Path mPath = new Path();
|
||||
mPath.moveTo(-itemWidth * 3, mProgressY);//起始坐标
|
||||
//核心的代码就是这里
|
||||
for (int i = -3; i < 4; i++) {
|
||||
int startX = i * itemWidth;
|
||||
mPath.quadTo(
|
||||
startX + itemWidth/2 + mStep,//控制点的X,(起始点X + itemWidth/2 + offset)
|
||||
getWaveHeigh( i ),//控制点的Y
|
||||
startX + itemWidth + mStep,//结束点的X
|
||||
mProgressY//结束点的Y
|
||||
);//只需要处理完半个波长,剩下的有for循环自已就添加了。
|
||||
}
|
||||
//下面这三句话很重要,它是形成了一封闭区间,让曲线以下的面积填充一种颜色,大家可以把这3句话注释了看看效果。
|
||||
mPath.lineTo(width,height);
|
||||
mPath.lineTo(0,height);
|
||||
mPath.close();
|
||||
return mPath;
|
||||
}
|
||||
|
||||
//奇数峰值是正的,偶数峰值是负数
|
||||
private float getWaveHeigh(int num){
|
||||
if(num % 2 == 0){
|
||||
return mProgressY + mWaterRange;
|
||||
}
|
||||
return mProgressY - mWaterRange;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Author: MrGao
|
||||
* CreateTime: 2018/1/4 16:29
|
||||
* MethodName:
|
||||
* Des:水波纹动画
|
||||
* Params:
|
||||
* Return:
|
||||
**/
|
||||
public void runWave(){
|
||||
mStep = mStep+mWaveLength/30 ;
|
||||
if(mStep>width)
|
||||
mStep=0;
|
||||
//mStep=rand.nextInt(20);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制外层的刻度
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.util.Log;
|
||||
|
||||
import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
|
||||
|
||||
//参考:https://blog.csdn.net/u014112893/article/details/78556098
|
||||
public class WindmillAnimator extends AbstractAnimator<WindmillAnimator.Windmill> {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean run() {
|
||||
for(Windmill windmill:list)
|
||||
windmill.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
for(Windmill windmill:list)
|
||||
windmill.onDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
addWindmill(3);
|
||||
}
|
||||
|
||||
private void addWindmill(int quantity){
|
||||
//用于个个之间保证有足够的间距,不会都在一起
|
||||
int step=width/quantity;
|
||||
|
||||
for(int i=0;i<quantity;i++) {
|
||||
int x=step*i+rand.nextInt(step);
|
||||
int y=rand.nextInt(height);
|
||||
int h=rand.nextInt(height-y);
|
||||
if(h<height/3) {
|
||||
h = h + height/3;
|
||||
}
|
||||
if(y+h>height)
|
||||
y=height-h-30;
|
||||
int w=h*3/4;
|
||||
if(x+w>width)
|
||||
x=width-w-30;
|
||||
if(randColor)
|
||||
randomColor();
|
||||
list.add(new Windmill(x,y,h,w,color));
|
||||
}
|
||||
}
|
||||
|
||||
public class Windmill{
|
||||
private Paint mPaint;
|
||||
private Path mPath;
|
||||
private int width, height;
|
||||
private int x,y;
|
||||
int color;
|
||||
|
||||
private int lineWidth = 5;
|
||||
private int windmillLeng; // 扇叶长度
|
||||
private float lengthOfSide; // 扇叶小三角形的斜边长
|
||||
private float angle = 0F;
|
||||
|
||||
private int delay=0;//使个个转动都不同
|
||||
|
||||
public Windmill(int x,int y,int width, int height,int color) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.x=x;
|
||||
this.y=y;
|
||||
this.color=color;
|
||||
delay=rand.nextInt(5);
|
||||
initPaint();
|
||||
}
|
||||
|
||||
private void initPaint() {
|
||||
mPaint = new Paint();
|
||||
mPath = new Path();
|
||||
mPaint.setColor(color);
|
||||
mPaint.setStrokeWidth(lineWidth);
|
||||
mPaint.setAntiAlias(true);
|
||||
windmillLeng = Math.min(width, height) / 2 - 20;
|
||||
lengthOfSide = (float) (windmillLeng / 10 / Math.cos(45));
|
||||
}
|
||||
|
||||
int step=0;
|
||||
public void run(){
|
||||
step++;
|
||||
if(step<delay)
|
||||
return;
|
||||
step=0;
|
||||
if (angle >= 360) angle = 0;
|
||||
angle += 5;
|
||||
}
|
||||
|
||||
protected void onDraw(Canvas canvas) {
|
||||
drawLines(canvas);
|
||||
drawWindMills(canvas);
|
||||
}
|
||||
|
||||
|
||||
// 每个扇叶由2个三角形组成,小三角形是由2个等边直角三角形组成,变成是扇叶长度的十分之一
|
||||
private void drawWindMills(Canvas canvas) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
//Log.i("drawWindMills", height + " / " + windmillLeng);
|
||||
mPath.moveTo(x+width / 2, y+ windmillLeng);
|
||||
mPath.lineTo(x+width / 2 + lengthOfSide * (float) Math.sin(Math.PI / 180 * (-45 + angle + 120 * i)),
|
||||
y+ windmillLeng - lengthOfSide * (float) Math.cos(Math.PI / 180 * (-45 + angle + 120 * i)));
|
||||
mPath.lineTo(x+width / 2 + windmillLeng * (float) Math.sin(Math.PI / 180 * (120 * i + angle)),
|
||||
y+ windmillLeng - windmillLeng * (float) Math.cos(Math.PI / 180 * (120 * i + angle)));
|
||||
mPath.lineTo(x+width / 2 + lengthOfSide * (float) Math.sin(Math.PI / 180 * (45 + angle + 120 * i)),
|
||||
y+ windmillLeng - lengthOfSide * (float) Math.cos(Math.PI / 180 * (45 + angle + 120 * i)));
|
||||
mPath.lineTo(x+width / 2, y+ windmillLeng);
|
||||
mPath.close();
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
}
|
||||
mPath.reset();
|
||||
}
|
||||
|
||||
// 绘制风车支架
|
||||
private void drawLines(Canvas canvas) {
|
||||
canvas.drawLine(x+width / 3, y+height, x+width / 2, y+ windmillLeng, mPaint);
|
||||
canvas.drawLine(x+width / 2, y+ windmillLeng, x+2 * width / 3, y+height, mPaint);
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.bean;
|
||||
|
||||
public class Particle {
|
||||
public int color;
|
||||
public Double direction;
|
||||
public float speed;
|
||||
public float x = 0;
|
||||
public float y = 0;
|
||||
public float r=10;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.particle;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
public interface I_PraticleDraw {
|
||||
void draw(Canvas canvas, Particle particle, Paint paint);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.particle;
|
||||
|
||||
public class Particle {
|
||||
//运动相关
|
||||
public float aX;//加速度
|
||||
public float aY;//加速度Y
|
||||
public float vX;//速度X
|
||||
public float vY;//速度Y
|
||||
public long born;//诞生时间
|
||||
|
||||
//绘制相关
|
||||
public float x;//点位X,统一为中心点X
|
||||
public float y;//点位Y,统一为中心点Y
|
||||
public int color;//颜色
|
||||
public float r;//半径,主要用于计算所占面积,不只用于圆
|
||||
public int alpha;//透明度
|
||||
public I_PraticleDraw style;
|
||||
|
||||
|
||||
|
||||
public Particle clone() {
|
||||
Particle clone = null;
|
||||
try {
|
||||
clone = (Particle) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.particle.drawer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.I_PraticleDraw;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.Particle;
|
||||
|
||||
public class CircleDrawer implements I_PraticleDraw {
|
||||
public static final CircleDrawer INSTANCE=new CircleDrawer();
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Particle particle, Paint paint) {
|
||||
paint.setAlpha(particle.alpha);
|
||||
paint.setColor(particle.color);
|
||||
canvas.drawCircle(particle.x,particle.y,particle.r,paint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.particle.drawer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Build;
|
||||
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.I_PraticleDraw;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.Particle;
|
||||
|
||||
public class FilletSquareDrawer implements I_PraticleDraw {
|
||||
public static FilletSquareDrawer getInstance() {
|
||||
return new FilletSquareDrawer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Particle particle, Paint paint) {
|
||||
paint.setAlpha(particle.alpha);
|
||||
paint.setColor(particle.color);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
canvas.drawRoundRect(particle.x - particle.r, particle.y - particle.r, particle.x + particle.r, particle.y + particle.r, particle.r / 2, particle.r / 2, paint);
|
||||
}else
|
||||
canvas.drawRect(particle.x-particle.r,particle.y-particle.r,particle.x+particle.r,particle.y+particle.r,paint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.particle.drawer;
|
||||
|
||||
public class PolygonDrawer {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.particle.drawer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.I_PraticleDraw;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.Particle;
|
||||
|
||||
public class SquareDrawer implements I_PraticleDraw {
|
||||
public static SquareDrawer getInstance(){
|
||||
return new SquareDrawer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Particle particle, Paint paint) {
|
||||
paint.setAlpha(particle.alpha);
|
||||
paint.setColor(particle.color);
|
||||
canvas.drawRect(particle.x-particle.r,particle.y-particle.r,particle.x+particle.r,particle.y+particle.r,paint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package clock.socoolby.com.clock.widget.animatorview.animator.particle.drawer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.I_PraticleDraw;
|
||||
import clock.socoolby.com.clock.widget.animatorview.animator.particle.Particle;
|
||||
|
||||
public class TriangleDraw implements I_PraticleDraw {
|
||||
public static TriangleDraw getInstance(){
|
||||
return new TriangleDraw();
|
||||
}
|
||||
|
||||
Direction direction;
|
||||
|
||||
public TriangleDraw() {
|
||||
this(Direction.UP);
|
||||
}
|
||||
|
||||
public TriangleDraw(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Particle particle, Paint paint) {
|
||||
canvas.save();
|
||||
paint.setAlpha(particle.alpha);
|
||||
paint.setColor(particle.color);
|
||||
canvas.rotate(direction.degree,particle.x,particle.y);
|
||||
canvas.drawLine(particle.x, particle.y-particle.r, particle.x-particle.r,particle.y+particle.r, paint);
|
||||
canvas.drawLine(particle.x, particle.y-particle.r, particle.x+particle.r,particle.y+particle.r, paint);
|
||||
canvas.drawLine(particle.x-particle.r, particle.y+particle.r, particle.x+particle.r,particle.y+particle.r, paint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
|
||||
public enum Direction{
|
||||
LEFT(-270),RIGHT(-90),UP(0),DOWN(-180);
|
||||
public float degree;
|
||||
|
||||
Direction(float degree) {
|
||||
this.degree = degree;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,12 +56,12 @@ public class AutoScrollTextView extends android.support.v7.widget.AppCompatTextV
|
||||
textLength = paint.measureText(text);
|
||||
viewWidth = getWidth();
|
||||
|
||||
Log.e("zmm","--->"+textLength+"--->"+viewWidth+"-->"+getTextSize());
|
||||
Log.e(TAG,"--->"+textLength+"--->"+viewWidth+"-->"+getTextSize());
|
||||
if(viewWidth == 0)
|
||||
{
|
||||
viewWidth = 600;//获取屏幕的宽度
|
||||
}
|
||||
Log.e("zmm","屏幕的宽度-->"+ 600);
|
||||
Log.e(TAG,"屏幕的宽度-->"+ 600);
|
||||
step = textLength;//文字真实的长度
|
||||
temp_view_plus_text_length = viewWidth/2 + textLength;
|
||||
temp_view_plus_two_text_length = viewWidth + textLength * 2;//文字移动的距离应该是控件的长度+左边一个文字的长度+右边一个文字的长度
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
package clock.socoolby.com.clock.widget.textview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Build;
|
||||
import android.text.TextPaint;
|
||||
import android.text.style.ReplacementSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
@SuppressLint("AppCompatCustomView")
|
||||
public class DigitTextView extends TextView {
|
||||
public DigitTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public DigitTextView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DigitTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public DigitTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使TextView中不同大小字体垂直居中
|
||||
*/
|
||||
public static class DigitSpan extends ReplacementSpan {
|
||||
private int fontSizeSp; //字体大小sp
|
||||
|
||||
public DigitSpan(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
|
||||
|
||||
String text1 = text.subSequence(start, end).toString();
|
||||
//Log.d("DigitSpan","getSize text:"+text+"\tstart:"+start+"\tend:"+end+"\tsubStr:"+text1);
|
||||
//Paint p = getCustomTextPaint(paint);
|
||||
return (int) getCharWidth("8",paint)*text1.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
|
||||
String text1 = text.subSequence(start, end).toString();
|
||||
//Log.d("DigitSpan","draw text:"+text+"\tstart:"+start+"\tend:"+end+"\tsubStr:"+text1);
|
||||
Paint p = getCustomTextPaint(paint);
|
||||
Paint.FontMetricsInt fm = p.getFontMetricsInt();
|
||||
int baseCharWitch= getCharWidth("8",paint);
|
||||
int currentCharWidth,moveWidthX;
|
||||
for(int i=0;i<text1.length();i++) {
|
||||
String currentChar=String.valueOf(text1.charAt(i));
|
||||
currentCharWidth= getCharWidth(currentChar,paint);
|
||||
moveWidthX=baseCharWitch*i+(baseCharWitch-currentCharWidth)/2;
|
||||
canvas.drawText(currentChar, x+moveWidthX, y - ((y + fm.descent + y + fm.ascent) / 2 - (bottom + top) / 2), p); //此处重新计算y坐标,使字体居中
|
||||
}
|
||||
}
|
||||
|
||||
private TextPaint getCustomTextPaint(Paint srcPaint) {
|
||||
TextPaint paint = new TextPaint(srcPaint);
|
||||
//paint.setTextSize(ViewUtils.getSpPixel(mContext, fontSizeSp)); //设定字体大小, sp转换为px
|
||||
return paint;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DigitFlagSpan extends ReplacementSpan {
|
||||
|
||||
public DigitFlagSpan(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
|
||||
String text1 = text.subSequence(start, end).toString();
|
||||
return (int) getCharWidth(":",paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
|
||||
String text1 = text.subSequence(start, end).toString();
|
||||
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
|
||||
canvas.drawText(text1, x, y - ((y + fm.descent + y + fm.ascent) / 2 - (bottom + top) / 2), paint); //此处重新计算y坐标,使字体居中
|
||||
}
|
||||
}
|
||||
|
||||
public static class DigitSmallSpan extends ReplacementSpan {
|
||||
private float fontSizeSp; //字体大小sp
|
||||
|
||||
public DigitSmallSpan(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
|
||||
|
||||
String text1 = text.subSequence(start, end).toString();
|
||||
//Log.d("DigitSpan","getSize text:"+text+"\tstart:"+start+"\tend:"+end+"\tsubStr:"+text1);
|
||||
fontSizeSp=paint.getTextSize()/2;
|
||||
Paint p = getCustomTextPaint(paint);
|
||||
return (int) getCharWidth("8",p)*text1.length();
|
||||
}
|
||||
|
||||
int currentCharWidth,moveWidthX;
|
||||
String currentChar;
|
||||
@Override
|
||||
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
|
||||
String text1 = text.subSequence(start, end).toString();
|
||||
if(text1.length()<=1)
|
||||
return;
|
||||
//Log.d("DigitSpan","draw text:"+text+"\tstart:"+start+"\tend:"+end+"\tsubStr:"+text1);
|
||||
Paint.FontMetricsInt fmBefor=paint.getFontMetricsInt();
|
||||
Paint p = getCustomTextPaint(paint);
|
||||
Paint.FontMetricsInt fm = p.getFontMetricsInt();
|
||||
int baseCharWitch= getCharWidth("8",p);
|
||||
for(int i=1;i<text1.length();i++) {
|
||||
currentChar=String.valueOf(text1.charAt(i));
|
||||
currentCharWidth= getCharWidth(currentChar,paint);
|
||||
moveWidthX=baseCharWitch*i+(baseCharWitch-currentCharWidth)/2;
|
||||
//canvas.drawText(currentChar, x+moveWidthX, bottom+fm.ascent, p); //此处重新计算y坐标,使字体居中
|
||||
canvas.drawText(currentChar, x+moveWidthX, bottom-fmBefor.descent, p); //此处重新计算y坐标,使字体居中
|
||||
}
|
||||
}
|
||||
|
||||
private TextPaint getCustomTextPaint(Paint srcPaint) {
|
||||
TextPaint paint = new TextPaint(srcPaint);
|
||||
paint.setTextSize(fontSizeSp); //设定字体大小, sp转换为px
|
||||
return paint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SuperSubSpan extends ReplacementSpan
|
||||
{
|
||||
|
||||
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm)
|
||||
{
|
||||
text = text.subSequence(start, end);
|
||||
String[] parts = text.toString().split(",");
|
||||
Paint p = getSuperSubPaint(paint);
|
||||
return (int) Math.max(p.measureText(parts[0]), p.measureText(parts[1]));
|
||||
}
|
||||
|
||||
private static TextPaint getSuperSubPaint(Paint src)
|
||||
{
|
||||
TextPaint paint = new TextPaint(src);
|
||||
paint.setTextSize(src.getTextSize() / 2.5f);
|
||||
return paint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)
|
||||
{
|
||||
text = text.subSequence(start, end);
|
||||
String[] parts = text.toString().split(",");
|
||||
|
||||
Paint p = getSuperSubPaint(paint);
|
||||
|
||||
float width1 = p.measureText(parts[0]);
|
||||
float width2 = p.measureText(parts[1]);
|
||||
float maxWidth = Math.max(width1, width2);
|
||||
|
||||
canvas.drawText(parts[0], x + (maxWidth - width1), y - (bottom - top) / 3f, p);
|
||||
canvas.drawText(parts[1], x + (maxWidth - width2), y + (bottom - top) / 10f, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getCharWidth(String str, Paint paint){
|
||||
return (int)paint.measureText(str);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user