├── .gitattributes ├── .gitignore ├── FlowImageView ├── .settings │ ├── org.eclipse.core.resources.prefs │ └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── libs │ └── android-support-v4.jar ├── project.properties └── src │ └── com │ └── coco │ └── flowimageview │ └── FlowImageView.java ├── FlowImageViewTest ├── .settings │ ├── org.eclipse.core.resources.prefs │ └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── libs │ └── android-support-v4.jar ├── project.properties ├── res │ ├── drawable-mdpi │ │ └── rootblock_default_bg.jpg │ ├── layout │ │ └── flow_image_view_test.xml │ └── values │ │ └── colors.xml └── src │ └── com │ └── coco │ └── flowimageview │ └── test │ └── FlowImageViewTestActivity.java ├── LICENSE ├── README.md └── snapshot └── flowing.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Intellij project files 26 | *.iml 27 | *.ipr 28 | *.iws 29 | .idea/ 30 | -------------------------------------------------------------------------------- /FlowImageView/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /FlowImageView/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /FlowImageView/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /FlowImageView/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzhouj/Android-FlowImageView/fc5c26f6fcac1f533b1421f07a7bd8406bc15e53/FlowImageView/libs/android-support-v4.jar -------------------------------------------------------------------------------- /FlowImageView/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-17 15 | android.library=true 16 | -------------------------------------------------------------------------------- /FlowImageView/src/com/coco/flowimageview/FlowImageView.java: -------------------------------------------------------------------------------- 1 | package com.coco.flowimageview; 2 | 3 | /* 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2014 justin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | this software and associated documentation files (the "Software"), to deal in 10 | the Software without restriction, including without limitation the rights to 11 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | the Software, and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 20 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 21 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | import android.content.Context; 27 | import android.graphics.Matrix; 28 | import android.graphics.drawable.Drawable; 29 | import android.support.v4.view.ViewCompat; 30 | import android.util.AttributeSet; 31 | import android.util.Log; 32 | import android.view.animation.LinearInterpolator; 33 | import android.widget.ImageView; 34 | import android.widget.Scroller; 35 | 36 | /** 37 | * Zaker style flow image view, it's image horizontal scrolling slowly, using as Zaker's main screen background. 38 | */ 39 | public class FlowImageView extends ImageView { 40 | private static final String TAG = "FlowImageView"; 41 | private static final boolean DEBUG = false; 42 | 43 | private static void DEBUG_LOG(String msg) { 44 | if (DEBUG) { 45 | Log.v(TAG, msg); 46 | } 47 | } 48 | 49 | private static final float MIN_FLOW_VELOCITY = 0.3333f; // dips per second 50 | private static final float DEFAULT_FLOW_VELOCITY = 0.6667f; // dips per second 51 | private static final int DEFAULT_EDGE_DELAY = 2000; // ms 52 | 53 | private float mMinFlowVelocity; 54 | private float mFlowVelocity; 55 | private int mEdgeDelay = DEFAULT_EDGE_DELAY; 56 | 57 | private Scroller mScroller; 58 | 59 | private boolean mIsFlowInited; 60 | private boolean mIsFlowPositive = true; 61 | private boolean mFlowStarted; 62 | 63 | private Matrix mImageMatrix = new Matrix(); 64 | private float mScale; 65 | private float mTranslateX; 66 | private float mTranslateXEnd; 67 | 68 | private final Runnable mReverseFlowRunnable = new Runnable() { 69 | public void run() { 70 | mIsFlowPositive = !mIsFlowPositive; 71 | DEBUG_LOG("mReverseFlowRunnable mIsFlowPositive=" + mIsFlowPositive); 72 | startFlow(); 73 | } 74 | }; 75 | 76 | public FlowImageView(Context context) { 77 | super(context); 78 | initFlowImageView(); 79 | } 80 | 81 | public FlowImageView(Context context, AttributeSet attrs) { 82 | super(context, attrs); 83 | initFlowImageView(); 84 | } 85 | 86 | public FlowImageView(Context context, AttributeSet attrs, int defStyle) { 87 | super(context, attrs, defStyle); 88 | initFlowImageView(); 89 | } 90 | 91 | private void initFlowImageView() { 92 | setScaleType(ImageView.ScaleType.MATRIX); 93 | 94 | final Context context = getContext(); 95 | final float density = context.getResources().getDisplayMetrics().density; 96 | 97 | mMinFlowVelocity = MIN_FLOW_VELOCITY * density; 98 | mFlowVelocity = DEFAULT_FLOW_VELOCITY * density; 99 | 100 | mScroller = new Scroller(context, new LinearInterpolator()); 101 | } 102 | 103 | @Override 104 | public void setEnabled(boolean enabled) { 105 | if (enabled == isEnabled()) { 106 | return; 107 | } 108 | super.setEnabled(enabled); 109 | if (enabled) { 110 | startFlow(); 111 | } else { 112 | stopFlow(); 113 | } 114 | } 115 | 116 | public float getFlowVelocity() { 117 | return mFlowVelocity; 118 | } 119 | 120 | /** 121 | * Setting flow velocity. 122 | * 123 | * @param flowVelocity 124 | * pixels per second 125 | */ 126 | public void setFlowVelocity(float flowVelocity) { 127 | if (flowVelocity < mMinFlowVelocity) { 128 | flowVelocity = mMinFlowVelocity; 129 | } 130 | mFlowVelocity = flowVelocity; 131 | restartFlow(); 132 | } 133 | 134 | public int getEdgeDelay() { 135 | return mEdgeDelay; 136 | } 137 | 138 | public void setEdgeDelay(int edgeDelay) { 139 | if (edgeDelay < 0) { 140 | edgeDelay = 0; 141 | } 142 | mEdgeDelay = edgeDelay; 143 | } 144 | 145 | @Override 146 | protected void onAttachedToWindow() { 147 | super.onAttachedToWindow(); 148 | startFlow(); 149 | } 150 | 151 | @Override 152 | protected void onDetachedFromWindow() { 153 | stopFlow(); 154 | super.onDetachedFromWindow(); 155 | } 156 | 157 | @Override 158 | public void onWindowFocusChanged(boolean hasWindowFocus) { 159 | super.onWindowFocusChanged(hasWindowFocus); 160 | DEBUG_LOG("onWindowFocusChanged hasWindowFocus=" + hasWindowFocus); 161 | if (hasWindowFocus) { 162 | startFlow(); 163 | } else { 164 | stopFlow(); 165 | } 166 | } 167 | 168 | @Override 169 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 170 | super.onLayout(changed, left, top, right, bottom); 171 | DEBUG_LOG("onLayout changed=" + changed + 172 | ", left=" + left + ", top=" + top + 173 | ", right=" + right + ", bottom=" + bottom); 174 | initFlow(); 175 | startFlow(); 176 | } 177 | 178 | private void initFlow() { 179 | Drawable drawable = getDrawable(); 180 | if (drawable != null) { 181 | final float viewWidth = getWidth(); 182 | final float viewHeight = getHeight(); 183 | final float imgWidth = drawable.getIntrinsicWidth(); 184 | final float imgHeight = drawable.getIntrinsicHeight(); 185 | mScale = viewHeight / imgHeight; 186 | mTranslateXEnd = viewWidth - imgWidth * mScale; 187 | mIsFlowInited = true; 188 | setImageMatrix(); 189 | } else { 190 | mIsFlowInited = false; 191 | } 192 | } 193 | 194 | private void restartFlow() { 195 | if (mFlowStarted) { 196 | startFlow(); 197 | } 198 | } 199 | 200 | private void startFlow() { 201 | if (!isEnabled() || !mIsFlowInited) { 202 | return; 203 | } 204 | final int sx = (int) mTranslateX; 205 | final int dx = (int) ((mIsFlowPositive ? mTranslateXEnd : 0) - mTranslateX); 206 | if (dx == 0) { 207 | getHandler().removeCallbacks(mReverseFlowRunnable); 208 | getHandler().post(mReverseFlowRunnable); 209 | return; 210 | } 211 | final int duration = (int) Math.abs(dx / mFlowVelocity * 1000); 212 | DEBUG_LOG("startFlow mIsFlowPositive=" + mIsFlowPositive + 213 | ", mTranslateX=" + mTranslateX + ", mTranslateXEnd=" + mTranslateXEnd + 214 | ", sx=" + sx + ", dx=" + dx + ", duration=" + duration); 215 | mScroller.abortAnimation(); 216 | mScroller.startScroll(sx * 100, 0, dx * 100, 0, duration); 217 | mFlowStarted = true; 218 | ViewCompat.postInvalidateOnAnimation(this); 219 | } 220 | 221 | private void stopFlow() { 222 | mScroller.abortAnimation(); 223 | if (getHandler() != null) { 224 | getHandler().removeCallbacks(mReverseFlowRunnable); 225 | } 226 | mFlowStarted = false; 227 | } 228 | 229 | @Override 230 | public void computeScroll() { 231 | if (!isEnabled() || !mIsFlowInited || !mFlowStarted) { 232 | return; 233 | } 234 | if (!mScroller.isFinished() && mScroller.computeScrollOffset()) { 235 | mTranslateX = mScroller.getCurrX() / 100f; 236 | DEBUG_LOG("computeScroll mTranslateX=" + mTranslateX); 237 | setImageMatrix(); 238 | 239 | // Keep on drawing until the animation has finished. 240 | ViewCompat.postInvalidateOnAnimation(this); 241 | return; 242 | } 243 | 244 | // Done with scroll, clean up state. 245 | stopFlow(); 246 | getHandler().postDelayed(mReverseFlowRunnable, mEdgeDelay); 247 | } 248 | 249 | private void setImageMatrix() { 250 | mImageMatrix.reset(); 251 | mImageMatrix.postScale(mScale, mScale); 252 | mImageMatrix.postTranslate(mTranslateX, 0); 253 | setImageMatrix(mImageMatrix); 254 | } 255 | 256 | } 257 | -------------------------------------------------------------------------------- /FlowImageViewTest/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /FlowImageViewTest/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /FlowImageViewTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /FlowImageViewTest/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzhouj/Android-FlowImageView/fc5c26f6fcac1f533b1421f07a7bd8406bc15e53/FlowImageViewTest/libs/android-support-v4.jar -------------------------------------------------------------------------------- /FlowImageViewTest/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-17 15 | android.library=false 16 | android.library.reference.1=../FlowImageView 17 | -------------------------------------------------------------------------------- /FlowImageViewTest/res/drawable-mdpi/rootblock_default_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzhouj/Android-FlowImageView/fc5c26f6fcac1f533b1421f07a7bd8406bc15e53/FlowImageViewTest/res/drawable-mdpi/rootblock_default_bg.jpg -------------------------------------------------------------------------------- /FlowImageViewTest/res/layout/flow_image_view_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 19 | 20 | 24 | 25 | 30 | 31 | 36 | 37 | 38 | 43 | 44 | 49 | 50 | 55 | 56 | 61 | 62 | 63 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /FlowImageViewTest/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #e52897d3 5 | #b215adff 6 | #7f15adff 7 | #e5e05c1b 8 | #b2ff5c0b 9 | #7fff5c0b 10 | #e5000000 11 | #b2000000 12 | #7f000000 13 | #e5d46630 14 | #b2d46630 15 | #7fd46630 16 | 17 | -------------------------------------------------------------------------------- /FlowImageViewTest/src/com/coco/flowimageview/test/FlowImageViewTestActivity.java: -------------------------------------------------------------------------------- 1 | package com.coco.flowimageview.test; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.Window; 6 | import android.widget.SeekBar; 7 | import android.widget.SeekBar.OnSeekBarChangeListener; 8 | import android.widget.TextView; 9 | 10 | import com.coco.flowimageview.FlowImageView; 11 | 12 | public class FlowImageViewTestActivity extends Activity implements OnSeekBarChangeListener { 13 | 14 | private FlowImageView mFlowImageView; 15 | 16 | private TextView mFlowVelocityText; 17 | private TextView mEdgeDelayText; 18 | 19 | private SeekBar mFlowVelocitySeek; 20 | private SeekBar mEdgeDelaySeek; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | requestWindowFeature(Window.FEATURE_NO_TITLE); 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.flow_image_view_test); 27 | 28 | mFlowImageView = (FlowImageView) findViewById(R.id.flow_image); 29 | 30 | mFlowVelocityText = (TextView) findViewById(R.id.flow_velocity_text); 31 | mEdgeDelayText = (TextView) findViewById(R.id.edge_delay_text); 32 | 33 | mFlowVelocityText.setText(String.valueOf(mFlowImageView.getFlowVelocity())); 34 | mEdgeDelayText.setText(String.valueOf(mFlowImageView.getEdgeDelay())); 35 | 36 | mFlowVelocitySeek = (SeekBar) findViewById(R.id.flow_velocity_seek); 37 | mEdgeDelaySeek = (SeekBar) findViewById(R.id.edge_delay_seek); 38 | 39 | mFlowVelocitySeek.setProgress((int) (mFlowImageView.getFlowVelocity() * 100)); 40 | mEdgeDelaySeek.setProgress((int) mFlowImageView.getEdgeDelay()); 41 | 42 | mFlowVelocitySeek.setOnSeekBarChangeListener(this); 43 | mEdgeDelaySeek.setOnSeekBarChangeListener(this); 44 | } 45 | 46 | @Override 47 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 48 | if (fromUser) { 49 | if (seekBar == mFlowVelocitySeek) { 50 | mFlowImageView.setFlowVelocity(progress / 100f); 51 | mFlowVelocityText.setText(String.valueOf(mFlowImageView.getFlowVelocity())); 52 | } else if (seekBar == mEdgeDelaySeek) { 53 | mFlowImageView.setEdgeDelay(progress); 54 | mEdgeDelayText.setText(String.valueOf(mFlowImageView.getEdgeDelay())); 55 | } 56 | } 57 | } 58 | 59 | @Override 60 | public void onStartTrackingTouch(SeekBar seekBar) { 61 | // do nothing 62 | } 63 | 64 | @Override 65 | public void onStopTrackingTouch(SeekBar seekBar) { 66 | // do nothing 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 justin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android-FlowImageView 2 | ===================== 3 | 4 | Zaker style flow image view, it's image horizontal scrolling slowly, using as Zaker's main screen background. 5 | 6 | Features 7 | ======== 8 | 9 | + Android SDK **level 4+**. 10 | + Image horizontal scrolling slowly (flowing). 11 | + Options settings: flow velocity, delay at edge. 12 | 13 | Snapshots 14 | ========= 15 | 16 | [flowing]: https://github.com/zzhouj/Android-FlowImageView/raw/master/snapshot/flowing.png "flowing" 17 | 18 | ![flowing snapshot][flowing] 19 | 20 | Usage 21 | ===== 22 | 1. Add layout xml fragment like below: 23 | 24 | 29 | 30 | 2. Options settings: 31 | 32 | // Flow velocity (pixels per second, min: 0.3333 dips/s) 33 | mFlowImageView.setFlowVelocity(flowVelocity); 34 | 35 | // Edge delay (ms) 36 | mFlowImageView.setEdgeDelay(edgeDelay); 37 | 38 | License 39 | ======= 40 | 41 | The MIT License (MIT) 42 | 43 | Copyright (c) 2014 justin 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining a copy of 46 | this software and associated documentation files (the "Software"), to deal in 47 | the Software without restriction, including without limitation the rights to 48 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 49 | the Software, and to permit persons to whom the Software is furnished to do so, 50 | subject to the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be included in all 53 | copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 57 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 58 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 59 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 60 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | -------------------------------------------------------------------------------- /snapshot/flowing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzhouj/Android-FlowImageView/fc5c26f6fcac1f533b1421f07a7bd8406bc15e53/snapshot/flowing.png --------------------------------------------------------------------------------