├── .idea ├── $CACHE_FILE$ ├── .gitignore ├── CustomProgressView.iml ├── codeStyles │ └── Project.xml ├── dbnavigator.xml ├── dictionaries ├── externalDependencies.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── CPV.jpeg ├── CustomView ├── .gitignore ├── .idea │ ├── $CACHE_FILE$ │ ├── .name │ ├── codeStyles │ │ └── Project.xml │ ├── compiler.xml │ ├── dbnavigator.xml │ ├── dictionaries │ ├── externalDependencies.xml │ ├── gradle.xml │ ├── inspectionProfiles │ │ ├── Project_Default.xml │ │ └── profiles_settings.xml │ ├── jarRepositories.xml │ ├── misc.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── androidstack │ │ │ └── customview │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── 706.svga │ │ │ ├── car.svga │ │ │ ├── images │ │ │ │ ├── img_0.png │ │ │ │ └── img_1.png │ │ │ ├── liwu.json │ │ │ ├── love.svga │ │ │ ├── posche.svga │ │ │ └── test.json │ │ ├── java │ │ │ └── androidstack │ │ │ │ └── customview │ │ │ │ ├── App.java │ │ │ │ ├── BasisViewActivity.java │ │ │ │ ├── CustomDialog.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MaskActivity.java │ │ │ │ ├── TestActivity.java │ │ │ │ ├── animation │ │ │ │ ├── advanced │ │ │ │ │ ├── LoadingPathView.java │ │ │ │ │ ├── LoadingSuccessView.java │ │ │ │ │ └── PathMeasureActivity.java │ │ │ │ ├── interpolator │ │ │ │ │ ├── InterpolatorActivity.java │ │ │ │ │ └── ReverseInterpolator.java │ │ │ │ ├── property │ │ │ │ │ ├── PropertyAnimationActivity.java │ │ │ │ │ ├── advanced │ │ │ │ │ │ ├── AdvancedPropertyActivity.java │ │ │ │ │ │ ├── PhoneActivity.java │ │ │ │ │ │ └── ViewGroupAnimateActivity.java │ │ │ │ │ ├── evaluator │ │ │ │ │ │ ├── CharEvaluator.java │ │ │ │ │ │ ├── EvaluatorActivity.java │ │ │ │ │ │ └── ReverseEvaluator.java │ │ │ │ │ ├── object │ │ │ │ │ │ ├── FallingBallObjectActivity.java │ │ │ │ │ │ ├── FallingImageView.java │ │ │ │ │ │ └── ObjectAnimatorActivity.java │ │ │ │ │ ├── set │ │ │ │ │ │ ├── AnimatorSetActivity.java │ │ │ │ │ │ └── MenuActivity.java │ │ │ │ │ └── value │ │ │ │ │ │ ├── FallingBallEvaluator.java │ │ │ │ │ │ ├── FallingBallValueActivity.java │ │ │ │ │ │ ├── LoadingImageView.java │ │ │ │ │ │ └── ValueAnimatorActivity.java │ │ │ │ └── view │ │ │ │ │ ├── ViewAnimationActivity.java │ │ │ │ │ ├── frame │ │ │ │ │ └── FrameAnimationActivity.java │ │ │ │ │ └── tween │ │ │ │ │ ├── AlphaAnimationActivity.java │ │ │ │ │ ├── RotateAnimationActivity.java │ │ │ │ │ ├── ScaleAnimationActivity.java │ │ │ │ │ ├── SetAnimationActivity.java │ │ │ │ │ ├── TranslateAnimationActivity.java │ │ │ │ │ ├── TweenAnimationActivity.java │ │ │ │ │ └── effect │ │ │ │ │ ├── CameraActivity.java │ │ │ │ │ ├── LoadingActivity.java │ │ │ │ │ └── ScannerActivity.java │ │ │ │ ├── custom │ │ │ │ └── CustomProgressActivity.java │ │ │ │ ├── drawing │ │ │ │ ├── PaintActivity.java │ │ │ │ └── matrix │ │ │ │ │ └── MatrixActivity.java │ │ │ │ ├── rv │ │ │ │ ├── layoutmanager │ │ │ │ │ ├── CardActivity.java │ │ │ │ │ ├── CardItemView.java │ │ │ │ │ ├── CardLayoutManager.java │ │ │ │ │ └── Pool.java │ │ │ │ └── partrv │ │ │ │ │ ├── PartRvActivity.java │ │ │ │ │ └── PartRvAdapter.java │ │ │ │ ├── svg │ │ │ │ ├── SvgActivity.java │ │ │ │ ├── lottie │ │ │ │ │ └── LottieActivity.java │ │ │ │ └── svga │ │ │ │ │ ├── SvgaActivity.java │ │ │ │ │ └── SvgaTextActivity.java │ │ │ │ ├── text │ │ │ │ ├── GradientTextView.java │ │ │ │ └── TextActivity.java │ │ │ │ ├── toolbar │ │ │ │ └── ToolBarActivity.java │ │ │ │ └── view │ │ │ │ ├── BasisView.java │ │ │ │ ├── CustomProgressView.java │ │ │ │ └── mask │ │ │ │ ├── GuideMask.java │ │ │ │ └── GuideMaskSet.java │ │ └── res │ │ │ ├── anim │ │ │ ├── alpha_test.xml │ │ │ ├── rotate_test.xml │ │ │ ├── scale_test.xml │ │ │ ├── set_sanner.xml │ │ │ ├── set_test.xml │ │ │ └── translate_test.xml │ │ │ ├── animator │ │ │ ├── animator_logo.xml │ │ │ └── animator_set.xml │ │ │ ├── drawable-v21 │ │ │ └── ic_logo.xml │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ ├── animation_list_loading.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── ic_logo.xml │ │ │ ├── ic_love.xml │ │ │ ├── item.jpg │ │ │ ├── shape_scanner.xml │ │ │ └── vector_logo.xml │ │ │ ├── layout │ │ │ ├── activity_advanced_property.xml │ │ │ ├── activity_alpha_animation.xml │ │ │ ├── activity_animator_set.xml │ │ │ ├── activity_basis_view.xml │ │ │ ├── activity_camera.xml │ │ │ ├── activity_card.xml │ │ │ ├── activity_custom_progress.xml │ │ │ ├── activity_evaluator.xml │ │ │ ├── activity_falling_ball_object.xml │ │ │ ├── activity_falling_ball_value.xml │ │ │ ├── activity_frame_animation.xml │ │ │ ├── activity_interpolator.xml │ │ │ ├── activity_loading.xml │ │ │ ├── activity_lottie.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_mask.xml │ │ │ ├── activity_matrix.xml │ │ │ ├── activity_menu.xml │ │ │ ├── activity_music.xml │ │ │ ├── activity_object_animator.xml │ │ │ ├── activity_paint.xml │ │ │ ├── activity_part_rv.xml │ │ │ ├── activity_path_measure.xml │ │ │ ├── activity_phone.xml │ │ │ ├── activity_property_animation.xml │ │ │ ├── activity_rotate_animation.xml │ │ │ ├── activity_scale_animation.xml │ │ │ ├── activity_svg.xml │ │ │ ├── activity_svga.xml │ │ │ ├── activity_svga_text.xml │ │ │ ├── activity_test.xml │ │ │ ├── activity_text.xml │ │ │ ├── activity_tool_bar.xml │ │ │ ├── activity_translate_animation.xml │ │ │ ├── activity_tween_animation.xml │ │ │ ├── activity_value_animator.xml │ │ │ ├── activity_view_animation.xml │ │ │ ├── activity_view_group_animate.xml │ │ │ ├── dialog_custom.xml │ │ │ ├── item.xml │ │ │ ├── item_part_rv.xml │ │ │ └── layout_mask.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── add_focus_big.png │ │ │ ├── ic_arrow.png │ │ │ ├── ic_camera.jpeg │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── ic_loading.png │ │ │ ├── ic_phone.png │ │ │ ├── ic_scanner.png │ │ │ ├── ic_test.png │ │ │ ├── loading_01.png │ │ │ ├── loading_010.png │ │ │ ├── loading_02.png │ │ │ ├── loading_03.png │ │ │ ├── loading_04.png │ │ │ ├── loading_05.png │ │ │ ├── loading_06.png │ │ │ ├── loading_07.png │ │ │ ├── loading_08.png │ │ │ └── loading_09.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_paper.jpeg │ │ │ └── values │ │ │ ├── attr.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── androidstack │ │ └── customview │ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── DrawingBasis.jpeg ├── Heartbeat1647.svga ├── Heartbeat1701.svga ├── Heartbeat1717.svga ├── Heartbeat1746.svga ├── HeartbeatText.svga ├── HeartbeatText1-3.svga ├── README.md ├── SVG2VECTOR.png ├── Video_20200819_071634_945.gif ├── Video_20200819_073506_981.gif ├── Video_20200819_073636_929.gif ├── ic_sing_single.png ├── ic_week_star_frame_new.9.png ├── svga_nihongdeng ├── tween.jpeg ├── 公众号.bmp ├── 抛物动画.gif ├── 插值器.jpeg ├── 电话响铃动画.gif ├── 菜单动画.gif └── 逐帧动画.jpeg /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Android 10 | 11 | 12 | CorrectnessLintAndroid 13 | 14 | 15 | General 16 | 17 | 18 | Kotlin 19 | 20 | 21 | LintAndroid 22 | 23 | 24 | PerformanceLintAndroid 25 | 26 | 27 | Plugin DevKit 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/CustomProgressView.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/dictionaries: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/externalDependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CPV.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CPV.jpeg -------------------------------------------------------------------------------- /CustomView/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /CustomView/.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Android 10 | 11 | 12 | CorrectnessLintAndroid 13 | 14 | 15 | General 16 | 17 | 18 | Kotlin 19 | 20 | 21 | LintAndroid 22 | 23 | 24 | PerformanceLintAndroid 25 | 26 | 27 | Plugin DevKit 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /CustomView/.idea/.name: -------------------------------------------------------------------------------- 1 | CustomProgressView -------------------------------------------------------------------------------- /CustomView/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CustomView/.idea/dictionaries: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CustomView/.idea/externalDependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CustomView/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /CustomView/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /CustomView/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /CustomView/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /CustomView/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /CustomView/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CustomView/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /CustomView/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | apply plugin: 'kotlin-android-extensions' 5 | 6 | android { 7 | compileSdkVersion 29 8 | buildToolsVersion "29.0.3" 9 | 10 | defaultConfig { 11 | applicationId "androidstack.customview" 12 | minSdkVersion 17 13 | targetSdkVersion 29 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | compileOptions { 27 | sourceCompatibility JavaVersion.VERSION_1_8 28 | targetCompatibility JavaVersion.VERSION_1_8 29 | } 30 | } 31 | 32 | dependencies { 33 | implementation fileTree(dir: "libs", include: ["*.jar"]) 34 | implementation 'androidx.appcompat:appcompat:1.2.0' 35 | implementation 'androidx.constraintlayout:constraintlayout:2.0.0' 36 | testImplementation 'junit:junit:4.13' 37 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 39 | 40 | implementation 'com.github.yyued:SVGAPlayer-Android:2.5.8' 41 | implementation 'com.airbnb.android:lottie:3.1.0' 42 | 43 | implementation 'com.google.android.material:material:1.2.0' 44 | } -------------------------------------------------------------------------------- /CustomView/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /CustomView/app/src/androidTest/java/androidstack/customview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("androidstack.progress", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /CustomView/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /CustomView/app/src/main/assets/706.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/assets/706.svga -------------------------------------------------------------------------------- /CustomView/app/src/main/assets/car.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/assets/car.svga -------------------------------------------------------------------------------- /CustomView/app/src/main/assets/images/img_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/assets/images/img_0.png -------------------------------------------------------------------------------- /CustomView/app/src/main/assets/images/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/assets/images/img_1.png -------------------------------------------------------------------------------- /CustomView/app/src/main/assets/liwu.json: -------------------------------------------------------------------------------- 1 | {"v":"5.1.8","fr":30,"ip":0,"op":41,"w":70,"h":70,"nm":"禮物盒","ddd":0,"assets":[{"id":"image_0","w":34,"h":17,"u":"images/","p":"img_0.png"},{"id":"image_1","w":30,"h":15,"u":"images/","p":"img_1.png"},{"id":"image_2","w":88,"h":76,"u":"images/","p":"img_2.png"},{"id":"image_3","w":36,"h":36,"u":"images/","p":"img_3.png"}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"liheshang.png","cl":"png","parent":2,"refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.227],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p227_1_0p333_0"],"t":9,"s":[0],"e":[-15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.769],"y":[0]},"n":["0p667_1_0p769_0"],"t":17,"s":[-15],"e":[7]},{"i":{"x":[0.384],"y":[0.384]},"o":{"x":[0.333],"y":[0]},"n":["0p384_0p384_0p333_0"],"t":24,"s":[7],"e":[-8]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":32,"s":[-8],"e":[0]},{"t":40}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":11,"s":[-2,0.75,0],"e":[-2,-2.25,0],"to":[0,-0.5,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":13,"s":[-2,-2.25,0],"e":[-2,0.75,0],"to":[0,0,0],"ti":[0,-1.16666662693024,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":24,"s":[-2,0.75,0],"e":[-2,4.75,0],"to":[0,1.16666662693024,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":32,"s":[-2,4.75,0],"e":[-2,0.75,0],"to":[0,0,0],"ti":[0,0.66666668653488,0]},{"t":40}],"ix":2},"a":{"a":0,"k":[0,17,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":5,"op":43,"st":5,"bm":0},{"ddd":0,"ind":2,"ty":2,"nm":"lihexia.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":13,"s":[34.75,38.781,0],"e":[34.75,42.781,0],"to":[0,0.66666668653488,0],"ti":[0,-0.66666668653488,0]},{"t":20}],"ix":2},"a":{"a":0,"k":[15,7.5,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":5,"s":[20,20,100],"e":[120,120,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":11,"s":[120,120,100],"e":[100,100,100]},{"t":20}],"ix":6}},"ao":0,"ip":5,"op":43,"st":5,"bm":0},{"ddd":0,"ind":3,"ty":2,"nm":"feichu.png","cl":"png","parent":2,"refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[13.302,0.097,0],"ix":2},"a":{"a":0,"k":[44,38,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":8,"s":[37.89,37.89,100],"e":[63.89,63.89,100]},{"t":16}],"ix":6}},"ao":0,"ip":8,"op":17,"st":3,"bm":0},{"ddd":0,"ind":4,"ty":2,"nm":"组 1132@2x.png","cl":"png","refId":"image_3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":3,"s":[100],"e":[0]},{"t":12}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2},"a":{"a":0,"k":[18,18,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":3,"s":[100,100,100],"e":[0,0,100]},{"t":12}],"ix":6}},"ao":0,"ip":0,"op":43,"st":-2,"bm":0}],"markers":[{"tm":3,"cm":"1","dr":0}]} -------------------------------------------------------------------------------- /CustomView/app/src/main/assets/love.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/assets/love.svga -------------------------------------------------------------------------------- /CustomView/app/src/main/assets/posche.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/assets/posche.svga -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/App.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview; 2 | 3 | import android.app.Application; 4 | import android.net.http.HttpResponseCache; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | /** 10 | * Created on 2020/8/17 15:05 11 | * 12 | * @author zhangchaozhou 13 | * @email 13760289294@139.com 14 | * @wechat 13760289294 15 | */ 16 | public class App extends Application { 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | try { 21 | File cacheDir = new File(getCacheDir(), "http"); 22 | HttpResponseCache.install(cacheDir, 1024 * 1024 * 128); 23 | } catch (IOException e) { 24 | System.out.println(e.getMessage()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/BasisViewActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.Nullable; 6 | import androidx.appcompat.app.AppCompatActivity; 7 | 8 | /** 9 | * Created on 2020/7/22 07:15 10 | * 11 | * @author zhangchaozhou 12 | * @email 13760289294@139.com 13 | * @wechat 13760289294 14 | */ 15 | public class BasisViewActivity extends AppCompatActivity { 16 | @Override 17 | protected void onCreate(@Nullable Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_basis_view); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/CustomDialog.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.view.Gravity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.Window; 11 | import android.view.WindowManager; 12 | 13 | import androidx.annotation.NonNull; 14 | import androidx.annotation.Nullable; 15 | import androidx.constraintlayout.widget.ConstraintLayout; 16 | 17 | import static android.graphics.Color.WHITE; 18 | 19 | /** 20 | * Created on 2020/8/20 16:55 21 | * 22 | * @author zhangchaozhou 23 | * @email 13760289294@139.com 24 | * @wechat 13760289294 25 | */ 26 | public class CustomDialog extends Dialog { 27 | public CustomDialog(@NonNull Context context) { 28 | super(context); 29 | } 30 | 31 | public CustomDialog(@NonNull Context context, int themeResId) { 32 | super(context, themeResId); 33 | } 34 | 35 | protected CustomDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { 36 | super(context, cancelable, cancelListener); 37 | } 38 | 39 | @Override 40 | protected void onStart() { 41 | super.onStart(); 42 | immerseStatusBarColor(getWindow(), true, WHITE, true); 43 | } 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | View v = LayoutInflater.from(getContext()).inflate(R.layout.dialog_custom, null); 49 | Window w = getWindow(); 50 | w.setContentView(v); 51 | WindowManager.LayoutParams lp = w.getAttributes(); 52 | lp.width = ConstraintLayout.LayoutParams.MATCH_PARENT; 53 | lp.height = ConstraintLayout.LayoutParams.MATCH_PARENT; 54 | lp.gravity = Gravity.BOTTOM; 55 | w.setAttributes(lp); 56 | w.setBackgroundDrawable(null); 57 | w.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 58 | } 59 | 60 | /** 61 | * 设置沉浸模式 62 | * @param isDarkMode 状态栏字体为黑色 63 | */ 64 | public static void immerseStatusBarColor(Window window, boolean isDarkMode, int color, boolean isDialog) { 65 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; 66 | int uiVisibility = window.getDecorView().getSystemUiVisibility(); 67 | if (isDarkMode) { 68 | uiVisibility ^= View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 69 | uiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 70 | } else { 71 | uiVisibility ^= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 72 | uiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 73 | } 74 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 75 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 76 | // if (isDialog){ 77 | // uiVisibility |=View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 78 | // View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_IMMERSIVE; 79 | // }else { 80 | // uiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 81 | // } 82 | window.setStatusBarColor(color); 83 | window.getDecorView().setSystemUiVisibility(uiVisibility); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/MaskActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.widget.ImageView; 6 | 7 | import androidstack.customview.view.mask.GuideMask; 8 | import androidstack.customview.view.mask.GuideMaskSet; 9 | import androidx.annotation.Nullable; 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | /** 13 | * Created on 2020/8/24 13:05 14 | * 15 | * @author zhangchaozhou 16 | * @email 13760289294@139.com 17 | * @wechat 13760289294 18 | */ 19 | public class MaskActivity extends AppCompatActivity { 20 | private ImageView mIvTest; 21 | @Override 22 | protected void onCreate(@Nullable Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_mask); 25 | 26 | mIvTest = findViewById(R.id.iv_test); 27 | 28 | GuideMask guideMask = new GuideMask.Builder(this) 29 | //蒙版所在activity 30 | .setMaskActivity(this) 31 | //目标布局 32 | .setTargetView(mIvTest) 33 | //蒙版背景颜色包括透明度 34 | .setBgColor(Color.parseColor("#40000000")) 35 | //蒙版布局 36 | .setMaskLayout(R.layout.layout_mask) 37 | //关闭蒙版的按钮 38 | .setMaskCloseId(R.id.btn_close) 39 | //围栏与目标布局的距离 40 | .setFencePadding(5,5,5,5) 41 | //围栏布局四角的角度 42 | .setFenceRadius(100) 43 | .build(); 44 | 45 | GuideMaskSet guideMaskSet = new GuideMaskSet(); 46 | //添加蒙版 47 | guideMaskSet.addGuide(guideMask); 48 | //显示所有蒙版 49 | guideMaskSet.show(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/TestActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.Nullable; 6 | import androidx.appcompat.app.AppCompatActivity; 7 | 8 | /** 9 | * Created on 2020/9/2 19:25 10 | * 11 | * @author zhangchaozhou 12 | * @email 13760289294@139.com 13 | * @wechat 13760289294 14 | */ 15 | public class TestActivity extends AppCompatActivity { 16 | @Override 17 | protected void onCreate(@Nullable Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_test); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/advanced/LoadingPathView.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.advanced; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Canvas; 8 | import android.graphics.Color; 9 | import android.graphics.Matrix; 10 | import android.graphics.Paint; 11 | import android.graphics.Path; 12 | import android.graphics.PathMeasure; 13 | import android.util.AttributeSet; 14 | import android.view.View; 15 | 16 | import androidstack.customview.R; 17 | import androidx.annotation.Nullable; 18 | 19 | /** 20 | * Created on 2020/8/16 17:42 21 | * 22 | * @author zhangchaozhou 23 | * @email 13760289294@139.com 24 | * @wechat 13760289294 25 | */ 26 | public class LoadingPathView extends View { 27 | 28 | private Bitmap mArrow; 29 | private Paint mPaint; 30 | private Path mDstPath; 31 | private Path mCirclePath; 32 | private PathMeasure mPathMeasure; 33 | private Float mCurrentAnimValue; 34 | float mStop = 0.0f; 35 | float mStart = 0.0f; 36 | private float[] mPos = new float[2]; 37 | private float[] mTan = new float[2]; 38 | private Matrix mMatrix; 39 | public LoadingPathView(Context context) { 40 | this(context,null); 41 | } 42 | 43 | public LoadingPathView(Context context, @Nullable AttributeSet attrs) { 44 | this(context, attrs,0); 45 | } 46 | 47 | public LoadingPathView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 48 | super(context, attrs, defStyleAttr); 49 | init(); 50 | } 51 | 52 | /** 53 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 54 | */ 55 | public static int dip2px(Context context, float dpValue) { 56 | final float scale = context.getResources().getDisplayMetrics().density; 57 | return (int) (dpValue * scale + 0.5f); 58 | } 59 | 60 | private void init() { 61 | setLayerType(LAYER_TYPE_SOFTWARE,null); 62 | mArrow = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_arrow); 63 | mMatrix = new Matrix(); 64 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 65 | mPaint.setStyle(Paint.Style.STROKE); 66 | mPaint.setStrokeWidth(4); 67 | mPaint.setColor(Color.RED); 68 | 69 | mDstPath = new Path(); 70 | mCirclePath = new Path(); 71 | mCirclePath.addCircle(dip2px(getContext(),100),dip2px(getContext(),100),dip2px(getContext(),25),Path.Direction.CW); 72 | mPathMeasure = new PathMeasure(mCirclePath,true); 73 | 74 | ValueAnimator animator = ValueAnimator.ofFloat(0,1); 75 | animator.setRepeatCount(ValueAnimator.INFINITE); 76 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 77 | @Override 78 | public void onAnimationUpdate(ValueAnimator animation) { 79 | //获取到旋转的角度值后刷新界面 80 | mCurrentAnimValue = (Float) animation.getAnimatedValue(); 81 | invalidate(); 82 | } 83 | }); 84 | animator.setDuration(2000); 85 | animator.start(); 86 | } 87 | 88 | 89 | 90 | 91 | @Override 92 | protected void onDraw(Canvas canvas) { 93 | super.onDraw(canvas); 94 | mStop = mPathMeasure.getLength()*mCurrentAnimValue; 95 | mStart = (float) (mStop-((0.5-Math.abs(mCurrentAnimValue-0.5))*mPathMeasure.getLength())); 96 | mDstPath.reset(); 97 | mPathMeasure.getSegment(mStart,mStop, mDstPath,true); 98 | //绘制路径 99 | canvas.drawPath(mDstPath, mPaint); 100 | 101 | mMatrix = new Matrix(); 102 | 103 | /** 104 | * 第一种方式 105 | */ 106 | mPathMeasure.getPosTan(mStop,mPos,mTan); 107 | float degrees = (float)(Math.atan2(mTan[1],mTan[0])*180.0/Math.PI); 108 | mMatrix.postRotate(degrees,mArrow.getWidth()/2,mArrow.getHeight()/2); 109 | mMatrix.postTranslate(mPos[0]-mArrow.getWidth()/2,mPos[1]-mArrow.getHeight()/2); 110 | 111 | /** 112 | * 第二种方式 113 | */ 114 | mPathMeasure.getMatrix(mStop,mMatrix,PathMeasure.POSITION_MATRIX_FLAG|PathMeasure.TANGENT_MATRIX_FLAG); 115 | mMatrix.preTranslate(mArrow.getWidth()/2,-mArrow.getHeight()/2); 116 | //绘制箭头 117 | canvas.drawBitmap(mArrow,mMatrix,mPaint); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/advanced/LoadingSuccessView.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.advanced; 2 | 3 | import android.content.Context; 4 | import android.graphics.Path; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | 8 | import androidx.annotation.Nullable; 9 | 10 | /** 11 | * Created on 2020/8/18 07:01 12 | * 13 | * @author zhangchaozhou 14 | * @email 13760289294@139.com 15 | * @wechat 13760289294 16 | */ 17 | public class LoadingSuccessView extends View { 18 | private Path mDstPath; 19 | private Path mCirclePath; 20 | 21 | public LoadingSuccessView(Context context) { 22 | this(context, null); 23 | } 24 | 25 | public LoadingSuccessView(Context context, @Nullable AttributeSet attrs) { 26 | this(context, attrs, 0); 27 | } 28 | 29 | public LoadingSuccessView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 30 | super(context, attrs, defStyleAttr); 31 | init(); 32 | } 33 | 34 | /** 35 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 36 | */ 37 | public static int dip2px(Context context, float dpValue) { 38 | final float scale = context.getResources().getDisplayMetrics().density; 39 | return (int) (dpValue * scale + 0.5f); 40 | } 41 | 42 | private void init() { 43 | mDstPath = new Path(); 44 | mCirclePath = new Path(); 45 | mCirclePath.addCircle(getWidth()/2,getHeight()/2, dip2px(getContext(),10), Path.Direction.CW); 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/advanced/PathMeasureActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.advanced; 2 | 3 | import android.graphics.Matrix; 4 | import android.graphics.Path; 5 | import android.graphics.PathMeasure; 6 | import android.os.Bundle; 7 | 8 | import androidstack.customview.R; 9 | import androidx.annotation.Nullable; 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | /** 13 | * Created on 2020/8/16 11:31 14 | * 15 | * @author zhangchaozhou 16 | * @email 13760289294@139.com 17 | * @wechat 13760289294 18 | */ 19 | public class PathMeasureActivity extends AppCompatActivity { 20 | private LoadingPathView mLoadingPathView; 21 | 22 | @Override 23 | protected void onCreate(@Nullable Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_path_measure); 26 | mLoadingPathView = findViewById(R.id.lpv_circle); 27 | } 28 | 29 | 30 | public void path() { 31 | 32 | Path path = new Path(); 33 | PathMeasure pathMeasure1 = new PathMeasure(); 34 | /** 35 | * 路径是否闭合 forceClosed 36 | */ 37 | pathMeasure1.setPath(path, true); 38 | 39 | 40 | PathMeasure pathMeasure2 = new PathMeasure(path, true); 41 | 42 | 43 | /** 44 | * 路径长度,测量的是当前路径状态的长度,如果forceClosed为true,则不论路径是否闭合,测量的都是路径的闭合长度。 45 | * 获取到的长度是当前曲线的长度。 46 | */ 47 | System.out.println(pathMeasure1.getLength()); 48 | 49 | System.out.println(pathMeasure2.getLength()); 50 | 51 | /** 52 | * 判断路径是否闭合 53 | */ 54 | System.out.println(pathMeasure1.isClosed()); 55 | 56 | 57 | /** 58 | * 跳转到下一条曲线,true表示跳转成功,false表示跳转失败。 59 | * 60 | */ 61 | System.out.println(pathMeasure1.nextContour()); 62 | 63 | 64 | /** 65 | * 通过nextContour得到的曲线的顺序和Path中添加的顺序相同。 66 | */ 67 | do { 68 | System.out.println(pathMeasure1.getLength()); 69 | } while (pathMeasure1.nextContour()); 70 | 71 | /** 72 | * 截取整个Path中startD到stopD的某个片段,如果不在范围则返回false,截取后添加Path到dst中。 73 | * startWithMoveTo:如果为true,则被截取的Path片段保持原状添加到dst中;如果为false,则被截取的Path片段的起始点移动到dst的最后一个点,保证dst路径的连续性。 74 | * 需要禁用硬件加速功能,setLayerType(LAYER_TYPE_SOFTWARE,null)。 75 | * 路径截取是以左上角顺时针Path.Direction.CW或逆时针Path.Direction.CCW截取。 76 | */ 77 | boolean isSuccess = pathMeasure1.getSegment(0, 10, new Path(), true); 78 | 79 | 80 | /** 81 | * 82 | * 获取路径上某一长度的位置以及该位置的正切值 83 | * distance:距离path起始点的长度,0<=distance<=pathMeasure1.getLength() 84 | * pos 位置的坐标值,pos[0]是x坐标,pos[1]是y坐标 85 | * tan 位置坐标的正切值,也就是坐标到原点与X轴所成夹角对应的正切值,tan[0]是x坐标,tan[1]是y坐标,是半径为1的圆的对应点,y/x就是正切值 86 | * 求反正切值,根据正切值获得对应夹角的度数,也就是反正切,atan(double d)传入弧度值也就是正切的结果值,atan2(double x, double y)传入正切的点的坐标值。 87 | * 如果想要让移动点旋转至与切线重合,则旋转角度要与正切角度相同。 88 | */ 89 | boolean isTanSuccess = pathMeasure1.getPosTan(1, new float[]{1F, 1F}, new float[]{1F, 1F}); 90 | 91 | 92 | /** 93 | * 得到路径上某一长度的位置,以及该位置的正切值的矩阵。 94 | * distance:距离Path起始点的长度 95 | * matrix:matrix会根据flags的设置而存入不同的内容。 96 | * flags:指定存入matrix中的内容。POSITION_MATRIX_FLAG:获取位置信息。TANGENT_MATRIX_FLAG:获取切边信息,使得图片按Path旋转。 97 | */ 98 | boolean isMatrixSuccess = pathMeasure1.getMatrix(1, new Matrix(), PathMeasure.POSITION_MATRIX_FLAG); 99 | 100 | 101 | /** 102 | * getMatrix()是getPosTan()函数的另一种实现。 103 | * getPosTan()将获取到的位置信息和切边信息存储在pos和tan数组中; 104 | * getMatrix()将位置信息和切边信息存储在matrix中。 105 | */ 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/interpolator/ReverseInterpolator.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.interpolator; 2 | 3 | import android.view.animation.Interpolator; 4 | 5 | /** 6 | * Created on 2020/8/15 09:29 7 | * 自定义插值器,实现时间插值器TimeInterpolator后,实现获取插值Interpolation的方法,此方法的实现需要数学知识。 8 | * 也可以直接实现Interpolator,因为Interpolator继承的是时间插值器TimeInterpolator。 9 | * 10 | * @author zhangchaozhou 11 | * @email 13760289294@139.com 12 | * @wechat 13760289294 13 | */ 14 | public class ReverseInterpolator implements Interpolator { 15 | 16 | /** 17 | * @param input 取值范围为0-1,表示当前动画进度,0刚开始动画,1结束动画,0-1,动画进行中。 18 | * @return 返回实际想要的进度,小于0表示小于开始位置,大于1表示超过目标位置,0-1表示在开始位置和目标位置中间。 19 | */ 20 | @Override 21 | public float getInterpolation(float input) { 22 | return 1 - input; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/advanced/PhoneActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.advanced; 2 | 3 | import android.animation.Keyframe; 4 | import android.animation.ObjectAnimator; 5 | import android.animation.PropertyValuesHolder; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | 10 | import androidstack.customview.R; 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | /** 15 | * Created on 2020/8/16 09:31 16 | * 17 | * @author zhangchaozhou 18 | * @email 13760289294@139.com 19 | * @wechat 13760289294 20 | */ 21 | public class PhoneActivity extends AppCompatActivity implements View.OnClickListener { 22 | private ImageView mIvPhone; 23 | 24 | @Override 25 | protected void onCreate(@Nullable Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_phone); 28 | mIvPhone = findViewById(R.id.iv_phone); 29 | mIvPhone.setOnClickListener(this); 30 | } 31 | 32 | @Override 33 | public void onClick(View v) { 34 | switch (v.getId()) { 35 | case R.id.iv_phone: 36 | //旋转效果,左右震动 37 | Keyframe keyframe1 = Keyframe.ofFloat(0f, 0); 38 | Keyframe keyframe2 = Keyframe.ofFloat(0.1f, -20f); 39 | Keyframe keyframe3 = Keyframe.ofFloat(0.2f, 20f); 40 | Keyframe keyframe4 = Keyframe.ofFloat(0.3f, -20f); 41 | Keyframe keyframe5 = Keyframe.ofFloat(0.4f, 20f); 42 | Keyframe keyframe6 = Keyframe.ofFloat(0.5f, -20f); 43 | Keyframe keyframe7 = Keyframe.ofFloat(0.6f, 20f); 44 | Keyframe keyframe8 = Keyframe.ofFloat(0.7f, -20f); 45 | Keyframe keyframe9 = Keyframe.ofFloat(0.8f, 20f); 46 | Keyframe keyframe10 = Keyframe.ofFloat(0.9f, -20f); 47 | Keyframe keyframe11 = Keyframe.ofFloat(1.0f, 0f); 48 | PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("rotation", 49 | keyframe1, keyframe1, keyframe2, keyframe3, keyframe4, keyframe5, 50 | keyframe6, keyframe7, keyframe8, keyframe9, keyframe10, keyframe11); 51 | //缩放效果 X 52 | Keyframe keyframeScaleX0 = Keyframe.ofFloat(0,1f); 53 | Keyframe keyframeScaleX1 = Keyframe.ofFloat(0.1f,1.1f); 54 | Keyframe keyframeScaleX9 = Keyframe.ofFloat(0.9f,1.1f); 55 | Keyframe keyframeScaleX10 = Keyframe.ofFloat(1f,1f); 56 | PropertyValuesHolder propertyValuesHolderScaleX = PropertyValuesHolder.ofKeyframe("ScaleX", 57 | keyframeScaleX0,keyframeScaleX1,keyframeScaleX9,keyframeScaleX10); 58 | 59 | //缩放效果 Y 60 | Keyframe keyframeScaleY0 = Keyframe.ofFloat(0,1f); 61 | Keyframe keyframeScaleY1 = Keyframe.ofFloat(0.1f,1.1f); 62 | Keyframe keyframeScaleY9 = Keyframe.ofFloat(0.9f,1.1f); 63 | Keyframe keyframeScaleY10 = Keyframe.ofFloat(1f,1f); 64 | PropertyValuesHolder propertyValuesHolderScaleY = PropertyValuesHolder.ofKeyframe("ScaleY", 65 | keyframeScaleY0,keyframeScaleY1,keyframeScaleY9,keyframeScaleY10); 66 | 67 | ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mIvPhone, 68 | propertyValuesHolder,propertyValuesHolderScaleX,propertyValuesHolderScaleY); 69 | objectAnimator.setDuration(1000); 70 | objectAnimator.start(); 71 | break; 72 | default: 73 | break; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/advanced/ViewGroupAnimateActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.advanced; 2 | 3 | import android.animation.LayoutTransition; 4 | import android.animation.ObjectAnimator; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | 9 | import androidstack.customview.R; 10 | import androidx.annotation.Nullable; 11 | import androidx.appcompat.app.AppCompatActivity; 12 | import androidx.constraintlayout.widget.ConstraintLayout; 13 | 14 | /** 15 | * Created on 2020/8/16 10:36 16 | *

17 | * LayoutAnimation:ListView的进场动画 18 | * GridLayoutAnimation:GridView的进场动画 19 | * android:animateLayoutChanges属性:ViewGroup添加删除子View默认动画 20 | * 布局动画 LayoutTransition:ViewGroup添加删除子View添加删除的自定义动画 21 | *

22 | * LayoutTransition.APPEARING;新元素在容器中出现时的动画; 23 | * LayoutTransition.CHANGE_APPEARING;容器中显示新元素,其他元素需要变化时的动画; 24 | * LayoutTransition.CHANGE_DISAPPEARING;容器中移除旧元素,其他元素需要变化时的动画; 25 | * LayoutTransition.CHANGING; 26 | * LayoutTransition.DISAPPEARING;旧元素在容器中移除时的动画; 27 | * 28 | * @author zhangchaozhou 29 | * @email 13760289294@139.com 30 | * @wechat 13760289294 31 | */ 32 | public class ViewGroupAnimateActivity extends AppCompatActivity implements View.OnClickListener { 33 | private ConstraintLayout mClLayoutTransition; 34 | private ImageView mIvTest; 35 | 36 | @Override 37 | protected void onCreate(@Nullable Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_view_group_animate); 40 | mClLayoutTransition = findViewById(R.id.cl_layout_transition); 41 | mIvTest = findViewById(R.id.iv_test); 42 | mIvTest.setOnClickListener(this); 43 | 44 | /** 45 | * 设置移除容器内图片控件时候的动画 46 | */ 47 | LayoutTransition layoutTransition = new LayoutTransition(); 48 | ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(null, "rotation", 0f, 90f, 0f); 49 | layoutTransition.setAnimator(LayoutTransition.DISAPPEARING, objectAnimator); 50 | /** 51 | * 设置动画间的间隔 52 | */ 53 | layoutTransition.setStagger(LayoutTransition.DISAPPEARING, 1000); 54 | mClLayoutTransition.setLayoutTransition(layoutTransition); 55 | 56 | } 57 | 58 | @Override 59 | public void onClick(View v) { 60 | switch (v.getId()) { 61 | case R.id.iv_test: 62 | /** 63 | * 移除布局 64 | */ 65 | mClLayoutTransition.removeView(mIvTest); 66 | break; 67 | default: 68 | break; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/evaluator/CharEvaluator.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.evaluator; 2 | 3 | import android.animation.TypeEvaluator; 4 | 5 | /** 6 | * Created on 2020/8/15 15:00 7 | * 8 | * @author zhangchaozhou 9 | * @email 13760289294@139.com 10 | * @wechat 13760289294 11 | */ 12 | public class CharEvaluator implements TypeEvaluator { 13 | @Override 14 | public Character evaluate(float fraction, Character startValue, Character endValue) { 15 | char currentChar = (char) (startValue+fraction*(endValue-startValue)); 16 | return currentChar; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/evaluator/ReverseEvaluator.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.evaluator; 2 | 3 | import android.animation.TypeEvaluator; 4 | 5 | /** 6 | * Created on 2020/8/15 11:24 7 | * 自定义估值器,实现类型估值器TypeEvaluator,并传入泛型的具体类型 8 | * 9 | * @author zhangchaozhou 10 | * @email 13760289294@139.com 11 | * @wechat 13760289294 12 | */ 13 | public class ReverseEvaluator implements TypeEvaluator { 14 | 15 | /** 16 | * @param fraction 插值器中的进度返回值 17 | * @param startValue 动画数值区间的起始数值 18 | * @param endValue 动画数值区间的结束数值 19 | * @return 估值器返回给监听器的具体动画数值 20 | */ 21 | @Override 22 | public Integer evaluate(float fraction, Integer startValue, Integer endValue) { 23 | return (int) (endValue - fraction * (endValue - startValue)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/object/FallingBallObjectActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.object; 2 | 3 | import android.animation.ObjectAnimator; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import androidstack.customview.R; 9 | import androidstack.customview.animation.property.value.FallingBallEvaluator; 10 | import androidx.annotation.Nullable; 11 | import androidx.appcompat.app.AppCompatActivity; 12 | 13 | /** 14 | * Created on 2020/8/15 15:55 15 | * 16 | * @author zhangchaozhou 17 | * @email 13760289294@139.com 18 | * @wechat 13760289294 19 | */ 20 | public class FallingBallObjectActivity extends AppCompatActivity implements View.OnClickListener { 21 | private FallingImageView mIvBall; 22 | @Override 23 | protected void onCreate(@Nullable Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_falling_ball_object); 26 | mIvBall = findViewById(R.id.iv_ball); 27 | mIvBall.setOnClickListener(this); 28 | } 29 | 30 | @Override 31 | public void onClick(View v) { 32 | switch (v.getId()){ 33 | case R.id.iv_ball: 34 | ObjectAnimator objectAnimator = ObjectAnimator.ofObject(mIvBall,"fallingPos",new FallingBallEvaluator(),new Point(0,0),new Point(500,500)); 35 | objectAnimator.setDuration(2000); 36 | objectAnimator.start(); 37 | break; 38 | default: 39 | break; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/object/FallingImageView.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.object; 2 | 3 | import android.content.Context; 4 | import android.graphics.Point; 5 | import android.util.AttributeSet; 6 | 7 | /** 8 | * Created on 2020/8/15 16:59 9 | * 10 | * @author zhangchaozhou 11 | * @email 13760289294@139.com 12 | * @wechat 13760289294 13 | */ 14 | public class FallingImageView extends androidx.appcompat.widget.AppCompatImageView { 15 | 16 | public FallingImageView(Context context) { 17 | super(context); 18 | } 19 | 20 | public FallingImageView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public FallingImageView(Context context, AttributeSet attrs, int defStyleAttr) { 25 | super(context, attrs, defStyleAttr); 26 | } 27 | 28 | /** 29 | * 对象动画会使用反射自动调用此set方法 30 | * @param point 31 | */ 32 | public void setFallingPos(Point point){ 33 | layout(point.x,point.y,point.x+getWidth(),point.y+getHeight()); 34 | } 35 | 36 | /** 37 | * 当指定一个动画值时,动画会通过get方法来获取初始值,否则会崩溃 38 | * @return 39 | */ 40 | public Point getFallingPos(){ 41 | return new Point(0,0); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/object/ObjectAnimatorActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.object; 2 | 3 | import android.animation.ObjectAnimator; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | 8 | import androidstack.customview.R; 9 | import androidx.annotation.Nullable; 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | /** 13 | * Created on 2020/8/15 16:25 14 | * 对象动画继承自值动画,让动画直接与控件关联,解放监听过程 15 | * 对象动画是通过控件中相关的set方法进行操作的,View已经实现了alpha、rotation、translate、scale等相关方法。 16 | * setTranslationX(float translationX) 17 | * setTranslationY(float translationY) 18 | * setTranslationZ(float translationZ) 19 | * setScaleX(float scaleX) 20 | * setScaleY(float scaleY) 21 | *

22 | * 属性动画之对象动画: 23 | * 1、指定动画数值区间以及属性和控件 24 | * 2、指定插值器,定义动画数值的进度变化规律 25 | * 3、指定估值器,根据插值器的进度变化规律,计算具体的动画数值 26 | * 4、系统自定调用控件的set方法,根据属性拼装set方法并反射调用,并将当前值作为参数传入 27 | * 28 | * @author zhangchaozhou 29 | * @email 13760289294@139.com 30 | * @wechat 13760289294 31 | */ 32 | public class ObjectAnimatorActivity extends AppCompatActivity implements View.OnClickListener { 33 | private ImageView mIvBall; 34 | 35 | @Override 36 | protected void onCreate(@Nullable Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_object_animator); 39 | mIvBall = findViewById(R.id.iv_ball); 40 | mIvBall.setOnClickListener(this); 41 | } 42 | 43 | /** 44 | * 根据ImageView的setAlpha(int alpha)方法设置 45 | */ 46 | public void alpha() { 47 | ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mIvBall, "alpha", 1, 0, 1); 48 | objectAnimator.setDuration(2000); 49 | objectAnimator.start(); 50 | } 51 | 52 | /** 53 | * 通过View的setRotation(float rotation)方法设置 54 | * setRotationY(float rotationY) 55 | * setRotationX(float rotationX) 56 | */ 57 | public void rotation() { 58 | ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mIvBall, "rotation", 0, 180, 0); 59 | objectAnimator.setDuration(2000); 60 | objectAnimator.start(); 61 | } 62 | 63 | @Override 64 | public void onClick(View v) { 65 | switch (v.getId()) { 66 | case R.id.iv_ball: 67 | // alpha(); 68 | rotation(); 69 | break; 70 | default: 71 | break; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/value/FallingBallEvaluator.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.value; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.graphics.Point; 5 | 6 | /** 7 | * Created on 2020/8/15 15:56 8 | * 自定义估值器,一般与自定义View配合使用 9 | * @author zhangchaozhou 10 | * @email 13760289294@139.com 11 | * @wechat 13760289294 12 | */ 13 | public class FallingBallEvaluator implements TypeEvaluator { 14 | private Point mPoint = new Point(); 15 | @Override 16 | public Point evaluate(float fraction, Point startValue, Point endValue) { 17 | mPoint.x = (int)(startValue.x+fraction*(endValue.x-startValue.x)); 18 | if (fraction*2<1){ 19 | mPoint.y = (int) (startValue.y+fraction*2*(endValue.y-startValue.y)); 20 | }else { 21 | mPoint.y = endValue.y; 22 | } 23 | return mPoint; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/value/FallingBallValueActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.value; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | 9 | import androidstack.customview.R; 10 | import androidx.annotation.Nullable; 11 | import androidx.appcompat.app.AppCompatActivity; 12 | 13 | /** 14 | * Created on 2020/8/15 15:55 15 | * 16 | * @author zhangchaozhou 17 | * @email 13760289294@139.com 18 | * @wechat 13760289294 19 | */ 20 | public class FallingBallValueActivity extends AppCompatActivity implements View.OnClickListener { 21 | private ImageView mIvBall; 22 | @Override 23 | protected void onCreate(@Nullable Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_falling_ball_value); 26 | mIvBall = findViewById(R.id.iv_ball); 27 | mIvBall.setOnClickListener(this); 28 | } 29 | private Point mPoint=null; 30 | @Override 31 | public void onClick(View v) { 32 | switch (v.getId()){ 33 | case R.id.iv_ball: 34 | ValueAnimator animator = ValueAnimator.ofObject(new FallingBallEvaluator(),new Point(0,0),new Point(500,500)); 35 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 36 | @Override 37 | public void onAnimationUpdate(ValueAnimator animation) { 38 | mPoint = (Point) animation.getAnimatedValue(); 39 | mIvBall.layout(mPoint.x,mPoint.y,mPoint.x+mIvBall.getWidth(),mPoint.y+mIvBall.getHeight()); 40 | } 41 | }); 42 | animator.setDuration(2000); 43 | animator.start(); 44 | break; 45 | default: 46 | break; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/property/value/LoadingImageView.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.property.value; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ValueAnimator; 5 | import android.content.Context; 6 | import android.util.AttributeSet; 7 | 8 | import androidstack.customview.R; 9 | import androidstack.customview.animation.interpolator.ReverseInterpolator; 10 | 11 | /** 12 | * Created on 2020/8/14 20:29 13 | * 自定义加载ImageView 14 | * 15 | * @author zhangchaozhou 16 | * @email 13760289294@139.com 17 | * @wechat 13760289294 18 | */ 19 | public class LoadingImageView extends androidx.appcompat.widget.AppCompatImageView { 20 | private int mTop; 21 | private int mCurrRepeatCount = 0; 22 | private int mImageCount = 3; 23 | 24 | public LoadingImageView(Context context) { 25 | this(context, null); 26 | } 27 | 28 | public LoadingImageView(Context context, AttributeSet attrs) { 29 | this(context, attrs, 0); 30 | } 31 | 32 | public LoadingImageView(Context context, AttributeSet attrs, int defStyleAttr) { 33 | super(context, attrs, defStyleAttr); 34 | initData(); 35 | } 36 | 37 | private void initData() { 38 | ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100, 0); 39 | valueAnimator.setRepeatMode(ValueAnimator.REVERSE); 40 | valueAnimator.setRepeatCount(ValueAnimator.INFINITE); 41 | valueAnimator.setDuration(2000); 42 | valueAnimator.setInterpolator(new ReverseInterpolator()); 43 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 44 | @Override 45 | public void onAnimationUpdate(ValueAnimator animation) { 46 | int dy = (int) animation.getAnimatedValue(); 47 | /** 48 | * 监听动画取值,根据取值改变空间的位置 49 | */ 50 | setTop(mTop - dy); 51 | } 52 | }); 53 | valueAnimator.addListener(new Animator.AnimatorListener() { 54 | @Override 55 | public void onAnimationStart(Animator animation) { 56 | setImageDrawable(getResources().getDrawable(R.mipmap.ic_test)); 57 | 58 | } 59 | 60 | @Override 61 | public void onAnimationEnd(Animator animation) { 62 | 63 | } 64 | 65 | @Override 66 | public void onAnimationCancel(Animator animation) { 67 | 68 | } 69 | 70 | @Override 71 | public void onAnimationRepeat(Animator animation) { 72 | /** 73 | * 通过对动画的重复次数的监听,改变空间的图片资源 74 | */ 75 | mCurrRepeatCount++; 76 | switch (mCurrRepeatCount % mImageCount) { 77 | case 0: 78 | setImageDrawable(getResources().getDrawable(R.mipmap.ic_test)); 79 | break; 80 | case 1: 81 | setImageDrawable(getResources().getDrawable(R.mipmap.ic_loading)); 82 | break; 83 | case 2: 84 | setImageDrawable(getResources().getDrawable(R.mipmap.ic_scanner)); 85 | break; 86 | default: 87 | break; 88 | } 89 | } 90 | }); 91 | valueAnimator.start(); 92 | 93 | } 94 | 95 | 96 | @Override 97 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 98 | super.onLayout(changed, left, top, right, bottom); 99 | /** 100 | * 获取初始top 101 | */ 102 | mTop = top; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/ViewAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | 8 | import androidstack.customview.R; 9 | import androidstack.customview.animation.view.frame.FrameAnimationActivity; 10 | import androidstack.customview.animation.view.tween.TweenAnimationActivity; 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | /** 15 | * Created on 2020/8/12 18:15 16 | * 17 | * @author zhangchaozhou 18 | * @email 13760289294@139.com 19 | * @wechat 13760289294 20 | */ 21 | public class ViewAnimationActivity extends AppCompatActivity implements View.OnClickListener { 22 | private Button mBtnTween; 23 | private Button mBtnFrame; 24 | 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_view_animation); 29 | mBtnTween = findViewById(R.id.btn_tween_animation); 30 | mBtnTween.setOnClickListener(this); 31 | 32 | mBtnFrame = findViewById(R.id.btn_frame_animation); 33 | mBtnFrame.setOnClickListener(this); 34 | } 35 | 36 | @Override 37 | public void onClick(View v) { 38 | switch (v.getId()) { 39 | case R.id.btn_tween_animation: 40 | startActivity(new Intent(this, TweenAnimationActivity.class)); 41 | break; 42 | 43 | case R.id.btn_frame_animation: 44 | startActivity(new Intent(this, FrameAnimationActivity.class)); 45 | break; 46 | default: 47 | break; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/frame/FrameAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.frame; 2 | 3 | import android.graphics.drawable.AnimationDrawable; 4 | import android.graphics.drawable.Drawable; 5 | import android.os.Bundle; 6 | import android.widget.ImageView; 7 | 8 | import androidstack.customview.R; 9 | import androidx.annotation.Nullable; 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | /** 13 | * Created on 2020/8/12 18:15 14 | * 15 | * @author zhangchaozhou 16 | * @email 13760289294@139.com 17 | * @wechat 13760289294 18 | */ 19 | public class FrameAnimationActivity extends AppCompatActivity { 20 | 21 | private ImageView mIvLoading; 22 | 23 | private ImageView mIvLoadingCode; 24 | 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_frame_animation); 29 | mIvLoading = findViewById(R.id.iv_loading); 30 | mIvLoadingCode = findViewById(R.id.iv_loading_code); 31 | codeAnimation(); 32 | xmlAnimation(); 33 | } 34 | 35 | 36 | /** 37 | * oneshot 表示是否只执行一次 38 | */ 39 | public void codeAnimation() { 40 | int num = 10; 41 | AnimationDrawable animationDrawable = new AnimationDrawable(); 42 | for (int i = 1; i <= num; i++) { 43 | int id = getResources().getIdentifier("loading_0" + i, "mipmap", getPackageName()); 44 | Drawable drawable = getResources().getDrawable(id); 45 | animationDrawable.addFrame(drawable, 50); 46 | } 47 | animationDrawable.setOneShot(false); 48 | mIvLoadingCode.setBackgroundDrawable(animationDrawable); 49 | animationDrawable.start(); 50 | } 51 | 52 | 53 | private void xmlAnimation() { 54 | AnimationDrawable animationDrawable = (AnimationDrawable) mIvLoading.getDrawable(); 55 | animationDrawable.start(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/AlphaAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.view.animation.AlphaAnimation; 6 | import android.view.animation.Animation; 7 | import android.view.animation.AnimationUtils; 8 | import android.widget.ImageView; 9 | 10 | import androidstack.customview.R; 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | /** 15 | * Created on 2020/8/12 18:06 16 | * 17 | * @author zhangchaozhou 18 | * @email 13760289294@139.com 19 | * @wechat 13760289294 20 | */ 21 | public class AlphaAnimationActivity extends AppCompatActivity implements View.OnClickListener { 22 | 23 | 24 | private ImageView mIvTest; 25 | 26 | @Override 27 | protected void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_alpha_animation); 30 | mIvTest = findViewById(R.id.iv_test); 31 | mIvTest.setOnClickListener(this); 32 | } 33 | 34 | private void codeAnimation() { 35 | AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f,0.1f); 36 | alphaAnimation.setDuration(1000); 37 | alphaAnimation.setRepeatCount(Animation.INFINITE); 38 | alphaAnimation.setRepeatMode(Animation.REVERSE); 39 | mIvTest.startAnimation(alphaAnimation); 40 | } 41 | 42 | private void xmlAnimation() { 43 | Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha_test); 44 | mIvTest.startAnimation(animation); 45 | } 46 | 47 | /** 48 | * 54 | * 55 | * 动画开始时的透明度:0-1 56 | * 动画结束时的透明度:0-1 57 | * 58 | * @param v 59 | */ 60 | @Override 61 | public void onClick(View v) { 62 | switch (v.getId()) { 63 | case R.id.iv_test: 64 | codeAnimation(); 65 | // xmlAnimation(); 66 | break; 67 | default: 68 | break; 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/RotateAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.view.animation.Animation; 6 | import android.view.animation.AnimationUtils; 7 | import android.view.animation.RotateAnimation; 8 | import android.widget.ImageView; 9 | 10 | import androidstack.customview.R; 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | /** 15 | * Created on 2020/8/12 18:06 16 | * 17 | * @author zhangchaozhou 18 | * @email 13760289294@139.com 19 | * @wechat 13760289294 20 | */ 21 | public class RotateAnimationActivity extends AppCompatActivity implements View.OnClickListener { 22 | 23 | 24 | private ImageView mIvTest; 25 | 26 | @Override 27 | protected void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_rotate_animation); 30 | mIvTest = findViewById(R.id.iv_test); 31 | mIvTest.setOnClickListener(this); 32 | } 33 | 34 | 35 | 36 | private void codeAnimation(){ 37 | RotateAnimation rotateAnimation = new RotateAnimation(90,-270,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f); 38 | rotateAnimation.setDuration(1000); 39 | rotateAnimation.setRepeatCount(Animation.INFINITE); 40 | rotateAnimation.setRepeatMode(Animation.REVERSE); 41 | mIvTest.startAnimation(rotateAnimation); 42 | } 43 | private void xmlAnimation() { 44 | Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate_test); 45 | mIvTest.startAnimation(animation); 46 | } 47 | /** 48 | * 59 | * 60 | * 动画开始旋转时的角度位置:正数顺时针,负数逆时针 61 | * 动画结束旋转时的角度位置:正数顺时针,负数逆时针 62 | * 63 | * @param v 64 | */ 65 | @Override 66 | public void onClick(View v) { 67 | switch (v.getId()) { 68 | case R.id.iv_test: 69 | codeAnimation(); 70 | // xmlAnimation(); 71 | break; 72 | default: 73 | break; 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/ScaleAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.view.animation.AccelerateInterpolator; 6 | import android.view.animation.Animation; 7 | import android.view.animation.AnimationUtils; 8 | import android.view.animation.ScaleAnimation; 9 | import android.widget.ImageView; 10 | 11 | import androidstack.customview.R; 12 | import androidx.annotation.Nullable; 13 | import androidx.appcompat.app.AppCompatActivity; 14 | 15 | /** 16 | * Created on 2020/8/12 17:43 17 | * pivot:枢轴 中心点 18 | * 19 | * @author zhangchaozhou 20 | * @email 13760289294@139.com 21 | * @wechat 13760289294 22 | */ 23 | public class ScaleAnimationActivity extends AppCompatActivity implements View.OnClickListener { 24 | 25 | private ImageView mIvTest; 26 | 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_scale_animation); 31 | mIvTest = findViewById(R.id.iv_test); 32 | mIvTest.setOnClickListener(this); 33 | } 34 | 35 | 36 | private void codeAnimation() { 37 | ScaleAnimation scaleAnimation = new ScaleAnimation(1.5f,0.5f,1.5f,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f); 38 | scaleAnimation.setDuration(1000); 39 | scaleAnimation.setFillAfter(true); 40 | scaleAnimation.setFillBefore(false); 41 | scaleAnimation.setFillEnabled(false); 42 | scaleAnimation.setRepeatCount(Animation.INFINITE); 43 | scaleAnimation.setRepeatMode(Animation.REVERSE); 44 | scaleAnimation.setInterpolator(new AccelerateInterpolator()); 45 | mIvTest.startAnimation(scaleAnimation); 46 | } 47 | 48 | private void xmlAnimation() { 49 | Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale_test); 50 | mIvTest.startAnimation(animation); 51 | } 52 | 53 | /** 54 | * 68 | * 69 | * 完成一次动画的持续时间,单位毫秒 70 | * 动画结束后,停留在结束时的状态 71 | * 动画结束后,回到开始前的状态 72 | * 动画结束后,回到开始前的状态 73 | * 动画开始时空间在X轴相对自身的缩放比例 74 | * 动画开始时空间在Y轴相对自身的缩放比例 75 | * 插值器:指定动画效果 76 | * 缩放起始点X轴坐标:以当前控件的左上角为原点加上:数值、百分数(自身宽度的百分数)、百分数p(父控件宽度的百分数) 77 | * 缩放起始点Y轴坐标:以当前控件的左上角为原点加上:数值、百分数(自身高度的百分数)、百分数p(父控件高度的百分数) 78 | * 重复次数:infinite为无限循环 79 | * 重复模式:reverse为倒序回放;restart为重放,且必须与repeatCount一起使用 80 | * 动画结束时空间在X轴相对自身的缩放比例 81 | * 动画结束时空间在Y轴相对自身的缩放比例 82 | * 83 | * @param v 84 | */ 85 | @Override 86 | public void onClick(View v) { 87 | switch (v.getId()) { 88 | case R.id.iv_test: 89 | codeAnimation(); 90 | // xmlAnimation(); 91 | break; 92 | default: 93 | break; 94 | } 95 | } 96 | 97 | 98 | 99 | 100 | } 101 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/TranslateAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.view.animation.Animation; 6 | import android.view.animation.AnimationUtils; 7 | import android.view.animation.TranslateAnimation; 8 | import android.widget.ImageView; 9 | 10 | import androidstack.customview.R; 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | /** 15 | * Created on 2020/8/12 17:43 16 | * 17 | * @author zhangchaozhou 18 | * @email 13760289294@139.com 19 | * @wechat 13760289294 20 | */ 21 | public class TranslateAnimationActivity extends AppCompatActivity implements View.OnClickListener { 22 | 23 | private ImageView mIvTest; 24 | 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_translate_animation); 29 | mIvTest = findViewById(R.id.iv_test); 30 | mIvTest.setOnClickListener(this); 31 | } 32 | 33 | 34 | private void codeAnimation() { 35 | TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.1f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0.1f, Animation.RELATIVE_TO_SELF, 1.0f); 36 | translateAnimation.setDuration(1000); 37 | translateAnimation.setRepeatCount(Animation.INFINITE); 38 | translateAnimation.setRepeatMode(Animation.REVERSE); 39 | mIvTest.startAnimation(translateAnimation); 40 | } 41 | 42 | private void xmlAnimation() { 43 | Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate_test); 44 | mIvTest.startAnimation(animation); 45 | } 46 | 47 | 48 | /** 49 | * 58 | * 59 | * 起始点X轴坐标 60 | * 起始点Y轴坐标 61 | * 结束点X轴坐标 62 | * 结束点Y轴坐标 63 | * 64 | * @param v 65 | */ 66 | @Override 67 | public void onClick(View v) { 68 | switch (v.getId()) { 69 | case R.id.iv_test: 70 | codeAnimation(); 71 | // xmlAnimation(); 72 | break; 73 | default: 74 | break; 75 | } 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/TweenAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | 8 | import androidstack.customview.R; 9 | import androidstack.customview.animation.view.tween.effect.CameraActivity; 10 | import androidstack.customview.animation.view.tween.effect.LoadingActivity; 11 | import androidstack.customview.animation.view.tween.effect.ScannerActivity; 12 | import androidx.annotation.Nullable; 13 | import androidx.appcompat.app.AppCompatActivity; 14 | 15 | /** 16 | * Created on 2020/8/12 18:12 17 | * 18 | * @author zhangchaozhou 19 | * @email 13760289294@139.com 20 | * @wechat 13760289294 21 | */ 22 | public class TweenAnimationActivity extends AppCompatActivity implements View.OnClickListener { 23 | 24 | private Button mBtnScale; 25 | private Button mBtnAlpha; 26 | private Button mBtnTranslate; 27 | private Button mBtnRotate; 28 | private Button mBtnSet; 29 | private Button mBtnCamera; 30 | private Button mBtnLoading; 31 | private Button mBtnScanner; 32 | @Override 33 | protected void onCreate(@Nullable Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_tween_animation); 36 | mBtnScale = findViewById(R.id.btn_scale_animation); 37 | mBtnScale.setOnClickListener(this); 38 | mBtnAlpha = findViewById(R.id.btn_alpha_animation); 39 | mBtnAlpha.setOnClickListener(this); 40 | mBtnTranslate = findViewById(R.id.btn_translate_animation); 41 | mBtnTranslate.setOnClickListener(this); 42 | mBtnRotate = findViewById(R.id.btn_rotate_animation); 43 | mBtnRotate.setOnClickListener(this); 44 | mBtnSet = findViewById(R.id.btn_set_animation); 45 | mBtnSet.setOnClickListener(this); 46 | mBtnCamera = findViewById(R.id.btn_camera); 47 | mBtnCamera.setOnClickListener(this); 48 | mBtnLoading = findViewById(R.id.btn_loading); 49 | mBtnLoading.setOnClickListener(this); 50 | mBtnScanner = findViewById(R.id.btn_scanner); 51 | mBtnScanner.setOnClickListener(this); 52 | } 53 | 54 | @Override 55 | public void onClick(View v) { 56 | switch (v.getId()){ 57 | case R.id.btn_scale_animation: 58 | startActivity(new Intent(this,ScaleAnimationActivity.class)); 59 | break; 60 | case R.id.btn_alpha_animation: 61 | startActivity(new Intent(this,AlphaAnimationActivity.class)); 62 | break; 63 | case R.id.btn_translate_animation: 64 | startActivity(new Intent(this,TranslateAnimationActivity.class)); 65 | break; 66 | case R.id.btn_rotate_animation: 67 | startActivity(new Intent(this,RotateAnimationActivity.class)); 68 | break; 69 | case R.id.btn_set_animation: 70 | startActivity(new Intent(this,SetAnimationActivity.class)); 71 | break; 72 | case R.id.btn_camera: 73 | startActivity(new Intent(this, CameraActivity.class)); 74 | break; 75 | case R.id.btn_loading: 76 | startActivity(new Intent(this, LoadingActivity.class)); 77 | break; 78 | 79 | case R.id.btn_scanner: 80 | startActivity(new Intent(this, ScannerActivity.class)); 81 | break; 82 | default: 83 | break; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/effect/CameraActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween.effect; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.view.animation.Animation; 6 | import android.view.animation.BounceInterpolator; 7 | import android.view.animation.ScaleAnimation; 8 | import android.widget.ImageView; 9 | 10 | import androidstack.customview.R; 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | /** 15 | * Created on 2020/8/13 12:56 16 | * 17 | * @author zhangchaozhou 18 | * @email 13760289294@139.com 19 | * @wechat 13760289294 20 | */ 21 | public class CameraActivity extends AppCompatActivity implements View.OnClickListener { 22 | private ImageView mIvTest; 23 | @Override 24 | protected void onCreate(@Nullable Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_camera); 27 | mIvTest = findViewById(R.id.iv_test); 28 | mIvTest.setOnClickListener(this); 29 | } 30 | 31 | @Override 32 | public void onClick(View v) { 33 | switch (v.getId()){ 34 | case R.id.iv_test: 35 | ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f,1.2f,1.0f,1.2f, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f); 36 | scaleAnimation.setDuration(6000); 37 | scaleAnimation.setFillAfter(true); 38 | scaleAnimation.setInterpolator(new BounceInterpolator()); 39 | mIvTest.startAnimation(scaleAnimation); 40 | break; 41 | default: 42 | break; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/effect/LoadingActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween.effect; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.view.animation.Animation; 6 | import android.view.animation.LinearInterpolator; 7 | import android.view.animation.RotateAnimation; 8 | import android.widget.ImageView; 9 | 10 | import androidstack.customview.R; 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | /** 15 | * Created on 2020/8/13 13:12 16 | * 17 | * @author zhangchaozhou 18 | * @email 13760289294@139.com 19 | * @wechat 13760289294 20 | */ 21 | public class LoadingActivity extends AppCompatActivity implements View.OnClickListener { 22 | private ImageView mIvTest; 23 | 24 | @Override 25 | protected void onCreate(@Nullable Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_loading); 28 | mIvTest = findViewById(R.id.iv_test); 29 | mIvTest.setOnClickListener(this); 30 | } 31 | 32 | 33 | 34 | private void codeAnimation(){ 35 | RotateAnimation rotateAnimation = new RotateAnimation(0,360, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f); 36 | rotateAnimation.setDuration(2000); 37 | rotateAnimation.setRepeatCount(Animation.INFINITE); 38 | rotateAnimation.setInterpolator(new LinearInterpolator()); 39 | mIvTest.startAnimation(rotateAnimation); 40 | } 41 | 42 | 43 | @Override 44 | public void onClick(View v) { 45 | switch (v.getId()) { 46 | case R.id.iv_test: 47 | codeAnimation(); 48 | break; 49 | default: 50 | break; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/animation/view/tween/effect/ScannerActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.animation.view.tween.effect; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.view.animation.Animation; 6 | import android.view.animation.AnimationUtils; 7 | import android.widget.ImageView; 8 | 9 | import androidstack.customview.R; 10 | import androidx.annotation.Nullable; 11 | import androidx.appcompat.app.AppCompatActivity; 12 | 13 | /** 14 | * Created on 2020/8/13 13:23 15 | * 16 | * @author zhangchaozhou 17 | * @email 13760289294@139.com 18 | * @wechat 13760289294 19 | */ 20 | public class ScannerActivity extends AppCompatActivity implements View.OnClickListener { 21 | private View mIv1; 22 | private View mIv2; 23 | private View mIv3; 24 | private View mIv4; 25 | private ImageView mIvScanner; 26 | 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_music); 31 | mIv1 = findViewById(R.id.iv_1); 32 | mIv2 = findViewById(R.id.iv_2); 33 | mIv3 = findViewById(R.id.iv_3); 34 | mIv4 = findViewById(R.id.iv_4); 35 | mIvScanner = findViewById(R.id.iv_scanner); 36 | mIvScanner.setOnClickListener(this); 37 | 38 | 39 | } 40 | 41 | @Override 42 | public void onClick(View v) { 43 | switch (v.getId()){ 44 | case R.id.iv_scanner: 45 | 46 | Animation animation1 = AnimationUtils.loadAnimation(this,R.anim.set_sanner); 47 | Animation animation2 = AnimationUtils.loadAnimation(this,R.anim.set_sanner); 48 | Animation animation3 = AnimationUtils.loadAnimation(this,R.anim.set_sanner); 49 | Animation animation4 = AnimationUtils.loadAnimation(this,R.anim.set_sanner); 50 | mIv1.startAnimation(animation1); 51 | animation2.setStartOffset(600); 52 | mIv2.startAnimation(animation2); 53 | 54 | animation3.setStartOffset(1200); 55 | mIv3.startAnimation(animation3); 56 | 57 | animation4.setStartOffset(1800); 58 | mIv4.startAnimation(animation4); 59 | break; 60 | default: 61 | break; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/custom/CustomProgressActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.custom; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | 6 | import androidstack.customview.R; 7 | import androidstack.customview.view.CustomProgressView; 8 | import androidx.annotation.Nullable; 9 | import androidx.appcompat.app.AppCompatActivity; 10 | 11 | /** 12 | * Created on 2020/8/13 23:44 13 | * 14 | * @author zhangchaozhou 15 | * @email 13760289294@139.com 16 | * @wechat 13760289294 17 | */ 18 | public class CustomProgressActivity extends AppCompatActivity { 19 | 20 | private CustomProgressView mCustomProgressView; 21 | @Override 22 | protected void onCreate(@Nullable Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_custom_progress); 25 | 26 | mCustomProgressView = findViewById(R.id.cpv); 27 | mCustomProgressView.setProgressMax(100); 28 | mCustomProgressView.setCpBackgroundColor(Color.parseColor("#FFF3F3")); 29 | mCustomProgressView.setCpPercentTextcolor(Color.parseColor("#666666")); 30 | mCustomProgressView.setCpProgressColor(Color.parseColor("#FEC7CD")); 31 | mCustomProgressView.setProgressCurrent(40); 32 | mCustomProgressView.setCpBackgroundIsStroke(false); 33 | mCustomProgressView.setCpPercentTextsize(40); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/drawing/PaintActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.drawing; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidstack.customview.R; 6 | import androidx.annotation.Nullable; 7 | import androidx.appcompat.app.AppCompatActivity; 8 | 9 | /** 10 | * Created on 2020/8/19 23:08 11 | * 12 | * @author zhangchaozhou 13 | * @email 13760289294@139.com 14 | * @wechat 13760289294 15 | */ 16 | public class PaintActivity extends AppCompatActivity { 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_paint); 21 | } 22 | /** 23 | * 硬件加速:GPU 图形处理器,全称Graphic Processing Unit,专门处理多媒体的计算、存储任务。 24 | * Android11之前没有GPU硬件加速; 25 | * Android11-13:有GPU硬件加速,但是默认关闭; 26 | * Android14开始:默认开启硬件加速。 27 | */ 28 | 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/drawing/matrix/MatrixActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.drawing.matrix; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidstack.customview.R; 6 | import androidx.annotation.Nullable; 7 | import androidx.appcompat.app.AppCompatActivity; 8 | 9 | /** 10 | * Created on 2020/8/18 18:09 11 | * 12 | * @author zhangchaozhou 13 | * @email 13760289294@139.com 14 | * @wechat 13760289294 15 | */ 16 | public class MatrixActivity extends AppCompatActivity { 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_matrix); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/rv/layoutmanager/CardActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.rv.layoutmanager; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import androidx.appcompat.app.AppCompatActivity; 11 | import androidx.recyclerview.widget.RecyclerView; 12 | 13 | import java.util.Random; 14 | 15 | import androidstack.customview.R; 16 | 17 | public class CardActivity extends AppCompatActivity { 18 | 19 | private static final int[] COLORS = {0xff00FFFF, 0xffDEB887, 0xff5F9EA0, 20 | 0xff7FFF00, 0xff6495ED, 0xffDC143C, 21 | 0xff008B8B, 0xff006400, 0xff2F4F4F, 22 | 0xffFF69B4, 0xffFF00FF, 0xffCD5C5C, 23 | 0xff90EE90, 0xff87CEFA, 0xff800000}; 24 | 25 | private RecyclerView mRecyclerView; 26 | private Adapter mAdapter = new Adapter(); 27 | 28 | private int mCount = 50; 29 | private int mGroupSize = 3; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_card); 35 | mRecyclerView = (RecyclerView) findViewById(R.id.list); 36 | init(); 37 | } 38 | 39 | private void init() { 40 | mRecyclerView.setLayoutManager(new CardLayoutManager(mGroupSize, true)); 41 | mRecyclerView.setAdapter(mAdapter); 42 | } 43 | 44 | public void add(View view) { 45 | mCount += 10; 46 | mAdapter.notifyDataSetChanged(); 47 | } 48 | 49 | public void change(View view) { 50 | if (mGroupSize == 3) { mGroupSize = 9;} 51 | else { mGroupSize = 3;} 52 | init(); 53 | } 54 | 55 | class Adapter extends RecyclerView.Adapter { 56 | 57 | @Override 58 | public Holder onCreateViewHolder(ViewGroup parent, int viewType) { 59 | View item = LayoutInflater.from(parent.getContext()) 60 | .inflate(R.layout.item, parent, false); 61 | return new Holder(item); 62 | } 63 | 64 | @Override 65 | public void onBindViewHolder(final Holder holder, final int position) { 66 | // holder.item.setText("" + position); 67 | holder.item.setCardColor(randomColor()); 68 | holder.text.setText("菜单" + position); 69 | holder.item.setOnClickListener(new View.OnClickListener() { 70 | @Override 71 | public void onClick(View view) { 72 | Toast.makeText(CardActivity.this, holder.text.getText(), Toast.LENGTH_SHORT).show(); 73 | } 74 | }); 75 | } 76 | 77 | @Override 78 | public int getItemCount() { 79 | return mCount; 80 | } 81 | 82 | private int randomColor() { 83 | return COLORS[new Random().nextInt(COLORS.length)]; 84 | } 85 | 86 | class Holder extends RecyclerView.ViewHolder { 87 | CardItemView item; 88 | TextView text; 89 | public Holder(View itemView) { 90 | super(itemView); 91 | item = (CardItemView) itemView.findViewById(R.id.item); 92 | text = (TextView) itemView.findViewById(R.id.text); 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/rv/layoutmanager/CardItemView.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.rv.layoutmanager; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Path; 9 | import android.graphics.RectF; 10 | import android.graphics.Region; 11 | import android.util.AttributeSet; 12 | import android.view.MotionEvent; 13 | import android.view.View; 14 | 15 | import androidstack.customview.R; 16 | 17 | /** 18 | * Created by qibin on 16-9-26. 19 | */ 20 | 21 | public class CardItemView extends View { 22 | 23 | private int mSize; 24 | private Paint mPaint; 25 | private Path mDrawPath; 26 | private Region mRegion; 27 | 28 | public CardItemView(Context context) { 29 | this(context, null, 0); 30 | } 31 | 32 | public CardItemView(Context context, AttributeSet attrs) { 33 | this(context, attrs, 0); 34 | } 35 | 36 | public CardItemView(Context context, AttributeSet attrs, int defStyleAttr) { 37 | super(context, attrs, defStyleAttr); 38 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 39 | mPaint.setStyle(Paint.Style.FILL); 40 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Card, defStyleAttr, 0); 41 | mSize = ta.getDimensionPixelSize(R.styleable.Card_size, 10); 42 | mPaint.setColor(ta.getColor(R.styleable.Card_bgColor, 0)); 43 | ta.recycle(); 44 | 45 | mRegion = new Region(); 46 | mDrawPath = new Path(); 47 | 48 | mDrawPath.moveTo(0, mSize / 2); 49 | mDrawPath.lineTo(mSize / 2, 0); 50 | mDrawPath.lineTo(mSize, mSize / 2); 51 | mDrawPath.lineTo(mSize / 2, mSize); 52 | mDrawPath.close(); 53 | } 54 | 55 | @Override 56 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 57 | setMeasuredDimension(mSize, mSize); 58 | } 59 | 60 | @Override 61 | public boolean dispatchTouchEvent(MotionEvent event) { 62 | if (event.getAction() == MotionEvent.ACTION_DOWN) { 63 | if (!isEventInPath(event)) { return false;} 64 | } 65 | 66 | return super.dispatchTouchEvent(event); 67 | } 68 | 69 | private boolean isEventInPath(MotionEvent event) { 70 | RectF bounds = new RectF(); 71 | mDrawPath.computeBounds(bounds, true); 72 | mRegion.setPath(mDrawPath, new Region((int)bounds.left, 73 | (int)bounds.top, (int)bounds.right, (int)bounds.bottom)); 74 | return mRegion.contains((int) event.getX(), (int) event.getY()); 75 | } 76 | 77 | @Override 78 | protected void onDraw(Canvas canvas) { 79 | canvas.drawColor(Color.TRANSPARENT); 80 | canvas.drawPath(mDrawPath, mPaint); 81 | } 82 | 83 | public void setCardColor(int color) { 84 | mPaint.setColor(color); 85 | invalidate(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/rv/layoutmanager/Pool.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.rv.layoutmanager; 2 | 3 | 4 | import androidx.collection.SparseArrayCompat; 5 | 6 | /** 7 | * Created by qibin on 16-9-25. 8 | */ 9 | 10 | public class Pool { 11 | private SparseArrayCompat mPool; 12 | private New mNewInstance; 13 | 14 | public Pool(New newInstance) { 15 | mPool = new SparseArrayCompat<>(); 16 | mNewInstance = newInstance; 17 | } 18 | 19 | public T get(int key) { 20 | T res = mPool.get(key); 21 | if (res == null) { 22 | res = mNewInstance.get(); 23 | mPool.put(key, res); 24 | } 25 | return res; 26 | } 27 | 28 | public interface New { 29 | T get(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/rv/partrv/PartRvActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.rv.partrv; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.Nullable; 6 | import androidx.appcompat.app.AppCompatActivity; 7 | import androidx.recyclerview.widget.GridLayoutManager; 8 | import androidx.recyclerview.widget.RecyclerView; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | import androidstack.customview.R; 14 | 15 | public class PartRvActivity extends AppCompatActivity { 16 | 17 | 18 | 19 | private PartRvAdapter mPartRvAdapter; 20 | private RecyclerView mRvPart; 21 | private RecyclerView mRvPart1; 22 | private RecyclerView mRvPart2; 23 | private List mParts; 24 | @Override 25 | protected void onCreate(@Nullable Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_part_rv); 28 | mRvPart = findViewById(R.id.rv_part); 29 | mRvPart1 = findViewById(R.id.rv_part_1); 30 | mRvPart2 = findViewById(R.id.rv_part_2); 31 | 32 | mPartRvAdapter = new PartRvAdapter(this); 33 | 34 | mParts = new ArrayList<>(); 35 | for (int i=0;i<20;i++){ 36 | mParts.add(getString(R.string.app_name)+" - "+i); 37 | } 38 | 39 | mPartRvAdapter.setParts(mParts); 40 | GridLayoutManager gridLayoutManager = new GridLayoutManager(this,5); 41 | gridLayoutManager.setOrientation(RecyclerView.HORIZONTAL); 42 | 43 | GridLayoutManager gridLayoutManager1 = new GridLayoutManager(this,5); 44 | gridLayoutManager1.setOrientation(RecyclerView.HORIZONTAL); 45 | 46 | 47 | GridLayoutManager gridLayoutManager2 = new GridLayoutManager(this,5); 48 | gridLayoutManager2.setOrientation(RecyclerView.HORIZONTAL); 49 | 50 | mRvPart.setHasFixedSize(true); 51 | mRvPart1.setHasFixedSize(true); 52 | mRvPart2.setHasFixedSize(true); 53 | mRvPart.setLayoutManager(gridLayoutManager); 54 | mRvPart1.setLayoutManager(gridLayoutManager1); 55 | mRvPart2.setLayoutManager(gridLayoutManager2); 56 | mRvPart.setAdapter(mPartRvAdapter); 57 | mRvPart1.setAdapter(mPartRvAdapter); 58 | mRvPart2.setAdapter(mPartRvAdapter); 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/rv/partrv/PartRvAdapter.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.rv.partrv; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.recyclerview.widget.RecyclerView; 11 | 12 | import java.util.List; 13 | 14 | import androidstack.customview.R; 15 | 16 | public class PartRvAdapter extends RecyclerView.Adapter { 17 | 18 | 19 | private List mParts; 20 | 21 | 22 | private Context mContext; 23 | 24 | public PartRvAdapter(Context mContext) { 25 | this.mContext = mContext; 26 | } 27 | 28 | public void setParts(List parts) { 29 | this.mParts = parts; 30 | } 31 | 32 | @NonNull 33 | @Override 34 | public PartRvHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 35 | View view = LayoutInflater.from(mContext).inflate(R.layout.item_part_rv, parent, false); 36 | return new PartRvHolder(view); 37 | } 38 | 39 | @Override 40 | public void onBindViewHolder(@NonNull PartRvHolder holder, int position) { 41 | holder.textView.setText(mParts.get(position)); 42 | } 43 | 44 | @Override 45 | public int getItemCount() { 46 | return mParts == null ? 0 : mParts.size(); 47 | } 48 | 49 | class PartRvHolder extends RecyclerView.ViewHolder { 50 | 51 | private TextView textView; 52 | 53 | public PartRvHolder(@NonNull View itemView) { 54 | super(itemView); 55 | textView = itemView.findViewById(R.id.tv_part_rv); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/svg/SvgActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.svg; 2 | 3 | import android.graphics.drawable.Animatable; 4 | import android.graphics.drawable.AnimatedVectorDrawable; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.widget.ImageView; 8 | 9 | import androidstack.customview.R; 10 | import androidx.annotation.Nullable; 11 | import androidx.annotation.RequiresApi; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; 14 | 15 | /** 16 | * Created on 2020/8/17 10:09 17 | *

18 | * SVG 可缩放矢量图形 Scalable Vector Graphics: 19 | * 经过数学计算利用直线和曲线绘制而成,无论怎么放大,都不会出现马赛克现象。 20 | * illustrator:矢量图绘图软件。 21 | *

22 | * Bitmap 位图: 23 | * 由一个个像素点组成,放大后会出现马赛克。 24 | * PhotoShop:位图绘图软件。 25 | *

26 | * SVG优势: 27 | * 使用xml格式定义图形,读取和修改的工具多。 28 | * 不会失真,无需根据分辨率适配多套图标。 29 | * 占用空间小。 30 | * 可以转换为Path路径,与Path动画相结合,形成更丰富的动画。 31 | *

32 | * SVG标签: 33 | * rect 矩形 34 | * circle 圆形 35 | * line 线段 36 | * polyline 折线段 37 | * ellipse 椭圆 38 | * polygon 多边形 39 | * path 路径 40 | *

41 | * https://editor.method.ac/ 42 | * 制作 SVG 图像。 43 | *

44 | * http://www.iconfont.cn/ 45 | * Iconfont是一种比较成熟的 SVG 解决方案,它的原理是: 46 | * 把矢量图标打包成一个.ttf文件,在 Android 中应用这个.ttf文件来方便地加载和指定各种图标。 47 | *

48 | * http://inloop.github.io/svg2android/ 49 | * SVG转vector 50 | *

51 | * Android Studio-File-New-Vector Asset-Local File-RTL 52 | * SVG转vector:ic_love.xml 53 | *

54 | * trimPathStart 属性表示截掉 从起点到某个位置的部分,保留剩下的部分; 55 | * trimPathEnd 属性表示截掉 从某个位置到终点的部分,保留剩下的部分。 56 | * 57 | * @author zhangchaozhou 58 | * @email 13760289294@139.com 59 | * @wechat 13760289294 60 | */ 61 | public class SvgActivity extends AppCompatActivity { 62 | 63 | private ImageView mIvSvgVectorAnimation; 64 | 65 | @Override 66 | protected void onCreate(@Nullable Bundle savedInstanceState) { 67 | super.onCreate(savedInstanceState); 68 | setContentView(R.layout.activity_svg); 69 | mIvSvgVectorAnimation = findViewById(R.id.iv_svg_vector_animation); 70 | start1(); 71 | // start2(); 72 | } 73 | 74 | private void start1() { 75 | AnimatedVectorDrawableCompat animatedVectorDrawableCompat = AnimatedVectorDrawableCompat.create( 76 | this, R.drawable.ic_logo 77 | ); 78 | mIvSvgVectorAnimation.setImageDrawable(animatedVectorDrawableCompat); 79 | ((Animatable) mIvSvgVectorAnimation.getDrawable()).start(); 80 | } 81 | 82 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 83 | private void start2() { 84 | AnimatedVectorDrawable anim = 85 | (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.ic_logo); 86 | mIvSvgVectorAnimation.setImageDrawable(anim); 87 | anim.start(); 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/svg/lottie/LottieActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.svg.lottie; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.airbnb.lottie.LottieAnimationView; 6 | 7 | import androidstack.customview.R; 8 | import androidx.annotation.Nullable; 9 | import androidx.appcompat.app.AppCompatActivity; 10 | 11 | import static com.airbnb.lottie.LottieDrawable.INFINITE; 12 | 13 | /** 14 | * Created on 2020/8/17 10:11 15 | * 16 | * @author zhangchaozhou 17 | * @email 13760289294@139.com 18 | * @wechat 13760289294 19 | */ 20 | public class LottieActivity extends AppCompatActivity { 21 | 22 | 23 | private LottieAnimationView mLavGift; 24 | private LottieAnimationView mLavTest; 25 | 26 | 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_lottie); 31 | mLavGift = findViewById(R.id.animation_view); 32 | mLavTest = findViewById(R.id.animation_view_test); 33 | // initGift(); 34 | initTest(); 35 | } 36 | 37 | private void initTest() { 38 | mLavGift.setAnimation("test.json"); 39 | mLavGift.setRepeatCount(INFINITE); 40 | mLavGift.playAnimation(); 41 | } 42 | 43 | private void initGift() { 44 | mLavTest.setAnimation("liwu.json"); 45 | mLavTest.setRepeatCount(INFINITE); 46 | mLavTest.setImageAssetsFolder("images/"); 47 | mLavTest.playAnimation(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/svg/svga/SvgaActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.svg.svga; 2 | 3 | import android.os.Bundle; 4 | import android.widget.FrameLayout; 5 | 6 | import com.opensource.svgaplayer.SVGADrawable; 7 | import com.opensource.svgaplayer.SVGAImageView; 8 | import com.opensource.svgaplayer.SVGAParser; 9 | import com.opensource.svgaplayer.SVGAVideoEntity; 10 | 11 | import java.net.MalformedURLException; 12 | import java.net.URL; 13 | 14 | import androidstack.customview.R; 15 | import androidx.annotation.Nullable; 16 | import androidx.appcompat.app.AppCompatActivity; 17 | import androidx.constraintlayout.widget.ConstraintLayout; 18 | 19 | /** 20 | * Created on 2020/8/17 14:39 21 | * 22 | * @author zhangchaozhou 23 | * @email 13760289294@139.com 24 | * @wechat 13760289294 25 | */ 26 | public class SvgaActivity extends AppCompatActivity { 27 | private SVGAImageView mSvgaTest; 28 | private ConstraintLayout mCLSvga; 29 | private FrameLayout mFlSvga1; 30 | private FrameLayout mFlSvga2; 31 | 32 | @Override 33 | protected void onCreate(@Nullable Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_svga); 36 | mSvgaTest = findViewById(R.id.svga_test); 37 | mCLSvga = findViewById(R.id.cl_svga); 38 | mFlSvga1 = findViewById(R.id.fl_svga1); 39 | mFlSvga2 = findViewById(R.id.fl_svga2); 40 | 41 | 42 | /** 43 | * xml代码实现: 44 | * source:表示 svga 文件的路径,提供一个在 assets 目录下的文件名,或者提供一个 http url 地址。 45 | * autoPlay:当动画加载完成后,自动播放。 46 | * loopCount:默认为 0,设置动画的循环次数,0 表示无限循环。 47 | * clearsAfterStop:默认为 true,当动画播放完成后,是否清空画布。 48 | * fillMode:默认为 Forward。Forward 表示动画结束后,将停留在最后一帧。Backward 表示动画结束后,将停留在第一帧。 49 | */ 50 | codeAnimation(); 51 | 52 | 53 | } 54 | 55 | private void codeAnimation() { 56 | 57 | SVGAImageView svgaImageView = new SVGAImageView(this); 58 | SVGAParser.Companion.shareParser().init(this); 59 | SVGAParser parser = SVGAParser.Companion.shareParser(); 60 | parser = new SVGAParser(this); 61 | parser.decodeFromAssets("car.svga", new SVGAParser.ParseCompletion() { 62 | @Override 63 | public void onComplete(SVGAVideoEntity svgaVideoEntity) { 64 | SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); 65 | svgaImageView.setImageDrawable(drawable); 66 | mFlSvga1.addView(svgaImageView ); 67 | svgaImageView.startAnimation(); 68 | } 69 | 70 | @Override 71 | public void onError() { 72 | 73 | System.out.println("解析错误decodeFromAssets"); 74 | } 75 | }); 76 | 77 | try { 78 | SVGAImageView svgaImageView1 = new SVGAImageView(this); 79 | SVGAParser parser1 = SVGAParser.Companion.shareParser(); 80 | parser1 = new SVGAParser(this); 81 | URL url = new URL("https://github.com/yyued/SVGA-Samples/blob/master/posche.svga?raw=true"); 82 | parser1.decodeFromURL(url, new SVGAParser.ParseCompletion() { 83 | @Override 84 | public void onComplete(SVGAVideoEntity svgaVideoEntity) { 85 | SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); 86 | svgaImageView1.setImageDrawable(drawable); 87 | mFlSvga2.addView(svgaImageView1 ); 88 | svgaImageView1.startAnimation(); 89 | } 90 | 91 | @Override 92 | public void onError() { 93 | System.out.println("解析错误decodeFromURL"); 94 | } 95 | }); 96 | } catch (MalformedURLException e) { 97 | System.out.println(e.getMessage()); 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/svg/svga/SvgaTextActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.svg.svga; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.text.TextPaint; 6 | import android.text.TextUtils; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | import android.widget.Toast; 11 | 12 | import androidx.annotation.Nullable; 13 | import androidx.appcompat.app.AppCompatActivity; 14 | 15 | import com.opensource.svgaplayer.SVGADrawable; 16 | import com.opensource.svgaplayer.SVGADynamicEntity; 17 | import com.opensource.svgaplayer.SVGAImageView; 18 | import com.opensource.svgaplayer.SVGAParser; 19 | import com.opensource.svgaplayer.SVGAVideoEntity; 20 | 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | import java.net.URL; 24 | 25 | import androidstack.customview.R; 26 | 27 | public class SvgaTextActivity extends AppCompatActivity { 28 | 29 | 30 | private Button mBtnSvgaText; 31 | private EditText mEdtSvgaText; 32 | 33 | 34 | private SVGAParser svgaParser; 35 | 36 | private SVGAImageView svgaImageView; 37 | 38 | private SVGAVideoEntity videoEntity; 39 | @Override 40 | protected void onCreate(@Nullable Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | setContentView(R.layout.activity_svga_text); 43 | 44 | mBtnSvgaText = findViewById(R.id.btn_svga_text); 45 | mEdtSvgaText = findViewById(R.id.edt_svga_text); 46 | svgaImageView = findViewById(R.id.svga_text); 47 | svgaParser = new SVGAParser(this); 48 | 49 | try { 50 | svgaParser.parse(new URL("https://github.com/yyued/SVGA-Samples/blob/master/kingset.svga?raw=true"), 51 | new SVGAParser.ParseCompletion() { 52 | 53 | 54 | @Override 55 | public void onComplete(@NotNull SVGAVideoEntity videoItem) { 56 | videoEntity =videoItem; 57 | } 58 | @Override 59 | public void onError() { 60 | Toast.makeText(SvgaTextActivity.this,"出错",Toast.LENGTH_LONG).show(); 61 | } 62 | } 63 | ); 64 | } catch (Exception e) { 65 | System.out.print(true); 66 | } 67 | 68 | 69 | mBtnSvgaText.setOnClickListener(new View.OnClickListener() { 70 | @Override 71 | public void onClick(View v) { 72 | String content = mEdtSvgaText.getText().toString(); 73 | if (TextUtils.isEmpty(content)){ 74 | Toast.makeText(SvgaTextActivity.this,"输入内容",Toast.LENGTH_LONG).show(); 75 | return; 76 | } 77 | if (videoEntity==null){ 78 | Toast.makeText(SvgaTextActivity.this,"svga资源解析中",Toast.LENGTH_LONG).show(); 79 | return; 80 | } 81 | SVGADynamicEntity dynamicEntity = new SVGADynamicEntity(); 82 | TextPaint textPaint = new TextPaint(); 83 | textPaint.setColor(Color.WHITE); 84 | textPaint.setTextSize(28); 85 | dynamicEntity.setDynamicText(content, textPaint, "banner"); 86 | SVGADrawable drawable = new SVGADrawable(videoEntity, dynamicEntity); 87 | svgaImageView.setImageDrawable(drawable); 88 | svgaImageView.startAnimation(); 89 | } 90 | }); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/text/GradientTextView.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.text; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.graphics.LinearGradient; 6 | import android.graphics.Shader; 7 | import android.util.AttributeSet; 8 | import android.widget.TextView; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.annotation.Nullable; 12 | 13 | /** 14 | * @author zhangchaozhou 15 | * @time 2021/3/21 22:42 16 | */ 17 | public class GradientTextView extends TextView { 18 | 19 | public enum GradientDirection { 20 | TOP_2_BOTTOM(1), 21 | START_2_END(2), 22 | TOP_START_2_BOTTOM_END(3); 23 | 24 | int direction; 25 | 26 | GradientDirection(int direction) { 27 | this.direction = direction; 28 | } 29 | 30 | 31 | public int getDirection() { 32 | return direction; 33 | } 34 | } 35 | 36 | 37 | public GradientTextView(@NonNull Context context) { 38 | super(context); 39 | } 40 | 41 | public GradientTextView(@NonNull Context context, @Nullable AttributeSet attrs) { 42 | super(context, attrs); 43 | } 44 | 45 | public GradientTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 46 | super(context, attrs, defStyleAttr); 47 | } 48 | 49 | @Override 50 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 51 | super.onLayout(changed, left, top, right, bottom); 52 | if (changed) { 53 | // getPaint().setShader(new LinearGradient( 54 | // 0, 0, getWidth(), getHeight(), 55 | // new int[]{0xFFFFEABA, 0xFFDFBB82, 0xFFBE8B49}, new float[]{0, 0.5f, 1}, 56 | // Shader.TileMode.CLAMP)); 57 | 58 | Shader shader = new LinearGradient(0, 0, 0, getHeight(), Color.parseColor("#EE6A00"), Color.parseColor("#B80000"), Shader.TileMode.CLAMP); 59 | getPaint().setShader(shader); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/text/TextActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.text; 2 | 3 | import android.graphics.LinearGradient; 4 | import android.graphics.Shader; 5 | import android.os.Bundle; 6 | 7 | import androidx.annotation.Nullable; 8 | import androidx.appcompat.app.AppCompatActivity; 9 | 10 | import androidstack.customview.R; 11 | 12 | /** 13 | * @author zhangchaozhou 14 | * @time 2021/3/21 22:43 15 | */ 16 | public class TextActivity extends AppCompatActivity { 17 | 18 | private GradientTextView mTvGradientText; 19 | @Override 20 | protected void onCreate(@Nullable Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_text); 23 | mTvGradientText = findViewById(R.id.tv_gradient_text); 24 | // mTvGradientText.getPaint().setShader(new LinearGradient( 25 | // 0, 0, mTvGradientText.getWidth(), mTvGradientText.getHeight(), 26 | // new int[]{0xFFFFEABA, 0xFFDFBB82, 0xFFBE8B49}, new float[]{0, 0.5f, 1}, 27 | // Shader.TileMode.CLAMP)); 28 | // Shader shader_vertical=new LinearGradient(0, mTvGradientText.getHeight()/4, 0, mTvGradientText.getHeight(), Color.parseColor("#D51400"), Color.parseColor("#F96F00"), Shader.TileMode.CLAMP); 29 | // mTvGradientText.getPaint().setShader(shader_vertical); 30 | 31 | mTvGradientText.setText("00000000999925"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/toolbar/ToolBarActivity.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.toolbar; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidstack.customview.R; 6 | import androidx.annotation.Nullable; 7 | import androidx.appcompat.app.AppCompatActivity; 8 | import androidx.appcompat.widget.Toolbar; 9 | 10 | /** 11 | * Created on 2020/8/31 12:19 12 | * 13 | * @author zhangchaozhou 14 | * @email 13760289294@139.com 15 | * @wechat 13760289294 16 | */ 17 | public class ToolBarActivity extends AppCompatActivity { 18 | @Override 19 | protected void onCreate(@Nullable Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_tool_bar); 22 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 23 | setSupportActionBar(toolbar); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CustomView/app/src/main/java/androidstack/customview/view/mask/GuideMaskSet.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview.view.mask; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 蒙版集合 8 | * @author zhangchaozhou 9 | */ 10 | public class GuideMaskSet { 11 | 12 | private List mGuideMasks = new ArrayList<>(); 13 | 14 | private int mPosition = 0; 15 | 16 | /** 17 | * 添加蒙版 18 | * @param guideMask 19 | */ 20 | public void addGuide(GuideMask guideMask) { 21 | mGuideMasks.add(guideMask); 22 | guideMask.setOnDismissListener(new GuideMask.OnDismissListener() { 23 | @Override 24 | public void onDismiss() {//关闭后显示下一个蒙版 25 | int nextPosition = mPosition + 1; 26 | if (mGuideMasks.size() > nextPosition) { 27 | GuideMask next = mGuideMasks.get(nextPosition); 28 | mPosition++; 29 | next.show(); 30 | } 31 | } 32 | }); 33 | } 34 | 35 | /** 36 | * 显示蒙版集合 37 | */ 38 | public void show(){ 39 | mGuideMasks.get(0).show(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/anim/alpha_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/anim/rotate_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/anim/scale_test.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/anim/set_sanner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 17 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/anim/set_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 18 | 19 | 24 | 25 | 35 | 36 | 44 | 45 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/anim/translate_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/animator/animator_logo.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/animator/animator_set.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable-v21/ic_logo.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable/animation_list_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 13 | 16 | 19 | 20 | 23 | 26 | 29 | 32 | 35 | 36 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable/ic_logo.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable/ic_love.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable/item.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/drawable/item.jpg -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable/shape_scanner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/drawable/vector_logo.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_advanced_property.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_alpha_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_animator_set.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_basis_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 20 | 21 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_falling_ball_object.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_falling_ball_value.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_frame_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_interpolator.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | 26 | 30 | 31 | 45 | 46 | 53 | 54 | 55 | 62 | 63 | 64 | 71 | 72 | 73 | 80 | 81 | 88 | 89 | 96 | 97 | 104 | 105 | 106 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_lottie.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | 15 | 22 | 23 | 24 | 25 | 26 | 31 | 32 | 33 | 40 | 41 | 48 | 49 | 56 | 57 | 62 | 63 | 64 | 69 | 70 | 75 | 76 | 81 | 82 | 87 | 88 | 93 | 94 | 99 | 100 | 101 | 106 | 107 | 112 | 113 | 114 | 119 | 120 | 121 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_mask.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_matrix.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 22 | 23 | 33 | 34 | 35 | 36 | 46 | 47 | 48 | 49 | 50 | 60 | 61 | 62 | 63 | 73 | 74 | 75 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_music.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 26 | 27 | 28 | 37 | 38 | 39 | 48 | 49 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_object_animator.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_paint.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_part_rv.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 11 | 12 | 16 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_path_measure.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_phone.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_property_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 14 | 15 | 21 | 22 | 28 | 29 | 30 | 36 | 37 | 38 | 44 | 45 | 51 | 52 | 53 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_rotate_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_scale_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_svg.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 16 | 17 | 18 | 26 | 27 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_svga.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_svga_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | 32 | 33 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_tool_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 26 | 27 | 35 | 36 | 41 | 42 | > 43 | 44 | 54 | 55 | 56 | 57 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_translate_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_tween_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 16 | 17 | 23 | 24 | 25 | 32 | 33 | 40 | 41 | 48 | 49 | 56 | 57 | 58 | 59 | 67 | 68 | 75 | 76 | 77 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_value_animator.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_view_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 16 | 17 | 23 | 24 | 25 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/activity_view_group_animate.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/dialog_custom.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 15 | 16 | 22 | 23 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/item_part_rv.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/layout/layout_mask.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 25 | 26 | 37 | 38 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/add_focus_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/add_focus_big.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_arrow.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_camera.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_camera.jpeg -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_loading.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_phone.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_scanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_scanner.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/ic_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/ic_test.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_01.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_010.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_010.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_02.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_03.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_04.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_05.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_06.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_07.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_08.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxhdpi/loading_09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxhdpi/loading_09.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /CustomView/app/src/main/res/mipmap-xxxhdpi/ic_paper.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/app/src/main/res/mipmap-xxxhdpi/ic_paper.jpeg -------------------------------------------------------------------------------- /CustomView/app/src/main/res/values/attr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | #733aaa 7 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CustomProgressView 3 | -------------------------------------------------------------------------------- /CustomView/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /CustomView/app/src/test/java/androidstack/customview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package androidstack.customview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /CustomView/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:4.0.0" 9 | 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72" 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | google() 19 | jcenter() 20 | //SVGA 21 | maven { url 'https://jitpack.io' } 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } -------------------------------------------------------------------------------- /CustomView/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /CustomView/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/CustomView/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /CustomView/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 22 21:59:46 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /CustomView/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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /CustomView/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "CustomProgressView" -------------------------------------------------------------------------------- /DrawingBasis.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/DrawingBasis.jpeg -------------------------------------------------------------------------------- /Heartbeat1647.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/Heartbeat1647.svga -------------------------------------------------------------------------------- /Heartbeat1701.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/Heartbeat1701.svga -------------------------------------------------------------------------------- /Heartbeat1717.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/Heartbeat1717.svga -------------------------------------------------------------------------------- /Heartbeat1746.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/Heartbeat1746.svga -------------------------------------------------------------------------------- /HeartbeatText.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/HeartbeatText.svga -------------------------------------------------------------------------------- /HeartbeatText1-3.svga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/HeartbeatText1-3.svga -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CustomView 2 | CustomView 3 | 4 | 5 | 欢迎关注微信公众号:Android技术堆栈 6 | 7 | ![](https://mp.weixin.qq.com/mp/qrcode?scene=10000004&size=102&__biz=MzU3NzQ0MzYxMg==&mid=2247484187&idx=1&sn=2b1c27c33d5ca1e5f9cee9de2bd6b6cd&send_time=) 8 | 9 | 10 | ![](https://github.com/chaozhouzhang/CustomProgressView/blob/master/CPV.jpeg?raw=true) 11 | 12 | 13 | ![](https://github.com/chaozhouzhang/CustomProgressView/blob/master/DrawingBasis.jpeg?raw=true) 14 | 15 | 16 | -------------------------------------------------------------------------------- /SVG2VECTOR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/SVG2VECTOR.png -------------------------------------------------------------------------------- /Video_20200819_071634_945.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/Video_20200819_071634_945.gif -------------------------------------------------------------------------------- /Video_20200819_073506_981.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/Video_20200819_073506_981.gif -------------------------------------------------------------------------------- /Video_20200819_073636_929.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/Video_20200819_073636_929.gif -------------------------------------------------------------------------------- /ic_sing_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/ic_sing_single.png -------------------------------------------------------------------------------- /ic_week_star_frame_new.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/ic_week_star_frame_new.9.png -------------------------------------------------------------------------------- /svga_nihongdeng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/svga_nihongdeng -------------------------------------------------------------------------------- /tween.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/tween.jpeg -------------------------------------------------------------------------------- /公众号.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/公众号.bmp -------------------------------------------------------------------------------- /抛物动画.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/抛物动画.gif -------------------------------------------------------------------------------- /插值器.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/插值器.jpeg -------------------------------------------------------------------------------- /电话响铃动画.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/电话响铃动画.gif -------------------------------------------------------------------------------- /菜单动画.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/菜单动画.gif -------------------------------------------------------------------------------- /逐帧动画.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaozhouzhang/CustomView/c053299b3201a268c4c3571f985dab92f91815e9/逐帧动画.jpeg --------------------------------------------------------------------------------