Github

Making address: https://github.com/Bigmercu/ACheckBox welcome star and issue.

The animation part

Do two kinds of animation can choose

hook

Use pathMeasure implementation

pathMeasure

  • setPathCan I do forpathMeasureSetting a path
  • getLength()You can getpathMeasureThe total length of the

A pathMeasure is very simple. It first adds a path to a pathMeasure and then retrieves a segment through getSegment.

mPath = new Path();
pathMeasure = new PathMeasure();
mPath.addRect(wStart,hStart,wSize + wStart,hSize + hStart, Path.Direction.CW);
pathMeasure.setPath(mPath,true);
pathLenth = pathMeasure.getLength();Copy the code

The power of animation

Send some number, it could be the Angle you want to change, it could be a length, it could be any number change you can think of. Given the interpolator setInterpolator and the duration setDuration, they will wait for the theme to be fired.

valueAnimator = ValueAnimator.ofInt(255, 0); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator  animation) { AnimationValue = (int) animation.getAnimatedValue(); }); valueAnimator1 = ValueAnimator.ofInt(180, 225); valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { AnimationValue1 = (int) animation.getAnimatedValue(); }); valueAnimator2 = ValueAnimator.ofFloat(hSize + wSize, wSize * 2 / 5); valueAnimator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { AnimationValue2 = (float) animation.getAnimatedValue(); }); valueAnimator3 = ValueAnimator.ofFloat(hSize + wSize, hSize + wSize * 2); valueAnimator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { AnimationValue3 = (float) animation.getAnimatedValue(); });Copy the code

onDraw

First, I wanted to get the padding behind it, because it would be too crowded without the padding, so I added a 10px padding by default

int paddingLeft = getPaddingLeft() + 10;
int paddingRight = getPaddingRight() + 10;
int paddingTop = getPaddingTop() + 10;
int paddingBottom = getPaddingBottom() + 10;Copy the code

Then all we need to do is draw, because the pathMeasure itself has a bug, so the first step is required

mDst.reset(); MDst. LineTo (0, 0);Copy the code


  • I saved the canvas for laterrestoreLet’s draw a border
  • I’m going to move the canvas coordinates so that I have the padding,drawTextDraw the text section.
  • For the CW rectangle:pathMeasure.getSegment(0)Is the bottom right corner of the rectangle, increase to the left and then up…
  • I get the parts I need to draw in several segments, using two brushesmPaintandmPaintAfterALPHA property change to make the entire animation color change.
  • The lastcanvas.restore();Restore the previously saved canvas state and draw the border if required
