├── app
├── .gitignore
├── release
│ ├── app-release.apk
│ └── output.json
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.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
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── king
│ │ │ └── circleprogressview
│ │ │ └── MainActivity.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── king
│ │ │ └── circleprogressview
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── king
│ │ └── circleprogressview
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── lib
├── .gitignore
├── gradle.properties
├── src
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── attrs.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── king
│ │ │ └── view
│ │ │ └── circleprogressview
│ │ │ └── CircleProgressView.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── king
│ │ │ └── view
│ │ │ └── circleprogressview
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── king
│ │ └── view
│ │ └── circleprogressview
│ │ └── ExampleInstrumentedTest.java
├── bintray.gradle
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── GIF.gif
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .circleci
└── config.yml
├── .github
└── workflows
│ ├── gradle.yml
│ └── issues-stale.yml
├── .travis.yml
├── LICENSE
├── versions.gradle
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/lib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':lib'
2 |
--------------------------------------------------------------------------------
/GIF.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/GIF.gif
--------------------------------------------------------------------------------
/lib/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=CircleProgressView
2 | POM_ARTIFACT_ID=circleprogressview
3 | POM_PACKAGING=aar
--------------------------------------------------------------------------------
/app/release/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/release/app-release.apk
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CircleProgressView
3 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/lib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenly1314/CircleProgressView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | android: circleci/android@0.2.0
5 |
6 | jobs:
7 | build:
8 | executor: android/android
9 |
10 | steps:
11 | - checkout
12 | - run:
13 | command: ./gradlew build
--------------------------------------------------------------------------------
/app/release/output.json:
--------------------------------------------------------------------------------
1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":5,"versionName":"1.1.2","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #008577
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Aug 19 10:11:07 CST 2019
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-5.6.4-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/bintray.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.novoda.bintray-release'
2 |
3 | //添加
4 | publish {
5 | userOrg = 'jenly'//bintray.com用户名
6 | groupId = 'com.king.view'//jcenter上的路径s
7 | artifactId = 'circleprogressview'//项目名称
8 | publishVersion = app_version.versionName//版本号
9 | desc = 'CircleProgressView for Android'//描述
10 | website = 'https://github.com/jenly1314/CircleProgressView'//网站
11 | licences = ['MIT']//开源协议
12 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: Set up JDK 1.8
16 | uses: actions/setup-java@v1
17 | with:
18 | java-version: 1.8
19 | - name: Build with Gradle
20 | run: ./gradlew build
--------------------------------------------------------------------------------
/app/src/test/java/com/king/circleprogressview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.king.circleprogressview;
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 | }
--------------------------------------------------------------------------------
/lib/src/test/java/com/king/view/circleprogressview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.king.view.circleprogressview;
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 | }
--------------------------------------------------------------------------------
/.github/workflows/issues-stale.yml:
--------------------------------------------------------------------------------
1 | name: 'Close stale issues and PRs'
2 | on:
3 | schedule:
4 | - cron: '0 16 * * *'
5 |
6 | jobs:
7 | stale:
8 | runs-on: ubuntu-latest
9 | permissions:
10 | issues: write
11 | pull-requests: write
12 | steps:
13 | - uses: actions/stale@v5
14 | with:
15 | stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
16 | days-before-stale: 30
17 | days-before-close: 5
18 | exempt-all-pr-milestones: true
19 | exempt-issue-labels: 'help wanted'
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/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
22 |
--------------------------------------------------------------------------------
/lib/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
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | dist: trusty
3 | jdk: oraclejdk8
4 | sudo: false
5 |
6 | env:
7 | global:
8 | - ANDROID_API_LEVEL=28
9 | - ANDROID_BUILD_TOOLS_VERSION=28.0.3
10 | - TRAVIS_SECURE_ENV_VARS=true
11 |
12 | before_install:
13 | - chmod +x gradlew
14 | - mkdir "$ANDROID_HOME/licenses" || true
15 | # Hack to accept Android licenses
16 | - yes | sdkmanager "platforms;android-$ANDROID_API_LEVEL"
17 |
18 |
19 | android:
20 | components:
21 | # The BuildTools version used by your project
22 | - tools
23 | - platform-tools
24 | - build-tools-$ANDROID_BUILD_TOOLS_VERSION
25 | # The SDK version used to compile your project
26 | - android-$ANDROID_API_LEVEL
27 | - extra-android-m2repository
28 | - extra-google-android-support
29 |
30 | script:
31 | - ./gradlew clean
32 | - ./gradlew assembleRelease
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/king/circleprogressview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.king.circleprogressview;
2 |
3 | import android.content.Context;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 |
8 | import androidx.test.InstrumentationRegistry;
9 | import androidx.test.runner.AndroidJUnit4;
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.getTargetContext();
24 |
25 | assertEquals("com.king.circleprogressview", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/src/androidTest/java/com/king/view/circleprogressview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.king.view.circleprogressview;
2 |
3 | import android.content.Context;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 |
8 | import androidx.test.InstrumentationRegistry;
9 | import androidx.test.runner.AndroidJUnit4;
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.getTargetContext();
24 |
25 | assertEquals("com.king.view.circleprogressview.test", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion build_versions.compileSdk
5 | buildToolsVersion build_versions.buildTools
6 |
7 | defaultConfig {
8 | applicationId "com.king.circleprogressview"
9 | minSdkVersion build_versions.minSdk
10 | targetSdkVersion build_versions.targetSdk
11 | versionCode app_version.versionCode
12 | versionName app_version.versionName
13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation fileTree(include: ['*.jar'], dir: 'libs')
26 | testImplementation deps.junit
27 | androidTestImplementation deps.runner
28 | androidTestImplementation deps.espresso
29 |
30 | implementation deps.appcompat
31 |
32 | implementation project(':lib')
33 | }
34 |
--------------------------------------------------------------------------------
/lib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | //apply from: 'bintray.gradle'
3 | apply plugin: "com.vanniktech.maven.publish"
4 |
5 | android {
6 | compileSdkVersion build_versions.compileSdk
7 | buildToolsVersion build_versions.buildTools
8 |
9 | defaultConfig {
10 | minSdkVersion build_versions.minSdk
11 | targetSdkVersion build_versions.targetSdk
12 | versionCode app_version.versionCode
13 | versionName app_version.versionName
14 |
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 |
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 |
25 | lintOptions {
26 | abortOnError false
27 | }
28 | }
29 |
30 | dependencies {
31 | implementation fileTree(include: ['*.jar'], dir: 'libs')
32 | testImplementation deps.junit
33 | androidTestImplementation deps.runner
34 | androidTestImplementation deps.espresso
35 |
36 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Jenly Yu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/versions.gradle:
--------------------------------------------------------------------------------
1 | //App
2 | def app_version = [:]
3 | app_version.versionCode = 6
4 | app_version.versionName = "1.1.3"
5 | ext.app_version = app_version
6 |
7 | //build version
8 | def build_versions = [:]
9 | build_versions.minSdk = 16
10 | build_versions.targetSdk = 28
11 | build_versions.compileSdk = 28
12 | build_versions.buildTools = "28.0.3"
13 | ext.build_versions = build_versions
14 |
15 | ext.deps = [:]
16 |
17 | // App dependencies
18 | def versions = [:]
19 | //support
20 | versions.appcompat = "1.1.0"
21 | versions.constraintlayout = "1.1.3"
22 |
23 | versions.mavenPublish = '0.13.0'
24 | versions.gradle = '3.6.1'
25 | //test
26 | versions.junit = "1.1.1"
27 | versions.runner = "1.2.0"
28 | versions.espressoCore = "3.2.0"
29 | ext.versions = versions
30 |
31 | def deps = [:]
32 | deps.junit = "androidx.test.ext:junit:$versions.junit"
33 | deps.runner = "androidx.test:runner:$versions.runner"
34 | deps.espresso = "androidx.test.espresso:espresso-core:$versions.espressoCore"
35 | deps.appcompat = "androidx.appcompat:appcompat:$versions.appcompat"
36 | deps.constraintlayout = "androidx.constraintlayout:constraintlayout:$versions.constraintlayout"
37 |
38 | ext.deps = deps
39 |
--------------------------------------------------------------------------------
/lib/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/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 = -Xmx1536m
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 | android.useAndroidX=true
15 | android.enableJetifier=true
16 |
17 | VERSION_NAME=1.1.3
18 | VERSION_CODE=6
19 | GROUP=com.github.jenly1314
20 |
21 | POM_DESCRIPTION=CircleProgressView for Android
22 | POM_URL=https://github.com/jenly1314/CircleProgressView
23 | POM_SCM_URL=https://github.com/jenly1314/CircleProgressView
24 | POM_SCM_CONNECTION=scm:git@github.com:jenly1314/CircleProgressView.git
25 | POM_SCM_DEV_CONNECTION=scm:git@github.com:jenly1314/CircleProgressView.git
26 | POM_LICENCE_NAME=The MIT License
27 | POM_LICENCE_URL=https://opensource.org/licenses/mit-license.php
28 | #POM_LICENCE_NAME=The Apache Software License, Version 2.0
29 | #POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
30 | POM_DEVELOPER_ID=jenly
31 | POM_DEVELOPER_NAME=Jenly Yu
32 | RELEASE_REPOSITORY_URL=https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
33 | SNAPSHOT_REPOSITORY_URL=https://s01.oss.sonatype.org/content/repositories/snapshots/
34 | RELEASE_SIGNING_ENABLED=false
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
18 |
22 |
29 |
36 |
37 |
38 |
45 |
51 |
57 |
63 |
64 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/king/circleprogressview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.king.circleprogressview;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.CheckBox;
6 | import android.widget.CompoundButton;
7 |
8 | import com.king.view.circleprogressview.CircleProgressView;
9 |
10 | import androidx.appcompat.app.AppCompatActivity;
11 |
12 | public class MainActivity extends AppCompatActivity {
13 |
14 | private CircleProgressView cpv;
15 |
16 | private CheckBox cbTick;
17 | private CheckBox cbTurn;
18 |
19 | private int[] mShaderColors = new int[]{0xFF4FEAAC,0xFFA8DD51,0xFFE8D30F,0xFFA8DD51,0xFF4FEAAC};
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.activity_main);
25 |
26 | cpv = findViewById(R.id.cpv);
27 | cbTick = findViewById(R.id.cbTick);
28 | cbTurn = findViewById(R.id.cbTurn);
29 | cbTick.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
30 | @Override
31 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
32 | cpv.setShowTick(isChecked);
33 | }
34 | });
35 |
36 | cbTurn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
37 | @Override
38 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
39 | cpv.setTurn(isChecked);
40 | }
41 | });
42 |
43 |
44 | }
45 |
46 |
47 | private void clickBtn1(){
48 | cpv.setProgressColor(mShaderColors);
49 | cpv.showAnimation(100,3000);
50 |
51 | }
52 |
53 | private void clickBtn2(){
54 | cpv.setProgressColor(mShaderColors);
55 | cpv.showAnimation(100,0,3000);
56 |
57 | }
58 |
59 | private void clickBtn3(){
60 | cpv.setProgressColor(0xFF4FEAAC);
61 | cpv.showAnimation(100,3000);
62 |
63 | }
64 |
65 | private void clickBtn4(){
66 | cpv.setProgressColor(0xFF4FEAAC);
67 | cpv.showAnimation(100,3000);
68 |
69 | }
70 |
71 | public void onClick(View view) {
72 | switch (view.getId()){
73 | case R.id.btn1:
74 | clickBtn1();
75 | break;
76 | case R.id.btn2:
77 | clickBtn2();
78 | break;
79 | case R.id.btn3:
80 | clickBtn3();
81 | break;
82 | case R.id.btn4:
83 | clickBtn4();
84 | break;
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CircleProgressView
2 |
3 | [](https://repo1.maven.org/maven2/com/github/jenly1314/CircleProgressView)
4 | [](https://jitpack.io/#jenly1314/CircleProgressView)
5 | [](https://github.com/jenly1314/CircleProgressView/actions/workflows/gradle.yml)
6 | [](https://raw.githubusercontent.com/jenly1314/CircleProgressView/master/app/release/app-release.apk)
7 | [](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels)
8 | [](https://opensource.org/licenses/mit)
9 |
10 |
11 | CircleProgressView for Android 是一个圆形的进度动画控件,动画效果纵享丝滑。
12 |
13 | ## 效果展示
14 | 
15 |
16 | > 你也可以直接下载 [演示App](https://raw.githubusercontent.com/jenly1314/CircleProgressView/master/app/release/app-release.apk) 体验效果
17 |
18 | ## 引入
19 |
20 | ### Gradle:
21 |
22 | 1. 在Project的 **build.gradle** 或 **setting.gradle** 中添加远程仓库
23 |
24 | ```gradle
25 | repositories {
26 | //...
27 | mavenCentral()
28 | }
29 | ```
30 |
31 | 2. 在Module的 **build.gradle** 中添加依赖项
32 |
33 | ```gradle
34 | implementation 'com.github.jenly1314:circleprogressview:1.1.3'
35 | ```
36 |
37 | ## 使用
38 |
39 | ### CircleProgressView自定义属性说明(进度默认渐变色)
40 | | 属性 | 值类型 | 默认值 | 说明 |
41 | | :------| :------ | :------ | :------ |
42 | | cpvStrokeWidth | dimension |12dp| 笔画描边的宽度 |
43 | | cpvNormalColor | color |#FFC8C8C8| 圆正常颜色 |
44 | | cpvProgressColor | color |#FF4FEAAC| 圆进度颜色 |
45 | | cpvStartAngle | integer | 270 | 开始角度,默认十二点钟方向 |
46 | | cpvSweepAngle | integer | 360 | 扫描角度范围 |
47 | | cpvMax | integer | 100 | 进度最大值 |
48 | | cpvProgress | integer | 0 | 当前进度 |
49 | | cpvDuration | integer | 500 | 动画时长 |
50 | | cpvLabelText | string | | 中间的标签文本,默认自动显示百分比 |
51 | | cpvLabelTextColor | color |#FF333333| 文本字体颜色 |
52 | | cpvLabelTextSize | dimension |30sp| 文本字体大小 |
53 | | cpvShowLabel | boolean | true | 是否显示文本 |
54 | | cpvShowTick | boolean | true | 是否显示外环刻度 |
55 | | cpvCirclePadding | dimension | 10dp | 外圆环刻度与内圆环间距 |
56 | | cpvTickSplitAngle | integer | 5 | 刻度间隔的角度大小 |
57 | | cpvBlockAngle | integer | 1 | 刻度的角度大小 |
58 | | cpvTickOffsetAngle | integer | 0 | 刻度偏移的角度大小 |
59 | | cpvTurn | boolean | false | 是否旋转 |
60 | | cpvCapRound | boolean | true | 是否是圆形线冒(圆角弧度) |
61 | | cpvLabelPaddingLeft | dimension |0dp| 文本居左边内间距 |
62 | | cpvLabelPaddingTop | dimension |0dp| 文本居顶边内间距 |
63 | | cpvLabelPaddingRight | dimension |0dp| 文本居右边内间距 |
64 | | cpvLabelPaddingBottom | dimension |0dp| 文本居底边内间距 |
65 |
66 | ### 示例
67 |
68 | 布局示例
69 | ```Xml
70 |
74 | ```
75 |
76 | 代码示例
77 | ```Java
78 | //显示进度动画,进度,动画时长
79 | circleProgressView.showAnimation(80,3000);
80 | //设置当前进度
81 | circleProgressView.setProgress(80);
82 | //设置进度改变监听
83 | circleProgressView.setOnChangeListener(onChangeListener);
84 |
85 | ```
86 | 更多使用详情,请查看[app](app)中的源码使用示例或直接查看 [API帮助文档](https://jitpack.io/com/github/jenly1314/CircleProgressView/latest/javadoc/)
87 |
88 | ## 相关推荐
89 |
90 | - [ArcSeekBar](https://github.com/jenly1314/ArcSeekBar) 一个弧形的拖动条进度控件,配置参数完全可定制化。
91 | - [SpinCounterView](https://github.com/jenly1314/SpinCounterView) 一个类似码表变化的旋转计数器动画控件。
92 | - [CounterView](https://github.com/jenly1314/CounterView) 一个数字变化效果的计数器视图控件。
93 | - [RadarView](https://github.com/jenly1314/RadarView) 一个雷达扫描动画后,然后展示得分效果的控件。
94 | - [SuperTextView](https://github.com/jenly1314/SuperTextView) 一个在TextView的基础上扩展了几种动画效果的控件。
95 | - [LoadingView](https://github.com/jenly1314/LoadingView) 一个圆弧加载过渡动画,圆弧个数,大小,弧度,渐变颜色,完全可配。
96 | - [WaveView](https://github.com/jenly1314/WaveView) 一个水波纹动画控件视图,支持波纹数,波纹振幅,波纹颜色,波纹速度,波纹方向等属性完全可配。
97 | - [GiftSurfaceView](https://github.com/jenly1314/GiftSurfaceView) 一个适用于直播间送礼物拼图案的动画控件。
98 | - [FlutteringLayout](https://github.com/jenly1314/FlutteringLayout) 一个适用于直播间点赞桃心飘动效果的控件。
99 | - [DragPolygonView](https://github.com/jenly1314/DragPolygonView) 一个支持可拖动多边形,支持通过拖拽多边形的角改变其形状的任意多边形控件。
100 | - [DrawBoard](https://github.com/jenly1314/DrawBoard) 一个自定义View实现的画板;方便对图片进行编辑和各种涂鸦相关操作。
101 | - [compose-component](https://github.com/jenly1314/compose-component) 一个Jetpack Compose的组件库;主要提供了一些小组件,便于快速使用。
102 |
103 |
104 | ## 版本日志
105 |
106 | #### v1.1.3:2021-9-2 (从v1.1.3开始发布至 MavenCentral)
107 | * 对外暴露更多getter和setter方法
108 | * 新增cpvTickOffsetAngle属性
109 |
110 | #### v1.1.2:2020-12-2
111 | * 优化设置渐变色过程处理
112 |
113 | #### v1.1.1:2020-4-2
114 | * 新增cpvLabelPadding..相关属性
115 |
116 | #### v1.1.0:2019-8-19
117 | * 移除appcompat依赖
118 |
119 | #### v1.0.1:2019-5-23
120 | * 新增cpvTurn属性(是否旋转)
121 |
122 | #### v1.0.0:2019-2-17
123 | * CircleProgressView初始版本
124 |
125 | ---
126 |
127 | 
128 |
129 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
21 |
26 |
31 |
36 |
41 |
46 |
51 |
56 |
61 |
66 |
71 |
76 |
81 |
86 |
91 |
96 |
101 |
106 |
111 |
116 |
121 |
126 |
131 |
136 |
141 |
146 |
151 |
156 |
161 |
166 |
171 |
172 |
--------------------------------------------------------------------------------
/lib/src/main/java/com/king/view/circleprogressview/CircleProgressView.java:
--------------------------------------------------------------------------------
1 | package com.king.view.circleprogressview;
2 |
3 | import java.lang.String;
4 |
5 | import android.animation.Animator;
6 | import android.animation.ValueAnimator;
7 | import android.content.Context;
8 | import android.content.res.TypedArray;
9 | import android.graphics.Canvas;
10 | import android.graphics.Paint;
11 | import android.graphics.RectF;
12 | import android.graphics.Shader;
13 | import android.graphics.SweepGradient;
14 | import android.text.TextPaint;
15 | import android.text.TextUtils;
16 | import android.util.AttributeSet;
17 | import android.util.DisplayMetrics;
18 | import android.util.TypedValue;
19 | import android.view.View;
20 |
21 |
22 | /**
23 | * @author Jenly
24 | */
25 | public class CircleProgressView extends View {
26 |
27 |
28 | /**
29 | * 画笔
30 | */
31 | private Paint mPaint;
32 |
33 | /**
34 | * 文本画笔
35 | */
36 | private TextPaint mTextPaint;
37 |
38 | /**
39 | * 笔画描边的宽度
40 | */
41 | private float mStrokeWidth;
42 |
43 | /**
44 | * 开始角度(默认从12点钟方向开始)
45 | */
46 | private int mStartAngle = 270;
47 | /**
48 | * 扫描角度(一个圆)
49 | */
50 | private int mSweepAngle = 360;
51 |
52 | /**
53 | * 圆心坐标x
54 | */
55 | private float mCircleCenterX;
56 | /**
57 | * 圆心坐标y
58 | */
59 | private float mCircleCenterY;
60 |
61 | /**
62 | * 圆正常颜色
63 | */
64 | private int mNormalColor = 0xFFC8C8C8;
65 | /**
66 | * 进度颜色
67 | */
68 | private int mProgressColor = 0xFF4FEAAC;
69 |
70 | /**
71 | * 是否使用着色器
72 | */
73 | private boolean isShader = true;
74 |
75 | /**
76 | * 着色器
77 | */
78 | private Shader mShader;
79 |
80 | /**
81 | * 着色器颜色
82 | */
83 | private int[] mShaderColors = new int[]{0xFF4FEAAC,0xFFA8DD51,0xFFE8D30F,0xFFA8DD51,0xFF4FEAAC};
84 |
85 | /**
86 | * 半径
87 | */
88 | private float mRadius;
89 |
90 | /**
91 | * 内圆与外圆的间距
92 | */
93 | private float mCirclePadding;
94 |
95 | /**
96 | * 刻度间隔的角度大小
97 | */
98 | private int mTickSplitAngle = 5;
99 |
100 | /**
101 | * 刻度的角度大小
102 | */
103 | private int mBlockAngle = 1;
104 |
105 | /**
106 | * 刻度偏移的角度大小
107 | */
108 | private float mTickOffsetAngle = 0;
109 |
110 | /**
111 | * 总刻度数
112 | */
113 | private int mTotalTickCount;
114 |
115 | /**
116 | * 最大进度
117 | */
118 | private int mMax = 100;
119 |
120 | /**
121 | * 当前进度
122 | */
123 | private int mProgress = 0;
124 |
125 | /**
126 | * 动画持续的时间
127 | */
128 | private int mDuration = 500;
129 |
130 | /**
131 | * 标签内容
132 | */
133 | private String mLabelText;
134 |
135 | /**
136 | * 字体大小
137 | */
138 | private float mLabelTextSize;
139 |
140 | /**
141 | * 字体颜色
142 | */
143 | private int mLabelTextColor = 0xFF333333;
144 |
145 | /**
146 | * 标签内容距圆形内间距
147 | */
148 | private float mLabelPaddingLeft;
149 | private float mLabelPaddingTop;
150 | private float mLabelPaddingRight;
151 | private float mLabelPaddingBottom;
152 |
153 | /**
154 | * 进度百分比
155 | */
156 | private int mProgressPercent;
157 |
158 | /**
159 | * 是否显示标签文字
160 | */
161 | private boolean isShowLabel = true;
162 | /**
163 | * 是否默认显示百分比为标签文字
164 | */
165 | private boolean isShowPercentText = true;
166 | /**
167 | * 是否显示外边框刻度
168 | */
169 | private boolean isShowTick = true;
170 |
171 | /**
172 | * 是否旋转
173 | */
174 | private boolean isTurn = false;
175 |
176 | /**
177 | * 是否是圆形线冒(圆角弧度)
178 | */
179 | private boolean isCapRound = true;
180 |
181 | private boolean isMeasureCircle = false;
182 |
183 |
184 | private OnChangeListener mOnChangeListener;
185 |
186 |
187 | public CircleProgressView(Context context) {
188 | this(context,null);
189 | }
190 |
191 | public CircleProgressView(Context context, AttributeSet attrs) {
192 | this(context, attrs,0);
193 | }
194 |
195 | public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
196 | super(context, attrs, defStyleAttr);
197 | init(context,attrs);
198 | }
199 |
200 | /**
201 | * 初始化
202 | * @param context
203 | * @param attrs
204 | */
205 | private void init(Context context,AttributeSet attrs){
206 | TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CircleProgressView);
207 |
208 | DisplayMetrics displayMetrics = getDisplayMetrics();
209 | mStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,12,displayMetrics);
210 |
211 | mLabelTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,30,displayMetrics);
212 |
213 | mCirclePadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,displayMetrics);
214 |
215 | int size = a.getIndexCount();
216 | for(int i = 0;i < size;i++){
217 | int attr = a.getIndex(i);
218 | if (attr == R.styleable.CircleProgressView_cpvStrokeWidth) {
219 | mStrokeWidth = a.getDimension(attr,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,12,displayMetrics));
220 | }else if(attr == R.styleable.CircleProgressView_cpvNormalColor){
221 | mNormalColor = a.getColor(attr,0xFFC8C8C8);
222 | }else if(attr == R.styleable.CircleProgressView_cpvProgressColor){
223 | mProgressColor = a.getColor(attr,0xFF4FEAAC);
224 | isShader = false;
225 | }else if(attr == R.styleable.CircleProgressView_cpvStartAngle){
226 | mStartAngle = a.getInt(attr,270);
227 | }else if(attr == R.styleable.CircleProgressView_cpvSweepAngle){
228 | mSweepAngle = a.getInt(attr,360);
229 | }else if(attr == R.styleable.CircleProgressView_cpvMax){
230 | mMax = a.getInt(attr,100);
231 | }else if(attr == R.styleable.CircleProgressView_cpvProgress){
232 | mProgress = a.getInt(attr,0);
233 | }else if(attr == R.styleable.CircleProgressView_cpvDuration){
234 | mDuration = a.getInt(attr,500);
235 | }else if(attr == R.styleable.CircleProgressView_cpvLabelText){
236 | mLabelText = a.getString(attr);
237 | }else if(attr == R.styleable.CircleProgressView_cpvLabelTextSize){
238 | mLabelTextSize = a.getDimension(attr,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,30,displayMetrics));
239 | }else if(attr == R.styleable.CircleProgressView_cpvLabelTextColor){
240 | mLabelTextColor = a.getColor(attr,0xFF333333);
241 | }else if(attr == R.styleable.CircleProgressView_cpvShowLabel) {
242 | isShowLabel = a.getBoolean(attr, isShowLabel);
243 | }else if(attr == R.styleable.CircleProgressView_cpvShowTick){
244 | isShowTick = a.getBoolean(attr,isShowTick);
245 | }else if(attr == R.styleable.CircleProgressView_cpvCirclePadding){
246 | mCirclePadding = a.getDimension(attr,TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,displayMetrics));
247 | }else if(attr == R.styleable.CircleProgressView_cpvTickSplitAngle){
248 | mTickSplitAngle = a.getInt(attr,mTickSplitAngle);
249 | }else if(attr == R.styleable.CircleProgressView_cpvBlockAngle){
250 | mBlockAngle = a.getInt(attr,mBlockAngle);
251 | }else if(attr == R.styleable.CircleProgressView_cpvTickOffsetAngle){
252 | mTickOffsetAngle = a.getInt(attr,0);
253 | }else if(attr == R.styleable.CircleProgressView_cpvTurn){
254 | isTurn = a.getBoolean(attr,isTurn);
255 | }else if(attr == R.styleable.CircleProgressView_cpvCapRound){
256 | isCapRound = a.getBoolean(attr,isCapRound);
257 | }else if(attr == R.styleable.CircleProgressView_cpvLabelPaddingLeft){
258 | mLabelPaddingLeft = a.getDimension(attr,0);
259 | }else if(attr == R.styleable.CircleProgressView_cpvLabelPaddingTop){
260 | mLabelPaddingTop = a.getDimension(attr,0);
261 | }else if(attr == R.styleable.CircleProgressView_cpvLabelPaddingRight){
262 | mLabelPaddingRight = a.getDimension(attr,0);
263 | }else if(attr == R.styleable.CircleProgressView_cpvLabelPaddingBottom){
264 | mLabelPaddingBottom = a.getDimension(attr,0);
265 | }
266 | }
267 |
268 | isShowPercentText = TextUtils.isEmpty(mLabelText);
269 |
270 | a.recycle();
271 | mProgressPercent = (int)(mProgress * 100.0f / mMax);
272 | mPaint = new Paint();
273 | mTextPaint = new TextPaint();
274 |
275 | mTotalTickCount = (int)(1.0f * mSweepAngle / (mTickSplitAngle + mBlockAngle));
276 |
277 | }
278 |
279 |
280 | private DisplayMetrics getDisplayMetrics(){
281 | return getResources().getDisplayMetrics();
282 | }
283 |
284 | @Override
285 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
286 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
287 |
288 | int defaultValue = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,200,getDisplayMetrics());
289 |
290 | int width = measureHandler(widthMeasureSpec,defaultValue);
291 | int height = measureHandler(heightMeasureSpec,defaultValue);
292 |
293 | //圆心坐标
294 | mCircleCenterX = (width + getPaddingLeft() - getPaddingRight())/ 2.0f;
295 | mCircleCenterY = (height + getPaddingTop() - getPaddingBottom())/ 2.0f;
296 | //计算间距
297 | int padding = Math.max(getPaddingLeft() + getPaddingRight(),getPaddingTop() + getPaddingBottom());
298 | //半径=视图宽度-横向或纵向内间距值 - 画笔宽度
299 | mRadius = (width - padding - mStrokeWidth) / 2.0f - mCirclePadding ;
300 |
301 | //默认着色器
302 | mShader = new SweepGradient(mCircleCenterX,mCircleCenterX,mShaderColors,null);
303 | isMeasureCircle = true;
304 |
305 | setMeasuredDimension(width,height);
306 |
307 |
308 | }
309 |
310 | /**
311 | * 测量
312 | * @param measureSpec
313 | * @param defaultSize
314 | * @return
315 | */
316 | private int measureHandler(int measureSpec,int defaultSize){
317 |
318 | int result = defaultSize;
319 | int measureMode = MeasureSpec.getMode(measureSpec);
320 | int measureSize = MeasureSpec.getSize(measureSpec);
321 | if(measureMode == MeasureSpec.EXACTLY){
322 | result = measureSize;
323 | }else if(measureMode == MeasureSpec.AT_MOST){
324 | result = Math.min(defaultSize,measureSize);
325 | }
326 | return result;
327 | }
328 |
329 |
330 | @Override
331 | protected void onDraw(Canvas canvas) {
332 | super.onDraw(canvas);
333 | drawArc(canvas);
334 | drawText(canvas);
335 | }
336 |
337 |
338 | /**
339 | * 绘制弧形(默认为一个圆)
340 | * @param canvas
341 | */
342 | private void drawArc(Canvas canvas){
343 | mPaint.reset();
344 | mPaint.setAntiAlias(true);
345 | mPaint.setStyle(Paint.Style.STROKE);
346 |
347 | mPaint.setStrokeWidth(mStrokeWidth);
348 |
349 | if(isShowTick){//是否显示外边框刻度
350 | float tickDiameter = mRadius * 2;
351 | float tickStartX = mCircleCenterX - mRadius;
352 | float tickStartY = mCircleCenterY - mRadius;
353 | RectF rectF = new RectF(tickStartX,tickStartY,tickStartX + tickDiameter,tickStartY + tickDiameter);
354 |
355 | final int currentBlockIndex = (int)(mProgressPercent / 100f * mTotalTickCount);
356 | if(isTurn){
357 | for (int i = 0; i < mTotalTickCount; i++) {
358 | //底层未选中刻度
359 | mPaint.setShader(null);
360 | mPaint.setColor(mNormalColor);
361 | //绘制外边框刻度
362 | canvas.drawArc(rectF, i * (mBlockAngle + mTickSplitAngle) + mStartAngle + mTickOffsetAngle, mBlockAngle, false, mPaint);
363 | }
364 |
365 | for (int i = currentBlockIndex; i < currentBlockIndex + currentBlockIndex; i++) {
366 | //已选中的刻度
367 | if (isShader && mShader != null) {
368 | mPaint.setShader(mShader);
369 | } else {
370 | mPaint.setColor(mProgressColor);
371 | }
372 | //绘制外边框刻度
373 | canvas.drawArc(rectF, i * (mBlockAngle + mTickSplitAngle) + mStartAngle + mTickOffsetAngle, mBlockAngle, false, mPaint);
374 | }
375 | }else{
376 | for (int i = 0; i < mTotalTickCount; i++) {
377 | if (i < currentBlockIndex) {
378 | //已选中的刻度
379 | if (isShader && mShader != null) {
380 | mPaint.setShader(mShader);
381 | } else {
382 | mPaint.setColor(mProgressColor);
383 | }
384 | //绘制外边框刻度
385 | canvas.drawArc(rectF, i * (mBlockAngle + mTickSplitAngle) + mStartAngle + mTickOffsetAngle, mBlockAngle, false, mPaint);
386 | } else if(mNormalColor != 0){
387 | //未选中的刻度
388 | mPaint.setShader(null);
389 | mPaint.setColor(mNormalColor);
390 | //绘制外边框刻度
391 | canvas.drawArc(rectF, i * (mBlockAngle + mTickSplitAngle) + mStartAngle + mTickOffsetAngle, mBlockAngle, false, mPaint);
392 | }
393 |
394 | }
395 | }
396 |
397 | }
398 |
399 | mPaint.setShader(null);
400 | if(isCapRound){
401 | mPaint.setStrokeCap(Paint.Cap.ROUND);
402 | }
403 |
404 | //进度圆半径
405 | float circleRadius = isShowTick ? mRadius - mCirclePadding - mStrokeWidth : mRadius;
406 | float diameter = circleRadius * 2;
407 | float startX = mCircleCenterX - circleRadius;
408 | float startY = mCircleCenterY - circleRadius;
409 | RectF rectF1 = new RectF(startX,startY,startX + diameter,startY + diameter);
410 |
411 | if(mNormalColor != 0){
412 | mPaint.setColor(mNormalColor);
413 | //绘制底层弧形
414 | canvas.drawArc(rectF1,mStartAngle,mSweepAngle,false,mPaint);
415 | }
416 |
417 | //着色器不为空则设置着色器,反之用纯色
418 | if(isShader && mShader!=null){
419 | mPaint.setShader(mShader);
420 | }else{
421 | mPaint.setColor(mProgressColor);
422 | }
423 |
424 | if(isTurn){
425 | //绘制当前进度弧形
426 | canvas.drawArc(rectF1,mStartAngle + mSweepAngle * getRatio(),mSweepAngle * getRatio(),false,mPaint);
427 | }else{
428 | //绘制当前进度弧形
429 | canvas.drawArc(rectF1,mStartAngle,mSweepAngle * getRatio(),false,mPaint);
430 | }
431 |
432 | }
433 |
434 | /**
435 | * 绘制中间的文本
436 | * @param canvas
437 | */
438 | private void drawText(Canvas canvas){
439 | if(!isShowLabel){
440 | return;
441 | }
442 | mTextPaint.reset();
443 | mTextPaint.setAntiAlias(true);
444 | mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
445 | mTextPaint.setTextSize(mLabelTextSize);
446 | mTextPaint.setColor(mLabelTextColor);
447 | mTextPaint.setTextAlign(Paint.Align.CENTER);
448 |
449 | Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
450 | // 计算文字高度
451 | float fontHeight = fontMetrics.bottom - fontMetrics.top;
452 | // 计算文字baseline
453 | float textBaseX = getWidth() / 2 + mLabelPaddingLeft - mLabelPaddingRight;
454 | float textBaseY = getHeight() - (getHeight() - fontHeight) / 2 - fontMetrics.bottom + mLabelPaddingTop - mLabelPaddingBottom;
455 | if(isShowPercentText){//是否显示百分比
456 | canvas.drawText(mProgressPercent + "%",textBaseX,textBaseY,mTextPaint);
457 | }else if(!TextUtils.isEmpty(mLabelText)){//显示自定义文本
458 | canvas.drawText(mLabelText,textBaseX,textBaseY,mTextPaint);
459 | }
460 |
461 | }
462 |
463 | /**
464 | * 显示进度动画效果(根据当前已有进度开始)
465 | * @param progress
466 | */
467 | public void showAppendAnimation(int progress){
468 | showAnimation(mProgress,progress,mDuration);
469 | }
470 |
471 | /**
472 | * 显示进度动画效果
473 | * @param progress
474 | */
475 | public void showAnimation(int progress){
476 | showAnimation(progress,mDuration);
477 | }
478 |
479 | /**
480 | * 显示进度动画效果
481 | * @param progress
482 | * @param duration 动画时长
483 | */
484 | public void showAnimation(int progress,int duration){
485 | showAnimation(0,progress,duration);
486 | }
487 |
488 | /**
489 | * 显示进度动画效果,从from到to变化
490 | * @param from
491 | * @param to
492 | * @param duration 动画时长
493 | */
494 | public void showAnimation(int from,int to,int duration){
495 | showAnimation(from,to,duration,null);
496 | }
497 |
498 | /**
499 | * 显示进度动画效果,从from到to变化
500 | * @param from
501 | * @param to
502 | * @param duration 动画时长
503 | * @param listener
504 | */
505 | public void showAnimation(int from, int to, int duration, Animator.AnimatorListener listener){
506 | this.mDuration = duration;
507 | this.mProgress = from;
508 | ValueAnimator valueAnimator = ValueAnimator.ofInt(from,to);
509 | valueAnimator.setDuration(duration);
510 |
511 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
512 | @Override
513 | public void onAnimationUpdate(ValueAnimator animation) {
514 | setProgress((int)animation.getAnimatedValue());
515 | }
516 | });
517 |
518 | if(listener!=null){
519 | valueAnimator.removeAllUpdateListeners();
520 | valueAnimator.addListener(listener);
521 | }
522 |
523 | valueAnimator.start();
524 | }
525 |
526 | /**
527 | * 进度比例
528 | * @return
529 | */
530 | private float getRatio(){
531 | return mProgress * 1.0f /mMax;
532 | }
533 |
534 | /**
535 | * 设置最大进度
536 | * @param max
537 | */
538 | public void setMax(int max){
539 | this.mMax = max;
540 | invalidate();
541 | }
542 |
543 | /**
544 | * 设置当前进度
545 | * @param progress
546 | */
547 | public void setProgress(int progress){
548 | this.mProgress = progress;
549 | mProgressPercent = (int)(mProgress * 100.0f / mMax);
550 | invalidate();
551 |
552 | if(mOnChangeListener!=null){
553 | mOnChangeListener.onProgressChanged(mProgress,mMax);
554 | }
555 | }
556 |
557 | /**
558 | * 设置正常颜色
559 | * @param color
560 | */
561 | public void setNormalColor(int color){
562 | this.mNormalColor = color;
563 | invalidate();
564 | }
565 |
566 |
567 | /**
568 | * 设置着色器
569 | * @param shader
570 | */
571 | public void setShader(Shader shader){
572 | isShader = true;
573 | this.mShader = shader;
574 | invalidate();
575 | }
576 |
577 | /**
578 | * 设置进度颜色(通过着色器实现渐变色)
579 | * @param colors
580 | */
581 | public void setProgressColor(int... colors){
582 | if(isMeasureCircle){
583 | Shader shader = new SweepGradient(mCircleCenterX,mCircleCenterX,colors,null);
584 | setShader(shader);
585 | }else{
586 | mShaderColors = colors;
587 | isShader = true;
588 | }
589 |
590 | }
591 |
592 | /**
593 | * 设置进度颜色(纯色)
594 | * @param color
595 | */
596 | public void setProgressColor(int color){
597 | isShader = false;
598 | this.mProgressColor = color;
599 | invalidate();
600 | }
601 |
602 | /**
603 | * 设置进度颜色
604 | * @param resId
605 | */
606 | public void setProgressColorResource(int resId){
607 | int color = getResources().getColor(resId);
608 | setProgressColor(color);
609 | }
610 |
611 | /**
612 | * 设置是否显示外环刻度
613 | * @param isShowTick
614 | */
615 | public void setShowTick(boolean isShowTick){
616 | this.isShowTick = isShowTick;
617 | invalidate();
618 | }
619 |
620 | /**
621 | * 设置是否旋转
622 | * @param isTurn
623 | */
624 | public void setTurn(boolean isTurn){
625 | this.isTurn = isTurn;
626 | invalidate();
627 | }
628 |
629 | /**
630 | * 是否是圆形线冒(圆角弧度)
631 | * @param capRound
632 | */
633 | public void setCapRound(boolean capRound) {
634 | isCapRound = capRound;
635 | invalidate();
636 | }
637 |
638 | public int getStartAngle() {
639 | return mStartAngle;
640 | }
641 |
642 | public int getSweepAngle() {
643 | return mSweepAngle;
644 | }
645 |
646 | public float getCircleCenterX() {
647 | return mCircleCenterX;
648 | }
649 |
650 | public float getCircleCenterY() {
651 | return mCircleCenterY;
652 | }
653 |
654 | public float getRadius() {
655 | return mRadius;
656 | }
657 |
658 | public int getMax() {
659 | return mMax;
660 | }
661 |
662 | public int getProgress(){
663 | return mProgress;
664 | }
665 |
666 | public String getLabelText() {
667 | return mLabelText;
668 | }
669 |
670 | public boolean isShowLabel() {
671 | return isShowLabel;
672 | }
673 |
674 | public boolean isShowPercentText() {
675 | return isShowPercentText;
676 | }
677 |
678 | public boolean isShowTick() {
679 | return isShowTick;
680 | }
681 |
682 | public boolean isTurn() {
683 | return isTurn;
684 | }
685 |
686 | public boolean isCapRound() {
687 | return isCapRound;
688 | }
689 |
690 | public void setShowLabel(boolean showLabel) {
691 | isShowLabel = showLabel;
692 | invalidate();
693 | }
694 |
695 | public void setShowPercentText(boolean showPercentText) {
696 | isShowPercentText = showPercentText;
697 | invalidate();
698 | }
699 |
700 | public void setLabelPaddingLeft(float labelPaddingLeft) {
701 | this.mLabelPaddingLeft = labelPaddingLeft;
702 | invalidate();
703 | }
704 |
705 | public void setLabelPaddingTop(float labelPaddingTop) {
706 | this.mLabelPaddingTop = labelPaddingTop;
707 | invalidate();
708 | }
709 |
710 | public void setLabelPaddingRight(float labelPaddingRight) {
711 | this.mLabelPaddingRight = labelPaddingRight;
712 | invalidate();
713 | }
714 |
715 | public void setLabelPaddingBottom(float labelPaddingBottom) {
716 | this.mLabelPaddingBottom = labelPaddingBottom;
717 | invalidate();
718 | }
719 |
720 | /**
721 | * 设置标签文本
722 | * @param labelText
723 | */
724 | public void setLabelText(String labelText) {
725 | this.mLabelText = labelText;
726 | this.isShowPercentText = TextUtils.isEmpty(labelText);
727 | invalidate();
728 | }
729 |
730 | /**
731 | * 进度百分比
732 | * @return
733 | */
734 | public int getProgressPercent() {
735 | return mProgressPercent;
736 | }
737 |
738 | /**
739 | * 如果自定义设置过{@link #setLabelText(String)} 或通过xml设置过{@code app:labelText}则
740 | * 返回{@link #mLabelText},反之默认返回百分比{@link #mProgressPercent}
741 | * @return
742 | */
743 | public String getText(){
744 | if(isShowPercentText){
745 | return mProgressPercent + "%";
746 | }
747 |
748 | return mLabelText;
749 | }
750 |
751 | public int getLabelTextColor() {
752 | return mLabelTextColor;
753 | }
754 |
755 | public void setLabelTextColor(int color) {
756 | this.mLabelTextColor = color;
757 | invalidate();
758 | }
759 |
760 | public void setLabelTextColorResource(int resId){
761 | int color = getResources().getColor(resId);
762 | setLabelTextColor(color);
763 | }
764 |
765 | public void setLabelTextSize(float textSize){
766 | setLabelTextSize(TypedValue.COMPLEX_UNIT_SP,textSize);
767 | }
768 |
769 | public void setLabelTextSize(int unit,float textSize){
770 | float size = TypedValue.applyDimension(unit,textSize,getDisplayMetrics());
771 | if(mLabelTextSize!= size){
772 | this.mLabelTextSize = size;
773 | invalidate();
774 | }
775 |
776 | }
777 |
778 | /**
779 | * 设置进度改变监听
780 | * @param onChangeListener
781 | */
782 | public void setOnChangeListener(OnChangeListener onChangeListener){
783 | this.mOnChangeListener = onChangeListener;
784 | }
785 |
786 | public interface OnChangeListener{
787 | void onProgressChanged(float progress,float max);
788 | }
789 | }
790 |
--------------------------------------------------------------------------------