編輯:關於Android編程
穿插一篇自定義view 的動畫效果,偶然看到的一個gif刷新齒輪效果圖片,原圖如下:
感覺挺有意思的,就想自己也做一個,發費了一番功夫,算是做出了基本效果,但原諒我使其美觀盡毀,做出的效果如下:
gif錄制有些掉幀
好了,放源碼了:
public class GearView extends View { private Context context; private Paint paint; private float PI = 3.1415926f; private int circleGrade = 1;//圓的齒輪個數 9+circleGrade 個 private float gearWidth = 40; private float gearHeight = 50; private float length = 60;//弧長 private Listcircles;//存儲圓的參數 private Map bitmaps;//把已經繪制好的bitmap存儲起來,循環利用 private int speedArgu = 20;//旋轉速度參數 private int viewWidth;//所在view 的寬度 private int viewHeight;//所在view 的高度 private boolean startRotato = true;//是否開始動畫 private int r1; private int r2; private int r3; private int r4; private int r5; private float fTran = 0;//平移基本數 private float translationArgu = 4.0f;//平移乘數 private float fRotate = 0;//平移後中心旋轉基本數 private float transientRotate = 70.0f;//平移後中心旋轉乘數 private float scale = 0.001f;//平移後中心縮放 程度 private float scaleBase = 1.0f;//平移後中心縮放基本數 public boolean isStartRotato() { return startRotato; } public void setStartRotato(boolean startRotato) { this.startRotato = startRotato; } public int getSpeedArgu() { return speedArgu; } public void setSpeedArgu(int speedArgu) { if(speedArgu > 70){ speedArgu = 70; } if(speedArgu < 5 && speedArgu > 0){ speedArgu = 5; } if(speedArgu < -70){ speedArgu = -70; } if(speedArgu <0 && speedArgu > -5){ speedArgu = -5; } this.speedArgu = speedArgu; } public GearView(Context context) { super(context); this.context = context; init(); } public GearView(Context context, AttributeSet attrs) { super(context, attrs); context = context; init(); } public GearView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); context = context; init(); } private void init() { paint = new Paint(); paint.setAntiAlias(false); bitmaps = new HashMap (); circles = new ArrayList (); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.viewHeight = h; this.viewWidth = w; initCircle(); } private void initCircle() { float centerX = viewWidth/2; float centerY = viewHeight/2; //添加圓和設置位置,在此處添加和修改即可 r1 = 3; // float c1Top = centerY-getRaidus(r1) * 2; float c1Top = centerY-getRaidus(r1) -20; float c1Left = centerX-getRaidus(r1) * 2; int color1 = getResources().getColor(R.color.colorGear1); Circle circle = new Circle(c1Top,c1Left,getRaidus(r1), false,0,0,color1); circles.add(circle); r2 = 8; updataHeight(r2); float c2Top = c1Top + getRaidus(r2) + gearHeight; float c2Left = c1Left - getRaidus(r2) - gearHeight; int color2 = getResources().getColor(R.color.colorGear2); circle = new Circle(c2Top ,c2Left, getRaidus(r2), true,0,3, color2); circles.add(circle); r3 = 18; updataHeight(r3); float c3Top = c2Top - getRaidus(r3) -getRaidus(r2) - gearHeight + 5; float c3Left = c2Left - getRaidus(r3) - getRaidus(r2)- gearHeight + 5; int color3 = getResources().getColor(R.color.colorGear3); circle = new Circle(c3Top ,c3Left, getRaidus(r3), false,0,6, color3); circles.add(circle); r4 = 11; updataHeight(r4); float c4Top = c1Top - getRaidus(r4) - gearHeight - getRaidus(r1); float c4Left = c1Left + getRaidus(r4) + gearHeight - getRaidus(r1); int color4 = getResources().getColor(R.color.colorGear4); circle = new Circle(c4Top ,c4Left, getRaidus(r4), true,0,-5, color4); circles.add(circle); r5 = 16; updataHeight(r5); float c5Top = c4Top +getRaidus(r5) + gearHeight + 10 ; float c5Left = c4Left + getRaidus(r5)+ gearHeight +10 ; int color5 = getResources().getColor(R.color.colorGear5); circle = new Circle(c5Top ,c5Left, getRaidus(r5), false,0,2, color5); circles.add(circle); } /** * 供外部調用旋轉 * */ public void startRotato(float dy){ int speed = (int) (dy * 4); setSpeedArgu(speed); startRotato = true; isTranslation = false; if((speed < 20 && speed >0) || (speed < 0 && speed > -20)){ speed = 20; } if(speed <= -20){ speed = Math.abs(speed); } if(speed > 100 || speed < -100){ speed = 100; } for(int i = 0;i 0.01f && scale <0.03f){ scaleBase = scaleBase -scale +0.01f; } matrix.postScale(scaleBase,scaleBase); matrix.postTranslate(circle.getLeft() + offsetX, circle.getTop() + offsetY); canvas.drawBitmap(bitmap,matrix,null); fTran+=1.0f * translationArgu; Bitmap bitmap1 = bitmaps.get(getRaidus(r2)); Matrix matrix1 = new Matrix(); Circle circle1 = circles.get(1); matrix1.postTranslate(circle1.getLeft()-fTran,circle1.getTop()+fTran); canvas.drawBitmap(bitmap1,matrix1,null); Bitmap bitmap2 = bitmaps.get(getRaidus(r3)); Matrix matrix2 = new Matrix(); Circle circle2 = circles.get(2); matrix2.postTranslate(circle2.getLeft()-fTran,circle2.getTop()-fTran); canvas.drawBitmap(bitmap2,matrix2,null); Bitmap bitmap3 = bitmaps.get(getRaidus(r4)); Matrix matrix3 = new Matrix(); Circle circle3 = circles.get(3); matrix3.postTranslate(circle3.getLeft()+fTran,circle3.getTop()-fTran); canvas.drawBitmap(bitmap3,matrix3,null); Bitmap bitmap4 = bitmaps.get(getRaidus(r5)); Matrix matrix4 = new Matrix(); Circle circle4 = circles.get(4); matrix4.postTranslate(circle4.getLeft()+fTran,circle4.getTop()+fTran); canvas.drawBitmap(bitmap4,matrix4,null); } /*繪制圓的動畫效果*/ private void drawCircle(Canvas canvas, Circle circle) { float top = circle.getTop(); float left = circle.getLeft(); float radius = circle.getRaidus(); boolean isClockwise = circle.isClockwise(); float speed = circle.getSpeed(); canvas.drawColor(Color.TRANSPARENT); Paint paint = new Paint(this.paint); paint.setColor(Color.YELLOW); Bitmap trapezoidBitmap = getTrapezoidBitmap(circle, paint); Matrix matrix = new Matrix(); int offsetX = trapezoidBitmap.getWidth() / 2; int offsetY = trapezoidBitmap.getHeight() / 2; matrix.postTranslate(-offsetX, -offsetY); if (isClockwise) { matrix.postRotate(speed+circle.getStartDegree()); } else { matrix.postRotate(-speed+circle.getStartDegree()); } float degree = getDegree(0.1f * speedArgu, radius); speed += degree; circle.setSpeed(speed); matrix.postTranslate(left + offsetX, top + offsetY); canvas.drawBitmap(trapezoidBitmap, matrix, null); } /*繪制圓*/ private Bitmap getTrapezoidBitmap(Circle circle, Paint paint) { float radius = circle.getRaidus(); if(bitmaps == null){ bitmaps = new HashMap (); } Bitmap bitmap = bitmaps.get(radius); if (bitmap != null) { return bitmap; } Bitmap bitmapTmp = Bitmap.createBitmap((int) (radius * 2 + gearHeight * 2), (int) (radius * 2 + gearHeight * 2), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmapTmp); canvas.drawColor(Color.TRANSPARENT); canvas.translate(bitmapTmp.getWidth() / 2, bitmapTmp.getHeight() / 2); /* 設置漸變色 */ /*Shader mShader = new LinearGradient(0, 0, 100, 100, new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.LTGRAY}, null, Shader.TileMode.REPEAT); // 一個材質,打造出一個線性梯度沿著一條線。 paint.setShader(mShader);*/ paint.setColor(circle.getColor()); canvas.drawCircle(0, 0, radius, paint); drawGear(canvas,circle, paint); bitmaps.put(radius,bitmapTmp); return bitmapTmp; } /*在圓上畫齒輪*/ private void drawGear(Canvas canvas, Circle circle, Paint paint) { updataHeight(circle.getRaidus()); float radius = circle.getRaidus(); Path path = new Path(); path.moveTo(-(gearWidth / 2), -radius + 5); path.lineTo(gearWidth / 2, -radius + 5); path.lineTo(gearWidth / 2 - 10, -radius - gearHeight + 10); path.lineTo(-(gearWidth / 2 - 10), -radius - gearHeight + 10); path.lineTo(-(gearWidth / 2), -radius + 5); int num = (int) (360 / getDegree(length, radius)); Paint p = new Paint(paint); p.setColor(circle.getColor()); for (int i = 0; i <= num; i++) { canvas.drawPath(path, p); canvas.rotate(getDegree(length, radius)); } canvas.save(); } private void updataHeight(float radius) { gearHeight = radius/4f; if(gearHeight<35){ gearHeight = 35; } else if(gearHeight > 50){ gearHeight = 50; } } /** * 由弧長獲取度數 */ public float getDegree(float length, float r) { float degree = 360 * length / (2 * PI * r); return degree; } public float getPerimeter(float r) { float perimeter = 2 * PI * r; return perimeter; } /** * 對圓的半徑有要求 * * @param multiple * @return */ public float getRaidus(int multiple) { int gearNum = 5; gearNum += multiple;//gearNum代表圓上齒輪的個數 float f1 = length * gearNum; float f = f1 / (2 * PI); return f; } public void setGear(int gear) { gearHeight = gearHeight + gear*3; } class Circle { float top;//頂部坐標 float left;//左側坐標 float raidus;//半徑 float speed;//旋轉速度 boolean clockwise;//旋轉方向 float gearWidth; float gearHeight; float startDegree;//起始角度 private int color; public int getColor() { return color; } public void setColor(int color) { this.color = color; } public float getStartDegree() { return startDegree; } public void setStartDegree(float startDegree) { this.startDegree = startDegree; } public float getGearWidth() { return gearWidth; } public void setGearWidth(float gearWidth) { this.gearWidth = gearWidth; } public float getGearHeight() { return gearHeight; } public void setGearHeight(float gearHeight) { this.gearHeight = gearHeight; } public Circle(float top, float left, float raidus, boolean clockwise, float speed, float startDegree, int color) { this.left = left; this.top = top; this.raidus = raidus; this.clockwise = clockwise; this.speed = speed; this.startDegree = startDegree; this.color = color; } public boolean isClockwise() { return clockwise; } public void setClockwise(boolean clockwise) { this.clockwise = clockwise; } public float getTop() { return top; } public void setTop(float top) { this.top = top; } public float getLeft() { return left; } public void setLeft(float left) { this.left = left; } public float getRaidus() { return raidus; } public void setRaidus(float raidus) { this.raidus = raidus; } public float getSpeed() { return speed; } public void setSpeed(float speed) { this.speed = speed; } } }
最近做的項目有個需求就是判斷一下還 剩多少字符可輸入,也就是對EditText 的文本變化做監聽 ,功能實現了,但是感覺使用組合方式,每次都要編寫,還不如寫
前言?android5.X新增的一個控件Toolbar,這個控件比ActionBar更加自由,可控,由於以前的ActionBar的靈活性比較差,所以google逐漸使用T
具體代碼如下:main.xml復制代碼 代碼如下:<LinearLayout xmlns:android=http://schemas.android.com/ap
前言: 最近一直在看Launcher模塊,經過差不多兩個月學習,終於摸透了Launcher的一些主要功能實現,目前繼續還處於摸索狀態。未看Launcher時,於我而言,只