├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── TIM图片20180115113215.jpg ├── app-debug.apk ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── thl │ │ └── demo │ │ ├── DemoApplication.java │ │ └── MainActivity.java │ └── res │ ├── drawable-hdpi │ ├── back_img.png │ └── ic_func_myworker.png │ ├── drawable │ ├── bg_circular_blue.xml │ ├── bg_circular_light_blue.xml │ ├── bg_circular_light_yellow.xml │ ├── bg_circular_yellow.xml │ ├── bg_gradient_linear_blue_0.xml │ ├── bg_gradient_linear_blue_270.xml │ ├── bg_gradient_linear_purple_0.xml │ ├── bg_gradient_linear_yellow_0.xml │ ├── bg_ib_back_selector.xml │ ├── bg_rectangle_white_r5.xml │ └── bg_rectangle_white_s1.xml │ ├── layout │ ├── activity_main.xml │ ├── layout_home_content.xml │ └── layout_title.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── config.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lib_ui ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── www │ │ └── thl │ │ └── com │ │ └── ui │ │ ├── BarChartView.java │ │ ├── LineChartView.java │ │ ├── RingView.java │ │ └── utils │ │ ├── DensityUtil.java │ │ └── ScreenUtils.java │ └── res │ ├── drawable-hdpi │ └── ic_func_myworker.png │ └── values │ ├── colors.xml │ └── strings.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ui介绍 2 | 3 | 提供android 折现图、图形图,扇形图,渐变图等常用报表ui,功能强大,一个报表一个类,代码十分简单,易修改易维护,绘制性能高效,库没有导入其他的第三方包,干净整洁。 4 | 主要是: 5 | 代码简单、代码简单、代码简单,易修改易维护 6 | 7 | 8 | # 效果图 9 | 10 | 11 | 12 | apk下载链接 13 | https://github.com/supertaohaili/UI/blob/master/app-debug.apk 14 | 15 | # 使用 16 | ``` 17 | allprojects { 18 | repositories { 19 | ... 20 | maven { url 'https://jitpack.io' } 21 | } 22 | } 23 | 24 | dependencies { 25 | compile 'com.github.supertaohaili:UI:1.0.0' 26 | } 27 | ``` 28 | 29 | 示例代码: 30 | ``` java 31 | 32 | 33 | //扇形 34 | mRingViewOne.setProgress(progress); 35 | 36 | 37 | //条形 38 | List xnames = new ArrayList<>(); 39 | xnames.add("1月"); 40 | xnames.add("2月"); 41 | xnames.add("3月"); 42 | xnames.add("4月"); 43 | xnames.add("5月"); 44 | xnames.add("6月"); 45 | 46 | List> datas = new ArrayList<>(); 47 | 48 | List list = new ArrayList<>(); 49 | List list2 = new ArrayList<>(); 50 | for (int j = 0; j < xnames.size(); ++j) { 51 | list.add(Float.valueOf((float) (new Random()).nextInt(5000) / 50.0F)); 52 | list2.add(Float.valueOf((float) (new Random()).nextInt(5000) / 50.0F)); 53 | } 54 | datas.add(list); 55 | datas.add(list2); 56 | mBarChartView.initData(datas, xnames); 57 | 58 | 59 | 60 | //折现图 61 | String[] series = {"满意", "良好", "一般"}; 62 | ArrayList datas = new ArrayList(); 63 | ArrayList xnames = new ArrayList(); 64 | 65 | for (int i = 0; i < 12; ++i) { 66 | xnames.add((i + 1) + "月"); 67 | } 68 | for (int i = 0; i < series.length; ++i) { 69 | ArrayList tmpList = new ArrayList(); 70 | for (int j = 0; j < xnames.size(); ++j) { 71 | tmpList.add(Float.valueOf((float) (new Random()).nextInt(10000) / 50.0F)); 72 | } 73 | datas.add(tmpList); 74 | } 75 | mLineChartView.initData(series, datas, xnames); 76 | ``` 77 | 78 | 79 | 80 | ### Known Issues 81 | If you have any questions/queries/Bugs/Hugs please mail @ 82 | taohailili@gmail.com 83 | -------------------------------------------------------------------------------- /TIM图片20180115113215.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertaohaili/UI/a84cc71f6d73d3596771caf1638faac72b822091/TIM图片20180115113215.jpg -------------------------------------------------------------------------------- /app-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertaohaili/UI/a84cc71f6d73d3596771caf1638faac72b822091/app-debug.apk -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | android { 3 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 4 | buildToolsVersion rootProject.ext.android["buildToolsVersion"] 5 | 6 | compileOptions { 7 | targetCompatibility JavaVersion.VERSION_1_8 8 | sourceCompatibility JavaVersion.VERSION_1_8 9 | } 10 | 11 | defaultConfig { 12 | applicationId rootProject.ext.android["applicationId"] 13 | minSdkVersion rootProject.ext.android["minSdkVersion"] 14 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 15 | versionCode rootProject.ext.android["versionCode"] 16 | versionName rootProject.ext.android["versionName"] 17 | resConfigs "zh" 18 | multiDexEnabled true 19 | ndk { 20 | //设置支持的SO库架构 21 | abiFilters 'armeabi', 'armeabi-v7a', 'x86' 22 | } 23 | } 24 | 25 | buildTypes { 26 | 27 | debug { 28 | buildConfigField "boolean", "LOG_DEBUG", "true" 29 | buildConfigField "boolean", "USE_CANARY", "true" 30 | versionNameSuffix "-debug" 31 | debuggable true 32 | minifyEnabled false 33 | zipAlignEnabled false 34 | shrinkResources false 35 | signingConfig signingConfigs.debug 36 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 37 | 38 | } 39 | 40 | release { 41 | buildConfigField "boolean", "LOG_DEBUG", "false" 42 | buildConfigField "boolean", "USE_CANARY", "false" 43 | debuggable false 44 | minifyEnabled true 45 | zipAlignEnabled true 46 | shrinkResources true 47 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 48 | } 49 | } 50 | 51 | //删除META-INF信息 52 | packagingOptions { 53 | exclude 'META-INF/rxjava.properties' 54 | exclude 'META-INF/maven/com.squareup.okhttp3/okhttp/pom.xml' 55 | exclude 'META-INF/maven/com.squareup.okhttp3/okhttp/pom.properties' 56 | exclude 'META-INF/maven/com.squareup.okio/okio/pom.xml' 57 | exclude 'META-INF/maven/com.squareup.okio/okio/pom.properties' 58 | exclude 'META-INF/maven/com.google.code.gson/gson/pom.xml' 59 | exclude 'META-INF/maven/com.google.code.gson/gson/pom.properties' 60 | } 61 | 62 | lintOptions { 63 | disable 'InvalidPackage' 64 | disable "ResourceType" 65 | abortOnError false 66 | } 67 | dexOptions { 68 | incremental true 69 | } 70 | } 71 | 72 | buildscript { 73 | repositories { 74 | jcenter() 75 | } 76 | } 77 | 78 | dependencies { 79 | compile fileTree(include: ['*.jar'], dir: 'libs') 80 | compile 'com.android.support:appcompat-v7:24.2.1' 81 | compile project(path: ':lib_ui') 82 | } -------------------------------------------------------------------------------- /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 C:\android\android-sdk/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 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/thl/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.thl.demo; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * Created by MasterCom on 2017/3/17. 7 | */ 8 | 9 | public class DemoApplication extends Application { 10 | 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/thl/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.thl.demo; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.v4.app.FragmentActivity; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.Random; 13 | 14 | import www.thl.com.ui.BarChartView; 15 | import www.thl.com.ui.LineChartView; 16 | import www.thl.com.ui.RingView; 17 | 18 | 19 | public class MainActivity extends FragmentActivity implements View.OnClickListener { 20 | 21 | private RingView mRingViewOne; 22 | private RingView mRingViewTwo; 23 | private BarChartView mBarChartView; 24 | private LineChartView mLineChartView; 25 | 26 | private TextView tvWeiChaoShiOne; 27 | private TextView tvChaoShiOne; 28 | private TextView tvWeiChaoShiTwo; 29 | private TextView tvChaoShiTwo; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | ((TextView)findViewById(R.id.tv_title)).setText("uidemo"); 36 | initView(); 37 | initListen(); 38 | 39 | initRingViewData(); 40 | initBarChartViewData(); 41 | initLineChartViewdata(); 42 | } 43 | 44 | private void initView() { 45 | 46 | tvWeiChaoShiOne = (TextView) findViewById(R.id.tv_weichaoshi_one); 47 | tvChaoShiOne = (TextView) findViewById(R.id.tv_chaoshi_one); 48 | tvWeiChaoShiTwo = (TextView) findViewById(R.id.tv_weichaoshi_two); 49 | tvChaoShiTwo = (TextView) findViewById(R.id.tv_chaoshi_two); 50 | 51 | mRingViewOne = (RingView) findViewById(R.id.ringview_one); 52 | mRingViewOne.setBgColor(Color.parseColor("#ffdeb2")); 53 | mRingViewOne.setProgressColor(Color.parseColor("#ff9d1d")); 54 | 55 | mRingViewTwo = (RingView) findViewById(R.id.ringview_two); 56 | mRingViewTwo.setBgColor(Color.parseColor("#7ed4fe")); 57 | mRingViewTwo.setProgressColor(Color.parseColor("#28b0ff")); 58 | 59 | mBarChartView = (BarChartView) findViewById(R.id.bcv3_yonghushu); 60 | mBarChartView.setTextColor(Color.parseColor("#bfbccf")); 61 | mBarChartView.setCanTouch(true); 62 | 63 | mLineChartView = (LineChartView) findViewById(R.id.lcv); 64 | mLineChartView.setShowSeries(false); 65 | mLineChartView.setTextColor(Color.parseColor("#bfbccf")); 66 | mLineChartView.setSericeTextColor(Color.parseColor("#706c8d")); 67 | mLineChartView.setShowMaxMin(false); 68 | mLineChartView.setCanDrag(false); 69 | mLineChartView.setShowSeriesTip(true); 70 | mLineChartView.setCanOnTouch(true); 71 | } 72 | 73 | private void initListen() { 74 | findViewById(R.id.tv_ziyuan).setOnClickListener(this); 75 | findViewById(R.id.tv_guzhang).setOnClickListener(this); 76 | findViewById(R.id.tv_quanyewu).setOnClickListener(this); 77 | findViewById(R.id.tv_yunwei).setOnClickListener(this); 78 | findViewById(R.id.tv_wangyou).setOnClickListener(this); 79 | } 80 | 81 | private void initRingViewData() { 82 | Integer progress = Integer.valueOf(new Random().nextInt(100)); 83 | tvWeiChaoShiOne.setText("未超时" + progress + "%"); 84 | tvChaoShiOne.setText("超时" + (100 - progress) + "%"); 85 | mRingViewOne.setProgress(progress); 86 | 87 | Integer progress2 = Integer.valueOf(new Random().nextInt(100)); 88 | tvWeiChaoShiTwo.setText("未超时" + progress2 + "%"); 89 | tvChaoShiTwo.setText("超时" + (100 - progress2) + "%"); 90 | mRingViewTwo.setProgress(progress2); 91 | } 92 | 93 | private void initBarChartViewData() { 94 | List xnames = new ArrayList<>(); 95 | xnames.add("1月"); 96 | xnames.add("2月"); 97 | xnames.add("3月"); 98 | xnames.add("4月"); 99 | xnames.add("5月"); 100 | xnames.add("6月"); 101 | List> datas = new ArrayList<>(); 102 | List list = new ArrayList<>(); 103 | List list2 = new ArrayList<>(); 104 | for (int j = 0; j < xnames.size(); ++j) { 105 | list.add(Float.valueOf((float) (new Random()).nextInt(5000) / 50.0F)); 106 | list2.add(Float.valueOf((float) (new Random()).nextInt(5000) / 50.0F)); 107 | } 108 | datas.add(list); 109 | datas.add(list2); 110 | mBarChartView.initData(datas, xnames); 111 | } 112 | 113 | private void initLineChartViewdata() { 114 | String[] series = {"满意", "良好", "一般"}; 115 | ArrayList datas = new ArrayList(); 116 | ArrayList xnames = new ArrayList(); 117 | 118 | for (int i = 0; i < 12; ++i) { 119 | xnames.add((i + 1) + "月"); 120 | } 121 | for (int i = 0; i < series.length; ++i) { 122 | ArrayList tmpList = new ArrayList(); 123 | for (int j = 0; j < xnames.size(); ++j) { 124 | tmpList.add(Float.valueOf((float) (new Random()).nextInt(10000) / 50.0F)); 125 | } 126 | datas.add(tmpList); 127 | } 128 | mLineChartView.initData(series, datas, xnames); 129 | } 130 | 131 | @Override 132 | public void onClick(View view) { 133 | switch (view.getId()) { 134 | case R.id.tv_ziyuan: 135 | break; 136 | case R.id.tv_guzhang: 137 | break; 138 | case R.id.tv_quanyewu: 139 | break; 140 | case R.id.tv_yunwei: 141 | break; 142 | case R.id.tv_wangyou: 143 | break; 144 | } 145 | 146 | if (view instanceof TextView) { 147 | Toast.makeText(this, ((TextView) view).getText(), Toast.LENGTH_SHORT).show(); 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/back_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertaohaili/UI/a84cc71f6d73d3596771caf1638faac72b822091/app/src/main/res/drawable-hdpi/back_img.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_func_myworker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertaohaili/UI/a84cc71f6d73d3596771caf1638faac72b822091/app/src/main/res/drawable-hdpi/ic_func_myworker.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_circular_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_circular_light_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_circular_light_yellow.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_circular_yellow.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gradient_linear_blue_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gradient_linear_blue_270.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gradient_linear_purple_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gradient_linear_yellow_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_ib_back_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_rectangle_white_r5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_rectangle_white_s1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_home_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 15 | 16 | 21 | 22 | 27 | 28 | 33 | 34 | 39 | 40 | 45 | 46 | 47 | 48 | 54 | 55 | 56 | 57 | 60 | 61 | 64 | 65 | 66 | 67 | 68 | 71 | 72 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 84 | 85 | 88 | 89 | 90 | 91 | 92 | 97 | 98 | 102 | 103 | 111 | 112 | 117 | 118 | 119 | 120 | 128 | 129 | 134 | 135 | 141 | 142 | 149 | 150 | 154 | 155 | 159 | 160 | 164 | 165 | 166 | 167 | 168 | 172 | 173 | 177 | 178 | 182 | 183 | 184 | 185 | 191 | 192 | 193 | 194 | 198 | 199 | 202 | 203 | 209 | 210 | 211 | 212 | 217 | 218 | 225 | 226 | 234 | 235 | 242 | 243 | 249 | 250 | 257 | 258 | 259 | 260 | 261 | 266 | 267 | 274 | 275 | 283 | 284 | 291 | 292 | 298 | 299 | 306 | 307 | 308 | 309 | 310 | 317 | 318 | 319 | 320 | 324 | 325 | 329 | 330 | 331 | 332 | 333 | 337 | 338 | 342 | 343 | 344 | 345 | 346 | 350 | 351 | 355 | 356 | 357 | 358 | 359 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 18 | 19 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertaohaili/UI/a84cc71f6d73d3596771caf1638faac72b822091/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #24abff 4 | #24abff 5 | #24abff 6 | 7 | #24abff 8 | #22c5eaf8 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | UIDemo 3 | 4 | 菜单 5 | 菜单 6 | 菜单 7 | 菜单 8 | 菜单 9 | 及格 10 | 良好 11 | 优秀 12 | 生活水平 13 | 14 | 用户数 15 | 单位人数(万) 16 | 维护 17 | 活动工单 18 | 归档工单数 19 | 小康小区占比 20 | 温饱小区占比 21 | 贫困小区占比 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 | 20 | 21 | 25 | 26 | 31 | 32 | 37 | 38 | 39 | 46 | 47 | 48 | 54 | 55 | 56 | 61 | 62 | 63 | 64 | 65 | 70 | 71 | 72 | 81 | 82 | 83 | 87 | 88 | 89 | 95 | 96 | 97 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "config.gradle" 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | maven { 6 | url 'https://maven.google.com/' 7 | name 'Google' 8 | } 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.0.0' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | maven { url "https://jitpack.io" } 19 | maven { 20 | url 'https://maven.google.com/' 21 | name 'Google' 22 | } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /config.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | android = [ 3 | compileSdkVersion : 25, 4 | buildToolsVersion : "25.0.0", 5 | applicationId : "com.android.project.video", 6 | minSdkVersion : 15, 7 | targetSdkVersion : 25, 8 | versionCode : 1, 9 | versionName :"1.0.0", 10 | 11 | ] 12 | 13 | version = [ 14 | androidSupportSdkVersion: "25.0.0", 15 | ijkplayer :"0.8.4", 16 | transitionseverywhere :"1.7.0", 17 | ] 18 | 19 | dependencies = [ 20 | //support 21 | "design" : "com.android.support:design:${version["androidSupportSdkVersion"]}", 22 | "support-v4" : "com.android.support:support-v4:${version["androidSupportSdkVersion"]}", 23 | "appcompat-v7" : "com.android.support:appcompat-v7:${version["androidSupportSdkVersion"]}", 24 | "cardview-v7" : "com.android.support:cardview-v7:${version["androidSupportSdkVersion"]}", 25 | "recyclerview-v7" : "com.android.support:recyclerview-v7:${version["androidSupportSdkVersion"]}", 26 | 27 | 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertaohaili/UI/a84cc71f6d73d3596771caf1638faac72b822091/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Oct 31 19:05:26 CST 2017 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-4.1-all.zip 7 | -------------------------------------------------------------------------------- /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 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib_ui/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lib_ui/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.android["compileSdkVersion"] 5 | buildToolsVersion rootProject.ext.android["buildToolsVersion"] 6 | 7 | compileOptions { 8 | targetCompatibility JavaVersion.VERSION_1_8 9 | sourceCompatibility JavaVersion.VERSION_1_8 10 | } 11 | 12 | defaultConfig { 13 | minSdkVersion rootProject.ext.android["minSdkVersion"] 14 | targetSdkVersion rootProject.ext.android["targetSdkVersion"] 15 | versionCode rootProject.ext.android["versionCode"] 16 | versionName rootProject.ext.android["versionName"] 17 | resConfigs "zh" 18 | } 19 | } 20 | 21 | buildscript { 22 | repositories { 23 | jcenter() 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(dir: 'libs', include: ['*.jar']) 29 | } 30 | -------------------------------------------------------------------------------- /lib_ui/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 C:\android\android-sdk/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /lib_ui/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib_ui/src/main/java/www/thl/com/ui/BarChartView.java: -------------------------------------------------------------------------------- 1 | package www.thl.com.ui; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.DashPathEffect; 8 | import android.graphics.LinearGradient; 9 | import android.graphics.Paint; 10 | import android.graphics.Path; 11 | import android.graphics.PathEffect; 12 | import android.graphics.Shader; 13 | import android.os.Handler; 14 | import android.text.TextPaint; 15 | import android.util.AttributeSet; 16 | import android.view.MotionEvent; 17 | import android.view.View; 18 | 19 | import www.thl.com.ui.utils.DensityUtil; 20 | 21 | import java.text.DecimalFormat; 22 | import java.util.ArrayList; 23 | import java.util.Iterator; 24 | import java.util.List; 25 | import java.util.Random; 26 | 27 | 28 | import www.thl.com.ui.utils.ScreenUtils; 29 | 30 | /** 31 | * 条形图 32 | */ 33 | @SuppressLint({"DrawAllocation"}) 34 | public class BarChartView extends View { 35 | private List> datas = new ArrayList(); 36 | private List xnames = new ArrayList(); 37 | private String title; 38 | private int[] colors = {Color.parseColor("#6accff"), Color.parseColor("#ffcb8a"), Color.parseColor("#6accff")}; 39 | private float maxvalue = 1.4E-45F; 40 | private float minvalue = 3.4028235E38F; 41 | private float intervalY = 0.0F; 42 | private float intervalX = 0.0F; 43 | private float intervalValue = 0.0F; 44 | private float Y1ToScreen = 0.0F; 45 | private int Ycount = -1; 46 | private float zeroY; 47 | private String[] series; 48 | private float maxY; 49 | private float minY; 50 | private int intervalGroup; 51 | private Paint paintline; 52 | private Paint paintRect; 53 | private Paint paintwhite; 54 | private Paint paintValue; 55 | private TextPaint textpaint; 56 | private DecimalFormat df = new DecimalFormat("##0"); 57 | private DecimalFormat df2 = new DecimalFormat("##0.00"); 58 | private int intervalTime = 35; 59 | private int duration = 500; 60 | private int time; 61 | private int timeSum; 62 | private Handler handler; 63 | private float x_down; 64 | private float y_down; 65 | private boolean isCanTouch = false; 66 | private List rectList; 67 | private BarChartView.MRect seletedMrect; 68 | 69 | public BarChartView(Context context) { 70 | this(context, (AttributeSet) null); 71 | } 72 | 73 | public BarChartView(Context context, AttributeSet attrs) { 74 | super(context, attrs); 75 | this.time = this.duration / this.intervalTime; 76 | this.timeSum = this.duration / this.intervalTime; 77 | this.handler = new Handler(); 78 | this.x_down = 0.0F; 79 | this.y_down = 0.0F; 80 | this.rectList = new ArrayList(); 81 | this.seletedMrect = null; 82 | this.textpaint = new TextPaint(); 83 | this.textpaint.setStyle(Paint.Style.FILL); 84 | this.textpaint.setColor(Color.GRAY); 85 | this.textpaint.setAntiAlias(true); 86 | this.textpaint.setTextSize(DensityUtil.dip2pxf(this.getContext(), 9)); 87 | if (this.isInEditMode()) { 88 | this.test(); 89 | } 90 | } 91 | 92 | private void test() { 93 | this.setTextColor(Color.parseColor("#bfbccf")); 94 | this.setCanTouch(true); 95 | List xnames = new ArrayList<>(); 96 | xnames.add("1月"); 97 | xnames.add("2月"); 98 | xnames.add("3月"); 99 | xnames.add("4月"); 100 | xnames.add("5月"); 101 | xnames.add("6月"); 102 | List> datas = new ArrayList<>(); 103 | List list = new ArrayList<>(); 104 | for (int j = 0; j < xnames.size(); ++j) { 105 | list.add(Float.valueOf((float) (new Random()).nextInt(1000) / 10.0F)); 106 | } 107 | List list2 = new ArrayList<>(); 108 | for (int j = 0; j < xnames.size(); ++j) { 109 | list2.add(Float.valueOf((float) (new Random()).nextInt(1000) / 10.0F)); 110 | } 111 | datas.add(list); 112 | datas.add(list2); 113 | int[] colors = {Color.parseColor("#3285ff"), Color.YELLOW}; 114 | 115 | float maxvalue = 100f; 116 | String[] series = {}; 117 | String title = ""; 118 | this.initData(datas, colors, xnames, maxvalue, series, title); 119 | } 120 | 121 | public void initData(List> datas, List xnames) { 122 | this.datas = datas; 123 | this.xnames = xnames; 124 | String[] series = {}; 125 | this.series = series; 126 | this.init(); 127 | } 128 | 129 | public void initData(List> datas, List xnames, String[] series) { 130 | this.datas = datas; 131 | this.xnames = xnames; 132 | this.series = series; 133 | this.init(); 134 | } 135 | 136 | public void initData(List> datas, int[] colors, List xnames, float maxvalue, String[] series) { 137 | this.datas = datas; 138 | this.colors = colors; 139 | this.xnames = xnames; 140 | this.maxvalue = maxvalue; 141 | this.series = series; 142 | this.init(); 143 | } 144 | 145 | public void initData(List> datas, List xnames, String[] series, String title) { 146 | this.datas = datas; 147 | this.xnames = xnames; 148 | this.series = series; 149 | this.title = title; 150 | this.init(); 151 | } 152 | 153 | public void initData(List> datas, int[] colors, List xnames, float maxvalue, String[] series, String title) { 154 | this.datas = datas; 155 | this.colors = colors; 156 | this.xnames = xnames; 157 | this.maxvalue = maxvalue; 158 | this.series = series; 159 | this.title = title; 160 | this.init(); 161 | } 162 | 163 | private void init() { 164 | //提示框的画笔 165 | this.paintValue = new Paint(); 166 | this.paintValue.setStyle(Paint.Style.FILL); 167 | this.paintValue.setAntiAlias(true); 168 | this.paintValue.setColor(getResources().getColor(R.color.theme_color)); 169 | this.paintValue.setStrokeWidth((float) DensityUtil.dip2px(this.getContext(), 2.0F)); 170 | 171 | this.paintline = new Paint(); 172 | this.paintline.setStyle(Paint.Style.STROKE); 173 | this.paintline.setAntiAlias(true); 174 | this.paintline.setColor(Color.parseColor("#ececec")); 175 | this.paintline.setStrokeWidth(1.0F); 176 | this.paintwhite = new Paint(); 177 | this.paintwhite.setStyle(Paint.Style.FILL); 178 | this.paintwhite.setAntiAlias(true); 179 | this.paintwhite.setColor(Color.WHITE); 180 | this.paintwhite.setStrokeWidth((float) DensityUtil.dip2px(this.getContext(), 1.0F)); 181 | this.paintwhite.setTextAlign(Paint.Align.CENTER); 182 | this.paintRect = new Paint(); 183 | this.paintRect.setStyle(Paint.Style.FILL); 184 | this.paintRect.setAntiAlias(true); 185 | this.maxvalue = this.maxvalue == 1.4E-45F ? this.getMinOrMaxValues(this.datas, true) : this.maxvalue; 186 | this.minvalue = this.minvalue == 3.4028235E38F ? this.getMinOrMaxValues(this.datas, false) : this.minvalue; 187 | this.intervalGroup = DensityUtil.dip2px(this.getContext(), 5.0F); 188 | this.invalidate(); 189 | } 190 | 191 | protected void onDraw(Canvas canvas) { 192 | super.onDraw(canvas); 193 | if (this.datas.size() != 0) { 194 | int width = this.getWidth(); 195 | int height = this.getHeight(); 196 | this.maxY = (float) DensityUtil.dip2px(this.getContext(), 20.0F); 197 | this.minY = (float) ((double) (height - DensityUtil.dip2px(this.getContext(), 15.0F)) - (double) DensityUtil.dip2px(this.getContext(), 10.0F) * Math.ceil((double) this.series.length / 2.0D)); 198 | if (this.Ycount == -1) { 199 | this.cal(this.maxvalue, this.minvalue); 200 | this.intervalY = (this.minY - this.maxY) / (float) this.Ycount; 201 | } 202 | 203 | float maxX = (float) (width - DensityUtil.dip2px(this.getContext(), 15.0F)); 204 | float minX = (float) DensityUtil.dip2px(this.getContext(), 30.0F); 205 | this.textpaint.setTextAlign(Paint.Align.CENTER); 206 | if (this.title != null && !this.title.equals("")) { 207 | canvas.drawText(this.title, (float) (width / 2), ScreenUtils.getTextHeight(this.textpaint.getTextSize()), this.textpaint); 208 | } 209 | this.textpaint.setTextAlign(Paint.Align.RIGHT); 210 | 211 | for (int rectw = 0; rectw < this.Ycount + 1; ++rectw) { 212 | 213 | //绘制虚线 214 | Path path = new Path(); 215 | path.moveTo(minX, this.maxY + this.intervalY * (float) rectw); 216 | path.lineTo(maxX, this.maxY + this.intervalY * (float) rectw); 217 | PathEffect effects = new DashPathEffect(new float[]{25, 3, 25, 3}, 0); 218 | this.paintline.setPathEffect(effects); 219 | canvas.drawPath(path, this.paintline); 220 | //绘制实线 221 | // canvas.drawLine(minX, this.maxY + this.intervalY * (float) rectw, maxX, this.maxY + this.intervalY * (float) rectw, this.paintline); 222 | if ((double) Math.abs(this.maxvalue - (float) rectw * this.intervalValue) < 1.0E-4D) { 223 | this.zeroY = this.maxY + this.intervalY * (float) rectw; 224 | canvas.drawText("0", minX - (float) DensityUtil.dip2px(this.getContext(), 5.0F), this.maxY + this.intervalY * (float) rectw, this.textpaint); 225 | } else if ((int) Math.abs(this.intervalValue) < 1) { 226 | canvas.drawText(this.df2.format((double) (this.maxvalue - (float) rectw * this.intervalValue)) + "", minX - (float) DensityUtil.dip2px(this.getContext(), 5.0F), this.maxY + this.intervalY * (float) rectw, this.textpaint); 227 | } else { 228 | canvas.drawText(this.df.format((double) (this.maxvalue - (float) rectw * this.intervalValue)) + "", minX - (float) DensityUtil.dip2px(this.getContext(), 5.0F), this.maxY + this.intervalY * (float) rectw, this.textpaint); 229 | } 230 | } 231 | 232 | this.textpaint.setTextAlign(Paint.Align.CENTER); 233 | this.intervalX = (maxX - minX - (float) DensityUtil.dip2px(this.getContext(), 10.0F)) / (float) ((List) this.datas.get(0)).size(); 234 | 235 | //条形图的宽度 236 | float var11 = (this.intervalX - (float) this.intervalGroup) / (float) this.datas.size() - DensityUtil.dip2px(this.getContext(), 42) / this.datas.get(0).size(); 237 | float startx = this.intervalX * 1.0F / 6.0F + (float) DensityUtil.dip2px(this.getContext(), 5.0F); 238 | this.drawData(canvas, minX, startx, var11); 239 | 240 | int i; 241 | for (i = 0; i < this.xnames.size(); ++i) { 242 | canvas.drawText((String) this.xnames.get(i), minX + (float) i * this.intervalX + startx + var11 * (float) this.datas.size() / 2.0F, this.zeroY + (float) DensityUtil.dip2px(this.getContext(), 10.0F), this.textpaint); 243 | } 244 | 245 | if (this.seletedMrect != null) { 246 | 247 | //Canvas canvas,String var,float x,float y 248 | //冒泡弹出提示 249 | drawTouchValue(canvas, this.seletedMrect.getValue(), this.seletedMrect.getxCenter(), this.seletedMrect.getTop()); 250 | 251 | //提示框 252 | // Bitmap var12 = ScreenUtils.getBitmap(this.getContext(), this.seletedMrect.getValue() + "", cn.mastercom.ui.R.drawable.mt_popup_blue, 13, -1); 253 | // canvas.drawBitmap(var12, this.seletedMrect.getxCenter() - (float) (var12.getWidth() / 2), this.seletedMrect.getTop() - (float) var12.getHeight(), this.paintwhite); 254 | } 255 | 256 | this.textpaint.setTextAlign(Paint.Align.LEFT); 257 | 258 | for (i = 0; i < this.series.length; ++i) { 259 | this.paintRect.setColor(this.colors[i]); 260 | float xt = i % 2 > 0 ? (float) (width / 2 - DensityUtil.dip2px(this.getContext(), 20.0F)) : 0.0F; 261 | float yt = (float) (i / 2 * DensityUtil.dip2px(this.getContext(), 10.0F)); 262 | canvas.drawRect((float) DensityUtil.dip2px(this.getContext(), 20.0F) + xt, this.minY + (float) DensityUtil.dip2px(this.getContext(), 12.0F) + yt, (float) DensityUtil.dip2px(this.getContext(), 40.0F) + xt, this.minY + (float) DensityUtil.dip2px(this.getContext(), 20.0F) + yt, this.paintRect); 263 | canvas.drawText(this.series[i], (float) DensityUtil.dip2px(this.getContext(), 42.0F) + xt, this.minY + (float) DensityUtil.dip2px(this.getContext(), 18.0F) + yt, this.textpaint); 264 | } 265 | 266 | if (this.datas.size() > 0 && this.timeSum > this.time) { 267 | ++this.time; 268 | this.handler.postDelayed(new Runnable() { 269 | public void run() { 270 | BarChartView.this.invalidate(); 271 | } 272 | }, (long) this.intervalTime); 273 | } 274 | 275 | } 276 | } 277 | 278 | private int getTextWidth(Paint paint, String str) { 279 | int iRet = 0; 280 | if (str != null && str.length() > 0) { 281 | int len = str.length(); 282 | float[] widths = new float[len]; 283 | paint.getTextWidths(str, widths); 284 | 285 | for (int j = 0; j < len; ++j) { 286 | iRet += (int) Math.ceil((double) widths[j]); 287 | } 288 | } 289 | return iRet; 290 | } 291 | 292 | private int getFontHeight(Paint paint) { 293 | Paint.FontMetrics fm = paint.getFontMetrics(); 294 | return (int) Math.ceil((double) (fm.descent - fm.ascent)); 295 | } 296 | 297 | 298 | private void drawTouchValue(Canvas canvas, float var, float x, float y) { 299 | String format = "%.0f"; 300 | if ((float) ((int) var) == var) { 301 | format = "%.0f"; 302 | } else { 303 | format = "%.2f"; 304 | } 305 | //提示字体大小 306 | paintwhite.setTextSize(DensityUtil.sp2px(this.getContext(), 10)); 307 | int textLength = this.getTextWidth(this.paintwhite, String.format(format, new Object[]{Float.valueOf(var)})); 308 | int textHeight = this.getFontHeight(this.paintwhite); 309 | float ascent = Math.abs(this.paintwhite.getFontMetrics().ascent); 310 | int dp2 = DensityUtil.dip2px(this.getContext(), 2.0F); 311 | Path path; 312 | path = new Path(); 313 | path.moveTo(x, y); 314 | path.lineTo(x + (float) (2 * dp2), y - (float) (3 * dp2)); 315 | 316 | path.lineTo(x + (float) (2 * dp2) + (float) textLength / 2, y - (float) (3 * dp2)); 317 | path.lineTo(x + (float) (2 * dp2) + (float) textLength / 2, y - (float) (3 * dp2) - (float) (2 * dp2) - (float) textHeight); 318 | path.lineTo(x - (float) (2 * dp2) - (float) textLength / 2, y - (float) (3 * dp2) - (float) (2 * dp2) - (float) textHeight); 319 | path.lineTo(x - (float) (2 * dp2) - (float) textLength / 2, y - (float) (3 * dp2)); 320 | 321 | path.lineTo(x - (float) (2 * dp2), y - (float) (3 * dp2)); 322 | path.close(); 323 | canvas.drawPath(path, this.paintValue); 324 | canvas.drawText(String.format(format, new Object[]{Float.valueOf(var)}), x, y - (float) (3 * dp2) - (float) dp2 - (float) textHeight + ascent, this.paintwhite); 325 | } 326 | 327 | private boolean isShowSeriesTip = true; 328 | 329 | private void drawData(Canvas canvas, float minX, float startx, float rectw) { 330 | boolean isEmpty = this.rectList.isEmpty(); 331 | 332 | for (int i = 0; i < this.datas.size(); ++i) { 333 | for (int j = 0; j < ((List) this.datas.get(i)).size(); ++j) { 334 | float y = (this.maxvalue - ((Float) ((List) this.datas.get(i)).get(j)).floatValue()) * this.Y1ToScreen + this.maxY; 335 | float offsetY = this.zeroY - y - (float) this.time * 1.0F / (float) this.timeSum * (this.zeroY - y); 336 | if (((Float) ((List) this.datas.get(i)).get(j)).floatValue() > 0.0F) { 337 | //添加渐变效果 338 | if (i == 0) { 339 | LinearGradient mLinearGradient = new LinearGradient(minX + (float) j * this.intervalX + startx + (float) i * rectw, y + offsetY, minX + (float) j * this.intervalX + startx + (float) i * rectw, this.zeroY, Color.parseColor("#6accff"), Color.parseColor("#2f81ff"), Shader.TileMode.CLAMP); 340 | this.paintRect.setShader(mLinearGradient); 341 | } else if (i == 1) { 342 | LinearGradient mLinearGradient = new LinearGradient(minX + (float) j * this.intervalX + startx + (float) i * rectw, y + offsetY, minX + (float) j * this.intervalX + startx + (float) i * rectw, this.zeroY, Color.parseColor("#ffcb8a"), Color.parseColor("#ff9b1d"), Shader.TileMode.CLAMP); 343 | this.paintRect.setShader(mLinearGradient); 344 | } else { 345 | this.paintRect.setColor(this.colors[i]); 346 | } 347 | //绘制矩形 348 | canvas.drawRect(minX + (float) j * this.intervalX + startx + (float) i * rectw, y + offsetY, minX + (float) j * this.intervalX + startx + (float) i * rectw + rectw, this.zeroY, this.paintRect); 349 | if (isEmpty) { 350 | BarChartView.MRect rect = new BarChartView.MRect(minX + (float) j * this.intervalX + startx + (float) i * rectw, y + offsetY, minX + (float) j * this.intervalX + startx + (float) i * rectw + rectw, this.zeroY, (Float) ((List) this.datas.get(i)).get(j)); 351 | this.rectList.add(rect); 352 | } 353 | } else { 354 | canvas.drawRect(minX + (float) j * this.intervalX + startx + (float) i * rectw, this.zeroY, minX + (float) j * this.intervalX + startx + (float) i * rectw + rectw, y + offsetY, this.paintRect); 355 | } 356 | this.paintRect.setColor(this.colors[i]); 357 | } 358 | } 359 | } 360 | 361 | private float getMinOrMaxValues(List> ls, boolean isMax) { 362 | float max = 1.4E-45F; 363 | float min = 3.4028235E38F; 364 | if (ls != null && ls.size() != 0) { 365 | for (int i = 0; i < ls.size(); ++i) { 366 | for (int j = 0; j < ((List) ls.get(i)).size(); ++j) { 367 | if (((Float) ((List) ls.get(i)).get(j)).floatValue() != 1.4E-45F) { 368 | if (((Float) ((List) ls.get(i)).get(j)).floatValue() > max) { 369 | max = ((Float) ((List) ls.get(i)).get(j)).floatValue(); 370 | } 371 | 372 | if (((Float) ((List) ls.get(i)).get(j)).floatValue() < min) { 373 | min = ((Float) ((List) ls.get(i)).get(j)).floatValue(); 374 | } 375 | } 376 | } 377 | } 378 | 379 | max = max == 1.4E-45F ? 0.0F : max; 380 | min = min == 3.4028235E38F ? 0.0F : min; 381 | return isMax ? max : min; 382 | } else { 383 | return 0.0F; 384 | } 385 | } 386 | 387 | private boolean isPrime(int n) { 388 | if (n < 2) { 389 | return false; 390 | } else if (n == 2) { 391 | return true; 392 | } else if (n % 2 == 0) { 393 | return false; 394 | } else { 395 | for (int i = 3; i * i <= n; i += 2) { 396 | if (n % i == 0) { 397 | return false; 398 | } 399 | } 400 | return true; 401 | } 402 | } 403 | 404 | private int getYCount(int values) { 405 | int[] num = new int[]{7, 6, 5, 4, 3, 2}; 406 | 407 | for (int i = 0; i < num.length; ++i) { 408 | if (values % num[i] == 0) { 409 | return num[i]; 410 | } 411 | } 412 | return 5; 413 | } 414 | 415 | private void cal(float maxValue, float minValue) { 416 | this.Ycount = 0; 417 | if (maxValue == 0.0F && minValue == 0.0F) { 418 | this.Ycount = 3; 419 | this.Y1ToScreen = (this.minY - this.maxY) / (float) this.Ycount; 420 | this.maxvalue = 3.0F; 421 | this.minvalue = 0.0F; 422 | this.intervalValue = 1.0F; 423 | } 424 | 425 | float[] e = new float[]{1.0F, 2.0F, 5.0F}; 426 | float maxAbs = Math.abs(maxValue) > Math.abs(minValue) ? Math.abs(maxValue) : Math.abs(minValue); 427 | float minAbs = Math.abs(maxValue) < Math.abs(minValue) ? Math.abs(maxValue) : Math.abs(minValue); 428 | float multiple = 0.0F; 429 | 430 | float tmp; 431 | for (tmp = 0.001F; tmp < maxAbs; tmp *= 10.0F) { 432 | ; 433 | } 434 | 435 | multiple = tmp / 100.0F; 436 | 437 | for (int count = 0; (this.Ycount > 7 || this.Ycount < 3) && count < 100; multiple *= 10.0F) { 438 | ++count; 439 | 440 | for (int i = 0; i < e.length; ++i) { 441 | this.Ycount = (int) Math.ceil((double) (maxAbs / (e[i] * multiple))); 442 | if (maxValue > 0.0F && minValue < 0.0F) { 443 | this.Ycount += (int) Math.ceil((double) (minAbs / (e[i] * multiple))); 444 | } 445 | 446 | if (this.Ycount <= 7) { 447 | this.Y1ToScreen = (this.minY - this.maxY) / ((float) this.Ycount * e[i] * multiple); 448 | this.intervalValue = e[i] * multiple; 449 | if (maxValue <= 0.0F) { 450 | this.maxvalue = 0.0F; 451 | this.minvalue = (float) (-this.Ycount) * e[i] * multiple; 452 | } else if (minValue >= 0.0F) { 453 | this.maxvalue = (float) this.Ycount * e[i] * multiple; 454 | this.minvalue = 0.0F; 455 | } else { 456 | this.maxvalue = (float) ((int) Math.ceil((double) (maxAbs / (e[i] * multiple)))) * e[i] * multiple; 457 | this.minvalue = (float) ((int) Math.ceil((double) (minAbs / (e[i] * multiple)))) * e[i] * multiple; 458 | } 459 | break; 460 | } 461 | } 462 | } 463 | 464 | } 465 | 466 | public void setAnimation(boolean animation) { 467 | this.time = animation ? 1 : this.timeSum; 468 | } 469 | 470 | public void setDuration(int duration) { 471 | this.duration = duration; 472 | this.timeSum = duration / this.intervalTime; 473 | } 474 | 475 | public void setTextColor(int color) { 476 | this.textpaint.setColor(color); 477 | } 478 | 479 | public boolean onTouchEvent(MotionEvent event) { 480 | if (isCanTouch) { 481 | switch (event.getAction() & 255) { 482 | case 0: 483 | this.x_down = event.getX(); 484 | this.y_down = event.getY(); 485 | this.isContainMrect(this.x_down, this.y_down); 486 | this.invalidate(); 487 | case 1: 488 | case 2: 489 | case 3: 490 | case 4: 491 | case 5: 492 | case 6: 493 | default: 494 | } 495 | } 496 | return true; 497 | } 498 | 499 | public void setCanTouch(boolean canTouch) { 500 | isCanTouch = canTouch; 501 | } 502 | 503 | private boolean isContainMrect(float x_down, float y_down) { 504 | Iterator var3 = this.rectList.iterator(); 505 | 506 | BarChartView.MRect rect; 507 | do { 508 | if (!var3.hasNext()) { 509 | this.seletedMrect = null; 510 | return false; 511 | } 512 | 513 | rect = (BarChartView.MRect) var3.next(); 514 | } 515 | while (x_down <= rect.getLeft() || x_down >= rect.getRight() || y_down >= rect.getBttomm()); 516 | 517 | this.seletedMrect = rect; 518 | return true; 519 | } 520 | 521 | class MRect { 522 | private float left; 523 | private float top; 524 | private float right; 525 | private float bttomm; 526 | private float xCenter; 527 | private Float value; 528 | 529 | public MRect(float left, float top, float right, float bttomm, Float value) { 530 | this.left = left; 531 | this.right = right; 532 | this.bttomm = bttomm; 533 | this.top = top; 534 | this.value = value; 535 | this.xCenter = (left + right) / 2.0F; 536 | } 537 | 538 | public float getLeft() { 539 | return this.left; 540 | } 541 | 542 | public void setLeft(float left) { 543 | this.left = left; 544 | } 545 | 546 | public float getTop() { 547 | return this.top; 548 | } 549 | 550 | public void setTop(float top) { 551 | this.top = top; 552 | } 553 | 554 | public float getRight() { 555 | return this.right; 556 | } 557 | 558 | public void setRight(float right) { 559 | this.right = right; 560 | } 561 | 562 | public float getBttomm() { 563 | return this.bttomm; 564 | } 565 | 566 | public void setBttomm(float bttomm) { 567 | this.bttomm = bttomm; 568 | } 569 | 570 | public Float getValue() { 571 | return this.value; 572 | } 573 | 574 | public void setValue(Float value) { 575 | this.value = value; 576 | } 577 | 578 | public float getxCenter() { 579 | return this.xCenter; 580 | } 581 | 582 | public void setxCenter(float xCenter) { 583 | this.xCenter = xCenter; 584 | } 585 | } 586 | } 587 | -------------------------------------------------------------------------------- /lib_ui/src/main/java/www/thl/com/ui/LineChartView.java: -------------------------------------------------------------------------------- 1 | package www.thl.com.ui; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Canvas; 8 | import android.graphics.Color; 9 | import android.graphics.Matrix; 10 | import android.graphics.Paint; 11 | import android.graphics.Path; 12 | import android.graphics.PointF; 13 | import android.graphics.Rect; 14 | import android.graphics.Region; 15 | import android.os.Handler; 16 | import android.text.TextPaint; 17 | import android.util.AttributeSet; 18 | import android.view.MotionEvent; 19 | import android.view.View; 20 | import android.view.ViewTreeObserver; 21 | 22 | import www.thl.com.ui.utils.DensityUtil; 23 | import www.thl.com.ui.utils.ScreenUtils; 24 | 25 | import java.text.DecimalFormat; 26 | import java.util.ArrayList; 27 | import java.util.Iterator; 28 | import java.util.List; 29 | import java.util.Random; 30 | 31 | 32 | /** 33 | * 区域折线图 34 | */ 35 | @SuppressLint({"DrawAllocation", "ViewConstructor"}) 36 | public class LineChartView extends View { 37 | private List> datas; 38 | private String title; 39 | private boolean isBezier; 40 | private List xnames; 41 | private float maxvalue; 42 | private float minvalue; 43 | private DecimalFormat df; 44 | private DecimalFormat df2; 45 | private String[] series; 46 | private int[] colors; 47 | private List paintlist; 48 | private List regionlist; 49 | private int regionwidth; 50 | private float intervalY; 51 | private float intervalX; 52 | private float Y1ToScreen; 53 | private float intervalY_values; 54 | boolean flag; 55 | private int Ycount; 56 | private String x_unit; 57 | private int[] touchitem; 58 | 59 | private Paint paintline; 60 | private Paint paintwhite; 61 | private Paint paintValue; 62 | private Paint painttest; 63 | private Paint paint_select; 64 | private TextPaint textpaint; 65 | private TextPaint sericeTextpaint; 66 | 67 | private List> pointslist; 68 | 69 | private int width; 70 | private int height; 71 | private float dx; 72 | private float dy; 73 | private float dscale; 74 | private float maxY; 75 | private float maxX; 76 | private float minY; 77 | private float minX; 78 | private int x_count_max; 79 | private boolean canDrag; 80 | private boolean showMaxMin; 81 | private int intervalTime; 82 | private int duration; 83 | private int time; 84 | private int timeSum; 85 | private Handler handler; 86 | private Bitmap bitmap_fullScreen; 87 | private Rect dst_fullScreen; 88 | private boolean canFullScreen; 89 | private List seriesRegionList; 90 | float x_down; 91 | float y_down; 92 | private PointF start; 93 | private PointF mid; 94 | float oldDist; 95 | float oldRotation; 96 | Matrix matrix; 97 | Matrix matrix1; 98 | Matrix savedMatrix; 99 | private static final int NONE = 0; 100 | private static final int DRAG = 1; 101 | private static final int ZOOM = 2; 102 | int mode; 103 | 104 | private boolean isShowSeries = false; 105 | private boolean isShowSeriesTip = false; 106 | private boolean isShowX = false; 107 | 108 | public LineChartView(Context context) { 109 | this(context, (AttributeSet) null); 110 | } 111 | 112 | public LineChartView(Context context, AttributeSet attrs) { 113 | super(context, attrs); 114 | this.datas = new ArrayList(); 115 | this.isBezier = false; 116 | this.isShowSeries = true; 117 | this.xnames = new ArrayList(); 118 | this.maxvalue = 1.4E-45F; 119 | this.minvalue = 3.4028235E38F; 120 | this.df = new DecimalFormat("##0.00"); 121 | this.df2 = new DecimalFormat("##0"); 122 | this.series = null; 123 | this.paintlist = new ArrayList(); 124 | this.regionlist = new ArrayList(); 125 | this.regionwidth = 40; 126 | this.intervalY = 0.0F; 127 | this.intervalX = 0.0F; 128 | this.Y1ToScreen = 0.0F; 129 | this.intervalY_values = 0.0F; 130 | this.flag = false; 131 | this.Ycount = -1; 132 | this.x_unit = ""; 133 | this.touchitem = new int[]{-1, -1}; 134 | this.pointslist = new ArrayList(); 135 | this.dx = 0.0F; 136 | this.dy = 0.0F; 137 | this.dscale = 1.0F; 138 | this.x_count_max = 15; 139 | this.canDrag = false; 140 | this.showMaxMin = false; 141 | this.intervalTime = 25; 142 | this.duration = 500; 143 | this.time = this.duration / this.intervalTime; 144 | this.timeSum = this.duration / this.intervalTime; 145 | this.handler = new Handler(); 146 | this.dst_fullScreen = new Rect(); 147 | this.canFullScreen = false; 148 | this.seriesRegionList = new ArrayList(); 149 | this.x_down = 0.0F; 150 | this.y_down = 0.0F; 151 | this.start = new PointF(); 152 | this.mid = new PointF(); 153 | this.oldDist = 1.0F; 154 | this.oldRotation = 0.0F; 155 | this.matrix = new Matrix(); 156 | this.matrix1 = new Matrix(); 157 | this.savedMatrix = new Matrix(); 158 | this.mode = 0; 159 | 160 | this.textpaint = new TextPaint(); 161 | this.textpaint.setStyle(Paint.Style.FILL); 162 | this.textpaint.setColor(Color.WHITE); 163 | this.textpaint.setAntiAlias(true); 164 | this.textpaint.setTextAlign(Paint.Align.CENTER); 165 | this.textpaint.setTextSize(DensityUtil.dip2pxf(this.getContext(), 9)); 166 | 167 | this.sericeTextpaint = new TextPaint(); 168 | this.sericeTextpaint.setStyle(Paint.Style.FILL); 169 | this.sericeTextpaint.setColor(Color.WHITE); 170 | this.sericeTextpaint.setAntiAlias(true); 171 | this.sericeTextpaint.setTextAlign(Paint.Align.CENTER); 172 | this.sericeTextpaint.setTextSize(DensityUtil.dip2pxf(this.getContext(), 11)); 173 | if (this.isInEditMode()) { 174 | this.test(); 175 | } 176 | 177 | } 178 | 179 | private void test() { 180 | this.showMaxMin = true; 181 | String[] series = new String[]{"Series1"}; 182 | ArrayList datas = new ArrayList(); 183 | ArrayList xnames = new ArrayList(); 184 | 185 | int i; 186 | for (i = 0; i < 20; ++i) { 187 | xnames.add("X" + (i + 1)); 188 | } 189 | 190 | for (i = 0; i < series.length; ++i) { 191 | ArrayList tmpList = new ArrayList(); 192 | 193 | for (int j = 0; j < xnames.size(); ++j) { 194 | tmpList.add(Float.valueOf((float) (new Random()).nextInt(1000) / 50.0F)); 195 | } 196 | 197 | datas.add(tmpList); 198 | } 199 | this.setShowSeries(false); 200 | this.initData(series, datas, "曲线图例子", xnames, "m"); 201 | } 202 | 203 | public void initData(String[] series, int[] colors, List> datas, String title, List xnames, float maxvalue, float minvalue, String x_unit) { 204 | this.datas = datas; 205 | this.title = title; 206 | this.xnames = xnames; 207 | this.maxvalue = maxvalue; 208 | this.minvalue = minvalue; 209 | this.series = series; 210 | this.colors = colors; 211 | this.x_unit = x_unit; 212 | this.init(); 213 | } 214 | 215 | public void initData(int[] colors, List> datas, List xnames) { 216 | this.datas = datas; 217 | this.xnames = xnames; 218 | this.colors = colors; 219 | this.maxvalue = 1.4E-45F; 220 | this.minvalue = 3.4028235E38F; 221 | this.init(); 222 | } 223 | 224 | public void initData(String[] series, List> datas, String title, List xnames, float maxvalue, float minvalue, String x_unit) { 225 | this.datas = datas; 226 | this.title = title; 227 | this.xnames = xnames; 228 | this.maxvalue = maxvalue; 229 | this.minvalue = minvalue; 230 | this.series = series; 231 | this.x_unit = x_unit; 232 | this.init(); 233 | } 234 | 235 | public void initData(String[] series, List> datas, String title, List xnames, String x_unit) { 236 | this.datas = datas; 237 | this.title = title; 238 | this.xnames = xnames; 239 | this.series = series; 240 | this.x_unit = x_unit; 241 | this.maxvalue = 1.4E-45F; 242 | this.minvalue = 3.4028235E38F; 243 | this.init(); 244 | } 245 | 246 | 247 | public void initData(String[] series, int[] colors, List> datas, List xnames) { 248 | this.datas = datas; 249 | this.xnames = xnames; 250 | this.series = series; 251 | 252 | this.maxvalue = 1.4E-45F; 253 | this.minvalue = 3.4028235E38F; 254 | this.init(); 255 | } 256 | 257 | public void initData(String[] series, List> datas, List xnames) { 258 | this.datas = datas; 259 | this.xnames = xnames; 260 | this.colors = colors; 261 | this.series = series; 262 | int[] colors = {Color.parseColor("#7139ff"), Color.parseColor("#44a4fc"), Color.parseColor("#12f1ff")}; 263 | this.colors = colors; 264 | this.maxvalue = 1.4E-45F; 265 | this.minvalue = 3.4028235E38F; 266 | this.init(); 267 | } 268 | 269 | public void initData(String[] series, List> datas, String title, List xnames, String x_unit, float maxvalue, float minvalue) { 270 | this.datas = datas; 271 | this.title = title; 272 | this.xnames = xnames; 273 | this.series = series; 274 | this.x_unit = x_unit; 275 | this.maxvalue = maxvalue; 276 | this.minvalue = minvalue; 277 | this.init(); 278 | } 279 | 280 | public void initData(String[] series, List> datas, String title, List xnames, String x_unit, float intervalX, float intervalY, float intervalY_values) { 281 | this.datas = datas; 282 | this.title = title; 283 | this.xnames = xnames; 284 | this.series = series; 285 | this.x_unit = x_unit; 286 | this.intervalY = intervalY; 287 | this.intervalX = intervalX; 288 | this.Y1ToScreen = intervalY / intervalY_values; 289 | this.intervalY_values = intervalY_values; 290 | this.canDrag = true; 291 | this.flag = true; 292 | this.maxvalue = this.getMinOrMaxValues(datas, true); 293 | this.minvalue = this.getMinOrMaxValues(datas, false); 294 | if (this.fMod(this.maxvalue, intervalY_values) != 0.0F) { 295 | this.maxvalue += intervalY_values - this.fMod(this.maxvalue, intervalY_values); 296 | } 297 | 298 | if (this.fMod(this.minvalue, intervalY_values) != 0.0F) { 299 | this.minvalue -= this.fMod(this.minvalue, intervalY_values); 300 | } 301 | 302 | this.init(); 303 | this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 304 | public void onGlobalLayout() { 305 | LineChartView.this.dy = (float) LineChartView.this.getHeight() - (LineChartView.this.maxvalue - LineChartView.this.minvalue) * LineChartView.this.Y1ToScreen - (float) DensityUtil.dip2px(LineChartView.this.getContext(), 55.0F) - (float) (LineChartView.this.series.length / 2 * DensityUtil.dip2px(LineChartView.this.getContext(), 10.0F)); 306 | LineChartView.this.matrix.postTranslate(0.0F, LineChartView.this.dy); 307 | LineChartView.this.getViewTreeObserver().removeGlobalOnLayoutListener(this); 308 | } 309 | }); 310 | } 311 | 312 | private void init() { 313 | this.pointslist.clear(); 314 | if (this.colors == null) { 315 | int[] colors = {Color.parseColor("#7139ff"), Color.parseColor("#44a4fc"), Color.parseColor("#12f1ff"), Color.parseColor("#44a4fc"), Color.parseColor("#12f1ff")}; 316 | this.colors = colors; 317 | } 318 | int i; 319 | if (this.maxvalue == 1.4E-45F) { 320 | this.maxvalue = this.getMinOrMaxValues(this.datas, true); 321 | this.minvalue = this.getMinOrMaxValues(this.datas, false); 322 | if (this.maxvalue - this.minvalue >= 5.0F) { 323 | this.maxvalue = (float) Math.ceil((double) this.maxvalue); 324 | this.minvalue = (float) Math.floor((double) this.minvalue); 325 | i = 0; 326 | 327 | for (int[] paint = new int[]{7, 6, 5, 4, 3}; i < 100; ++i) { 328 | for (int j = 0; j < paint.length; ++j) { 329 | if ((this.maxvalue - this.minvalue) % (float) paint[j] == 0.0F) { 330 | this.Ycount = paint[j]; 331 | i = 100; 332 | break; 333 | } 334 | } 335 | 336 | if (i % 2 == 1) { 337 | ++this.maxvalue; 338 | } else if (this.minvalue != 0.0F) { 339 | --this.minvalue; 340 | } 341 | } 342 | } 343 | } 344 | 345 | for (i = 0; i < this.datas.size(); ++i) { 346 | Paint var4 = new Paint(); 347 | var4.setStyle(Paint.Style.STROKE); 348 | var4.setAntiAlias(true); 349 | var4.setColor(this.colors[i]); 350 | var4.setTextAlign(Paint.Align.CENTER); 351 | var4.setStrokeWidth((float) DensityUtil.dip2px(this.getContext(), 1.0F)); 352 | this.paintlist.add(var4); 353 | } 354 | 355 | //选择的画笔设置 356 | this.paint_select = new Paint(); 357 | this.paint_select.setStyle(Paint.Style.STROKE); 358 | this.paint_select.setAntiAlias(true); 359 | this.paint_select.setColor(Color.rgb(0, 155, 0)); 360 | this.paint_select.setStrokeWidth((float) DensityUtil.dip2px(this.getContext(), 2.0F)); 361 | 362 | //提示框的画笔 363 | this.paintValue = new Paint(); 364 | this.paintValue.setStyle(Paint.Style.FILL); 365 | this.paintValue.setAntiAlias(true); 366 | this.paintValue.setColor(getResources().getColor(R.color.theme_color)); 367 | this.paintValue.setStrokeWidth((float) DensityUtil.dip2px(this.getContext(), 2.0F)); 368 | 369 | this.paintline = new Paint(); 370 | this.paintline.setStyle(Paint.Style.STROKE); 371 | this.paintline.setAntiAlias(true); 372 | this.paintline.setColor(Color.parseColor("#ececec")); 373 | this.paintline.setStrokeWidth(1.0F); 374 | 375 | this.paintwhite = new Paint(); 376 | this.paintwhite.setStyle(Paint.Style.FILL); 377 | this.paintwhite.setAntiAlias(true); 378 | this.paintwhite.setColor(Color.WHITE); 379 | this.paintwhite.setStrokeWidth((float) DensityUtil.dip2px(this.getContext(), 1.0F)); 380 | this.paintwhite.setTextAlign(Paint.Align.LEFT); 381 | 382 | this.painttest = new Paint(); 383 | this.painttest.setStyle(Paint.Style.FILL); 384 | this.painttest.setAntiAlias(true); 385 | this.painttest.setColor(Color.WHITE); 386 | this.bitmap_fullScreen = BitmapFactory.decodeResource(this.getResources(), R.drawable.ic_func_myworker); 387 | 388 | this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 389 | public void onGlobalLayout() { 390 | LineChartView.this.getViewTreeObserver().removeGlobalOnLayoutListener(this); 391 | LineChartView.this.invalidate(); 392 | } 393 | }); 394 | } 395 | 396 | @SuppressLint({"DrawAllocation"}) 397 | protected void onDraw(Canvas canvas) { 398 | super.onDraw(canvas); 399 | if (this.datas.size() != 0) { 400 | canvas.save(); 401 | this.width = this.getWidth(); 402 | this.height = this.getHeight(); 403 | this.dst_fullScreen.left = this.getWidth() - DensityUtil.dip2px(this.getContext(), 36.0F); 404 | this.dst_fullScreen.top = this.getHeight() - DensityUtil.dip2px(this.getContext(), 23.0F); 405 | this.dst_fullScreen.right = this.getWidth() - DensityUtil.dip2px(this.getContext(), 8.0F); 406 | this.dst_fullScreen.bottom = this.getHeight() - DensityUtil.dip2px(this.getContext(), 3.0F); 407 | this.maxY = (float) DensityUtil.dip2px(this.getContext(), 15.0F); 408 | if (this.series != null) { 409 | this.minY = (float) (this.height - DensityUtil.dip2px(this.getContext(), 30.0F) - this.series.length / 3 * DensityUtil.dip2px(this.getContext(), 10.0F) - (this.series.length % 3 == 0 ? 0 : 1) * DensityUtil.dip2px(this.getContext(), 10.0F)); 410 | } else { 411 | this.minY = (float) (this.height - DensityUtil.dip2px(this.getContext(), 30.0F)); 412 | } 413 | 414 | if (this.flag) { 415 | this.Ycount = (int) ((this.maxvalue - this.minvalue) / this.intervalY_values); 416 | } else { 417 | if (this.Ycount == -1) { 418 | this.Ycount = 5; 419 | } 420 | 421 | if (Math.abs(this.maxvalue - this.minvalue) < 5.0F) { 422 | this.Ycount = (int) Math.abs(this.maxvalue - this.minvalue) + 1; 423 | } 424 | this.intervalY = (this.minY - this.maxY) / (float) this.Ycount; 425 | this.Y1ToScreen = (this.minY - this.maxY) / (this.maxvalue - this.minvalue); 426 | } 427 | 428 | this.maxX = (float) (this.width - DensityUtil.dip2px(this.getContext(), 10.0F)); 429 | this.minX = (float) ScreenUtils.gettextwidth(this.getContext(), this.df.format((double) this.maxvalue), 8); 430 | if (!this.flag) { 431 | this.intervalX = (this.maxX - this.minX - (float) DensityUtil.dip2px(this.getContext(), 10.0F)) / (float) ((List) this.datas.get(0)).size(); 432 | } 433 | float rectw = this.intervalX * 2.0F / 3.0F; 434 | float startx = this.intervalX * 1.0F / 6.0F + (float) DensityUtil.dip2px(this.getContext(), 5.0F); 435 | this.regionwidth = this.intervalY > this.intervalX ? (int) this.intervalX : (int) this.intervalY; 436 | canvas.concat(this.matrix); 437 | 438 | int touchpoint; 439 | if (isShowX) { 440 | for (touchpoint = 0; touchpoint < this.Ycount + 1; ++touchpoint) { 441 | //画x轴 442 | canvas.drawLine(this.minX, this.maxY + this.intervalY * (float) touchpoint, this.maxX, this.maxY + this.intervalY * (float) touchpoint, this.paintline); 443 | } 444 | } 445 | 446 | int isEmpty; 447 | int var12; 448 | if (this.pointslist.size() == 0) { 449 | LineChartView.MPoint i; 450 | for (touchpoint = 0; touchpoint < this.datas.size(); ++touchpoint) { 451 | ArrayList ii = new ArrayList(); 452 | 453 | for (isEmpty = 0; isEmpty < ((List) this.datas.get(touchpoint)).size(); ++isEmpty) { 454 | if (((Float) ((List) this.datas.get(touchpoint)).get(isEmpty)).floatValue() >= this.minvalue) { 455 | i = new LineChartView.MPoint(this.minX + (float) isEmpty * this.intervalX + startx + rectw / 2.0F, this.maxY + (this.maxvalue - ((Float) ((List) this.datas.get(touchpoint)).get(isEmpty)).floatValue()) * this.Y1ToScreen); 456 | ii.add(i); 457 | } 458 | } 459 | this.pointslist.add(ii); 460 | } 461 | 462 | for (touchpoint = 0; touchpoint < this.pointslist.size(); ++touchpoint) { 463 | if (((List) this.pointslist.get(touchpoint)).size() > 1) { 464 | for (var12 = 1; var12 < ((List) this.pointslist.get(touchpoint)).size(); ++var12) { 465 | if (var12 >= 0) { 466 | LineChartView.MPoint var14 = (LineChartView.MPoint) ((List) this.pointslist.get(touchpoint)).get(var12); 467 | if (var12 == 0) { 468 | i = (LineChartView.MPoint) ((List) this.pointslist.get(touchpoint)).get(var12 + 1); 469 | var14.dx = (i.x - var14.x) / 5.0F; 470 | var14.dy = (i.y - var14.y) / 5.0F; 471 | } else if (var12 == ((List) this.pointslist.get(touchpoint)).size() - 1) { 472 | i = (LineChartView.MPoint) ((List) this.pointslist.get(touchpoint)).get(var12 - 1); 473 | var14.dx = (var14.x - i.x) / 5.0F; 474 | var14.dy = (var14.y - i.y) / 5.0F; 475 | } else { 476 | i = (LineChartView.MPoint) ((List) this.pointslist.get(touchpoint)).get(var12 + 1); 477 | LineChartView.MPoint modeNum = (LineChartView.MPoint) ((List) this.pointslist.get(touchpoint)).get(var12 - 1); 478 | var14.dx = (i.x - modeNum.x) / 5.0F; 479 | var14.dy = (i.y - modeNum.y) / 5.0F; 480 | } 481 | } 482 | } 483 | } 484 | } 485 | } 486 | 487 | this.regionlist.clear(); 488 | LineChartView.TPoint var13 = null; 489 | 490 | for (var12 = 0; var12 < this.datas.size(); ++var12) { 491 | for (isEmpty = 0; isEmpty < ((List) this.datas.get(var12)).size(); ++isEmpty) { 492 | if (((Float) ((List) this.datas.get(var12)).get(isEmpty)).floatValue() >= this.minvalue) { 493 | PointF var17 = new PointF(this.minX + (float) isEmpty * this.intervalX + startx + rectw / 2.0F, this.maxY + (this.maxvalue - ((Float) ((List) this.datas.get(var12)).get(isEmpty)).floatValue()) * this.Y1ToScreen); 494 | if (this.touchitem[0] == var12 && this.touchitem[1] == isEmpty) { 495 | var13 = new LineChartView.TPoint(); 496 | var13.x = var17.x; 497 | var13.y = var17.y; 498 | var13.setIndex(var12); 499 | var13.value = ((Float) ((List) this.datas.get(var12)).get(isEmpty)).floatValue(); 500 | } 501 | 502 | LineChartView.MRegion var18 = new LineChartView.MRegion(); 503 | var18.set((int) ((this.minX + (float) isEmpty * this.intervalX + startx + rectw / 2.0F - (float) (this.regionwidth / 2)) * this.dscale + this.dx), (int) ((this.maxY + (this.maxvalue - ((Float) ((List) this.datas.get(var12)).get(isEmpty)).floatValue()) * this.Y1ToScreen - (float) (this.regionwidth / 2)) * this.dscale + this.dy), (int) ((this.minX + (float) isEmpty * this.intervalX + startx + rectw / 2.0F + (float) (this.regionwidth / 2)) * this.dscale + this.dx), (int) ((this.maxY + (this.maxvalue - ((Float) ((List) this.datas.get(var12)).get(isEmpty)).floatValue()) * this.Y1ToScreen + (float) (this.regionwidth / 2)) * this.dscale + this.dy)); 504 | var18.setValue(((Float) ((List) this.datas.get(var12)).get(isEmpty)).floatValue()); 505 | var18.setIJ(var12, isEmpty); 506 | this.regionlist.add(var18); 507 | } 508 | } 509 | } 510 | 511 | this.drawData(canvas); 512 | if (var13 != null) { 513 | if (this.seriesRegionList != null && this.seriesRegionList.size() != 0) { 514 | var12 = var13.getIndex(); 515 | Iterator var15 = this.seriesRegionList.iterator(); 516 | 517 | while (var15.hasNext()) { 518 | LineChartView.MRegion var19 = (LineChartView.MRegion) var15.next(); 519 | if (var19.getI() == var12 && var19.isShow()) { 520 | this.drawTouchValue(canvas, var13); 521 | } 522 | } 523 | } else { 524 | this.drawTouchValue(canvas, var13); 525 | } 526 | } 527 | canvas.restore(); 528 | if (this.title != null) { 529 | //绘制标题 530 | canvas.drawText(this.title, (float) (this.width / 2), ScreenUtils.getTextHeight(this.textpaint.getTextSize()), this.textpaint); 531 | } 532 | for (var12 = 0; var12 < this.Ycount + 1; ++var12) { 533 | this.textpaint.setTextAlign(Paint.Align.RIGHT); 534 | String var16; 535 | if ((int) Math.abs(this.maxvalue - this.minvalue) < 5) { 536 | var16 = this.df.format((double) (this.maxvalue - (float) var12 * ((this.maxvalue - this.minvalue) * 1.0F / (float) this.Ycount))); 537 | } else { 538 | var16 = this.df2.format((double) (this.maxvalue - (float) var12 * ((this.maxvalue - this.minvalue) * 1.0F / (float) this.Ycount))); 539 | } 540 | canvas.drawText(var16, this.minX - (float) DensityUtil.dip2px(this.getContext(), 2.0F), (this.maxY + this.intervalY * (float) var12) * this.dscale + this.dy, this.textpaint); 541 | } 542 | 543 | this.textpaint.setTextAlign(Paint.Align.CENTER); 544 | var12 = this.xnames.size() / (this.x_count_max / 2 + 1); 545 | var12 = var12 == 0 ? 1 : var12; 546 | 547 | for (isEmpty = 0; isEmpty < this.xnames.size(); isEmpty += var12) { 548 | canvas.drawText((String) this.xnames.get(isEmpty), (this.minX + (float) isEmpty * this.intervalX + startx + rectw / 2.0F) * this.dscale + this.dx, this.minY + (float) DensityUtil.dip2px(this.getContext(), 10.0F), this.textpaint); 549 | } 550 | 551 | this.textpaint.setTextAlign(Paint.Align.LEFT); 552 | if (this.isShowSeries) { 553 | canvas.drawText("横坐标:" + this.x_unit, (float) DensityUtil.dip2px(this.getContext(), 15.0F), this.minY + (float) DensityUtil.dip2px(this.getContext(), 25.0F), this.textpaint); 554 | canvas.drawText("纵坐标:", (float) DensityUtil.dip2px(this.getContext(), 15.0F), this.minY + (float) DensityUtil.dip2px(this.getContext(), 37.0F), this.textpaint); 555 | } 556 | 557 | boolean var22 = this.seriesRegionList.isEmpty(); 558 | if (this.series != null) { 559 | for (int var21 = 0; var21 < this.series.length; ++var21) { 560 | int var20 = var21 % 3; 561 | float move = var20 > 0 ? (float) ((this.width - DensityUtil.dip2px(this.getContext(), 50.0F)) / 3) : 0.0F; 562 | float y = this.minY + (float) DensityUtil.dip2px(this.getContext(), (float) (var21 / 3 * 10 + 35)); 563 | if (isShowSeriesTip) { 564 | 565 | canvas.drawText(this.series[var21], (float) DensityUtil.dip2px(this.getContext(), 71.0F) + move * (float) var20, y + (float) DensityUtil.dip2px(this.getContext(), 2.0F), this.sericeTextpaint); 566 | 567 | Paint mPaint = this.paintlist.get(var21); 568 | mPaint.setStyle(Paint.Style.FILL); 569 | //绘制点 570 | canvas.drawCircle((float) DensityUtil.dip2px(this.getContext(), 40.0F) + move * (float) var20, y, (float) DensityUtil.dip2px(this.getContext(), 3.5F), mPaint); 571 | canvas.drawCircle((float) DensityUtil.dip2px(this.getContext(), 40.0F) + move * (float) var20, y, (float) DensityUtil.dip2px(this.getContext(), 3.0F), paintwhite); 572 | canvas.drawCircle((float) DensityUtil.dip2px(this.getContext(), 40.0F) + move * (float) var20, y, (float) DensityUtil.dip2px(this.getContext(), 1.5F), mPaint); 573 | mPaint.setStyle(Paint.Style.STROKE); 574 | } 575 | if (var22) { 576 | LineChartView.MRegion mRegion = new LineChartView.MRegion(); 577 | mRegion.set((int) ((float) DensityUtil.dip2px(this.getContext(), 50.0F) + move * (float) var20), (int) (y - (float) DensityUtil.dip2px(this.getContext(), 5.0F)), (int) ((float) DensityUtil.dip2px(this.getContext(), 70.0F) + move * (float) var20), (int) (y + (float) DensityUtil.dip2px(this.getContext(), 5.0F))); 578 | mRegion.setIJ(var21, 0); 579 | mRegion.setShow(true); 580 | this.seriesRegionList.add(mRegion); 581 | } 582 | } 583 | } 584 | 585 | if (this.pointslist.size() > 0 && this.timeSum > this.time) { 586 | ++this.time; 587 | this.handler.postDelayed(new Runnable() { 588 | public void run() { 589 | LineChartView.this.invalidate(); 590 | } 591 | }, (long) this.intervalTime); 592 | } 593 | 594 | if (this.canFullScreen) { 595 | canvas.drawBitmap(this.bitmap_fullScreen, (Rect) null, this.dst_fullScreen, (Paint) null); 596 | } 597 | 598 | } 599 | } 600 | 601 | private void drawTouchValue(Canvas canvas, LineChartView.TPoint tPoint) { 602 | String format = "%.0f"; 603 | if ((float) ((int) tPoint.getValue()) == tPoint.getValue()) { 604 | format = "%.0f"; 605 | } else { 606 | format = "%.2f"; 607 | } 608 | 609 | //提示字体大小 610 | paintwhite.setTextSize(DensityUtil.sp2px(this.getContext(), 10)); 611 | 612 | int textLength = this.getTextWidth(this.paintwhite, String.format(format, new Object[]{Float.valueOf(tPoint.getValue())})); 613 | int textHeight = this.getFontHeight(this.paintwhite); 614 | float ascent = Math.abs(this.paintwhite.getFontMetrics().ascent); 615 | int dp2 = DensityUtil.dip2px(this.getContext(), 2.0F); 616 | Path path; 617 | if (tPoint.x + (float) textLength + (float) (2 * dp2) > (float) this.width) { 618 | if (tPoint.y - (float) textHeight - (float) (2 * dp2) - (float) (3 * dp2) < 0.0F) { 619 | path = new Path(); 620 | path.moveTo(tPoint.x, tPoint.y); 621 | path.lineTo(tPoint.x - (float) (2 * dp2), tPoint.y + (float) (3 * dp2)); 622 | path.lineTo(tPoint.x - (float) (2 * dp2) - (float) textLength, tPoint.y + (float) (3 * dp2)); 623 | path.lineTo(tPoint.x - (float) (2 * dp2) - (float) textLength, tPoint.y + (float) (3 * dp2) + (float) (2 * dp2) + (float) textHeight); 624 | path.lineTo(tPoint.x, tPoint.y + (float) (3 * dp2) + (float) (2 * dp2) + (float) textHeight); 625 | path.close(); 626 | canvas.drawPath(path, this.paintValue); 627 | canvas.drawText(String.format(format, new Object[]{Float.valueOf(tPoint.getValue())}), tPoint.x - (float) dp2 - (float) textLength, tPoint.y + (float) (3 * dp2) + (float) dp2 + ascent, this.paintwhite); 628 | } else { 629 | path = new Path(); 630 | path.moveTo(tPoint.x, tPoint.y); 631 | path.lineTo(tPoint.x - (float) (2 * dp2), tPoint.y - (float) (3 * dp2)); 632 | path.lineTo(tPoint.x - (float) (2 * dp2) - (float) textLength, tPoint.y - (float) (3 * dp2)); 633 | path.lineTo(tPoint.x - (float) (2 * dp2) - (float) textLength, tPoint.y - (float) (3 * dp2) - (float) (2 * dp2) - (float) textHeight); 634 | path.lineTo(tPoint.x, tPoint.y - (float) (3 * dp2) - (float) (2 * dp2) - (float) textHeight); 635 | path.close(); 636 | canvas.drawPath(path, this.paintValue); 637 | canvas.drawText(String.format(format, new Object[]{Float.valueOf(tPoint.getValue())}), tPoint.x - (float) dp2 - (float) textLength, tPoint.y - (float) (3 * dp2) - (float) dp2 - (float) textHeight + ascent, this.paintwhite); 638 | } 639 | } else if (tPoint.y - (float) textHeight - (float) (2 * dp2) - (float) (3 * dp2) < 0.0F) { 640 | path = new Path(); 641 | path.moveTo(tPoint.x, tPoint.y); 642 | path.lineTo(tPoint.x + (float) (2 * dp2), tPoint.y + (float) (3 * dp2)); 643 | path.lineTo(tPoint.x + (float) (2 * dp2) + (float) textLength, tPoint.y + (float) (3 * dp2)); 644 | path.lineTo(tPoint.x + (float) (2 * dp2) + (float) textLength, tPoint.y + (float) (3 * dp2) + (float) (2 * dp2) + (float) textHeight); 645 | path.lineTo(tPoint.x, tPoint.y + (float) (3 * dp2) + (float) (2 * dp2) + (float) textHeight); 646 | path.close(); 647 | canvas.drawPath(path, this.paintValue); 648 | canvas.drawText(String.format(format, new Object[]{Float.valueOf(tPoint.getValue())}), tPoint.x + (float) dp2, tPoint.y + (float) (3 * dp2) + (float) dp2 + ascent, this.paintwhite); 649 | } else { 650 | path = new Path(); 651 | path.moveTo(tPoint.x, tPoint.y); 652 | path.lineTo(tPoint.x + (float) (2 * dp2), tPoint.y - (float) (3 * dp2)); 653 | path.lineTo(tPoint.x + (float) (2 * dp2) + (float) textLength, tPoint.y - (float) (3 * dp2)); 654 | path.lineTo(tPoint.x + (float) (2 * dp2) + (float) textLength, tPoint.y - (float) (3 * dp2) - (float) (2 * dp2) - (float) textHeight); 655 | path.lineTo(tPoint.x, tPoint.y - (float) (3 * dp2) - (float) (2 * dp2) - (float) textHeight); 656 | path.close(); 657 | canvas.drawPath(path, this.paintValue); 658 | canvas.drawText(String.format(format, new Object[]{Float.valueOf(tPoint.getValue())}), tPoint.x + (float) dp2, tPoint.y - (float) (3 * dp2) - (float) dp2 - (float) textHeight + ascent, this.paintwhite); 659 | } 660 | } 661 | 662 | private int getTextWidth(Paint paint, String str) { 663 | int iRet = 0; 664 | if (str != null && str.length() > 0) { 665 | int len = str.length(); 666 | float[] widths = new float[len]; 667 | paint.getTextWidths(str, widths); 668 | 669 | for (int j = 0; j < len; ++j) { 670 | iRet += (int) Math.ceil((double) widths[j]); 671 | } 672 | } 673 | return iRet; 674 | } 675 | 676 | private int getFontHeight(Paint paint) { 677 | Paint.FontMetrics fm = paint.getFontMetrics(); 678 | return (int) Math.ceil((double) (fm.descent - fm.ascent)); 679 | } 680 | 681 | private void drawData(Canvas canvas) { 682 | float time = (float) this.time * 1.0F / (float) this.timeSum * (float) ((List) this.pointslist.get(0)).size(); 683 | 684 | int i; 685 | LineChartView.MPoint point; 686 | for (i = 0; i < this.pointslist.size(); ++i) { 687 | // for (i = this.pointslist.size()-1; i >=0 ; --i) { 688 | if ((this.seriesRegionList.isEmpty() || ((LineChartView.MRegion) this.seriesRegionList.get(i)).isShow()) && ((List) this.pointslist.get(i)).size() > 0) { 689 | Path max = null; 690 | Path max2 = null; 691 | boolean min = true; 692 | float mMaxX = 0; 693 | 694 | for (int isDrawMax = 0; (float) isDrawMax < time; ++isDrawMax) { 695 | LineChartView.MPoint isDrawMin = (LineChartView.MPoint) ((List) this.pointslist.get(i)).get(isDrawMax); 696 | float j = this.minY - isDrawMin.y - (float) this.time * 1.0F / (float) this.timeSum * (this.minY - isDrawMin.y); 697 | 698 | if (isDrawMax == 0) { 699 | max2 = new Path(); 700 | max2.moveTo(isDrawMin.x, this.minY); 701 | } 702 | max2.lineTo(isDrawMin.x, isDrawMin.y); 703 | 704 | if (min) { 705 | max = new Path(); 706 | min = false; 707 | max.moveTo(isDrawMin.x, isDrawMin.y + j); 708 | } else if (((Float) ((List) this.datas.get(i)).get(isDrawMax)).floatValue() == 1.4E-45F) { 709 | canvas.drawPath(max, (Paint) this.paintlist.get(i)); 710 | min = true; 711 | --isDrawMax; 712 | } else if (this.isBezier) { 713 | point = (LineChartView.MPoint) ((List) this.pointslist.get(i)).get(isDrawMax - 1); 714 | max.cubicTo(point.x + point.dx, point.y + point.dy, isDrawMin.x - isDrawMin.dx, isDrawMin.y - isDrawMin.dy, isDrawMin.x, isDrawMin.y); 715 | } else { 716 | max.lineTo(isDrawMin.x, isDrawMin.y + j); 717 | } 718 | mMaxX = isDrawMin.x; 719 | } 720 | 721 | //绘制线条 722 | canvas.drawPath(max, (Paint) this.paintlist.get(i)); 723 | max2.lineTo(mMaxX, this.minY); 724 | 725 | this.paintlist.get(i).setStyle(Paint.Style.FILL); 726 | if (i == 0) { 727 | this.paintlist.get(i).setAlpha(77); 728 | } else if (i == 1) { 729 | this.paintlist.get(i).setAlpha(128); 730 | } else if (i == 2) { 731 | this.paintlist.get(i).setAlpha(55); 732 | } else { 733 | this.paintlist.get(i).setAlpha(80); 734 | } 735 | canvas.drawPath(max2, (Paint) (Paint) this.paintlist.get(i)); 736 | //恢复原来的配置 737 | this.paintlist.get(i).setStyle(Paint.Style.STROKE); 738 | this.paintlist.get(i).setAlpha(255); 739 | } 740 | 741 | //分层次显示点还是全部显示在第一层 742 | // } 743 | // for (i = 0; i < this.pointslist.size(); ++i) { 744 | 745 | if ((this.seriesRegionList.isEmpty() || ((LineChartView.MRegion) this.seriesRegionList.get(i)).isShow()) && ((List) this.pointslist.get(i)).size() > 0) { 746 | float var13 = 3.4028235E38F; 747 | float var14 = 1.4E-45F; 748 | if (this.showMaxMin) { 749 | var13 = this.getMaxValue((List) this.datas.get(i)); 750 | var14 = this.getMinValue((List) this.datas.get(i)); 751 | } 752 | 753 | boolean var15 = false; 754 | boolean var16 = false; 755 | for (int var17 = 0; (float) var17 < time; ++var17) { 756 | point = (LineChartView.MPoint) ((List) this.pointslist.get(i)).get(var17); 757 | float offsetY = this.minY - point.y - (float) this.time * 1.0F / (float) this.timeSum * (this.minY - point.y); 758 | if (this.showMaxMin) { 759 | String format; 760 | float strokewidth; 761 | if (var13 != var14) { 762 | if (!var15 && ((Float) ((List) this.datas.get(i)).get(var17)).floatValue() == var13) { 763 | format = "%.0f"; 764 | if ((float) ((Float) ((List) this.datas.get(i)).get(var17)).intValue() == ((Float) ((List) this.datas.get(i)).get(var17)).floatValue()) { 765 | format = "%.0f"; 766 | } else { 767 | format = "%.2f"; 768 | } 769 | 770 | strokewidth = ((Paint) this.paintlist.get(i)).getStrokeWidth(); 771 | ((Paint) this.paintlist.get(i)).setStrokeWidth(1.0F); 772 | canvas.drawText(String.format(format, new Object[]{((List) this.datas.get(i)).get(var17)}), point.x, point.y - 5.0F, (Paint) this.paintlist.get(i)); 773 | ((Paint) this.paintlist.get(i)).setStrokeWidth(strokewidth); 774 | ((Paint) this.paintlist.get(i)).setStyle(Paint.Style.FILL); 775 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 2.0F), this.touchitem[0] == i && this.touchitem[1] == var17 ? this.paint_select : (Paint) this.paintlist.get(i)); 776 | ((Paint) this.paintlist.get(i)).setStyle(Paint.Style.STROKE); 777 | var15 = true; 778 | } else if (!var16 && ((Float) ((List) this.datas.get(i)).get(var17)).floatValue() == var14) { 779 | format = "%.0f"; 780 | if ((float) ((Float) ((List) this.datas.get(i)).get(var17)).intValue() == ((Float) ((List) this.datas.get(i)).get(var17)).floatValue()) { 781 | format = "%.0f"; 782 | } else { 783 | format = "%.2f"; 784 | } 785 | 786 | strokewidth = ((Paint) this.paintlist.get(i)).getStrokeWidth(); 787 | ((Paint) this.paintlist.get(i)).setStrokeWidth(1.0F); 788 | canvas.drawText(String.format(format, new Object[]{((List) this.datas.get(i)).get(var17)}), point.x, point.y - 5.0F, (Paint) this.paintlist.get(i)); 789 | ((Paint) this.paintlist.get(i)).setStrokeWidth(strokewidth); 790 | ((Paint) this.paintlist.get(i)).setStyle(Paint.Style.FILL); 791 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 2.0F), this.touchitem[0] == i && this.touchitem[1] == var17 ? this.paint_select : (Paint) this.paintlist.get(i)); 792 | ((Paint) this.paintlist.get(i)).setStyle(Paint.Style.STROKE); 793 | var16 = true; 794 | } else { 795 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 1.0F), this.paintwhite); 796 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 2.0F), this.touchitem[0] == i && this.touchitem[1] == var17 ? this.paint_select : (Paint) this.paintlist.get(i)); 797 | } 798 | } else if (!var16 && !var15) { 799 | format = "%.0f"; 800 | if ((float) ((Float) ((List) this.datas.get(i)).get(var17)).intValue() == ((Float) ((List) this.datas.get(i)).get(var17)).floatValue()) { 801 | format = "%.0f"; 802 | } else { 803 | format = "%.2f"; 804 | } 805 | 806 | strokewidth = ((Paint) this.paintlist.get(i)).getStrokeWidth(); 807 | ((Paint) this.paintlist.get(i)).setStrokeWidth(1.0F); 808 | canvas.drawText(String.format(format, new Object[]{((List) this.datas.get(i)).get(var17)}), point.x, point.y - 5.0F, (Paint) this.paintlist.get(i)); 809 | ((Paint) this.paintlist.get(i)).setStrokeWidth(strokewidth); 810 | ((Paint) this.paintlist.get(i)).setStyle(Paint.Style.FILL); 811 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 2.0F), this.touchitem[0] == i && this.touchitem[1] == var17 ? this.paint_select : (Paint) this.paintlist.get(i)); 812 | ((Paint) this.paintlist.get(i)).setStyle(Paint.Style.STROKE); 813 | var16 = true; 814 | var15 = true; 815 | } else { 816 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 1.0F), this.paintwhite); 817 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 2.0F), this.touchitem[0] == i && this.touchitem[1] == var17 ? this.paint_select : (Paint) this.paintlist.get(i)); 818 | } 819 | } else { 820 | //绘制点 821 | Paint mPaint = this.touchitem[0] == i && this.touchitem[1] == var17 ? this.paint_select : (Paint) this.paintlist.get(i); 822 | mPaint.setStyle(Paint.Style.FILL); 823 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 3.5F), mPaint); 824 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 3.0F), paintwhite); 825 | canvas.drawCircle(point.x, point.y + offsetY, (float) DensityUtil.dip2px(this.getContext(), 1.5F), mPaint); 826 | mPaint.setStyle(Paint.Style.STROKE); 827 | } 828 | } 829 | } 830 | } 831 | } 832 | 833 | private float getMaxValue(List values) { 834 | float max = 1.4E-45F; 835 | 836 | for (int i = 0; i < values.size(); ++i) { 837 | if (((Float) values.get(i)).floatValue() > max) { 838 | max = ((Float) values.get(i)).floatValue(); 839 | } 840 | } 841 | 842 | return max; 843 | } 844 | 845 | private float getMinValue(List values) { 846 | float min = 3.4028235E38F; 847 | 848 | for (int i = 0; i < values.size(); ++i) { 849 | if (((Float) values.get(i)).floatValue() < min) { 850 | min = ((Float) values.get(i)).floatValue(); 851 | } 852 | } 853 | 854 | return min; 855 | } 856 | 857 | private float getMinOrMaxValues(List> ls, boolean isMax) { 858 | float max = 1.4E-45F; 859 | float min = 3.4028235E38F; 860 | if (ls != null && ls.size() != 0) { 861 | for (int i = 0; i < ls.size(); ++i) { 862 | for (int j = 0; j < ((List) ls.get(i)).size(); ++j) { 863 | if (((Float) ((List) ls.get(i)).get(j)).floatValue() != 1.4E-45F) { 864 | if (((Float) ((List) ls.get(i)).get(j)).floatValue() > max) { 865 | max = ((Float) ((List) ls.get(i)).get(j)).floatValue(); 866 | } 867 | 868 | if (((Float) ((List) ls.get(i)).get(j)).floatValue() < min) { 869 | min = ((Float) ((List) ls.get(i)).get(j)).floatValue(); 870 | } 871 | } 872 | } 873 | } 874 | 875 | max = max == 1.4E-45F ? 0.0F : max * 1.1F; 876 | min = min == 3.4028235E38F ? 0.0F : min * 0.9F; 877 | return isMax ? max : min; 878 | } else { 879 | return 0.0F; 880 | } 881 | } 882 | 883 | private float fMod(float f1, float f2) { 884 | int i1 = (int) (f1 * 100.0F); 885 | int i2 = (int) (f2 * 100.0F); 886 | return (float) ((double) (i1 % i2) / 100.0D); 887 | } 888 | 889 | boolean isCanOnTouch = false; 890 | 891 | public boolean onTouchEvent(MotionEvent event) { 892 | if (isCanOnTouch) { 893 | switch (event.getAction() & 255) { 894 | case 0: 895 | this.mode = 1; 896 | this.x_down = event.getX(); 897 | this.y_down = event.getY(); 898 | this.savedMatrix.set(this.matrix); 899 | boolean showPoint = false; 900 | 901 | for (int var6 = 0; var6 < this.regionlist.size(); ++var6) { 902 | if (((LineChartView.MRegion) this.regionlist.get(var6)).contains((int) event.getX(), (int) event.getY())) { 903 | this.touchitem[0] = ((LineChartView.MRegion) this.regionlist.get(var6)).getI(); 904 | this.touchitem[1] = ((LineChartView.MRegion) this.regionlist.get(var6)).getJ(); 905 | showPoint = true; 906 | this.invalidate(); 907 | break; 908 | } 909 | } 910 | 911 | Iterator var7 = this.seriesRegionList.iterator(); 912 | 913 | while (var7.hasNext()) { 914 | LineChartView.MRegion var8 = (LineChartView.MRegion) var7.next(); 915 | if (var8.contains((int) this.x_down, (int) this.y_down)) { 916 | var8.setShow(!var8.isShow()); 917 | this.invalidate(); 918 | break; 919 | } 920 | } 921 | 922 | //点击跳转至大屏幕的 923 | if (this.canFullScreen && this.dst_fullScreen.contains((int) event.getX(), (int) event.getY())) { 924 | // Bundle var9 = new Bundle(); 925 | // var9.putSerializable("datas", (ArrayList) this.datas); 926 | // var9.putStringArrayList("xnames", (ArrayList) this.xnames); 927 | // var9.putStringArray("series", this.series); 928 | // var9.putFloat("maxvalue", this.maxvalue); 929 | // var9.putFloat("minvalue", this.minvalue); 930 | // var9.putString("x_unit", this.x_unit); 931 | // var9.putString("chartType", "曲线图"); 932 | // Intent var10 = new Intent(this.getContext(), MainActivity.class); 933 | // var10.putExtras(var9); 934 | // this.getContext().startActivity(var10); 935 | } 936 | break; 937 | case 1: 938 | case 6: 939 | this.mode = 0; 940 | break; 941 | case 2: 942 | if (this.mode == 2) { 943 | this.matrix1.set(this.savedMatrix); 944 | float rotation = this.rotation(event) - this.oldRotation; 945 | float newDist = this.spacing(event); 946 | float var10000 = newDist / this.oldDist; 947 | if (!this.matrixCheck()) { 948 | this.matrix.set(this.matrix1); 949 | this.invalidate(); 950 | } 951 | } else if (this.mode == 1 && this.canDrag) { 952 | this.matrix1.set(this.savedMatrix); 953 | this.matrix1.postTranslate(event.getX() - this.x_down, event.getY() - this.y_down); 954 | if (!this.matrixCheck()) { 955 | this.matrix.set(this.matrix1); 956 | this.invalidate(); 957 | } 958 | } 959 | case 3: 960 | case 4: 961 | default: 962 | break; 963 | case 5: 964 | this.mode = 2; 965 | this.oldDist = this.spacing(event); 966 | this.oldRotation = this.rotation(event); 967 | this.savedMatrix.set(this.matrix); 968 | this.midPoint(this.mid, event); 969 | } 970 | } 971 | return true; 972 | } 973 | 974 | private boolean matrixCheck() { 975 | float[] f = new float[9]; 976 | this.matrix1.getValues(f); 977 | float x1 = f[0] * 0.0F + f[1] * 0.0F + f[2]; 978 | float y1 = f[3] * 0.0F + f[4] * 0.0F + f[5]; 979 | float x2 = f[0] * (float) this.width + f[1] * 0.0F + f[2]; 980 | float y2 = f[3] * (float) this.width + f[4] * 0.0F + f[5]; 981 | float x3 = f[0] * 0.0F + f[1] * (float) this.height + f[2]; 982 | float y3 = f[3] * 0.0F + f[4] * (float) this.height + f[5]; 983 | float x4 = f[0] * (float) this.width + f[1] * (float) this.height + f[2]; 984 | float y4 = f[3] * (float) this.width + f[4] * (float) this.height + f[5]; 985 | double width = Math.sqrt((double) ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))); 986 | this.dscale = (float) (width / (double) this.width); 987 | if (width >= width / 3.0D && width <= (double) (this.height * 3)) { 988 | float miny; 989 | if (this.intervalX * (float) this.xnames.size() + (float) DensityUtil.dip2px(this.getContext(), 20.0F) > (float) this.width) { 990 | miny = (float) this.width - this.intervalX * (float) this.xnames.size() - (float) DensityUtil.dip2px(this.getContext(), 20.0F); 991 | if (x1 > 0.0F) { 992 | x1 = 0.0F; 993 | } else if (x1 < miny) { 994 | x1 = miny; 995 | } 996 | } else { 997 | x1 = 0.0F; 998 | } 999 | 1000 | if (this.intervalY * (this.maxvalue - this.minvalue) > (float) this.height) { 1001 | miny = (float) this.height - (this.maxvalue - this.minvalue) * this.Y1ToScreen - (float) DensityUtil.dip2px(this.getContext(), 55.0F) - (float) (this.series != null ? this.series.length / 2 * DensityUtil.dip2px(this.getContext(), 10.0F) : 0); 1002 | if (y1 < miny) { 1003 | y1 = miny; 1004 | } else if (y1 > 0.0F) { 1005 | y1 = 0.0F; 1006 | } 1007 | } else { 1008 | y1 = this.dy; 1009 | } 1010 | 1011 | this.dx = x1; 1012 | this.dy = y1; 1013 | this.matrix1.setTranslate(x1, y1); 1014 | return false; 1015 | } else { 1016 | return true; 1017 | } 1018 | } 1019 | 1020 | private float spacing(MotionEvent event) { 1021 | float x = event.getX(0) - event.getX(1); 1022 | float y = event.getY(0) - event.getY(1); 1023 | return (float) Math.sqrt(x * x + y * y); 1024 | } 1025 | 1026 | private void midPoint(PointF point, MotionEvent event) { 1027 | float x = event.getX(0) + event.getX(1); 1028 | float y = event.getY(0) + event.getY(1); 1029 | point.set(x / 2.0F, y / 2.0F); 1030 | } 1031 | 1032 | private float rotation(MotionEvent event) { 1033 | double delta_x = (double) (event.getX(0) - event.getX(1)); 1034 | double delta_y = (double) (event.getY(0) - event.getY(1)); 1035 | double radians = Math.atan2(delta_y, delta_x); 1036 | return (float) Math.toDegrees(radians); 1037 | } 1038 | 1039 | public void setBezier(boolean isBezier) { 1040 | this.isBezier = isBezier; 1041 | this.invalidate(); 1042 | } 1043 | 1044 | public void setTextColor(int color) { 1045 | this.textpaint.setColor(color); 1046 | } 1047 | 1048 | public void setTextSize(float size) { 1049 | this.textpaint.setTextSize(size); 1050 | } 1051 | 1052 | public void setSericeTextColor(int color) { 1053 | this.sericeTextpaint.setColor(color); 1054 | } 1055 | 1056 | public void setSericeTextSize(int color) { 1057 | this.sericeTextpaint.setTextSize(color); 1058 | } 1059 | 1060 | public void setShowSeriesTip(boolean showSeriesTip) { 1061 | isShowSeriesTip = showSeriesTip; 1062 | } 1063 | 1064 | public void setCanDrag(boolean canDrag) { 1065 | this.canDrag = canDrag; 1066 | } 1067 | 1068 | public void setShowMaxMin(boolean showMaxMin) { 1069 | this.showMaxMin = showMaxMin; 1070 | } 1071 | 1072 | public void setAnimation(boolean animation) { 1073 | this.time = animation ? 1 : this.timeSum; 1074 | } 1075 | 1076 | public void setShowSeries(boolean isShowSeries) { 1077 | this.isShowSeries = isShowSeries; 1078 | } 1079 | 1080 | public void setDuration(int duration) { 1081 | this.duration = duration; 1082 | this.timeSum = duration / this.intervalTime; 1083 | } 1084 | 1085 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 1086 | this.pointslist.clear(); 1087 | super.onSizeChanged(w, h, oldw, oldh); 1088 | } 1089 | 1090 | public void setCanOnTouch(boolean canOnTouch) { 1091 | isCanOnTouch = canOnTouch; 1092 | } 1093 | 1094 | public void setShowX(boolean showX) { 1095 | isShowX = showX; 1096 | } 1097 | 1098 | public void setCanFullScreen(boolean canFullScreen) { 1099 | this.canFullScreen = canFullScreen; 1100 | } 1101 | 1102 | class TPoint extends PointF { 1103 | private float value; 1104 | private int index; 1105 | 1106 | TPoint() { 1107 | } 1108 | 1109 | public int getIndex() { 1110 | return this.index; 1111 | } 1112 | 1113 | public void setIndex(int index) { 1114 | this.index = index; 1115 | } 1116 | 1117 | public float getValue() { 1118 | return this.value; 1119 | } 1120 | 1121 | public void setValue(float value) { 1122 | this.value = value; 1123 | } 1124 | } 1125 | 1126 | class MRegion extends Region { 1127 | private float value; 1128 | private int i; 1129 | private int j; 1130 | private boolean isShow; 1131 | 1132 | MRegion() { 1133 | } 1134 | 1135 | public int getI() { 1136 | return this.i; 1137 | } 1138 | 1139 | public int getJ() { 1140 | return this.j; 1141 | } 1142 | 1143 | public void setIJ(int i, int j) { 1144 | this.i = i; 1145 | this.j = j; 1146 | } 1147 | 1148 | public float getValue() { 1149 | return this.value; 1150 | } 1151 | 1152 | public void setValue(float value) { 1153 | this.value = value; 1154 | } 1155 | 1156 | public boolean isShow() { 1157 | return this.isShow; 1158 | } 1159 | 1160 | public void setShow(boolean isShow) { 1161 | this.isShow = isShow; 1162 | } 1163 | } 1164 | 1165 | class MPoint { 1166 | float x; 1167 | float y; 1168 | float dx; 1169 | float dy; 1170 | 1171 | public MPoint(float x, float y) { 1172 | this.x = x; 1173 | this.y = y; 1174 | } 1175 | 1176 | public String toString() { 1177 | return "x:" + this.x + ", y:" + this.y + " dx:" + this.dx + " dy:" + this.dy; 1178 | } 1179 | } 1180 | } 1181 | -------------------------------------------------------------------------------- /lib_ui/src/main/java/www/thl/com/ui/RingView.java: -------------------------------------------------------------------------------- 1 | package www.thl.com.ui; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.RectF; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | 11 | import www.thl.com.ui.utils.DensityUtil; 12 | /** 13 | * 绘制圆环 14 | */ 15 | public class RingView extends View { 16 | 17 | //默认值 18 | public final static int DIRECTION_T = 0; //顺时针 19 | public final static int DIRECTION_F = 1; //逆时针 20 | 21 | private int ringWidth = 0; 22 | private int max = 100; 23 | private int progress = 0; 24 | private int bgColor = Color.parseColor("#4897fe"); 25 | private int progressColor = Color.parseColor("#9fc8ff"); 26 | private int startAngle = 270; //起始角度 27 | private int direction = DIRECTION_T; 28 | 29 | private Paint paint; 30 | private Paint whitePaint; 31 | private Paint progressPaint; 32 | 33 | public RingView(Context context) { 34 | this(context, null); 35 | init(context); 36 | } 37 | 38 | public RingView(Context context, AttributeSet attrs) { 39 | super(context, attrs); 40 | init(context); 41 | } 42 | 43 | private void init(Context context) { 44 | 45 | this.paint = new Paint(); 46 | this.paint.setAntiAlias(true); 47 | this.paint.setStyle(Paint.Style.STROKE); 48 | this.paint.setColor(Color.BLUE); 49 | 50 | this.whitePaint = new Paint(); 51 | this.whitePaint.setAntiAlias(true); 52 | this.whitePaint.setStyle(Paint.Style.FILL); 53 | this.whitePaint.setColor(Color.WHITE); 54 | 55 | this.progressPaint = new Paint(); 56 | this.progressPaint.setAntiAlias(true); 57 | this.progressPaint.setStyle(Paint.Style.FILL); 58 | this.progressPaint.setColor(Color.YELLOW); 59 | 60 | if (ringWidth == 0) { 61 | ringWidth = DensityUtil.dip2px(context, 15); 62 | } 63 | } 64 | 65 | @Override 66 | protected void onDraw(Canvas canvas) { 67 | int x = getMeasuredWidth() / 2; 68 | int y = getMeasuredWidth() / 2; 69 | 70 | //绘制背景圆环 71 | this.paint.setColor(bgColor); 72 | this.paint.setStrokeWidth(ringWidth); 73 | canvas.drawCircle(x, y, x - ringWidth / 2, this.paint); 74 | 75 | //绘制弧线 76 | this.progressPaint.setColor(progressColor); 77 | RectF oval = new RectF(); 78 | oval.left = 0; 79 | oval.top = 0; 80 | oval.right = 2 * x; 81 | oval.bottom = 2 * x; 82 | float numAngle = ((float) progress / (float) max) * 360; 83 | if (direction == DIRECTION_F) { 84 | numAngle = -numAngle; 85 | } 86 | canvas.drawArc(oval, startAngle, numAngle, true, progressPaint); //绘制圆弧 87 | 88 | //绘制白色实心背景圆环 89 | canvas.drawCircle(x, y, x - ringWidth, this.whitePaint); 90 | } 91 | 92 | public void setProgress(int progress) { 93 | this.progress = progress; 94 | invalidate(); 95 | } 96 | 97 | public int getMax() { 98 | return max; 99 | } 100 | 101 | public int getProgress() { 102 | return progress; 103 | } 104 | 105 | public void setRingWidth(int ringWidth) { 106 | this.ringWidth = ringWidth; 107 | } 108 | 109 | public void setMax(int max) { 110 | this.max = max; 111 | } 112 | 113 | public void setBgColor(int bgColor) { 114 | this.bgColor = bgColor; 115 | } 116 | 117 | public void setProgressColor(int progressColor) { 118 | this.progressColor = progressColor; 119 | } 120 | 121 | public void setStartAngle(int startAngle) { 122 | this.startAngle = startAngle; 123 | } 124 | } -------------------------------------------------------------------------------- /lib_ui/src/main/java/www/thl/com/ui/utils/DensityUtil.java: -------------------------------------------------------------------------------- 1 | package www.thl.com.ui.utils; 2 | 3 | import android.content.Context; 4 | 5 | 6 | public class DensityUtil { 7 | 8 | public static int dip2px(Context context, float dpValue) { 9 | float scale = context.getResources().getDisplayMetrics().density; 10 | return (int) (dpValue * scale + 0.5f); 11 | } 12 | 13 | public static int px2dip(Context context, float pxValue) { 14 | float scale = context.getResources().getDisplayMetrics().density; 15 | return (int) (pxValue / scale + 0.5f); 16 | } 17 | 18 | public static float dip2pxf(Context context, int dpValue) { 19 | float scale = context.getResources().getDisplayMetrics().density; 20 | return dpValue * scale + 0.5f; 21 | } 22 | 23 | public static float dip2pxf(Context context, float dpValue) { 24 | float scale = context.getResources().getDisplayMetrics().density; 25 | return dpValue * scale + 0.5f; 26 | } 27 | 28 | 29 | public static int px2sp(Context context, float pxValue) { 30 | float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 31 | return (int) (pxValue / fontScale + 0.5f); 32 | } 33 | 34 | 35 | public static int sp2px(Context context, float spValue) { 36 | float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 37 | return (int) (spValue * fontScale + 0.5f); 38 | } 39 | 40 | public static float sp2pxf(Context context, float spValue) { 41 | float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 42 | return spValue * fontScale + 0.5f; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib_ui/src/main/java/www/thl/com/ui/utils/ScreenUtils.java: -------------------------------------------------------------------------------- 1 | package www.thl.com.ui.utils; 2 | import android.content.Context; 3 | import android.graphics.Paint; 4 | import android.util.TypedValue; 5 | import android.widget.TextView; 6 | 7 | public class ScreenUtils { 8 | 9 | 10 | public static int gettextwidth(Context context, String str, int fontsize) { 11 | TextView tv = new TextView(context); 12 | tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontsize); 13 | Paint paint = new Paint(); 14 | paint = tv.getPaint(); 15 | return (int) paint.measureText(str); 16 | } 17 | 18 | public static float getTextHeight(float fontSize) { 19 | Paint paint = new Paint(); 20 | paint.setTextSize(fontSize); 21 | Paint.FontMetrics fm = paint.getFontMetrics(); 22 | return (float) Math.ceil(fm.descent - fm.ascent); 23 | } 24 | } -------------------------------------------------------------------------------- /lib_ui/src/main/res/drawable-hdpi/ic_func_myworker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supertaohaili/UI/a84cc71f6d73d3596771caf1638faac72b822091/lib_ui/src/main/res/drawable-hdpi/ic_func_myworker.png -------------------------------------------------------------------------------- /lib_ui/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #24abff 4 | #24abff 5 | #24abff 6 | 7 | #24abff 8 | #22c5eaf8 9 | 10 | -------------------------------------------------------------------------------- /lib_ui/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':lib_ui' 2 | --------------------------------------------------------------------------------