16 | * Created by androidcjj on 2016/4/1. 17 | */ 18 | public class JJSearchView extends View { 19 | private Paint mPaint; 20 | private Path mPath; 21 | private JJBaseController mController = new JJChangeArrowController(); 22 | 23 | public JJSearchView(Context context) { 24 | this(context, null); 25 | } 26 | 27 | public JJSearchView(Context context, AttributeSet attrs) { 28 | this(context, attrs, 0); 29 | } 30 | 31 | public JJSearchView(Context context, AttributeSet attrs, int defStyleAttr) { 32 | super(context, attrs, defStyleAttr); 33 | init(); 34 | } 35 | 36 | private void init() { 37 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 38 | mPaint.setStrokeWidth(4); 39 | 40 | mPath = new Path(); 41 | } 42 | 43 | public void setController(JJBaseController controller) { 44 | this.mController = controller; 45 | mController.setSearchView(this); 46 | invalidate(); 47 | } 48 | 49 | @Override 50 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 51 | super.onSizeChanged(w, h, oldw, oldh); 52 | } 53 | 54 | @Override 55 | protected void onDraw(Canvas canvas) { 56 | super.onDraw(canvas); 57 | mController.draw(canvas, mPaint); 58 | } 59 | 60 | public void startAnim() { 61 | if (mController != null) 62 | mController.startAnim(); 63 | } 64 | 65 | public void resetAnim() { 66 | if (mController != null) 67 | mController.resetAnim(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/src/main/java/com/cjj/sva/anim/controller/JJScaleCircleAndTailController.java: -------------------------------------------------------------------------------- 1 | package com.cjj.sva.anim.controller; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | 7 | import com.cjj.sva.anim.JJBaseController; 8 | 9 | /** 10 | * 这是一个神奇的类,SearchView可以放大缩小,别私用哦! 11 | * 12 | * Created by androidcjj on 2016/4/2. 13 | */ 14 | public class JJScaleCircleAndTailController extends JJBaseController { 15 | private String mColor = "#2196F3"; 16 | private int cx, cy, cr, scr; 17 | 18 | @Override 19 | public void draw(Canvas canvas, Paint paint) { 20 | switch (mState) { 21 | case STATE_ANIM_NONE: 22 | drawNormalView(paint, canvas); 23 | break; 24 | case STATE_ANIM_START: 25 | drawStartAnimView(paint, canvas); 26 | break; 27 | case STATE_ANIM_STOP: 28 | drawStopAnimView(paint, canvas); 29 | break; 30 | } 31 | } 32 | 33 | private void drawStopAnimView(Paint paint, Canvas canvas) { 34 | drawNormalView(paint, canvas); 35 | drawSearchView(paint, canvas, false); 36 | } 37 | 38 | private void drawStartAnimView(Paint paint, Canvas canvas) { 39 | drawNormalView(paint, canvas); 40 | drawSearchView(paint, canvas, true); 41 | } 42 | 43 | private void drawSearchView(Paint paint, Canvas canvas, boolean start) { 44 | drawNormalView(paint, canvas); 45 | paint.setStyle(Paint.Style.FILL); 46 | canvas.drawCircle(cx, cy, (cr - 25) * (start ? 47 | mPro : 1 - mPro), paint); 48 | canvas.rotate(130, cx, cy); 49 | 50 | canvas.save(); 51 | paint.setColor(Color.WHITE); 52 | paint.setStrokeWidth(25); 53 | canvas.drawLine(cx + cr/2 + cr/2 * (start ? mPro : 1 - mPro) 54 | + 20, cy, (cx + cr + getWidth() / 5 * 55 | (start ? mPro : 1 - mPro)), cy, paint); 56 | canvas.restore(); 57 | } 58 | 59 | private void drawNormalView(Paint paint, Canvas canvas) { 60 | cr = getWidth() / 6; 61 | cx = getWidth() / 2; 62 | cy = getHeight() / 2; 63 | scr = getWidth() / 18; 64 | 65 | canvas.drawColor(Color.parseColor(mColor)); 66 | paint.reset(); 67 | paint.setAntiAlias(true); 68 | paint.setColor(Color.WHITE); 69 | canvas.drawCircle(cx, cy, cr, paint); 70 | 71 | canvas.save(); 72 | paint.setColor(Color.parseColor(mColor)); 73 | paint.setStrokeWidth(10); 74 | paint.setStyle(Paint.Style.STROKE); 75 | canvas.rotate(130, cx, cy); 76 | canvas.drawLine(cx + scr + 10, cy, cx + scr * 2, cy, paint); 77 | canvas.drawCircle(cx, cy, scr, paint); 78 | canvas.restore(); 79 | } 80 | 81 | @Override 82 | public void startAnim() { 83 | if (mState == STATE_ANIM_START) return; 84 | mState = STATE_ANIM_START; 85 | startSearchViewAnim(); 86 | } 87 | 88 | @Override 89 | public void resetAnim() { 90 | if (mState == STATE_ANIM_STOP) return; 91 | mState = STATE_ANIM_STOP; 92 | startSearchViewAnim(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/cjj/jjsearchviewanim/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.cjj.jjsearchviewanim; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.Menu; 6 | import android.view.MenuItem; 7 | import android.view.View; 8 | 9 | import com.cjj.sva.JJSearchView; 10 | import com.cjj.sva.anim.controller.JJAroundCircleBornTailController; 11 | import com.cjj.sva.anim.controller.JJBarWithErrorIconController; 12 | import com.cjj.sva.anim.controller.JJChangeArrowController; 13 | import com.cjj.sva.anim.controller.JJCircleToBarController; 14 | import com.cjj.sva.anim.controller.JJCircleToLineAlphaController; 15 | import com.cjj.sva.anim.controller.JJCircleToSimpleLineController; 16 | import com.cjj.sva.anim.controller.JJDotGoPathController; 17 | import com.cjj.sva.anim.controller.JJScaleCircleAndTailController; 18 | 19 | public class MainActivity extends AppCompatActivity { 20 | JJSearchView mJJSearchView; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_main); 26 | mJJSearchView = (JJSearchView) findViewById(R.id.jjsv); 27 | mJJSearchView.setController(new JJChangeArrowController()); 28 | } 29 | 30 | public void start(View v) { 31 | mJJSearchView.startAnim(); 32 | } 33 | 34 | public void reset(View v) { 35 | mJJSearchView.resetAnim(); 36 | } 37 | 38 | @Override 39 | public boolean onCreateOptionsMenu(Menu menu) { 40 | // Inflate the menu; this adds items to the action bar if it is present. 41 | getMenuInflater().inflate(R.menu.menu_main, menu); 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean onOptionsItemSelected(MenuItem item) { 47 | // Handle action bar item clicks here. The action bar will 48 | // automatically handle clicks on the Home/Up button, so long 49 | // as you specify a parent activity in AndroidManifest.xml. 50 | int id = item.getItemId(); 51 | 52 | switch (id) { 53 | case R.id.action1: 54 | mJJSearchView.setController(new JJAroundCircleBornTailController()); 55 | break; 56 | case R.id.action2: 57 | mJJSearchView.setController(new JJBarWithErrorIconController()); 58 | break; 59 | case R.id.action3: 60 | mJJSearchView.setController(new JJChangeArrowController()); 61 | break; 62 | case R.id.action4: 63 | mJJSearchView.setController(new JJCircleToBarController()); 64 | break; 65 | case R.id.action5: 66 | mJJSearchView.setController(new JJCircleToLineAlphaController()); 67 | break; 68 | case R.id.action6: 69 | mJJSearchView.setController(new JJCircleToSimpleLineController()); 70 | break; 71 | case R.id.action7: 72 | mJJSearchView.setController(new JJDotGoPathController()); 73 | break; 74 | case R.id.action8: 75 | mJJSearchView.setController(new JJScaleCircleAndTailController()); 76 | break; 77 | } 78 | 79 | return super.onOptionsItemSelected(item); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /library/src/main/java/com/cjj/sva/anim/controller/JJCircleToLineAlphaController.java: -------------------------------------------------------------------------------- 1 | package com.cjj.sva.anim.controller; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.graphics.RectF; 7 | 8 | import com.cjj.sva.anim.JJBaseController; 9 | 10 | /** 11 | * 这是一个神奇的类,searchview释放外面的圈圈,呼吸新鲜空气! 12 | * 13 | * Created by androidcjj on 2016/4/2. 14 | */ 15 | public class JJCircleToLineAlphaController extends JJBaseController { 16 | private String mColor = "#673AB7"; 17 | private int cx, cy, cr; 18 | private RectF mRectF, mRectF2; 19 | private float sign = 0.707f; 20 | private float tran = 120; 21 | 22 | public JJCircleToLineAlphaController() { 23 | mRectF = new RectF(); 24 | mRectF2 = new RectF(); 25 | } 26 | 27 | @Override 28 | public void draw(Canvas canvas, Paint paint) { 29 | canvas.drawColor(Color.parseColor(mColor)); 30 | switch (mState) { 31 | case STATE_ANIM_NONE: 32 | drawNormalView(paint, canvas); 33 | break; 34 | case STATE_ANIM_START: 35 | drawStartAnimView(paint, canvas); 36 | break; 37 | case STATE_ANIM_STOP: 38 | drawStopAnimView(paint, canvas); 39 | break; 40 | } 41 | } 42 | 43 | private void drawStopAnimView(Paint paint, Canvas canvas) { 44 | canvas.save(); 45 | if (mPro > 0.7) { 46 | paint.setAlpha((int) (mPro * 255)); 47 | drawNormalView(paint, canvas); 48 | } 49 | canvas.restore(); 50 | } 51 | 52 | private void drawStartAnimView(Paint paint, Canvas canvas) { 53 | canvas.save(); 54 | canvas.drawLine(mRectF.left + cr + (cr * sign), mRectF.top + cr + (cr * sign), 55 | mRectF.left + cr + (2 * cr * sign), mRectF.top + cr + (2 * cr * sign), paint); 56 | canvas.drawArc(mRectF, 0, 360, false, paint); 57 | canvas.drawArc(mRectF2, 90, -360 * (1 - mPro), false, paint); 58 | if (mPro >= 0.7f) { 59 | canvas.drawLine((1 - mPro + 0.7f) * (mRectF2.right - 3 * cr), mRectF2.bottom, 60 | (mRectF2.right - 3 * cr), mRectF2.bottom, paint); 61 | } 62 | canvas.restore(); 63 | mRectF.left = cx - cr + tran * mPro; 64 | mRectF.right = cx + cr + tran * mPro; 65 | mRectF2.left = cx - 3 * cr + tran * mPro; 66 | mRectF2.right = cx + 3 * cr + tran * mPro; 67 | } 68 | 69 | private void drawNormalView(Paint paint, Canvas canvas) { 70 | cr = getWidth() / 50; 71 | cx = getWidth() / 2; 72 | cy = getHeight() / 2; 73 | mRectF.left = cx - cr; 74 | mRectF.right = cx + cr; 75 | mRectF.top = cy - cr; 76 | mRectF.bottom = cy + cr; 77 | 78 | mRectF2.left = cx - 3 * cr; 79 | mRectF2.right = cx + 3 * cr; 80 | mRectF2.top = cy - 3 * cr; 81 | mRectF2.bottom = cy + 3 * cr; 82 | 83 | canvas.save(); 84 | paint.reset(); 85 | paint.setAntiAlias(true); 86 | paint.setColor(Color.WHITE); 87 | paint.setStrokeWidth(4); 88 | paint.setStyle(Paint.Style.STROKE); 89 | 90 | canvas.rotate(45, cx, cy); 91 | canvas.drawLine(cx + cr, cy, cx + cr * 2, cy, paint); 92 | canvas.drawArc(mRectF, 0, 360, false, paint); 93 | canvas.drawArc(mRectF2, 0, 360, false, paint); 94 | canvas.restore(); 95 | } 96 | 97 | @Override 98 | public void startAnim() { 99 | if (mState == STATE_ANIM_START) return; 100 | mState = STATE_ANIM_START; 101 | startSearchViewAnim(); 102 | } 103 | 104 | @Override 105 | public void resetAnim() { 106 | if (mState == STATE_ANIM_STOP) return; 107 | mState = STATE_ANIM_STOP; 108 | startSearchViewAnim(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /library/src/main/java/com/cjj/sva/anim/controller/JJCircleToSimpleLineController.java: -------------------------------------------------------------------------------- 1 | package com.cjj.sva.anim.controller; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.graphics.RectF; 7 | 8 | import com.cjj.sva.anim.JJBaseController; 9 | 10 | /** 11 | * 这是一个神奇的类,SearchView变成一条线,然而并没有什么卵用! 12 | *
13 | * Created by androidcjj on 2016/4/2. 14 | */ 15 | public class JJCircleToSimpleLineController extends JJBaseController { 16 | private String mColor = "#4CAF50"; 17 | private int cx, cy, cr; 18 | private RectF mRectF; 19 | private int j = 10; 20 | 21 | public JJCircleToSimpleLineController() { 22 | mRectF = new RectF(); 23 | } 24 | 25 | @Override 26 | public void draw(Canvas canvas, Paint paint) { 27 | canvas.drawColor(Color.parseColor(mColor)); 28 | switch (mState) { 29 | case STATE_ANIM_NONE: 30 | drawNormalView(paint, canvas); 31 | break; 32 | case STATE_ANIM_START: 33 | drawStartAnimView(paint, canvas); 34 | break; 35 | case STATE_ANIM_STOP: 36 | drawStopAnimView(paint, canvas); 37 | break; 38 | } 39 | } 40 | 41 | private void drawStopAnimView(Paint paint, Canvas canvas) { 42 | canvas.save(); 43 | canvas.drawLine((mRectF.right + cr - j) * (mPro >= 0.2f ? mPro : 0.2f), 44 | mRectF.bottom + cr - j, mRectF.right + cr - j, mRectF.bottom + cr - j, paint); 45 | if (mPro > 0.5f) { 46 | canvas.drawArc(mRectF, 45, -((mPro - 0.5f) * 360 * 2), false, paint); 47 | canvas.drawLine(mRectF.right - j, mRectF.bottom - j, 48 | mRectF.right + cr - j, mRectF.bottom + cr - j, paint); 49 | } else { 50 | canvas.drawLine(mRectF.right - j + cr * (1 - mPro), mRectF.bottom - j + 51 | cr * (1 - mPro), mRectF.right + cr - j, mRectF.bottom + cr - j, paint); 52 | } 53 | canvas.restore(); 54 | mRectF.left = cx - cr + 240 * (1 - mPro); 55 | mRectF.right = cx + cr + 240 * (1 - mPro); 56 | mRectF.top = cy - cr; 57 | mRectF.bottom = cy + cr; 58 | } 59 | 60 | private void drawStartAnimView(Paint paint, Canvas canvas) { 61 | canvas.save(); 62 | if (mPro <= 0.5f) { 63 | canvas.drawArc(mRectF, 45, -(360 - 360 * 2 * (mPro == -1 ? 1 : mPro)), false, paint); 64 | canvas.drawLine(mRectF.right - j, mRectF.bottom - j, 65 | mRectF.right + cr - j, mRectF.bottom + cr - j, paint); 66 | } else { 67 | canvas.drawLine(mRectF.right - j + cr * mPro, mRectF.bottom - j + cr * mPro, 68 | mRectF.right + cr - j, mRectF.bottom + cr - j, paint); 69 | } 70 | 71 | canvas.drawLine((mRectF.right + cr - j) * (1 - mPro * .8f), mRectF.bottom + cr - j, 72 | mRectF.right + cr - j, mRectF.bottom + cr - j, paint); 73 | canvas.restore(); 74 | 75 | mRectF.left = cx - cr + 240 * mPro; 76 | mRectF.right = cx + cr + 240 * mPro; 77 | mRectF.top = cy - cr; 78 | mRectF.bottom = cy + cr; 79 | } 80 | 81 | private void drawNormalView(Paint paint, Canvas canvas) { 82 | cr = getWidth() / 24; 83 | cx = getWidth() / 2; 84 | cy = getHeight() / 2; 85 | mRectF.left = cx - cr; 86 | mRectF.right = cx + cr; 87 | mRectF.top = cy - cr; 88 | mRectF.bottom = cy + cr; 89 | 90 | canvas.save(); 91 | 92 | paint.reset(); 93 | paint.setAntiAlias(true); 94 | paint.setColor(Color.WHITE); 95 | paint.setStrokeWidth(4); 96 | paint.setStyle(Paint.Style.STROKE); 97 | 98 | canvas.rotate(45, cx, cy); 99 | canvas.drawLine(cx + cr, cy, cx + cr * 2, cy, paint); 100 | canvas.drawArc(mRectF, 0, 360, false, paint); 101 | canvas.restore(); 102 | } 103 | 104 | @Override 105 | public void startAnim() { 106 | if (mState == STATE_ANIM_START) return; 107 | mState = STATE_ANIM_START; 108 | startSearchViewAnim(); 109 | } 110 | 111 | @Override 112 | public void resetAnim() { 113 | if (mState == STATE_ANIM_STOP) return; 114 | mState = STATE_ANIM_STOP; 115 | startSearchViewAnim(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /library/src/main/java/com/cjj/sva/anim/controller/JJAroundCircleBornTailController.java: -------------------------------------------------------------------------------- 1 | package com.cjj.sva.anim.controller; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.graphics.RectF; 7 | 8 | import com.cjj.sva.anim.JJBaseController; 9 | 10 | /** 11 | * 这是一个神奇的效果,SearchView可以转圈圈生成尾巴! 12 | *
13 | * Created by androidcjj on 2016/4/2. 14 | */ 15 | public class JJAroundCircleBornTailController extends JJBaseController { 16 | private String mColor = "#2196F3"; 17 | private String mColorTran = "#50FFFFFF"; 18 | private int mAngle = 10; 19 | private RectF mRectF; 20 | private int cx, cy, cr; 21 | 22 | public JJAroundCircleBornTailController() { 23 | mRectF = new RectF(); 24 | } 25 | 26 | @Override 27 | public void draw(Canvas canvas, Paint paint) { 28 | canvas.drawColor(Color.parseColor(mColor)); 29 | switch (mState) { 30 | case STATE_ANIM_NONE: 31 | drawNormalView(paint, canvas); 32 | break; 33 | case STATE_ANIM_START: 34 | drawStartAnimView(paint, canvas); 35 | break; 36 | case STATE_ANIM_STOP: 37 | drawStopAnimView(paint, canvas); 38 | break; 39 | } 40 | } 41 | 42 | private void drawStopAnimView(Paint paint, Canvas canvas) { 43 | paint.reset(); 44 | canvas.save(); 45 | paint.setColor(Color.WHITE); 46 | paint.setStrokeWidth(14); 47 | paint.setStyle(Paint.Style.STROKE); 48 | canvas.rotate(45, cx, cy); 49 | canvas.drawLine(cx + cr, cy, cx + cr * 2, cy, paint); 50 | canvas.drawCircle(cx, cy, cr, paint); 51 | canvas.restore(); 52 | } 53 | 54 | private void drawStartAnimView(Paint paint, Canvas canvas) { 55 | paint.setAntiAlias(true); 56 | paint.setColor(Color.parseColor(mColorTran)); 57 | paint.setStrokeWidth(10); 58 | paint.setStyle(Paint.Style.STROKE); 59 | canvas.rotate(45, cx, cy); 60 | canvas.drawCircle(cx, cy, cr, paint); 61 | mRectF.left = cx - cr; 62 | mRectF.right = cx + cr; 63 | mRectF.top = cy - cr; 64 | mRectF.bottom = cy + cr; 65 | 66 | if (mPro <= 0.2) { 67 | canvas.drawLine(cx + cr, cy, cx + cr + cr * (.2f - mPro), 68 | cy, paint); 69 | canvas.save(); 70 | paint.setAntiAlias(true); 71 | paint.setColor(Color.WHITE); 72 | canvas.drawArc(mRectF, 6, -14, false, paint); 73 | canvas.restore(); 74 | } else if (mPro > 0.2 && mPro < 4.5) { 75 | canvas.save(); 76 | paint.setColor(Color.WHITE); 77 | mAngle += 20; 78 | canvas.rotate(mAngle, getWidth() / 2, getHeight() / 2); 79 | canvas.drawArc(mRectF, 0, mAngle / 4, false, paint); 80 | canvas.restore(); 81 | } else { 82 | canvas.save(); 83 | paint.setAntiAlias(true); 84 | paint.setColor(Color.WHITE); 85 | paint.setStrokeWidth(14); 86 | paint.setStyle(Paint.Style.STROKE); 87 | canvas.drawLine(cx + cr, cy, cx + cr + cr * ((mPro - 4.5f) * 2), cy, paint); 88 | canvas.drawCircle(cx, cy, cr, paint); 89 | canvas.restore(); 90 | } 91 | 92 | } 93 | 94 | private void drawNormalView(Paint paint, Canvas canvas) { 95 | cr = getWidth() / 15; 96 | cx = getWidth() / 2; 97 | cy = getHeight() / 2; 98 | 99 | paint.reset(); 100 | paint.setAntiAlias(true); 101 | canvas.save(); 102 | paint.setColor(Color.WHITE); 103 | paint.setStrokeWidth(14); 104 | paint.setStyle(Paint.Style.STROKE); 105 | canvas.rotate(45, cx, cy); 106 | canvas.drawLine(cx + cr, cy, cx + cr * 2, cy, paint); 107 | canvas.drawCircle(cx, cy, cr, paint); 108 | canvas.restore(); 109 | } 110 | 111 | @Override 112 | public void startAnim() { 113 | if (mState == STATE_ANIM_START) return; 114 | mState = STATE_ANIM_START; 115 | startSearchViewAnim(0, 5, 2000); 116 | } 117 | 118 | @Override 119 | public void resetAnim() { 120 | if (mState == STATE_ANIM_STOP) return; 121 | mState = STATE_ANIM_STOP; 122 | mAngle = 0; 123 | startSearchViewAnim(); 124 | } 125 | 126 | } 127 | 128 | -------------------------------------------------------------------------------- /library/src/main/java/com/cjj/sva/anim/JJBaseController.java: -------------------------------------------------------------------------------- 1 | package com.cjj.sva.anim; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.ValueAnimator; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.PathMeasure; 9 | import android.support.annotation.IntDef; 10 | import android.util.Log; 11 | import android.view.View; 12 | import android.view.animation.AccelerateInterpolator; 13 | import android.view.animation.LinearInterpolator; 14 | 15 | import com.cjj.sva.utils.LogHelper; 16 | 17 | import java.lang.annotation.Retention; 18 | import java.lang.annotation.RetentionPolicy; 19 | import java.lang.ref.WeakReference; 20 | 21 | /** 22 | * 这是一个神奇的controller,神奇你妹啊...妹啊...啊。 23 | * 24 | * Created by androidcjj on 2016/4/1. 25 | */ 26 | public abstract class JJBaseController { 27 | public static final int STATE_ANIM_NONE = 0; 28 | public static final int STATE_ANIM_START = 1; 29 | public static final int STATE_ANIM_STOP = 2; 30 | public static final int DEFAULT_ANIM_TIME = 500; 31 | public static final float DEFAULT_ANIM_STARTF = 0; 32 | public static final float DEFAULT_ANIM_ENDF = 1; 33 | 34 | protected float mPro = -1; 35 | private WeakReference13 | * Created by cjj on 2016/4/3. 14 | */ 15 | public class JJCircleToBarController extends JJBaseController { 16 | private String mColor = "#E91E63"; 17 | private float cx, cy, cr; 18 | private float sign = 0.707f; 19 | private float mCircleBig = 10; 20 | private RectF mRectF, mRectF2; 21 | private float mCirCleDis = 200; 22 | private Paint mFontPaint; 23 | 24 | public JJCircleToBarController() { 25 | mRectF = new RectF(); 26 | mRectF2 = new RectF(); 27 | mFontPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 28 | mFontPaint.setStrokeWidth(1); 29 | mFontPaint.setColor(Color.WHITE); 30 | mFontPaint.setStyle(Paint.Style.FILL); 31 | mFontPaint.setTextSize(40); 32 | } 33 | 34 | @Override 35 | public void draw(Canvas canvas, Paint paint) { 36 | canvas.drawColor(Color.parseColor(mColor)); 37 | switch (mState) { 38 | case STATE_ANIM_NONE: 39 | drawNormalView(paint, canvas); 40 | break; 41 | case STATE_ANIM_START: 42 | drawStartAnimView(paint, canvas); 43 | break; 44 | case STATE_ANIM_STOP: 45 | drawStopAnimView(paint, canvas); 46 | break; 47 | } 48 | } 49 | 50 | private void drawStopAnimView(Paint paint, Canvas canvas) { 51 | drawNormalView(paint, canvas); 52 | 53 | } 54 | 55 | private void drawStartAnimView(Paint paint, Canvas canvas) { 56 | canvas.save(); 57 | 58 | if (mPro <= 0.1f) { 59 | canvas.drawLine(cx + cr * sign, cy + cr * sign, cx + cr * sign + cr * sign * 60 | (1 - mPro * 10), cy + cr * sign + cr * sign * (1 - mPro * 10), paint); 61 | canvas.drawCircle(cx, cy, cr, paint); 62 | } else if (mPro > 0.1f && mPro <= 0.2) { 63 | canvas.drawCircle(cx, cy, cr + (mPro - 0.1f) * mCircleBig * 10, paint); 64 | } else if (mPro > 0.2 && mPro <= 0.3) { 65 | mRectF.left = cx - cr - mCircleBig + mCirCleDis * (mPro - 0.2f) * 10; 66 | mRectF.right = cx + cr + mCircleBig + mCirCleDis * (mPro - 0.2f) * 10; 67 | canvas.drawArc(mRectF, 0, 360, false, paint); 68 | } else if (mPro > 0.3 && mPro <= 0.4) { 69 | mRectF2.left = cx - cr - mCircleBig + mCirCleDis * (1 - (mPro - 0.3f) * 10); 70 | mRectF2.right = cx + cr + mCircleBig + mCirCleDis * (1 - (mPro - 0.3f) * 10); 71 | canvas.drawArc(mRectF, 90, -180, false, paint); 72 | canvas.drawLine(mRectF2.left + cr + mCircleBig, mRectF.top, mRectF.right - cr - mCircleBig, mRectF.top, paint); 73 | canvas.drawLine(mRectF2.left + cr + mCircleBig, mRectF.bottom, mRectF.right - cr - mCircleBig, mRectF.bottom, paint); 74 | canvas.drawArc(mRectF2, 90, 180, false, paint); 75 | } else if (mPro > 0.4 && mPro <= 0.5) { 76 | mRectF2.left = cx - cr - mCircleBig - mCirCleDis * (mPro - 0.4f) * 10; 77 | mRectF2.right = cx + cr + mCircleBig - mCirCleDis * (mPro - 0.4f) * 10; 78 | canvas.drawArc(mRectF, 90, -180, false, paint); 79 | canvas.drawLine(mRectF2.left + cr + mCircleBig, mRectF.top, mRectF.right - cr - mCircleBig, mRectF.top, paint); 80 | canvas.drawLine(mRectF2.left + cr + mCircleBig, mRectF.bottom, mRectF.right - cr - mCircleBig, mRectF.bottom, paint); 81 | canvas.drawArc(mRectF2, 90, 180, false, paint); 82 | } else if (mPro > 0.5 && mPro <= 0.6) { 83 | canvas.drawArc(mRectF, 90, -180, false, paint); 84 | canvas.drawLine(mRectF2.left + cr + mCircleBig, mRectF.top, mRectF.right - cr - mCircleBig, mRectF.top, paint); 85 | canvas.drawLine(mRectF2.left + cr + mCircleBig, mRectF.bottom, mRectF.right - cr - mCircleBig, mRectF.bottom, paint); 86 | canvas.drawArc(mRectF2, 90, 180, false, paint); 87 | 88 | if (mPro > 0.5f && mPro <= 0.52f) { 89 | canvas.drawText("J", cx - mCirCleDis, cy + cr / 2, mFontPaint); 90 | } else if (mPro > 0.52 && mPro <= 0.53f) { 91 | canvas.drawText("JJ", cx - mCirCleDis, cy + cr / 2, mFontPaint); 92 | } else if (mPro > 0.53 && mPro <= 0.54f) { 93 | canvas.drawText("JJ Search", cx - mCirCleDis, cy + cr / 2, mFontPaint); 94 | } else if (mPro > 0.54 && mPro <= 0.55f) { 95 | canvas.drawText("JJ Search Anim", cx - mCirCleDis, cy + cr / 2, mFontPaint); 96 | } else { 97 | canvas.drawText("JJ Search Animations", cx - mCirCleDis, cy + cr / 2, mFontPaint); 98 | } 99 | } else if (mPro > 0.6 && mPro <= 0.7) { 100 | canvas.drawCircle(cx, cy, cr + mCircleBig, paint); 101 | canvas.drawLine(cx - cr / 2 + 4, cy + cr / 2, cx - cr / 2 + 4 - cr / 2, cy - cr / 2 + 8, paint); 102 | canvas.drawLine(cx - cr / 2 + 4, cy + cr / 2, (cx + cr - 4), (cy - cr / 2), paint); 103 | } else { 104 | canvas.drawCircle(cx, cy, cr + mCircleBig, paint); 105 | canvas.drawText("BUG", cx - cr / 2 - 8, cy + cr / 2, mFontPaint); 106 | //年轻的骚年啊 收尾工作交给你了 107 | } 108 | 109 | canvas.restore(); 110 | } 111 | 112 | private void drawNormalView(Paint paint, Canvas canvas) { 113 | cr = getWidth() / 15; 114 | cx = getWidth() / 2; 115 | cy = getHeight() / 2; 116 | mRectF.top = cy - cr - mCircleBig; 117 | mRectF.bottom = cy + cr + mCircleBig; 118 | mRectF2.top = cy - cr - mCircleBig; 119 | mRectF2.bottom = cy + cr + mCircleBig; 120 | 121 | paint.reset(); 122 | paint.setAntiAlias(true); 123 | paint.setStrokeCap(Paint.Cap.ROUND); 124 | canvas.save(); 125 | paint.setColor(Color.WHITE); 126 | paint.setStrokeWidth(4); 127 | paint.setStyle(Paint.Style.STROKE); 128 | canvas.drawCircle(cx, cy, cr, paint); 129 | canvas.drawLine(cx + cr * sign, cy + cr * sign, cx + cr * 2 * sign, 130 | cy + cr * 2 * sign, paint); 131 | canvas.restore(); 132 | } 133 | 134 | @Override 135 | public void startAnim() { 136 | if (mState == STATE_ANIM_START) return; 137 | mState = STATE_ANIM_START; 138 | startSearchViewAnim(0, 1, 3000); 139 | } 140 | 141 | @Override 142 | public void resetAnim() { 143 | if (mState == STATE_ANIM_STOP) return; 144 | mState = STATE_ANIM_STOP; 145 | startSearchViewAnim(); 146 | } 147 | 148 | 149 | } 150 | -------------------------------------------------------------------------------- /library/src/main/java/com/cjj/sva/anim/controller/JJBarWithErrorIconController.java: -------------------------------------------------------------------------------- 1 | package com.cjj.sva.anim.controller; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.graphics.RectF; 7 | 8 | import com.cjj.sva.anim.JJBaseController; 9 | 10 | /** 11 | * 这是一个神奇的类,神奇的是开始的时候好好的,后来作者偷懒就不画结束动画了 12 | * 13 | * Created by cjj on 2016/4/3. 14 | */ 15 | public class JJBarWithErrorIconController extends JJBaseController { 16 | private String mColor = "#E91E63"; 17 | private float cx, cy, cr; 18 | private float sign = 0.707f; 19 | private float mCircleBig = 10; 20 | private RectF mRectF, mRectF2; 21 | private float mCirCleDis = 200; 22 | private Paint mFontPaint; 23 | 24 | public JJBarWithErrorIconController() { 25 | mRectF = new RectF(); 26 | mRectF2 = new RectF(); 27 | mFontPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 28 | mFontPaint.setStrokeWidth(1); 29 | mFontPaint.setColor(Color.WHITE); 30 | mFontPaint.setStyle(Paint.Style.FILL); 31 | mFontPaint.setTextSize(40); 32 | } 33 | 34 | @Override 35 | public void draw(Canvas canvas, Paint paint) { 36 | canvas.drawColor(Color.parseColor(mColor)); 37 | switch (mState) { 38 | case STATE_ANIM_NONE: 39 | drawNormalView(paint, canvas); 40 | break; 41 | case STATE_ANIM_START: 42 | drawStartAnimView(paint, canvas); 43 | break; 44 | case STATE_ANIM_STOP: 45 | drawStopAnimView(paint, canvas); 46 | break; 47 | } 48 | } 49 | 50 | private void drawStopAnimView(Paint paint, Canvas canvas) { 51 | canvas.save(); 52 | if (mPro <= 0.25) { 53 | canvas.drawArc(mRectF, 90, -180, false, paint); 54 | canvas.drawLine(mRectF2.left + cr, mRectF.top, mRectF.right - cr, mRectF.top, paint); 55 | canvas.drawLine(mRectF2.left + cr, mRectF.bottom, mRectF.right - cr, mRectF.bottom, 56 | paint); 57 | canvas.drawArc(mRectF2, 90, 180, false, paint); 58 | canvas.drawLine(mRectF.left + cr - sign * cr / 2, cy + cr * sign / 2, mRectF.left + cr + sign * cr / 2, cy - cr * sign / 2, paint); 59 | } else if (mPro > 0.25 && mPro <= 0.5f) { 60 | canvas.drawArc(mRectF, 90, -180, false, paint); 61 | canvas.drawLine(mRectF2.left + cr, mRectF.top, mRectF.right - cr, mRectF.top, paint); 62 | canvas.drawLine(mRectF2.left + cr, mRectF.bottom, mRectF.right - cr, mRectF.bottom, 63 | paint); 64 | canvas.drawArc(mRectF2, 90, 180, false, paint); 65 | canvas.drawArc(mRectF2, 90, 180, false, paint); 66 | } else if (mPro > 0.5f && mPro <= 0.75f) { 67 | canvas.drawCircle(cx, cy, cr, paint); 68 | } else { 69 | canvas.drawLine(cx + cr * sign, cy + cr * sign, cx + cr * sign + cr * sign * 70 | (mPro - 0.75f) * 4, cy + cr * sign + cr * sign * (mPro - 0.75f) * 4, paint); 71 | canvas.drawCircle(cx, cy, cr, paint); 72 | } 73 | canvas.restore(); 74 | } 75 | 76 | private void drawStartAnimView(Paint paint, Canvas canvas) { 77 | canvas.save(); 78 | 79 | if (mPro <= 0.25) { 80 | canvas.drawLine(cx + cr * sign, cy + cr * sign, cx + cr * sign + cr * sign * 81 | (1 - mPro * 4), cy + cr * sign + cr * sign * (1 - mPro * 4), paint); 82 | canvas.drawCircle(cx, cy, cr, paint); 83 | } else if (mPro > 0.25 && mPro <= 0.5f) { 84 | mRectF.left = cx - cr + mCirCleDis * (mPro - 0.25f) * 4; 85 | mRectF.right = cx + cr + mCirCleDis * (mPro - 0.25f) * 4; 86 | mRectF2.left = cx - cr - mCirCleDis * (mPro - 0.25f) * 4; 87 | mRectF2.right = cx + cr - mCirCleDis * (mPro - 0.25f) * 4; 88 | canvas.drawArc(mRectF, 90, -180, false, paint); 89 | canvas.drawLine(mRectF2.left + cr, mRectF.top, mRectF.right - cr, mRectF.top, paint); 90 | canvas.drawLine(mRectF2.left + cr, mRectF.bottom, mRectF.right - cr, mRectF.bottom, 91 | paint); 92 | canvas.drawArc(mRectF2, 90, 180, false, paint); 93 | } else if (mPro > 0.5f && mPro <= 0.75f) { 94 | canvas.drawArc(mRectF, 90, -180, false, paint); 95 | canvas.drawLine(mRectF2.left + cr, mRectF.top, mRectF.right - cr, mRectF.top, paint); 96 | canvas.drawLine(mRectF2.left + cr, mRectF.bottom, mRectF.right - cr, mRectF.bottom, 97 | paint); 98 | canvas.drawArc(mRectF2, 90, 180, false, paint); 99 | canvas.drawLine(mRectF.left + cr - sign * cr / 2 * (mPro - 0.5f) * 4, cy + cr * 100 | sign / 2 * (mPro - 0.5f) * 4, mRectF.left + cr + sign * cr / 2 + sign * 101 | cr / 2 * (1 - (mPro - 0.5f) * 4), cy - cr * sign / 2 - sign * cr / 2 * 102 | (1 - (mPro - 0.5f) * 4), paint); 103 | 104 | } else { 105 | canvas.drawArc(mRectF, 90, -180, false, paint); 106 | canvas.drawLine(mRectF2.left + cr, mRectF.top, mRectF.right - cr, mRectF.top, paint); 107 | canvas.drawLine(mRectF2.left + cr, mRectF.bottom, mRectF.right - cr, mRectF.bottom, 108 | paint); 109 | canvas.drawArc(mRectF2, 90, 180, false, paint); 110 | canvas.drawLine(mRectF.left + cr - sign * cr / 2, cy + cr * sign / 2, mRectF.left + 111 | cr + sign * cr / 2, cy - cr * sign / 2, paint); 112 | canvas.drawLine(mRectF.left + cr - sign * cr / 2 * (mPro - 0.75f) * 4, cy - cr * 113 | sign / 2 * (mPro - 0.75f) * 4, mRectF.left + cr + sign * cr / 2 + sign * 114 | cr / 2 * (1 - (mPro - 0.75f) * 4), cy + cr * sign / 2 + sign * cr / 2 * 115 | (1 - (mPro - 0.75f) * 4), paint); 116 | } 117 | 118 | canvas.restore(); 119 | } 120 | 121 | private void drawNormalView(Paint paint, Canvas canvas) { 122 | cr = getWidth() / 15; 123 | cx = getWidth() / 2; 124 | cy = getHeight() / 2; 125 | mRectF.top = cy - cr; 126 | mRectF.bottom = cy + cr; 127 | mRectF2.top = cy - cr; 128 | mRectF2.bottom = cy + cr; 129 | 130 | paint.reset(); 131 | paint.setAntiAlias(true); 132 | paint.setStrokeCap(Paint.Cap.ROUND); 133 | canvas.save(); 134 | paint.setColor(Color.WHITE); 135 | paint.setStrokeWidth(8); 136 | paint.setStyle(Paint.Style.STROKE); 137 | canvas.drawCircle(cx, cy, cr, paint); 138 | canvas.drawLine(cx + cr * sign, cy + cr * sign, cx + cr * 2 * sign, 139 | cy + cr * 2 * sign, paint); 140 | canvas.restore(); 141 | } 142 | 143 | @Override 144 | public void startAnim() { 145 | if (mState == STATE_ANIM_START) return; 146 | mState = STATE_ANIM_START; 147 | startSearchViewAnim(); 148 | } 149 | 150 | @Override 151 | public void resetAnim() { 152 | if (mState == STATE_ANIM_STOP) return; 153 | mState = STATE_ANIM_STOP; 154 | startSearchViewAnim(); 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JJSearchViewAnim 2 | ============================ 3 | [中文版文档及相关文章](https://github.com/android-cjj/JJSearchViewAnim/blob/master/README-CN.md) 4 | 5 | [](https://android-arsenal.com/details/1/3390) 6 | 7 |  8 | 9 | ####A cool search view animation library ,I hope you like it. 10 | 11 | ###look 12 |
| Design | 16 |Demo | 17 |Designer | 18 |Class | 19 |
|---|---|---|---|
![]() |
24 | ![]() |
25 | Nick | 26 |JJDotGoPathController | 27 |
![]() |
30 | ![]() |
31 | Oleg Frolov | 32 |JJAroundCircleBornTailController | 33 |
![]() |
36 | ![]() |
37 | sandeep virk | 38 |JJBarWithErrorIconController | 39 |
![]() |
42 | ![]() |
43 | Jurre Houtkamp | 44 |JJScaleCircleAndTailController | 45 |
![]() |
48 | ![]() |
49 | Rahul Bhosale | 50 |JJChangeArrowController | 51 |
![]() |
54 | ![]() |
55 | Nicolás J. Engler | 56 |JJCircleToLineAlphaController | 57 |
![]() |
60 | ![]() |
61 | Boris Kirov | 62 |JJCircleToBarController | 63 |
![]() |
66 | ![]() |
67 | Anish Chandran | 68 |JJCircleToSimpleLineController | 69 |
![]() |
72 | Antonio Di Nardo | 74 |MaterialSearchView | 75 |
| Design | 14 |Demo | 15 |Designer | 16 |Class | 17 |
|---|---|---|---|
![]() |
22 | ![]() |
23 | Nick | 24 |JJDotGoPathController | 25 |
![]() |
28 | ![]() |
29 | Oleg Frolov | 30 |JJAroundCircleBornTailController | 31 |
![]() |
34 | ![]() |
35 | sandeep virk | 36 |JJBarWithErrorIconController | 37 |
![]() |
40 | ![]() |
41 | Jurre Houtkamp | 42 |JJScaleCircleAndTailController | 43 |
![]() |
46 | ![]() |
47 | Rahul Bhosale | 48 |JJChangeArrowController | 49 |
![]() |
52 | ![]() |
53 | Nicolás J. Engler | 54 |JJCircleToLineAlphaController | 55 |
![]() |
58 | ![]() |
59 | Boris Kirov | 60 |JJCircleToBarController | 61 |
![]() |
64 | ![]() |
65 | Anish Chandran | 66 |JJCircleToSimpleLineController | 67 |
![]() |
70 | Antonio Di Nardo | 72 |MaterialSearchView | 73 |