mirror of
				https://gitee.com/51danju/workclock.git
				synced 2025-10-25 19:31:26 +08:00 
			
		
		
		
	时间显示增加霓虹灯、阴影效果。
This commit is contained in:
		| @@ -1604,6 +1604,10 @@ public class MainActivity extends Activity implements Handler.Callback, View.OnC | ||||
|  | ||||
|     @Override | ||||
|     public boolean onDoubleTap(MotionEvent e) { | ||||
|         if(!isArtificialHiddle) { | ||||
|             tv_time.setLinearGradientRandom(!tv_time.isLinearGradientAble()); | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,102 @@ | ||||
| package clock.socoolby.com.clock.widget.animatorview.animator; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.graphics.Bitmap; | ||||
| import android.graphics.BitmapFactory; | ||||
| import android.graphics.Canvas; | ||||
| import android.graphics.Paint; | ||||
|  | ||||
| import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator; | ||||
| import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry; | ||||
|  | ||||
|  | ||||
| //参考自:https://github.com/Q42/AndroidScrollingImageView | ||||
| public class ScrollingImageAnimator extends AbstractAnimator<ScrollingImageAnimator.ScrollingImage> { | ||||
|  | ||||
|     public ScrollingImageAnimator() { | ||||
|         super(DYNAMIC_QUANTITY); | ||||
|     } | ||||
|  | ||||
|     public void addResourceIds(int[] resourceIds,int speed,boolean randStartX){ | ||||
|         for(int i=0;i<resourceIds.length;i++) | ||||
|            list.add(new ScrollingImage(speed,resourceIds[i],rand.nextInt(width),rand.nextInt(height),randStartX)); | ||||
|     } | ||||
|  | ||||
|     public void addBackgroundResourceId(int resourceId,int left,int top){ | ||||
|         list.add(new ScrollingImage(0,resourceId,left,top,false)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ScrollingImage createNewEntry() { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public class ScrollingImage implements I_AnimatorEntry { | ||||
|         private Bitmap bitmap; | ||||
|         private float speed; | ||||
|         private float offset; | ||||
|         private boolean isStarted; | ||||
|         int resourceID; | ||||
|         private int startX,startY; | ||||
|         boolean randStartX; | ||||
|  | ||||
|         public ScrollingImage(float speed,int resourceID,int startX,int startY,boolean randStartX) { | ||||
|             this.speed = speed; | ||||
|             this.resourceID=resourceID; | ||||
|             this.startX=startX; | ||||
|             offset=startX; | ||||
|             this.startY=startY; | ||||
|             this.randStartX=randStartX; | ||||
|             init(); | ||||
|         } | ||||
|  | ||||
|         private void init(){ | ||||
|             bitmap = loadBitmap(mainView.getContext(), resourceID); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Start the animation | ||||
|          */ | ||||
|         public void start() { | ||||
|             if (!isStarted) { | ||||
|                 isStarted = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Stop the animation | ||||
|          */ | ||||
|         public void stop() { | ||||
|             if (isStarted) { | ||||
|                 isStarted = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void setSpeed(float speed) { | ||||
|             this.speed = speed; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void move(int maxWidth, int maxHight) { | ||||
|             if (isStarted && speed != 0) { | ||||
|                 offset -= Math.abs(speed); | ||||
|                 if(offset<-bitmap.getWidth()) { | ||||
|                     offset = width; | ||||
|                     if(randStartX) { | ||||
|                         offset = rand.nextInt(width); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void onDraw(Canvas canvas, Paint mPaint) { | ||||
|             canvas.drawBitmap(bitmap, offset, startY, null); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|    public static Bitmap loadBitmap(Context context, int resourceId) { | ||||
|             return BitmapFactory.decodeResource(context.getResources(), resourceId); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,92 @@ | ||||
| package clock.socoolby.com.clock.widget.animatorview.animator.view; | ||||
|  | ||||
| import android.graphics.Canvas; | ||||
| import android.graphics.LinearGradient; | ||||
| import android.graphics.Matrix; | ||||
| import android.graphics.Paint; | ||||
| import android.graphics.PorterDuff; | ||||
| import android.graphics.PorterDuffXfermode; | ||||
| import android.graphics.Rect; | ||||
| import android.graphics.Shader; | ||||
|  | ||||
| import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator; | ||||
| import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry; | ||||
|  | ||||
| //参考:https://www.jianshu.com/p/0dda922897cf | ||||
| public class LightningAnimator extends AbstractAnimator<LightningAnimator.Lightning> { | ||||
|  | ||||
|     public LightningAnimator(int entryQuantity) { | ||||
|         super(entryQuantity); | ||||
|     } | ||||
|  | ||||
|     public LightningAnimator() { | ||||
|         super(1); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Lightning createNewEntry() { | ||||
|         return new Lightning(0,0,width,height); | ||||
|     } | ||||
|  | ||||
|     public class Lightning implements I_AnimatorEntry { | ||||
|         private Shader mGradient; | ||||
|         private Matrix mGradientMatrix; | ||||
|         private Paint mPaint1; | ||||
|         private int mViewWidth = 0, mViewHeight = 0; | ||||
|         private float mTranslateX = 0, mTranslateY = 0; | ||||
|         private boolean mAnimating = true; | ||||
|         private Rect rect; | ||||
|  | ||||
|         public Lightning(int left,int top,int mViewWidth,int mViewHeight) { | ||||
|             this.mViewWidth = mViewWidth; | ||||
|             this.mViewHeight = mViewHeight; | ||||
|             rect.set(left, top, mViewWidth, mViewHeight); | ||||
|             init(); | ||||
|         } | ||||
|  | ||||
|         private void init() { | ||||
|             rect = new Rect(); | ||||
|             mPaint1 = new Paint(); | ||||
|  | ||||
|             if (mViewWidth > 0) { | ||||
|                 //亮光闪过 | ||||
|                 mGradient = new LinearGradient(0, 0, mViewWidth / 2, mViewHeight, | ||||
|                         new int[]{0x00ffffff, 0x73ffffff, 0x00ffffff,  0x99ffffff, 0x00ffffff}, | ||||
|                         new float[]{0.2f,       0.35f,      0.5f,        0.7f,      1}, | ||||
|                         Shader.TileMode.CLAMP); | ||||
|                 mPaint1.setShader(mGradient); | ||||
|                 mPaint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN)); | ||||
|                 mGradientMatrix = new Matrix(); | ||||
|                 mGradientMatrix.setTranslate(-2 * mViewWidth, mViewHeight); | ||||
|                 mGradient.setLocalMatrix(mGradientMatrix); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         float step =0;//0-1 | ||||
|  | ||||
|         @Override | ||||
|         public void move(int maxWidth, int maxHight) { | ||||
|             step = step +0.1f; | ||||
|             if(step >1) | ||||
|                 step =0; | ||||
|             //❶ 改变每次动画的平移x、y值,范围是[-2mViewWidth, 2mViewWidth] | ||||
|             mTranslateX = 4 * mViewWidth * step - mViewWidth * 2; | ||||
|             mTranslateY = mViewHeight * step; | ||||
|             //❷ 平移matrix, 设置平移量 | ||||
|             if (mGradientMatrix != null) { | ||||
|                 mGradientMatrix.setTranslate(mTranslateX, mTranslateY); | ||||
|             } | ||||
|             //❸ 设置线性变化的matrix | ||||
|             if (mGradient != null) { | ||||
|                 mGradient.setLocalMatrix(mGradientMatrix); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void onDraw(Canvas canvas, Paint mPaint) { | ||||
|             if (mAnimating && mGradientMatrix != null) { | ||||
|                 canvas.drawRect(rect, mPaint1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -2,18 +2,33 @@ package clock.socoolby.com.clock.widget.textview; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.graphics.Canvas; | ||||
| import android.graphics.Color; | ||||
| import android.graphics.LinearGradient; | ||||
| import android.graphics.Paint; | ||||
| import android.graphics.Shader; | ||||
| import android.text.TextPaint; | ||||
| import android.text.style.ReplacementSpan; | ||||
| import android.util.AttributeSet; | ||||
| import android.util.Log; | ||||
| import androidx.annotation.Nullable; | ||||
|  | ||||
| import java.util.Random; | ||||
|  | ||||
| public class DigitTextView extends android.support.v7.widget.AppCompatTextView { | ||||
|     public static final String Tag=DigitTextView.class.getSimpleName(); | ||||
|  | ||||
|     float baseLineDown=0; | ||||
|  | ||||
|     private LinearGradient mLinearGradient; | ||||
|  | ||||
|     private boolean isLinearGradientAble=false; | ||||
|  | ||||
|     private int shadowType=0;//0:不设置,1:阴影,2:浮雕 | ||||
|  | ||||
|     private int[] linearGradientColors; | ||||
|  | ||||
|     int textWidth=0; | ||||
|  | ||||
|     public DigitTextView(Context context) { | ||||
|         super(context); | ||||
|     } | ||||
| @@ -30,6 +45,76 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { | ||||
|         this.baseLineDown = baseLineDown; | ||||
|     } | ||||
|  | ||||
|     float[]  pos = {0f,0.2f,0.4f,0.5f,0.6f,0.8f,1.0f}; | ||||
|  | ||||
|     boolean isLinearGradientPosAble=false; | ||||
|  | ||||
|     public void setLinearGradientRandom(boolean able){ | ||||
|         if(able){ | ||||
|             linearGradientColors= new int[]{roundColor(), roundColor(), roundColor(), roundColor(), roundColor(), roundColor(), roundColor()}; | ||||
|             isLinearGradientPosAble=rand.nextBoolean(); | ||||
|         } | ||||
|         setLinearGradientAble(able); | ||||
|         setShadowType(rand.nextInt(3)); | ||||
|     } | ||||
|  | ||||
|     public void setLinearGradientAble(boolean able){ | ||||
|         isLinearGradientAble=able; | ||||
|         Paint mTextPaint=getPaint(); | ||||
|         if(isLinearGradientAble){ | ||||
|             setLinearGradient(linearGradientColors); | ||||
|         }else{ | ||||
|             mTextPaint.setShader(null); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void setLinearGradient(int[] colors){ | ||||
|         Paint mTextPaint=getPaint(); | ||||
|         if(isLinearGradientPosAble&&colors.length==pos.length) | ||||
|             mLinearGradient = new LinearGradient(0, 0, getWidth(), getHeight(), colors , pos, Shader.TileMode.CLAMP); | ||||
|         else | ||||
|             mLinearGradient = new LinearGradient(0, 0, getWidth(), 0,colors, null, Shader.TileMode.CLAMP); | ||||
|         mTextPaint.setShader(mLinearGradient); | ||||
|     } | ||||
|  | ||||
|     public void setShadowType(int shadowType){ | ||||
|         this.shadowType=shadowType; | ||||
|         switch (shadowType){ | ||||
|             case 1://阴影效果 | ||||
|                 setShadowLayer(4, 10, 10, Color.BLACK); | ||||
|                 break; | ||||
|             case 2://浮雕效果 | ||||
|                 setShadowLayer(1, 0.5f, 0.5f, Color.argb(200,204,204,204)); | ||||
|                 break; | ||||
|             default: | ||||
|                 setShadowLayer(0,0,0,getPaint().getColor()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public int getShadowType(){ | ||||
|         return shadowType; | ||||
|     } | ||||
|  | ||||
|     public boolean isLinearGradientAble(){ | ||||
|         return isLinearGradientAble; | ||||
|     } | ||||
|  | ||||
|     public boolean isLinearGradientPosAble() { | ||||
|         return isLinearGradientPosAble; | ||||
|     } | ||||
|  | ||||
|     public int[] getLinearGradientColors() { | ||||
|         return linearGradientColors; | ||||
|     } | ||||
|  | ||||
|     public void setLinearGradientPosAble(boolean linearGradientPosAble) { | ||||
|         isLinearGradientPosAble = linearGradientPosAble; | ||||
|     } | ||||
|  | ||||
|     public void setLinearGradientColors(int[] linearGradientColors) { | ||||
|         this.linearGradientColors = linearGradientColors; | ||||
|     } | ||||
|  | ||||
|     protected void onDraw(Canvas canvas) { | ||||
|         int color = getCurrentTextColor(); | ||||
|  | ||||
| @@ -49,13 +134,12 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { | ||||
|         Paint smallCharPaint=null; | ||||
|  | ||||
|         int textLength=textToDraw.length(); | ||||
|         int textWidth=0; | ||||
|         int textSmallSpan=0; | ||||
|  | ||||
|  | ||||
|         if(textLength>4){ | ||||
|             textWidth=baseCharWidth*4+flagCharwidth; | ||||
|         } | ||||
|  | ||||
|         if(textLength>7){ | ||||
|             float fontScale = getResources().getDisplayMetrics().scaledDensity; | ||||
|             smallCharPaint = getCustomTextPaint(mTextPaint,mTextPaint.getTextSize()/fontScale*4/5); | ||||
| @@ -70,12 +154,12 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { | ||||
|  | ||||
|         for(int i=0;i<textLength;i++){ | ||||
|             String c=String.valueOf(textToDraw.charAt(i)); | ||||
|             int charWidth= getCharWidth("8",mTextPaint); | ||||
|             if(i<5){ | ||||
|                 if(i==2){ | ||||
|                     canvas.drawText(c, startX, startY+baseLineDown, mTextPaint); | ||||
|                     startX+=flagCharwidth; | ||||
|                 }else{ | ||||
|                     int charWidth= getCharWidth(c,mTextPaint); | ||||
|                     canvas.drawText(c, startX+(baseCharWidth-charWidth)/2, startY+baseLineDown, mTextPaint); | ||||
|                     startX+=baseCharWidth; | ||||
|                 } | ||||
| @@ -86,7 +170,7 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { | ||||
|                     centerY=centerY+(startY-centerY)/2+smallCharPaint.getFontMetrics().descent; | ||||
|                     canvas.drawText(c, startX, centerY+baseLineDown, smallCharPaint); | ||||
|                     startX+=smallCharWidth; | ||||
|                     Log.d(Tag,"view hight:"+getHeight()+"\t startY:"+startY+"\t text hight:"+textHight+"small text hight:"+smallTextHight); | ||||
|                     //Log.d(Tag,"view hight:"+getHeight()+"\t startY:"+startY+"\t text hight:"+textHight+"small text hight:"+smallTextHight); | ||||
|              } | ||||
|         } | ||||
|     } | ||||
| @@ -249,6 +333,14 @@ public class DigitTextView extends android.support.v7.widget.AppCompatTextView { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static Random rand=new Random(); | ||||
|     public static int roundColor(){ | ||||
|         int alpha = 200; | ||||
|         int r = rand.nextInt(255); | ||||
|         int g = rand.nextInt(255); | ||||
|         int b = rand.nextInt(255); | ||||
|         return alpha << 24 | r << 16 | g << 8 | b; | ||||
|     } | ||||
|  | ||||
|     private static int getCharWidth(String str, Paint paint){ | ||||
|         return (int)paint.measureText(str); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user