|
| 1 | +<div align="center"><img src="/screens/search_back.gif" width = 250/></div> |
| 2 | + |
| 3 | +# Search-Back animation |
| 4 | + |
| 5 | +#### search_back_vector.xml |
| 6 | +```xml |
| 7 | +<vector xmlns:android="http://schemas.android.com/apk/res/android" |
| 8 | + android:width="48dp" |
| 9 | + android:height="24dp" |
| 10 | + android:viewportHeight="24" |
| 11 | + android:viewportWidth="48"> |
| 12 | + |
| 13 | + <group |
| 14 | + android:pivotX="24" |
| 15 | + android:pivotY="12"> |
| 16 | + <path |
| 17 | + android:name="stem" |
| 18 | + android:pathData="M24.7,12.7 C24.70,12.7 31.8173374,19.9066081 31.8173371,19.9066082 C32.7867437,20.7006357 34.4599991,23 37.5,23 C40.54,23 43,20.54 43,17.5 C43,14.46 40.54,12 37.5,12 C34.46,12 33.2173088,12 31.8173371,12 C31.8173374,12 18.8477173,12 18.8477173,12" |
| 19 | + android:strokeColor="#5D5D5D" |
| 20 | + android:strokeWidth="2" |
| 21 | + android:trimPathEnd="0.185" |
| 22 | + android:trimPathStart="0" /> |
| 23 | + |
| 24 | + <path |
| 25 | + android:name="search_circle" |
| 26 | + android:pathData="M25.39,13.39 A 5.5 5.5 0 1 1 17.61 5.61 A 5.5 5.5 0 1 1 25.39 13.39" |
| 27 | + android:strokeColor="#5D5D5D" |
| 28 | + android:strokeWidth="2" |
| 29 | + android:trimPathEnd="1" /> |
| 30 | + |
| 31 | + <group android:name="arrow_head"> |
| 32 | + <path |
| 33 | + android:name="arrow_head_top" |
| 34 | + android:pathData="M16.7017297,12.6957157 L24.7043962,4.69304955" |
| 35 | + android:strokeColor="#5D5D5D" |
| 36 | + android:strokeWidth="2" |
| 37 | + android:trimPathEnd="0" /> |
| 38 | + |
| 39 | + <path |
| 40 | + android:name="arrow_head_bottom" |
| 41 | + android:pathData="M16.7107986,11.2764828 L24.7221527,19.2878361" |
| 42 | + android:strokeColor="#5D5D5D" |
| 43 | + android:strokeWidth="2" |
| 44 | + android:trimPathEnd="0" /> |
| 45 | + </group> |
| 46 | + </group> |
| 47 | +</vector> |
| 48 | +``` |
| 49 | +<div align="center"><img src="/screens/search_back_img_1.png"/></div> |
| 50 | + |
| 51 | +# Flow |
| 52 | +1. Transitions have to take place when the view is clicked. |
| 53 | +2. `searchBackState` store the current state. *(0 --> Search visible, 1 --> Back visible)* |
| 54 | +3. If searchBackState == 0 |
| 55 | + - Animate `search_circle` trimEnd from **1** to **0** |
| 56 | + - Animate `stem` trimStart from **0** to **0.75** and trimEnd from **0.185** to **1**. |
| 57 | + - Animate `arrow_head_top` and `arrow_head_bottom` trimEnd from **0** to **1**. |
| 58 | + - Set searchBackState = 1. |
| 59 | +4. If searchBackState == 1 |
| 60 | + - Animate `search_circle` trimEnd from **0** to **1** |
| 61 | + - Animate `stem` trimStart from **0.75** to **0** and trimEnd from **1** to **0.185**. |
| 62 | + - Animate `arrow_head_top` and `arrow_head_bottom` trimEnd from **1** to **0**. |
| 63 | + - Set searchBackState = 0. |
| 64 | + |
| 65 | +#### Java |
| 66 | +```java |
| 67 | +int searchBackState = 0; |
| 68 | +PathModel searchCircle, stem, arrowUp, arrowDown; |
| 69 | +@Override |
| 70 | +protected void onCreate(Bundle savedInstanceState) { |
| 71 | + super.onCreate(savedInstanceState); |
| 72 | + setContentView(R.layout.activity_main); |
| 73 | + |
| 74 | + searchBackView = (VectorMasterView) findViewById(R.id.search_back_vector); |
| 75 | + searchCircle = searchBackView.getPathModelByName("search_circle"); |
| 76 | + stem = searchBackView.getPathModelByName("stem"); |
| 77 | + arrowUp = searchBackView.getPathModelByName("arrow_head_top"); |
| 78 | + arrowDown = searchBackView.getPathModelByName("arrow_head_bottom"); |
| 79 | + searchBackView.setOnClickListener(new View.OnClickListener() { |
| 80 | + @Override |
| 81 | + public void onClick(View view) { |
| 82 | + if (searchBackState == 0) { |
| 83 | + animateSearchToBack(); |
| 84 | + } else { |
| 85 | + animateBackToSearch(); |
| 86 | + } |
| 87 | + } |
| 88 | + }); |
| 89 | +} |
| 90 | + |
| 91 | +void animateSearchToBack() { |
| 92 | + Timer timer = new Timer(); |
| 93 | + timer.scheduleAtFixedRate(new TimerTask() { |
| 94 | + @Override |
| 95 | + public void run() { |
| 96 | + circleTrimEnd -= 1.0f / 20; |
| 97 | + stemTrimStart += 0.75f / 20; |
| 98 | + stemTrimEnd += (1 - 0.185f) / 20; |
| 99 | + arrowHeadBottomTrimEnd += 1.0f / 20; |
| 100 | + arrowHeadTopTrimEnd += 1.0f / 20; |
| 101 | + if (circleTrimEnd <= 0) { |
| 102 | + searchBackState = 1; |
| 103 | + cancel(); |
| 104 | + } |
| 105 | + |
| 106 | + searchCircle.setTrimPathEnd(circleTrimEnd); |
| 107 | + stem.setTrimPathEnd(stemTrimEnd); |
| 108 | + stem.setTrimPathStart(stemTrimStart); |
| 109 | + arrowUp.setTrimPathEnd(arrowHeadTopTrimEnd); |
| 110 | + arrowDown.setTrimPathEnd(arrowHeadBottomTrimEnd); |
| 111 | + |
| 112 | + runOnUiThread(new Runnable() { |
| 113 | + @Override |
| 114 | + public void run() { |
| 115 | + searchBackView.update(); |
| 116 | + } |
| 117 | + }); |
| 118 | + |
| 119 | + } |
| 120 | + }, 0, 1000 / 60); |
| 121 | +} |
| 122 | + |
| 123 | +void animateBackToSearch() { |
| 124 | + Timer timer = new Timer(); |
| 125 | + timer.scheduleAtFixedRate(new TimerTask() { |
| 126 | + @Override |
| 127 | + public void run() { |
| 128 | + arrowHeadBottomTrimEnd -= 1.0f / 20; |
| 129 | + arrowHeadTopTrimEnd -= 1.0f / 20; |
| 130 | + stemTrimStart -= 0.75f / 20; |
| 131 | + stemTrimEnd -= (1 - 0.185f) / 20; |
| 132 | + circleTrimEnd += 1.0f / 20; |
| 133 | + if (circleTrimEnd >= 1) { |
| 134 | + searchBackState = 0; |
| 135 | + cancel(); |
| 136 | + } |
| 137 | + |
| 138 | + searchCircle.setTrimPathEnd(circleTrimEnd); |
| 139 | + stem.setTrimPathEnd(stemTrimEnd); |
| 140 | + stem.setTrimPathStart(stemTrimStart); |
| 141 | + arrowUp.setTrimPathEnd(arrowHeadTopTrimEnd); |
| 142 | + arrowDown.setTrimPathEnd(arrowHeadBottomTrimEnd); |
| 143 | + |
| 144 | + runOnUiThread(new Runnable() { |
| 145 | + @Override |
| 146 | + public void run() { |
| 147 | + searchBackView.update(); |
| 148 | + } |
| 149 | + }); |
| 150 | + } |
| 151 | + }, 0, 1000 / 60); |
| 152 | +} |
| 153 | + |
| 154 | +``` |
| 155 | + |
| 156 | +#### Result |
| 157 | +<div align="center"><img src="/screens/search_back.gif" width="250"/></div> |
0 commit comments