MDst. LineTo (0, 0); canvas.translate(wStart + paddingLeft, hStart + paddingTop); if(isShowBorder) { canvas.save(); canvas.drawText(boxText, wStart + wSize + 18, (hSize + textSize )/2, mPaintText); Canvas. Translate (-animationValue4 * wSize, (float) (-animationValue4 * hSize * 1.5)); * If startWithMoveTo is true, the truncated Path fragment remains unchanged. If startWithMoveTo is false, * moves the truncated Path fragment's starting point to the last point in the DST. To ensure DST continuity. * */ pathMeasure.getSegment(AnimationValue3, pathLenth, mDst, true); pathMeasure.getSegment(0, wSize * 2 / 5, mDst, true); pathMeasure.getSegment(wSize * 2 / 5, AnimationValue2, mDst, true); mPaint.setAlpha(AnimationValue); mPaintAfter.setAlpha(255 - AnimationValue); canvas.rotate(AnimationValue1, wStart + wSize / 2, hStart + hSize / 2); canvas.drawPath(mDst, mPaint); canvas.drawPath(mDst, mPaintAfter); if(isShowBorder) { canvas.restore(); canvas.drawRect(wStart, hStart, wStart + wSize, hSize + hStart, mPaintText);Copy the code

Finally, start all valueAnimators and postInvalidate(); Can.

fork

Use valueAnimator implementation This is simple, I use a valueAnimator to radiate the radius of a rectangle by calculating the positions of the four corners of the rectangle, connecting the top left corner of the rectangle, the top midpoint (Y axis adds valueAnimator), the top right corner, the right midpoint (X axis reduces valueAnimator), the bottom right corner… You end up with an animation where the rectangle changes to a cross. Also be careful with the padding, custom views don’t do the padding for you, you don’t do the padding for you.

MDst. LineTo (0, 0); canvas.translate(wStart+ paddingLeft , hStart + paddingTop ); if(isShowBorder) { canvas.save(); canvas.drawText(boxText, wStart + wSize + 18, (hSize + textSize )/2, mPaintText); Mdst.moveto ((float) (wStart + cAnimationValue * 0.3), (float) (hStart + cAnimationValue * 0.3)); Mdst. lineTo(wStart + wSize/2, (float) (hStart + cAnimationValue + cAnimationValue * 0.2)); Mdst. lineTo((float) (wStart+ wSize - cAnimationValue * 0.2), (float) (hStart + cAnimationValue * 0.2)); Mdst. lineTo((float) (wStart+ wSize -cAnimationValue -cAnimationValue * 0.2),hSize/2 + hStart); Mdst. lineTo((float) (wStart+ wsize-canimationValue * 0.2), (float) (hStart + hsize-canimationValue * 0.2)); Mdst. lineTo(wStart+ wSize/2, (float) (hStart + hSize - cAnimationValue - cAnimationValue * 0.2)); Mdst. lineTo((float) (wStart + cAnimationValue * 0.2), (float) (hStart + hSize - cAnimationValue * 0.2)); Mdst. lineTo((float) (wStart + cAnimationValue + cAnimationValue * 0.2),hStart + hSize/2); Mdst.lineto ((float) (wStart + cAnimationValue * 0.3), (float) (hStart + cAnimationValue * 0.3)); mPaint.setAlpha((int) cAnimationValue2); canvas.drawPath(mDst,mPaint); mPaintAfter.setAlpha((int) (255-cAnimationValue2)); canvas.drawPath(mDst,mPaintAfter); if(isShowBorder) { canvas.restore(); canvas.drawRect(wStart, hStart, wStart + wSize, hSize + hStart, mPaintText);Copy the code

Wrap_content processing

Rewrite onMeasure to calculate the width and height of the View, set different dimensions according to different SpecMode, and finally achieve the effect of WRAP_content. In this:

  • My View width is :2 ‘strokeWidth + wStart + wSize + 20 + paddingLeft + textSize boxText.length()’ 2 times border width + left margin + rectangle width + 20 is the distance between the word and the border + the padding + the string width

  • My View height is :hStart + hSize + paddingTop + paddingBottom + 2 * strokeWidth Top margin + top width + rectangle height + bottom padding + 2 times border width

Once you have the width and height of these two views, you can go into wrap_content.

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int paddingLeft = getPaddingLeft() + 10; int paddingRight = getPaddingRight() + 10; int paddingTop = getPaddingTop() + 10; int paddingBottom = getPaddingBottom() + 10; if(widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){ setMeasuredDimension(2* strokeWidth +  wStart + wSize + 20 + paddingLeft + textSize * boxText.length(),hStart + hSize + paddingTop + paddingBottom + 2 * strokeWidth); Log.d(TAG, wStart+" "+ wSize +" "+ textSize * boxText.length() + " " +boxText.length()); }else if(widthSpecMode == MeasureSpec.AT_MOST){ setMeasuredDimension(2* strokeWidth +wStart + wSize + paddingLeft + 20 +  textSize * boxText.length(),widthSpecSize); }else if(heightSpecMode == MeasureSpec.AT_MOST){ setMeasuredDimension(heightSpecSize,hStart + hSize + paddingTop + paddingBottom+ 2 * strokeWidth);Copy the code

The effect









Upload Jcenter

Classpath 'com. Jfrog. Bintray. Gradle: gradle bintray - plugin: 1.7.1' classpath 'com. Making. Dcendents: android - maven - gradle - plugin: 1.4.1'Copy the code
  • Insert it under the original code in build.gradle of the module you want to upload
apply plugin: 'com.github.dcendents.android-maven' apply plugin: '. Com. Jfrog bintray version = "1.05" / / version number def siteUrl = "https://github.com/Bigmercu/ACheckBox" / / def gitUrl = to upload the project home page [email protected]: Bigmercu/ACheckBox. "git" / / git to upload the project address group = "com. Bigmercu. The checkbox" / / package name directly related to the last generation of gradle connect install { repositories.mavenInstaller { // This generates POM.xml with proper parameters pom { project { packaging 'aar' name 'This is a simple checkbox with cool animation for android by bigmercu.' url siteUrl licenses { license { name 'The Apache Software License, Version 2.0 'url' http://www.apache.org/licenses/LICENSE-2.0.txt 'developers {developer {id "bigmercu" / / bintray.com Id name "Wallace" // Your bintray.com name email "[email protected]" SCM {connection gitUrl developerConnection gitUrl url siteUrl task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir artifacts { archives javadocJar archives sourcesJar Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) bintray { user = properties.getProperty("bintray.user") key = properties.getProperty("bintray.apikey") configurations = ['archives'] pkg {repo = "maven" name = "bCheckbox" // Project name websiteUrl = siteUrl vcsUrl = gitUrl licenses = [" apache-2.0 "] publish = trueCopy the code
  • Insert your information in local.propreties in the project root directory
Bintray. user= your ID Bintray. apiKey = your keyCopy the code

Step 2 Run the task as instructed

Be sure to follow all the steps successfully

  • javadocjar
  • sourcesjar
  • install
  • bintrayUpload

The following figure





There is basically no problem if there is no error in operation. Bintray has been successfully uploaded. It is easy to add jCenter and so on.