├── .gitattributes
├── .gitignore
├── README.md
└── RadarScanView
├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── RadarScanView.iml
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── guo
│ │ └── duoduo
│ │ └── radarscanview
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── guo
│ │ │ └── duoduo
│ │ │ └── radarscanview
│ │ │ ├── MainActivity.java
│ │ │ └── RefreshProgressActivity.java
│ └── res
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_refresh_progress.xml
│ │ └── content_refresh_progress.xml
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── guo
│ └── duoduo
│ └── radarscanview
│ └── ExampleUnitTest.java
├── build.gradle
├── gif
├── radar.gif
└── radarscan.gif
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── .gitignore
├── build.gradle
├── library.iml
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── guo
│ │ └── duoduo
│ │ └── library
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── guo
│ │ │ └── duoduo
│ │ │ └── library
│ │ │ ├── LinearAnimation.java
│ │ │ ├── RadarScanView.java
│ │ │ └── RefreshProgress.java
│ └── res
│ │ └── values
│ │ ├── attrs.xml
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── guo
│ └── duoduo
│ └── library
│ └── ExampleUnitTest.java
├── randomtextview
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── randomtextview.iml
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── guo
│ │ └── duoduo
│ │ └── randomtextview
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── guo
│ │ │ └── duoduo
│ │ │ └── randomtextview
│ │ │ └── RandomTextView.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── guo
│ └── duoduo
│ └── randomtextview
│ └── ExampleUnitTest.java
├── rippleview
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── rippleview.iml
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── guo
│ │ └── duoduo
│ │ └── rippleoutview
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── guo
│ │ │ └── duoduo
│ │ │ └── rippleoutview
│ │ │ └── RippleView.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── guo
│ └── duoduo
│ └── rippleoutview
│ └── ExampleUnitTest.java
└── settings.gradle
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # Windows shortcuts
18 | *.lnk
19 |
20 | # =========================
21 | # Operating System Files
22 | # =========================
23 |
24 | # OSX
25 | # =========================
26 |
27 | .DS_Store
28 | .AppleDouble
29 | .LSOverride
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear on external disk
35 | .Spotlight-V100
36 | .Trashes
37 |
38 | # Directories potentially created on remote AFP share
39 | .AppleDB
40 | .AppleDesktop
41 | Network Trash Folder
42 | Temporary Items
43 | .apdisk
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RadarScanView
2 | 自定义View之雷达扫描
3 |
4 |
5 |
6 | ## 原理
7 | 关键是使用SweepGradient进行扫描渲染
8 | 关键代码如下:
9 |
10 | ```JAVA
11 | Shader shader = new SweepGradient(centerX, centerY, Color.TRANSPARENT, tailColor);
12 | mPaintRadar.setShader(shader);
13 | ```
14 | 然后旋转起来即可
15 |
16 | ```JAVA
17 | matrix.postRotate(start, centerX, centerY);
18 | ```
19 |
20 | 代码中包含了如何自定义一个View,怎样重写onMeasure、onSizeChanged、onDraw函数、自定义属性等等知识点
21 |
22 | ## 效果图
23 |
24 | 
25 |
26 | ## 添加动态显示效果
27 |
28 | ```JAVA
29 | new Handler().postDelayed(new Runnable()
30 | {
31 | @Override
32 | public void run()
33 | {
34 | randomTextView.addKeyWord("彭丽媛");
35 | randomTextView.addKeyWord("习近平");
36 | randomTextView.show();
37 | }
38 | }, 2 * 1000);
39 | ```
40 |
41 | ## 添加动态发现水波效果
42 | 
43 |
44 |
45 |
--------------------------------------------------------------------------------
/RadarScanView/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/.name:
--------------------------------------------------------------------------------
1 | RadarScanView
--------------------------------------------------------------------------------
/RadarScanView/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
22 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/misc.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 |
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 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/RadarScanView/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/RadarScanView/RadarScanView.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/RadarScanView/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/RadarScanView/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
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 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/RadarScanView/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.0"
6 |
7 | defaultConfig {
8 | applicationId "com.guo.duoduo.radarscanview"
9 | minSdkVersion 15
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile project(':library')
26 | compile project(':randomtextview')
27 | compile 'com.android.support:appcompat-v7:23.1.0'
28 | compile 'com.android.support:design:23.1.0'
29 | }
30 |
--------------------------------------------------------------------------------
/RadarScanView/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\developtools\android sdk windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/androidTest/java/com/guo/duoduo/radarscanview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.radarscanview;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/java/com/guo/duoduo/radarscanview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.radarscanview;
2 |
3 |
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.os.Handler;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 |
12 | import com.guo.duoduo.randomtextview.RandomTextView;
13 |
14 |
15 | public class MainActivity extends AppCompatActivity
16 | {
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState)
20 | {
21 | super.onCreate(savedInstanceState);
22 | setContentView(R.layout.activity_main);
23 |
24 | final RandomTextView randomTextView = (RandomTextView) findViewById(
25 | R.id.random_textview);
26 | randomTextView.setOnRippleViewClickListener(
27 | new RandomTextView.OnRippleViewClickListener()
28 | {
29 | @Override
30 | public void onRippleViewClicked(View view)
31 | {
32 | MainActivity.this.startActivity(
33 | new Intent(MainActivity.this, RefreshProgressActivity.class));
34 | }
35 | });
36 |
37 | new Handler().postDelayed(new Runnable()
38 | {
39 | @Override
40 | public void run()
41 | {
42 | randomTextView.addKeyWord("彭丽媛");
43 | randomTextView.addKeyWord("习近平");
44 | randomTextView.show();
45 | }
46 | }, 2 * 1000);
47 | }
48 |
49 | @Override
50 | public boolean onCreateOptionsMenu(Menu menu)
51 | {
52 | getMenuInflater().inflate(R.menu.menu_main, menu);
53 | return true;
54 | }
55 |
56 | @Override
57 | public boolean onOptionsItemSelected(MenuItem item)
58 | {
59 | int id = item.getItemId();
60 | if (id == R.id.action_settings)
61 | {
62 | return true;
63 | }
64 | return super.onOptionsItemSelected(item);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/java/com/guo/duoduo/radarscanview/RefreshProgressActivity.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.radarscanview;
2 |
3 |
4 | import android.os.Bundle;
5 | import android.support.design.widget.FloatingActionButton;
6 | import android.support.design.widget.Snackbar;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.View;
10 |
11 |
12 | public class RefreshProgressActivity extends AppCompatActivity
13 | {
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState)
17 | {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_refresh_progress);
20 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
21 | setSupportActionBar(toolbar);
22 |
23 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
24 | fab.setOnClickListener(new View.OnClickListener()
25 | {
26 | @Override
27 | public void onClick(View view)
28 | {
29 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
30 | .setAction("Action", null).show();
31 | }
32 | });
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
10 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/layout/activity_refresh_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/layout/content_refresh_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/RadarScanView/bda53b8b9ca9d4f75e57c346842178773bceeb9c/RadarScanView/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/RadarScanView/bda53b8b9ca9d4f75e57c346842178773bceeb9c/RadarScanView/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/RadarScanView/bda53b8b9ca9d4f75e57c346842178773bceeb9c/RadarScanView/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/RadarScanView/bda53b8b9ca9d4f75e57c346842178773bceeb9c/RadarScanView/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RadarScanView
3 |
4 | Hello world!
5 | Settings
6 | RefreshProgressActivity
7 |
8 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/RadarScanView/app/src/test/java/com/guo/duoduo/radarscanview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.radarscanview;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/RadarScanView/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/RadarScanView/gif/radar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/RadarScanView/bda53b8b9ca9d4f75e57c346842178773bceeb9c/RadarScanView/gif/radar.gif
--------------------------------------------------------------------------------
/RadarScanView/gif/radarscan.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/RadarScanView/bda53b8b9ca9d4f75e57c346842178773bceeb9c/RadarScanView/gif/radarscan.gif
--------------------------------------------------------------------------------
/RadarScanView/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/RadarScanView/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/RadarScanView/bda53b8b9ca9d4f75e57c346842178773bceeb9c/RadarScanView/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/RadarScanView/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Aug 19 20:11:19 CST 2015
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-2.4-all.zip
7 |
--------------------------------------------------------------------------------
/RadarScanView/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
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 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/RadarScanView/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/RadarScanView/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/RadarScanView/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.0"
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:23.0.0'
25 | }
26 |
--------------------------------------------------------------------------------
/RadarScanView/library/library.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
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 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/RadarScanView/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\developtools\android sdk windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/RadarScanView/library/src/androidTest/java/com/guo/duoduo/library/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.library;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/RadarScanView/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/RadarScanView/library/src/main/java/com/guo/duoduo/library/LinearAnimation.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.library;
2 |
3 |
4 | import android.view.animation.Animation;
5 | import android.view.animation.Transformation;
6 |
7 |
8 | /**
9 | * Created by 郭攀峰 on 2015/11/22.
10 | */
11 | public class LinearAnimation extends Animation
12 | {
13 | private LinearAnimationListener mListener = null;
14 |
15 | public interface LinearAnimationListener
16 | {
17 | void applyTans(float interpolatedTime);
18 | }
19 |
20 | @Override
21 | protected void applyTransformation(float interpolatedTime, Transformation t)
22 | {
23 | super.applyTransformation(interpolatedTime, t);
24 | if (mListener != null)
25 | mListener.applyTans(interpolatedTime);
26 | }
27 |
28 | public void setLinearAnimationListener(LinearAnimationListener listener)
29 | {
30 | mListener = listener;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/RadarScanView/library/src/main/java/com/guo/duoduo/library/RadarScanView.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.library;
2 |
3 |
4 | import android.annotation.TargetApi;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Canvas;
8 | import android.graphics.Color;
9 | import android.graphics.Matrix;
10 | import android.graphics.Paint;
11 | import android.graphics.Shader;
12 | import android.graphics.SweepGradient;
13 | import android.os.Handler;
14 | import android.util.AttributeSet;
15 | import android.view.View;
16 |
17 |
18 | /**
19 | * Created by 郭攀峰 on 2015/8/19.
20 | */
21 | public class RadarScanView extends View
22 | {
23 | private static final int DEFAULT_WIDTH = 300;
24 | private static final int DEFAULT_HEIGHT = 300;
25 |
26 | private int defaultWidth;
27 | private int defaultHeight;
28 | private int start;
29 | private int centerX;
30 | private int centerY;
31 | private int radarRadius;
32 | private int circleColor = Color.parseColor("#a2a2a2");
33 | private int radarColor = Color.parseColor("#99a2a2a2");
34 | private int tailColor = Color.parseColor("#50aaaaaa");
35 |
36 | private Paint mPaintCircle;
37 | private Paint mPaintRadar;
38 | private Matrix matrix;
39 |
40 | private Handler handler = new Handler();
41 | private Runnable run = new Runnable()
42 | {
43 | @Override
44 | public void run()
45 | {
46 | start += 2;
47 | matrix = new Matrix();
48 | matrix.postRotate(start, centerX, centerY);
49 | postInvalidate();
50 | handler.postDelayed(run, 10);
51 | }
52 | };
53 |
54 | public RadarScanView(Context context)
55 | {
56 | super(context);
57 | init(null, context);
58 | }
59 |
60 | public RadarScanView(Context context, AttributeSet attrs)
61 | {
62 | super(context, attrs);
63 | init(attrs, context);
64 | }
65 |
66 | public RadarScanView(Context context, AttributeSet attrs, int defStyleAttr)
67 | {
68 | super(context, attrs, defStyleAttr);
69 | init(attrs, context);
70 | }
71 |
72 | @TargetApi(21)
73 | public RadarScanView(Context context, AttributeSet attrs, int defStyleAttr,
74 | int defStyleRes)
75 | {
76 | super(context, attrs, defStyleAttr, defStyleRes);
77 | init(attrs, context);
78 | }
79 |
80 | @Override
81 | protected void onSizeChanged(int w, int h, int oldw, int oldh)
82 | {
83 | super.onSizeChanged(w, h, oldw, oldh);
84 | centerX = w / 2;
85 | centerY = h / 2;
86 | radarRadius = Math.min(w, h);
87 | }
88 |
89 | private void init(AttributeSet attrs, Context context)
90 | {
91 | if (attrs != null)
92 | {
93 | TypedArray ta = context.obtainStyledAttributes(attrs,
94 | R.styleable.RadarScanView);
95 | circleColor = ta.getColor(R.styleable.RadarScanView_circleColor, circleColor);
96 | radarColor = ta.getColor(R.styleable.RadarScanView_radarColor, radarColor);
97 | tailColor = ta.getColor(R.styleable.RadarScanView_tailColor, tailColor);
98 | ta.recycle();
99 | }
100 |
101 | initPaint();
102 | //得到当前屏幕的像素宽高
103 |
104 | defaultWidth = dip2px(context, DEFAULT_WIDTH);
105 | defaultHeight = dip2px(context, DEFAULT_HEIGHT);
106 |
107 | matrix = new Matrix();
108 | handler.post(run);
109 | }
110 |
111 | private void initPaint()
112 | {
113 | mPaintCircle = new Paint();
114 | mPaintCircle.setColor(circleColor);
115 | mPaintCircle.setAntiAlias(true);//抗锯齿
116 | mPaintCircle.setStyle(Paint.Style.STROKE);//设置实心
117 | mPaintCircle.setStrokeWidth(2);//画笔宽度
118 |
119 | mPaintRadar = new Paint();
120 | mPaintRadar.setColor(radarColor);
121 | mPaintRadar.setAntiAlias(true);
122 | }
123 |
124 | @Override
125 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
126 | {
127 | int resultWidth = 0;
128 | int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
129 | int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
130 |
131 | if (modeWidth == MeasureSpec.EXACTLY)
132 | {
133 | resultWidth = sizeWidth;
134 | }
135 | else
136 | {
137 | resultWidth = defaultWidth;
138 | if (modeWidth == MeasureSpec.AT_MOST)
139 | {
140 | resultWidth = Math.min(resultWidth, sizeWidth);
141 | }
142 | }
143 |
144 | int resultHeight = 0;
145 | int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
146 | int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
147 | if (modeHeight == MeasureSpec.EXACTLY)
148 | {
149 | resultHeight = sizeHeight;
150 | }
151 | else
152 | {
153 | resultHeight = defaultHeight;
154 | if (modeHeight == MeasureSpec.AT_MOST)
155 | {
156 | resultHeight = Math.min(resultHeight, sizeHeight);
157 | }
158 | }
159 |
160 | setMeasuredDimension(resultWidth, resultHeight);
161 | }
162 |
163 | @Override
164 | protected void onDraw(Canvas canvas)
165 | {
166 | super.onDraw(canvas);
167 |
168 | //分别绘制四个圆
169 | canvas.drawCircle(centerX, centerY, radarRadius / 7, mPaintCircle);
170 | canvas.drawCircle(centerX, centerY, radarRadius / 4, mPaintCircle);
171 | canvas.drawCircle(centerX, centerY, radarRadius / 3, mPaintCircle);
172 | canvas.drawCircle(centerX, centerY, 3 * radarRadius / 7, mPaintCircle);
173 |
174 | //设置颜色渐变从透明到不透明
175 | // Shader shader = new SweepGradient(centerX, centerY, Color.TRANSPARENT, tailColor);
176 | Shader shader = new SweepGradient(centerX, centerY, Color.parseColor("#00A8D7A7"),
177 | Color.parseColor("#ffA8D7A7"));
178 | mPaintRadar.setShader(shader);
179 | canvas.concat(matrix);
180 | canvas.drawCircle(centerX, centerY, 3 * radarRadius / 7, mPaintRadar);
181 | }
182 |
183 | private int dip2px(Context context, float dipValue)
184 | {
185 | final float scale = context.getResources().getDisplayMetrics().density;
186 | return (int) (dipValue * scale + 0.5f);
187 | }
188 |
189 | private int px2dip(Context context, float pxValue)
190 | {
191 | final float scale = context.getResources().getDisplayMetrics().density;
192 | return (int) (pxValue / scale + 0.5f);
193 | }
194 |
195 | }
196 |
--------------------------------------------------------------------------------
/RadarScanView/library/src/main/java/com/guo/duoduo/library/RefreshProgress.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.library;
2 |
3 |
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Matrix;
8 | import android.graphics.Paint;
9 | import android.graphics.RectF;
10 | import android.graphics.SweepGradient;
11 | import android.util.AttributeSet;
12 | import android.view.MotionEvent;
13 | import android.view.View;
14 | import android.view.animation.Animation;
15 | import android.view.animation.LinearInterpolator;
16 |
17 | import java.util.Map;
18 |
19 |
20 | public class RefreshProgress extends View
21 | {
22 | private static final String tag = "RefreshProgress";
23 |
24 | private RectF mRect = new RectF(0, 0, 200, 200);
25 | private float mStartAngle = 0.0f;
26 | private int mRadarRadius;
27 | private Paint mPaint;
28 |
29 | public RefreshProgress(Context context)
30 | {
31 | this(context, null);
32 | }
33 |
34 | public RefreshProgress(Context context, AttributeSet attrs)
35 | {
36 | this(context, attrs, 0);
37 | }
38 |
39 | public RefreshProgress(Context context, AttributeSet attrs, int defStyleAttr)
40 | {
41 | super(context, attrs, defStyleAttr);
42 |
43 | mPaint = new Paint();
44 | mPaint.setAntiAlias(true);
45 | mPaint.setStrokeWidth(8);
46 | mPaint.setStyle(Paint.Style.STROKE); //注释了就是雷达扫描图
47 | }
48 |
49 | @Override
50 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
51 | {
52 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
53 | int width = View.MeasureSpec.getSize(widthMeasureSpec);
54 | int height = MeasureSpec.getSize(heightMeasureSpec);
55 |
56 | mRadarRadius = Math.min(width, height);
57 |
58 | setMeasuredDimension(width, height);
59 | mRect.set(17, 17, width - 17, height - 17);
60 | }
61 |
62 | @Override
63 | protected void onDraw(Canvas canvas)
64 | {
65 | super.onDraw(canvas);
66 | drawAccProgressbar(mStartAngle, canvas);
67 | }
68 |
69 | private void drawAccProgressbar(float startAngle, Canvas canvas)
70 | {
71 | int[] f = {Color.parseColor("#00A8D7A7"), Color.parseColor("#ffA8D7A7")};
72 | float[] p = {0.0f, 1.0f};
73 | SweepGradient sweepGradient = new SweepGradient(mRect.centerX(), mRect.centerX(),
74 | f, p);
75 | Matrix matrix = new Matrix();
76 | matrix.postRotate(mStartAngle, mRect.centerX(), mRect.centerY());
77 | mPaint.setShader(sweepGradient);
78 | canvas.concat(matrix);
79 | canvas.drawArc(mRect, 0, 360, true, mPaint);
80 | }
81 |
82 | private void startRotate(long duration)
83 | {
84 | LinearAnimation animation = new LinearAnimation();
85 | animation.setDuration(duration);
86 | animation.setRepeatCount(Animation.INFINITE);
87 | animation.setInterpolator(new LinearInterpolator());
88 | animation.setLinearAnimationListener(new LinearAnimation.LinearAnimationListener()
89 | {
90 | @Override
91 | public void applyTans(float interpolatedTime)
92 | {
93 | mStartAngle = 360 * interpolatedTime;
94 | invalidate();
95 | }
96 | });
97 | startAnimation(animation);
98 | }
99 |
100 | private void stopRotate()
101 | {
102 | clearAnimation();
103 | }
104 |
105 | @Override
106 | protected void onAttachedToWindow()
107 | {
108 | super.onAttachedToWindow();
109 | stopRotate();
110 | startRotate(1 * 1000);
111 | }
112 |
113 | @Override
114 | protected void onDetachedFromWindow()
115 | {
116 | super.onDetachedFromWindow();
117 | stopRotate();
118 | }
119 |
120 | @Override
121 | public boolean onTouchEvent(MotionEvent event)
122 | {
123 | stopRotate();
124 | return super.onTouchEvent(event);
125 | }
126 | }
--------------------------------------------------------------------------------
/RadarScanView/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RadarScanView/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | library
3 |
4 |
--------------------------------------------------------------------------------
/RadarScanView/library/src/test/java/com/guo/duoduo/library/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.library;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:22.2.0'
25 | compile project(':rippleview')
26 | }
27 |
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\developtools\android_sdk_windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript p2pinterface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.p2pinterface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/randomtextview.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
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 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/src/androidTest/java/com/guo/duoduo/randomtextview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.randomtextview;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/src/main/java/com/guo/duoduo/randomtextview/RandomTextView.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.randomtextview;
2 |
3 |
4 | import java.util.LinkedList;
5 | import java.util.Random;
6 | import java.util.Vector;
7 |
8 | import android.annotation.TargetApi;
9 | import android.content.Context;
10 | import android.util.AttributeSet;
11 | import android.util.Log;
12 | import android.util.TypedValue;
13 | import android.view.Gravity;
14 | import android.view.View;
15 | import android.view.ViewTreeObserver;
16 | import android.widget.FrameLayout;
17 |
18 | import com.guo.duoduo.rippleoutview.RippleView;
19 |
20 |
21 | /**
22 | * Created by 郭攀峰 on 2015/9/17.
23 | */
24 | public class RandomTextView extends FrameLayout
25 | implements
26 | ViewTreeObserver.OnGlobalLayoutListener
27 | {
28 |
29 | private static final String tag = RandomTextView.class.getSimpleName();
30 |
31 | private static final int MAX = 5;
32 | private static final int IDX_X = 0;
33 | private static final int IDX_Y = 1;
34 | private static final int IDX_TXT_LENGTH = 2;
35 | private static final int IDX_DIS_Y = 3;
36 | private static final int TEXT_SIZE = 12;
37 |
38 | private Random random;
39 | private Vector vecKeywords;
40 | private int width;
41 | private int height;
42 | private int mode = RippleView.MODE_OUT;
43 | private int fontColor = 0xff0000ff;
44 | private int shadowColor = 0xdd696969;
45 |
46 | public interface OnRippleViewClickListener
47 | {
48 | void onRippleViewClicked(View view);
49 | }
50 |
51 | private OnRippleViewClickListener onRippleOutViewClickListener;
52 |
53 | public RandomTextView(Context context)
54 | {
55 | super(context);
56 | init(null, context);
57 | }
58 |
59 | public RandomTextView(Context context, AttributeSet attrs)
60 | {
61 | super(context, attrs);
62 | init(attrs, context);
63 | }
64 |
65 | public RandomTextView(Context context, AttributeSet attrs, int defStyleAttr)
66 | {
67 | super(context, attrs, defStyleAttr);
68 | init(attrs, context);
69 | }
70 |
71 | @TargetApi(21)
72 | public RandomTextView(Context context, AttributeSet attrs, int defStyleAttr,
73 | int defStyleRes)
74 | {
75 | super(context, attrs, defStyleAttr, defStyleRes);
76 | init(attrs, context);
77 | }
78 |
79 | public void setMode(int mode)
80 | {
81 | this.mode = mode;
82 | }
83 |
84 | public void setOnRippleViewClickListener(OnRippleViewClickListener listener)
85 | {
86 | onRippleOutViewClickListener = listener;
87 | }
88 |
89 | /**
90 | * 添加RippleOutView的内容
91 | *
92 | * @param keyword
93 | */
94 | public void addKeyWord(String keyword)
95 | {
96 | if (vecKeywords.size() < MAX)
97 | {
98 | if (!vecKeywords.contains(keyword))
99 | vecKeywords.add(keyword);
100 | }
101 | }
102 |
103 | public Vector getKeyWords()
104 | {
105 | return vecKeywords;
106 | }
107 |
108 | public void removeKeyWord(String keyword)
109 | {
110 | if (vecKeywords.contains(keyword))
111 | {
112 | vecKeywords.remove(keyword);
113 | }
114 | }
115 |
116 | private void init(AttributeSet attrs, Context context)
117 | {
118 | random = new Random();
119 | vecKeywords = new Vector(MAX);
120 | getViewTreeObserver().addOnGlobalLayoutListener(this);
121 |
122 | }
123 |
124 | @Override
125 | public void onGlobalLayout()
126 | {
127 | int tmpW = getWidth();
128 | int tmpH = getHeight();
129 | if (width != tmpW || height != tmpH)
130 | {
131 | width = tmpW;
132 | height = tmpH;
133 | Log.d(tag, "RandomTextView width = " + width + "; height = " + height);
134 | }
135 | }
136 |
137 | public void show()
138 | {
139 | this.removeAllViews();
140 |
141 | if (width > 0 && height > 0 && vecKeywords != null && vecKeywords.size() > 0)
142 | {
143 | //找到中心点
144 | int xCenter = width >> 1;
145 | int yCenter = height >> 1;
146 | //关键字的个数。
147 | int size = vecKeywords.size();
148 | int xItem = width / (size + 1);
149 | int yItem = height / (size + 1);
150 | LinkedList listX = new LinkedList<>();
151 | LinkedList listY = new LinkedList<>();
152 | for (int i = 0; i < size; i++)
153 | {
154 | // 准备随机候选数,分别对应x/y轴位置
155 | listX.add(i * xItem);
156 | listY.add(i * yItem + (yItem >> 2));
157 | }
158 | LinkedList listTxtTop = new LinkedList<>();
159 | LinkedList listTxtBottom = new LinkedList<>();
160 |
161 | for (int i = 0; i < size; i++)
162 | {
163 | String keyword = vecKeywords.get(i);
164 | // 随机颜色
165 | int ranColor = fontColor;
166 | // 随机位置,糙值
167 | int xy[] = randomXY(random, listX, listY, xItem);
168 |
169 | int txtSize = TEXT_SIZE;
170 | // 实例化RippleOutView
171 | final RippleView txt = new RippleView(getContext());
172 | if (mode == RippleView.MODE_IN)
173 | {
174 | txt.setMode(RippleView.MODE_IN);
175 | }
176 | else
177 | {
178 | txt.setMode(RippleView.MODE_OUT);
179 | }
180 |
181 | txt.setOnClickListener(new OnClickListener()
182 | {
183 | @Override
184 | public void onClick(View view)
185 | {
186 | if (onRippleOutViewClickListener != null)
187 | onRippleOutViewClickListener.onRippleViewClicked(view);
188 | }
189 | });
190 | txt.setText(keyword);
191 | txt.setTextColor(ranColor);
192 | txt.setTextSize(TypedValue.COMPLEX_UNIT_SP, txtSize);
193 | txt.setShadowLayer(1, 1, 1, shadowColor);
194 | txt.setGravity(Gravity.CENTER);
195 | txt.startRippleAnimation();
196 |
197 | // 获取文本长度
198 | //Paint paint = txt.getPaint();
199 | int strWidth = /* (int) Math.ceil(paint.measureText(keyword)) */txt
200 | .getMeasuredWidth();
201 | xy[IDX_TXT_LENGTH] = strWidth;
202 | // 第一次修正:修正x坐标
203 | if (xy[IDX_X] + strWidth > width - (xItem/* >> 1 */))
204 | {
205 | int baseX = width - strWidth;
206 | // 减少文本右边缘一样的概率
207 | xy[IDX_X] = baseX - xItem + random.nextInt(xItem >> 1);
208 | }
209 | else if (xy[IDX_X] == 0)
210 | {
211 | // 减少文本左边缘一样的概率
212 | xy[IDX_X] = Math.max(random.nextInt(xItem), xItem / 3);
213 | }
214 | xy[IDX_DIS_Y] = Math.abs(xy[IDX_Y] - yCenter);
215 | txt.setTag(xy);
216 | if (xy[IDX_Y] > yCenter)
217 | {
218 | listTxtBottom.add(txt);
219 | }
220 | else
221 | {
222 | listTxtTop.add(txt);
223 | }
224 | }
225 |
226 | attach2Screen(listTxtTop, xCenter, yCenter, yItem);
227 | attach2Screen(listTxtBottom, xCenter, yCenter, yItem);
228 | }
229 | }
230 |
231 | /** 修正RippleOutView的Y坐标将将其添加到容器上。 */
232 | private void attach2Screen(LinkedList listTxt, int xCenter, int yCenter,
233 | int yItem)
234 | {
235 | int size = listTxt.size();
236 | sortXYList(listTxt, size);
237 | for (int i = 0; i < size; i++)
238 | {
239 | RippleView txt = listTxt.get(i);
240 | int[] iXY = (int[]) txt.getTag();
241 | // 第二次修正:修正y坐标
242 | int yDistance = iXY[IDX_Y] - yCenter;
243 | // 对于最靠近中心点的,其值不会大于yItem
244 | // 对于可以一路下降到中心点的,则该值也是其应调整的大小
245 | int yMove = Math.abs(yDistance);
246 | inner : for (int k = i - 1; k >= 0; k--)
247 | {
248 | int[] kXY = (int[]) listTxt.get(k).getTag();
249 | int startX = kXY[IDX_X];
250 | int endX = startX + kXY[IDX_TXT_LENGTH];
251 | // y轴以中心点为分隔线,在同一侧
252 | if (yDistance * (kXY[IDX_Y] - yCenter) > 0)
253 | {
254 | if (isXMixed(startX, endX, iXY[IDX_X], iXY[IDX_X]
255 | + iXY[IDX_TXT_LENGTH]))
256 | {
257 | int tmpMove = Math.abs(iXY[IDX_Y] - kXY[IDX_Y]);
258 | if (tmpMove > yItem)
259 | {
260 | yMove = tmpMove;
261 | }
262 | else if (yMove > 0)
263 | {
264 | // 取消默认值。
265 | yMove = 0;
266 | }
267 | break inner;
268 | }
269 | }
270 | }
271 |
272 | if (yMove > yItem)
273 | {
274 | int maxMove = yMove - yItem;
275 | int randomMove = random.nextInt(maxMove);
276 | int realMove = Math.max(randomMove, maxMove >> 1) * yDistance
277 | / Math.abs(yDistance);
278 | iXY[IDX_Y] = iXY[IDX_Y] - realMove;
279 | iXY[IDX_DIS_Y] = Math.abs(iXY[IDX_Y] - yCenter);
280 | // 已经调整过前i个需要再次排序
281 | sortXYList(listTxt, i + 1);
282 | }
283 | FrameLayout.LayoutParams layParams = new FrameLayout.LayoutParams(
284 | /* FrameLayout.LayoutParams.WRAP_CONTENT */200,
285 | /* FrameLayout.LayoutParams.WRAP_CONTENT */200);
286 | layParams.gravity = Gravity.LEFT | Gravity.TOP;
287 | layParams.leftMargin = iXY[IDX_X];
288 | layParams.topMargin = iXY[IDX_Y];
289 | addView(txt, layParams);
290 | }
291 | }
292 |
293 | private int[] randomXY(Random ran, LinkedList listX,
294 | LinkedList listY, int xItem)
295 | {
296 | int[] arr = new int[4];
297 | arr[IDX_X] = listX.remove(ran.nextInt(listX.size()));
298 | arr[IDX_Y] = listY.remove(ran.nextInt(listY.size()));
299 | return arr;
300 | }
301 |
302 | /** A线段与B线段所代表的直线在X轴映射上是否有交集。 */
303 | private boolean isXMixed(int startA, int endA, int startB, int endB)
304 | {
305 | boolean result = false;
306 | if (startB >= startA && startB <= endA)
307 | {
308 | result = true;
309 | }
310 | else if (endB >= startA && endB <= endA)
311 | {
312 | result = true;
313 | }
314 | else if (startA >= startB && startA <= endB)
315 | {
316 | result = true;
317 | }
318 | else if (endA >= startB && endA <= endB)
319 | {
320 | result = true;
321 | }
322 | return result;
323 | }
324 |
325 | /**
326 | * 根据与中心点的距离由近到远进行冒泡排序。
327 | *
328 | * @param endIdx 起始位置。
329 | * @param listTxt 待排序的数组。
330 | *
331 | */
332 | private void sortXYList(LinkedList listTxt, int endIdx)
333 | {
334 | for (int i = 0; i < endIdx; i++)
335 | {
336 | for (int k = i + 1; k < endIdx; k++)
337 | {
338 | if (((int[]) listTxt.get(k).getTag())[IDX_DIS_Y] < ((int[]) listTxt
339 | .get(i).getTag())[IDX_DIS_Y])
340 | {
341 | RippleView iTmp = listTxt.get(i);
342 | RippleView kTmp = listTxt.get(k);
343 | listTxt.set(i, kTmp);
344 | listTxt.set(k, iTmp);
345 | }
346 | }
347 | }
348 | }
349 | }
350 |
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RandomTextView
3 |
4 |
--------------------------------------------------------------------------------
/RadarScanView/randomtextview/src/test/java/com/guo/duoduo/randomtextview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.randomtextview;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/RadarScanView/rippleview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/RadarScanView/rippleview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:22.2.0'
25 | }
26 |
--------------------------------------------------------------------------------
/RadarScanView/rippleview/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\developtools\android_sdk_windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript p2pinterface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.p2pinterface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/RadarScanView/rippleview/rippleview.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
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 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/RadarScanView/rippleview/src/androidTest/java/com/guo/duoduo/rippleoutview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.rippleoutview;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/RadarScanView/rippleview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/RadarScanView/rippleview/src/main/java/com/guo/duoduo/rippleoutview/RippleView.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.rippleoutview;
2 |
3 |
4 | import android.animation.ObjectAnimator;
5 | import android.animation.TypeEvaluator;
6 | import android.content.Context;
7 | import android.graphics.Canvas;
8 | import android.graphics.Color;
9 | import android.graphics.Paint;
10 | import android.util.AttributeSet;
11 | import android.util.Log;
12 | import android.view.animation.LinearInterpolator;
13 | import android.widget.TextView;
14 |
15 |
16 | /**
17 | * Created by 10129302 on 15-2-12.
18 | */
19 | public class RippleView extends TextView
20 | {
21 |
22 | private static final String tag = RippleView.class.getSimpleName();
23 |
24 | private static final int DEFAULT_RIPPLE_COLOR = Color.rgb(0x33, 0x99, 0xcc);
25 | /**
26 | * 波纹的颜色
27 | */
28 | private int mRippleColor = DEFAULT_RIPPLE_COLOR;
29 | /**
30 | * 默认的波纹的最小值
31 | */
32 | private int mMinSize = 200;
33 | /**
34 | * 波纹动画效果是否正在进行
35 | */
36 | private boolean animationRunning = false;
37 |
38 | private int currentProgress = 0;
39 | /**
40 | * 动画中波纹的个数
41 | */
42 | private int mRippleNum = 4;
43 | /**
44 | * //无限长的数值,使动画不停止
45 | */
46 | private int mTotalTime = 1000 * 1000;
47 |
48 | public static final int MODE_IN = 1;
49 | public static final int MODE_OUT = 2;
50 |
51 | private int mode = MODE_OUT;
52 |
53 | private int mPeriod = 30;
54 | private int mCenterX;
55 | private int mCenterY;
56 | private int mRadius;
57 | private Paint mPaint;
58 | private ObjectAnimator mAnimator;
59 |
60 | public RippleView(Context context)
61 | {
62 | super(context);
63 | initPaint();
64 | initAnimation();
65 | }
66 |
67 | public RippleView(Context context, AttributeSet attrs)
68 | {
69 | super(context, attrs);
70 | initPaint();
71 | initAnimation();
72 | }
73 |
74 | public RippleView(Context context, AttributeSet attrs, int defStyleAttr)
75 | {
76 | super(context, attrs, defStyleAttr);
77 | initPaint();
78 | initAnimation();
79 | }
80 |
81 | private void initPaint()
82 | {
83 | mPaint = new Paint();
84 | mPaint.setAntiAlias(true);
85 | mPaint.setStyle(Paint.Style.FILL);
86 | mPaint.setColor(mRippleColor);
87 | }
88 |
89 | private void initAnimation()
90 | {
91 | mAnimator = ObjectAnimator.ofInt(this, "currentProgress", 0, 100);
92 | mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
93 | mAnimator.setRepeatMode(ObjectAnimator.RESTART);
94 | mAnimator.setInterpolator(new LinearInterpolator());
95 | mAnimator.setEvaluator(mProgressEvaluator);
96 | mAnimator.setDuration(mTotalTime);
97 | }
98 |
99 | public void setMode(int mode)
100 | {
101 | this.mode = mode;
102 | }
103 |
104 | public void startRippleAnimation()
105 | {
106 | if (!animationRunning)
107 | {
108 | mAnimator.start();
109 | animationRunning = true;
110 | }
111 | }
112 |
113 | public void stopRippleAnimation()
114 | {
115 | if (animationRunning)
116 | {
117 | mAnimator.end();
118 | animationRunning = false;
119 | }
120 | }
121 |
122 | public boolean isRippleAnimationRunning()
123 | {
124 | return animationRunning;
125 | }
126 |
127 | public int getCurrentProgress()
128 | {
129 | return currentProgress;
130 | }
131 |
132 | public void setCurrentProgress(int currentProgress)
133 | {
134 | this.currentProgress = currentProgress;
135 | this.invalidate();
136 | }
137 |
138 | @Override
139 | protected void onSizeChanged(int w, int h, int oldw, int oldh)
140 | {
141 | super.onSizeChanged(w, h, oldw, oldh);
142 | }
143 |
144 | @Override
145 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
146 | {
147 | //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
148 | int resultWidth = 0;
149 | int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
150 | int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
151 | if (modeWidth == MeasureSpec.EXACTLY)
152 | {
153 | resultWidth = sizeWidth;
154 | }
155 | else
156 | {
157 | resultWidth = mMinSize;
158 | if (modeWidth == MeasureSpec.AT_MOST)
159 | {
160 | resultWidth = Math.min(resultWidth, sizeWidth);
161 | }
162 | }
163 |
164 | int resultHeight = 0;
165 | int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
166 | int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
167 | if (modeHeight == MeasureSpec.EXACTLY)
168 | {
169 | resultHeight = sizeHeight;
170 | }
171 | else
172 | {
173 | resultHeight = mMinSize;
174 | if (modeHeight == MeasureSpec.AT_MOST)
175 | {
176 | resultHeight = Math.min(resultHeight, sizeHeight);
177 | }
178 | }
179 |
180 | mCenterX = resultWidth / 2;
181 | mCenterY = resultHeight / 2;
182 | mRadius = Math.max(resultWidth, resultHeight) / 2;
183 |
184 | Log.d(tag, "ripple out view radius = " + mRadius + "; width =" + resultWidth
185 | + "; height = " + resultHeight);
186 |
187 | setMeasuredDimension(resultWidth, resultHeight);
188 | }
189 |
190 | @Override
191 | public void onDraw(Canvas canvas)
192 | {
193 | for (int i = 0; i < mRippleNum; i++)
194 | {
195 | int progress = (currentProgress + i * 100 / (mRippleNum)) % 100;
196 | if (mode == 1)
197 | progress = 100 - progress;
198 |
199 | mPaint.setAlpha(255 - 255 * progress / 100);
200 | canvas.drawCircle(mCenterX, mCenterY, mRadius * progress / 100, mPaint);
201 | }
202 | super.onDraw(canvas);
203 | }
204 |
205 | @Override
206 | protected void onDetachedFromWindow()
207 | {
208 | super.onDetachedFromWindow();
209 | if (isRippleAnimationRunning())
210 | stopRippleAnimation();
211 | }
212 |
213 | /**
214 | * 自定义估值器
215 | */
216 | private TypeEvaluator mProgressEvaluator = new TypeEvaluator()
217 | {
218 |
219 | @Override
220 | public Object evaluate(float fraction, Object startValue, Object endValue)
221 | {
222 | fraction = (fraction * mTotalTime / mPeriod) % 100;
223 | return fraction;
224 | }
225 | };
226 |
227 | }
228 |
--------------------------------------------------------------------------------
/RadarScanView/rippleview/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RippleOutView
3 |
4 |
--------------------------------------------------------------------------------
/RadarScanView/rippleview/src/test/java/com/guo/duoduo/rippleoutview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.guo.duoduo.rippleoutview;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/RadarScanView/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library', ':rippleview', ':randomtextview'
2 |
--------------------------------------------------------------------------------