├── .gitignore ├── .idea └── .gitignore ├── IMG_4115.GIF ├── KLineChartLib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── fujianlian │ │ └── klinechart │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── fujianlian │ │ │ └── klinechart │ │ │ ├── BaseKLineChartAdapter.java │ │ │ ├── BaseKLineChartView.java │ │ │ ├── DataHelper.java │ │ │ ├── KLineChartAdapter.java │ │ │ ├── KLineChartView.java │ │ │ ├── KLineEntity.java │ │ │ ├── ScrollAndScaleView.java │ │ │ ├── base │ │ │ ├── IAdapter.java │ │ │ ├── IChartDraw.java │ │ │ ├── IDateTimeFormatter.java │ │ │ └── IValueFormatter.java │ │ │ ├── draw │ │ │ ├── KDJDraw.java │ │ │ ├── MACDDraw.java │ │ │ ├── MainDraw.java │ │ │ ├── RSIDraw.java │ │ │ ├── Status.java │ │ │ ├── VolumeDraw.java │ │ │ └── WRDraw.java │ │ │ ├── entity │ │ │ ├── ICandle.java │ │ │ ├── IKDJ.java │ │ │ ├── IKLine.java │ │ │ ├── IMACD.java │ │ │ ├── IRSI.java │ │ │ ├── IVolume.java │ │ │ ├── IWR.java │ │ │ └── OrderEntity.java │ │ │ ├── formatter │ │ │ ├── BigValueFormatter.java │ │ │ ├── DateFormatter.java │ │ │ ├── TimeFormatter.java │ │ │ └── ValueFormatter.java │ │ │ └── utils │ │ │ ├── Constants.java │ │ │ ├── DateUtil.java │ │ │ └── ViewUtil.java │ └── res │ │ ├── drawable │ │ ├── ic_down_order.png │ │ ├── ic_point_kline.png │ │ ├── ic_start_time.png │ │ ├── ic_stop_time.png │ │ ├── ic_target_normal.png │ │ ├── ic_target_pressed.png │ │ ├── ic_up.png │ │ ├── selector_button_target.xml │ │ └── shape_rectangle_with.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── github │ └── fujianlian │ └── klinechart │ └── ExampleUnitTest.java ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── ibm.json │ ├── java │ └── com │ │ └── vincent │ │ └── story │ │ ├── DataBean.java │ │ ├── DataRequest.java │ │ ├── MainActivity.java │ │ ├── adapter │ │ └── DateCycleAdapter.java │ │ └── app │ │ ├── ActivityStack.java │ │ └── MyApp.java │ └── res │ ├── layout │ ├── activity_main.xml │ └── item_tv_layout.xml │ ├── mipmap-xhdpi │ ├── ic_launcher_round.png │ ├── ic_no_image.png │ └── icon_temp_load.png │ ├── mipmap-xxxhdpi │ └── ic_launcher_round.png │ ├── values-sw1024dp │ └── dimens.xml │ ├── values-sw1280dp │ └── dimens.xml │ ├── values-sw1365dp │ └── dimens.xml │ ├── values-sw384dp │ └── dimens.xml │ ├── values-sw392dp │ └── dimens.xml │ ├── values-sw400dp │ └── dimens.xml │ ├── values-sw410dp │ └── dimens.xml │ ├── values-sw411dp │ └── dimens.xml │ ├── values-sw432dp │ └── dimens.xml │ ├── values-sw480dp │ └── dimens.xml │ ├── values-sw533dp │ └── dimens.xml │ ├── values-sw592dp │ └── dimens.xml │ ├── values-sw600dp │ └── dimens.xml │ ├── values-sw640dp │ └── dimens.xml │ ├── values-sw662dp │ └── dimens.xml │ ├── values-sw720dp │ └── dimens.xml │ ├── values-sw768dp │ └── dimens.xml │ ├── values-sw800dp │ └── dimens.xml │ ├── values-sw811dp │ └── dimens.xml │ ├── values-sw820dp │ └── dimens.xml │ ├── values-sw960dp │ └── dimens.xml │ ├── values-sw961dp │ └── dimens.xml │ ├── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ ├── filepaths.xml │ └── network_security_config.xml ├── build.gradle ├── config.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img1.jpg ├── img2.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | *.aab 5 | 6 | # Files for the ART/Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | out/ 16 | 17 | # Gradle files 18 | .gradle/ 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # IntelliJ 37 | *.iml 38 | .idea/workspace.xml 39 | .idea/tasks.xml 40 | .idea/gradle.xml 41 | .idea/assetWizardSettings.xml 42 | .idea/dictionaries 43 | .idea/libraries 44 | .idea/caches 45 | 46 | # Keystore files 47 | # Uncomment the following lines if you do not want to check your keystore files in. 48 | #*.jks 49 | #*.keystore 50 | 51 | # External native build folder generated in Android Studio 2.2 and later 52 | .externalNativeBuild 53 | 54 | # Google Services (e.g. APIs or Firebase) 55 | # google-services.json 56 | 57 | # Freeline 58 | freeline.py 59 | freeline/ 60 | freeline_project_description.json 61 | 62 | # fastlane 63 | fastlane/report.xml 64 | fastlane/Preview.html 65 | fastlane/screenshots 66 | fastlane/test_output 67 | fastlane/readme.md 68 | 69 | # Version control 70 | vcs.xml 71 | 72 | # lint 73 | lint/intermediates/ 74 | lint/generated/ 75 | lint/outputs/ 76 | lint/tmp/ 77 | # lint/reports/ 78 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /IMG_4115.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/IMG_4115.GIF -------------------------------------------------------------------------------- /KLineChartLib/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /KLineChartLib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 27 5 | 6 | defaultConfig { 7 | minSdkVersion 16 8 | targetSdkVersion 27 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | 28 | implementation 'com.android.support:appcompat-v7:27.1.1' 29 | testImplementation 'junit:junit:4.12' 30 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 31 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 32 | 33 | } 34 | -------------------------------------------------------------------------------- /KLineChartLib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /KLineChartLib/src/androidTest/java/com/github/fujianlian/klinechart/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.github.fujianlian.klinechart.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/BaseKLineChartAdapter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | import android.database.DataSetObservable; 4 | import android.database.DataSetObserver; 5 | 6 | import com.github.fujianlian.klinechart.base.IAdapter; 7 | 8 | /** 9 | * k线图的数据适配器 10 | * Created by tifezh on 2016/6/9. 11 | */ 12 | 13 | public abstract class BaseKLineChartAdapter implements IAdapter { 14 | 15 | private final DataSetObservable mDataSetObservable = new DataSetObservable(); 16 | 17 | @Override 18 | public void notifyDataSetChanged() { 19 | if (getCount() > 0) { 20 | mDataSetObservable.notifyChanged(); 21 | } else { 22 | mDataSetObservable.notifyInvalidated(); 23 | } 24 | } 25 | 26 | 27 | @Override 28 | public void registerDataSetObserver(DataSetObserver observer) { 29 | mDataSetObservable.registerObserver(observer); 30 | } 31 | 32 | @Override 33 | public void unregisterDataSetObserver(DataSetObserver observer) { 34 | mDataSetObservable.unregisterObserver(observer); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/DataHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | 4 | import android.util.Log; 5 | 6 | import com.github.fujianlian.klinechart.utils.Constants; 7 | import com.github.fujianlian.klinechart.utils.DateUtil; 8 | 9 | import java.util.List; 10 | 11 | 12 | 13 | import static com.github.fujianlian.klinechart.utils.Constants.RANG_ITEM; 14 | 15 | /** 16 | * 数据辅助类 计算macd rsi等 17 | * Created by tifezh on 2016/11/26. 18 | */ 19 | public class DataHelper { 20 | 21 | /** 22 | * 计算RSI 23 | * 24 | * @param dataList 25 | */ 26 | static void calculateRSI(List dataList) { 27 | Float rsi; 28 | float rsiABSEma = 0; 29 | float rsiMaxEma = 0; 30 | for (int i = 0; i < dataList.size(); i++) { 31 | KLineEntity point = dataList.get(i); 32 | final float closePrice = point.getClosePrice(); 33 | if (i == 0) { 34 | rsi = 0f; 35 | rsiABSEma = 0; 36 | rsiMaxEma = 0; 37 | } else { 38 | float Rmax = Math.max(0, closePrice - dataList.get(i - 1).getClosePrice()); 39 | float RAbs = Math.abs(closePrice - dataList.get(i - 1).getClosePrice()); 40 | 41 | rsiMaxEma = (Rmax + (14f - 1) * rsiMaxEma) / 14f; 42 | rsiABSEma = (RAbs + (14f - 1) * rsiABSEma) / 14f; 43 | rsi = (rsiMaxEma / rsiABSEma) * 100; 44 | } 45 | if (i < 13) { 46 | rsi = 0f; 47 | } 48 | if (rsi.isNaN()) 49 | rsi = 0f; 50 | point.rsi = rsi; 51 | } 52 | } 53 | 54 | /** 55 | * 计算kdj 56 | * 57 | * @param dataList 58 | */ 59 | static void calculateKDJ(List dataList) { 60 | float k = 0; 61 | float d = 0; 62 | for (int i = 0; i < dataList.size(); i++) { 63 | KLineEntity point = dataList.get(i); 64 | final float closePrice = point.getClosePrice(); 65 | int startIndex = i - 13; 66 | if (startIndex < 0) { 67 | startIndex = 0; 68 | } 69 | float max14 = Float.MIN_VALUE; 70 | float min14 = Float.MAX_VALUE; 71 | for (int index = startIndex; index <= i; index++) { 72 | if (dataList.get(index) == null) 73 | return; 74 | max14 = Math.max(max14, dataList.get(index).getHighPrice()); 75 | min14 = Math.min(min14, dataList.get(index).getLowPrice()); 76 | } 77 | Float rsv = 100f * (closePrice - min14) / (max14 - min14); 78 | if (rsv.isNaN()) { 79 | rsv = 0f; 80 | } 81 | if (i == 0) { 82 | k = 50; 83 | d = 50; 84 | } else { 85 | k = (rsv + 2f * k) / 3f; 86 | d = (k + 2f * d) / 3f; 87 | } 88 | if (i < 13) { 89 | point.k = 0; 90 | point.d = 0; 91 | point.j = 0; 92 | } else if (i == 13 || i == 14) { 93 | point.k = k; 94 | point.d = 0; 95 | point.j = 0; 96 | } else { 97 | point.k = k; 98 | point.d = d; 99 | point.j = 3f * k - 2 * d; 100 | } 101 | } 102 | 103 | } 104 | 105 | /** 106 | * 计算wr 107 | * 108 | * @param dataList 109 | */ 110 | static void calculateWR(List dataList) { 111 | Float r; 112 | for (int i = 0; i < dataList.size(); i++) { 113 | KLineEntity point = dataList.get(i); 114 | int startIndex = i - 14; 115 | if (startIndex < 0) { 116 | startIndex = 0; 117 | } 118 | float max14 = Float.MIN_VALUE; 119 | float min14 = Float.MAX_VALUE; 120 | for (int index = startIndex; index <= i; index++) { 121 | 122 | max14 = Math.max(max14, dataList.get(index).getHighPrice()); 123 | min14 = Math.min(min14, dataList.get(index).getLowPrice()); 124 | } 125 | if (i < 13) { 126 | point.r = -10; 127 | } else { 128 | r = -100 * (max14 - dataList.get(i).getClosePrice()) / (max14 - min14); 129 | if (r.isNaN()) { 130 | point.r = 0; 131 | } else { 132 | point.r = r; 133 | } 134 | } 135 | } 136 | 137 | } 138 | 139 | /** 140 | * 计算macd 141 | * 142 | * @param dataList 143 | */ 144 | static void calculateMACD(List dataList) { 145 | float ema12 = 0; 146 | float ema26 = 0; 147 | float dif = 0; 148 | float dea = 0; 149 | float macd = 0; 150 | 151 | for (int i = 0; i < dataList.size(); i++) { 152 | KLineEntity point = dataList.get(i); 153 | final float closePrice = point.getClosePrice(); 154 | if (i == 0) { 155 | ema12 = closePrice; 156 | ema26 = closePrice; 157 | } else { 158 | // EMA(12) = 前一日EMA(12) X 11/13 + 今日收盘价 X 2/13 159 | ema12 = ema12 * 11f / 13f + closePrice * 2f / 13f; 160 | // EMA(26) = 前一日EMA(26) X 25/27 + 今日收盘价 X 2/27 161 | ema26 = ema26 * 25f / 27f + closePrice * 2f / 27f; 162 | } 163 | // DIF = EMA(12) - EMA(26) 。 164 | // 今日DEA = (前一日DEA X 8/10 + 今日DIF X 2/10) 165 | // 用(DIF-DEA)*2即为MACD柱状图。 166 | dif = ema12 - ema26; 167 | dea = dea * 8f / 10f + dif * 2f / 10f; 168 | macd = (dif - dea) * 2f; 169 | point.dif = dif; 170 | point.dea = dea; 171 | point.macd = macd; 172 | } 173 | 174 | } 175 | 176 | /** 177 | * 计算 BOLL 需要在计算ma之后进行 178 | * 179 | * @param dataList 180 | */ 181 | static void calculateBOLL(List dataList) { 182 | for (int i = 0; i < dataList.size(); i++) { 183 | KLineEntity point = dataList.get(i); 184 | if (i < 19) { 185 | point.mb = 0; 186 | point.up = 0; 187 | point.dn = 0; 188 | } else { 189 | int n = 20; 190 | float md = 0; 191 | for (int j = i - n + 1; j <= i; j++) { 192 | float c = dataList.get(j).getClosePrice(); 193 | float m = point.getMA20Price(); 194 | float value = c - m; 195 | md += value * value; 196 | } 197 | md = md / (n - 1); 198 | md = (float) Math.sqrt(md); 199 | point.mb = point.getMA20Price(); 200 | point.up = point.mb + 2f * md; 201 | point.dn = point.mb - 2f * md; 202 | } 203 | } 204 | 205 | } 206 | 207 | /** 208 | * @param dataList 209 | */ 210 | static void calculateSAR(List dataList) { 211 | 212 | //SAR指标py代码 213 | //def psar(barsdata, iaf = 0.02, maxaf = 0.2): 214 | //    length = len(barsdata) 215 | //    dates = list(barsdata['Date']) 216 | //    high = list(barsdata['High']) 217 | //    low = list(barsdata['Low']) 218 | //    close = list(barsdata['Close']) 219 | //    psar = close[0:len(close)] 220 | //    psarbull = [None] * length 221 | //    psarbear = [None] * length 222 | //    bull = True 223 | //    af = iaf 224 | //    ep = low[0] 225 | //    hp = high[0] 226 | //    lp = low[0] 227 | //     228 | //    for i in range(2,length): 229 | //        if bull: 230 | //            psar[i] = psar[i - 1] + af * (hp - psar[i - 1]) 231 | //        else: 232 | //            psar[i] = psar[i - 1] + af * (lp - psar[i - 1]) 233 | //         234 | //        reverse = False 235 | //         236 | //        if bull: 237 | //            if low[i] < psar[i]: 238 | //                bull = False 239 | //                reverse = True 240 | //                psar[i] = hp 241 | //                lp = low[i] 242 | //                af = iaf 243 | //        else: 244 | //            if high[i] > psar[i]: 245 | //                bull = True 246 | //                reverse = True 247 | //                psar[i] = lp 248 | //                hp = high[i] 249 | //                af = iaf 250 | //     251 | //        if not reverse: 252 | //            if bull: 253 | //                if high[i] > hp: 254 | //                    hp = high[i] 255 | //                    af = min(af + iaf, maxaf) 256 | //                if low[i - 1] < psar[i]: 257 | //                    psar[i] = low[i - 1] 258 | //                if low[i - 2] < psar[i]: 259 | //                    psar[i] = low[i - 2] 260 | //            else: 261 | //                if low[i] < lp: 262 | //                    lp = low[i] 263 | //                    af = min(af + iaf, maxaf) 264 | //                if high[i - 1] > psar[i]: 265 | //                    psar[i] = high[i - 1] 266 | //                if high[i - 2] > psar[i]: 267 | //                    psar[i] = high[i - 2] 268 | //                     269 | //        if bull: 270 | //            psarbull[i] = psar[i] 271 | //        else: 272 | //            psarbear[i] = psar[i] 273 | //  274 | //    return {"dates":dates, "high":high, "low":low, "close":close, "psar":psar, "psarbear":psarbear, "psarbull":psarbull} 275 | // 276 | //这段代码有点问题 需要修改下才能使用 277 | 278 | for (int i = 0; i < dataList.size(); i++) { 279 | KLineEntity point = dataList.get(i); 280 | 281 | } 282 | 283 | } 284 | 285 | /** 286 | * 计算ma 287 | * 288 | * @param dataList 289 | */ 290 | static void calculateMA(List dataList) { 291 | float ma5 = 0; 292 | float ma10 = 0; 293 | float ma20 = 0; 294 | float ma30 = 0; 295 | float ma60 = 0; 296 | 297 | for (int i = 0; i < dataList.size(); i++) { 298 | KLineEntity point = dataList.get(i); 299 | final float closePrice = point.getClosePrice(); 300 | 301 | ma5 += closePrice; 302 | ma10 += closePrice; 303 | ma20 += closePrice; 304 | ma30 += closePrice; 305 | ma60 += closePrice; 306 | if (i == 4) { 307 | point.MA5Price = ma5 / 5f; 308 | } else if (i >= 5) { 309 | ma5 -= dataList.get(i - 5).getClosePrice(); 310 | point.MA5Price = ma5 / 5f; 311 | } else { 312 | point.MA5Price = 0f; 313 | } 314 | if (i == 9) { 315 | point.MA10Price = ma10 / 10f; 316 | } else if (i >= 10) { 317 | ma10 -= dataList.get(i - 10).getClosePrice(); 318 | point.MA10Price = ma10 / 10f; 319 | } else { 320 | point.MA10Price = 0f; 321 | } 322 | if (i == 19) { 323 | point.MA20Price = ma20 / 20f; 324 | } else if (i >= 20) { 325 | ma20 -= dataList.get(i - 20).getClosePrice(); 326 | point.MA20Price = ma20 / 20f; 327 | } else { 328 | point.MA20Price = 0f; 329 | } 330 | if (i == 29) { 331 | point.MA30Price = ma30 / 30f; 332 | } else if (i >= 30) { 333 | ma30 -= dataList.get(i - 30).getClosePrice(); 334 | point.MA30Price = ma30 / 30f; 335 | } else { 336 | point.MA30Price = 0f; 337 | } 338 | if (i == 59) { 339 | point.MA60Price = ma60 / 60f; 340 | } else if (i >= 60) { 341 | ma60 -= dataList.get(i - 60).getClosePrice(); 342 | point.MA60Price = ma60 / 60f; 343 | } else { 344 | point.MA60Price = 0f; 345 | } 346 | } 347 | } 348 | 349 | /** 350 | * 计算MA BOLL RSI KDJ MACD 351 | * 352 | * @param dataList 353 | */ 354 | public static void calculate(List dataList) { 355 | calculateMA(dataList); 356 | // calculateSAR(dataList); 357 | calculateMACD(dataList); 358 | calculateBOLL(dataList); 359 | calculateRSI(dataList); 360 | calculateKDJ(dataList); 361 | calculateWR(dataList); 362 | calculateVolumeMA(dataList); 363 | } 364 | 365 | private static String[] periods = new String[]{Constants.ONE_MINUTE, Constants.FIVE_MINUTE, Constants.FIFTEEN_MINUTE, 366 | Constants.THIRTY_MINUTE, Constants.SIXTY_MINUTE, Constants.ONE_DAY, Constants.ONE_WEEK, Constants.ONE_MON}; 367 | 368 | private static String[] optionPeriods = new String[]{Constants.FIVE_SECOND}; 369 | 370 | public static String[] getPeriods(String currentType) { 371 | if (currentType.equals("2")) { 372 | return periods; 373 | } else { 374 | return optionPeriods; 375 | } 376 | } 377 | 378 | /** 379 | * 计算最后二十条数据时间 380 | * 381 | * @param entries 382 | */ 383 | public static void calculateEndData(List entries, int choosePosition, String currentType, float openPirce) { 384 | // DateUtil.DatePattern datePattern; 385 | if (entries.size() == 0) 386 | return; 387 | String time = entries.get(entries.size() - (Constants.RANG_ITEM + 1)).getTimestamp();//时间戳 388 | for (int i = entries.size() - (Constants.RANG_ITEM + 1); i < entries.size(); i++) { 389 | Long newTime = Long.valueOf(time) + DataHelper.getT(getPeriods(currentType)[choosePosition]) * (i - (entries.size() - (Constants.RANG_ITEM + 1))); 390 | entries.get(i).setDate(DateUtil.getStrTime(newTime + "", getDatePattern(getPeriods(currentType)[choosePosition]))); 391 | entries.get(i).setTimestamp(newTime + ""); 392 | entries.get(i).setOpen(openPirce); 393 | } 394 | } 395 | 396 | 397 | public static DateUtil.DatePattern getDatePattern(String time) { 398 | 399 | DateUtil.DatePattern datePattern = DateUtil.DatePattern.ONLY_HOUR_MINUTE; 400 | switch (time) { 401 | case Constants.FIVE_SECOND: 402 | datePattern = DateUtil.DatePattern.ONLY_TIME; 403 | break; 404 | case Constants.ONE_MINUTE: 405 | case Constants.FIVE_MINUTE: 406 | case Constants.FIFTEEN_MINUTE: 407 | case Constants.THIRTY_MINUTE: 408 | datePattern = DateUtil.DatePattern.ONLY_HOUR_MINUTE; 409 | break; 410 | case Constants.SIXTY_MINUTE: 411 | case Constants.ONE_DAY: 412 | case Constants.ONE_WEEK: 413 | datePattern = DateUtil.DatePattern.ONLY_MONTH_SEC; 414 | break; 415 | case Constants.ONE_MON: 416 | datePattern = DateUtil.DatePattern.ONLY_DAY; 417 | break; 418 | } 419 | 420 | return datePattern; 421 | } 422 | 423 | public static Long getT(String time) { 424 | long t = 0; 425 | switch (time) { 426 | case Constants.FIVE_SECOND: 427 | t = 1000 * 5; 428 | break; 429 | case Constants.ONE_MINUTE: 430 | t = 1000 * 60; 431 | break; 432 | case Constants.FIVE_MINUTE: 433 | t = 1000 * 60 * 5; 434 | break; 435 | case Constants.FIFTEEN_MINUTE: 436 | t = 1000 * 60 * 15; 437 | break; 438 | case Constants.THIRTY_MINUTE: 439 | t = 1000 * 60 * 30; 440 | break; 441 | case Constants.SIXTY_MINUTE: 442 | t = 1000 * 60 * 60; 443 | break; 444 | case Constants.ONE_DAY: 445 | t = 1000 * 60 * 60 * 24; 446 | break; 447 | case Constants.ONE_WEEK: 448 | t = 1000 * 60 * 60 * 24 * 7; 449 | break; 450 | case Constants.ONE_MON: 451 | t = 1000 * 60 * 60 * 24 * 30; 452 | break; 453 | } 454 | 455 | return t; 456 | } 457 | 458 | private static void calculateVolumeMA(List entries) { 459 | float volumeMa5 = 0; 460 | float volumeMa10 = 0; 461 | 462 | for (int i = 0; i < entries.size(); i++) { 463 | KLineEntity entry = entries.get(i); 464 | volumeMa5 += entry.getVolume(); 465 | volumeMa10 += entry.getVolume(); 466 | 467 | if (i == 4) { 468 | entry.MA5Volume = (volumeMa5 / 5f); 469 | } else if (i > 4) { 470 | volumeMa5 -= entries.get(i - 5).getVolume(); 471 | entry.MA5Volume = volumeMa5 / 5f; 472 | } else { 473 | entry.MA5Volume = 0f; 474 | } 475 | 476 | if (i == 9) { 477 | entry.MA10Volume = volumeMa10 / 10f; 478 | } else if (i > 9) { 479 | volumeMa10 -= entries.get(i - 10).getVolume(); 480 | entry.MA10Volume = volumeMa10 / 10f; 481 | } else { 482 | entry.MA10Volume = 0f; 483 | } 484 | } 485 | } 486 | } 487 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/KLineChartAdapter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import static com.github.fujianlian.klinechart.utils.Constants.RANG_ITEM; 7 | 8 | /** 9 | * 数据适配器 10 | * Created by tifezh on 2016/6/18. 11 | */ 12 | public class KLineChartAdapter extends BaseKLineChartAdapter { 13 | 14 | private List datas = new ArrayList<>(); 15 | // private List dates = new ArrayList<>(); 16 | 17 | 18 | public KLineChartAdapter() { 19 | 20 | } 21 | 22 | @Override 23 | public int getCount() { 24 | return datas.size(); 25 | } 26 | 27 | @Override 28 | public Object getItem(int position) { 29 | if (position < datas.size()) 30 | return datas.get(position); 31 | else return datas.get(datas.size() - 1); 32 | } 33 | 34 | 35 | public List getDatas() { 36 | return datas; 37 | } 38 | 39 | @Override 40 | public String getDate(int position) { 41 | if (position < datas.size()) 42 | return datas.get(position).Date; 43 | else return datas.get(datas.size() - 1).Date; 44 | 45 | 46 | } 47 | 48 | @Override 49 | public String getTimeStamp(int position) { 50 | if (position < datas.size()) 51 | return datas.get(position).timestamp; 52 | else return datas.get(datas.size() - 1).timestamp; 53 | } 54 | 55 | 56 | /** 57 | * 向头部添加数据 58 | */ 59 | public void addHeaderData(List data) { 60 | if (data != null && !data.isEmpty()) { 61 | datas.clear(); 62 | datas.addAll(data); 63 | } 64 | } 65 | 66 | /** 67 | * 向尾部添加数据 68 | */ 69 | public void addFooterData(List data) { 70 | if (data != null && !data.isEmpty()) { 71 | datas.clear(); 72 | datas.addAll(data); 73 | } 74 | } 75 | 76 | 77 | // public void addDates(List dates) { 78 | // if (dates != null && !dates.isEmpty()) { 79 | // this.dates.clear(); 80 | // this.dates.addAll(dates); 81 | // } 82 | // } 83 | 84 | public void addData(KLineEntity entity, int choosePosition, String type) { 85 | if (datas.size() < RANG_ITEM) 86 | return; 87 | datas.add(datas.size() - RANG_ITEM, entity); 88 | // DataHelper.calculateEndData(datas, choosePosition, type, entity.getOpenPrice()); 89 | DataHelper.calculate(datas); 90 | 91 | } 92 | 93 | public void replaceData(KLineEntity entity, int choosePosition, String type) { 94 | if (datas.size() > 0) { 95 | datas.set(datas.size() - RANG_ITEM-1, entity); 96 | } 97 | // DataHelper.calculateEndData(datas, choosePosition, type, entity.getOpenPrice()); 98 | DataHelper.calculate(datas); 99 | } 100 | 101 | 102 | public KLineEntity getData() { 103 | 104 | if (datas.size() > 0) 105 | return datas.get(0); 106 | else return new KLineEntity(); 107 | } 108 | 109 | /** 110 | * 改变某个点的值 111 | * 112 | * @param position 索引值 113 | */ 114 | public void changeItem(int position, KLineEntity data) { 115 | datas.set(position, data); 116 | notifyDataSetChanged(); 117 | } 118 | 119 | /** 120 | * 数据清除 121 | */ 122 | public void clearData() { 123 | datas.clear(); 124 | notifyDataSetChanged(); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/KLineChartView.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Color; 6 | import android.support.annotation.ColorRes; 7 | import android.support.annotation.DimenRes; 8 | import android.support.v4.content.ContextCompat; 9 | import android.util.AttributeSet; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | import android.widget.ProgressBar; 13 | 14 | import com.github.fujianlian.klinechart.draw.KDJDraw; 15 | import com.github.fujianlian.klinechart.draw.MACDDraw; 16 | import com.github.fujianlian.klinechart.draw.MainDraw; 17 | import com.github.fujianlian.klinechart.draw.RSIDraw; 18 | import com.github.fujianlian.klinechart.draw.VolumeDraw; 19 | import com.github.fujianlian.klinechart.draw.WRDraw; 20 | 21 | /** 22 | * k线图 23 | * Created by tian on 2016/5/20. 24 | */ 25 | public class KLineChartView extends BaseKLineChartView { 26 | 27 | ProgressBar mProgressBar; 28 | private boolean isRefreshing = false; 29 | private boolean isLoadMoreEnd = false; 30 | private boolean mLastScrollEnable; 31 | private boolean mLastScaleEnable; 32 | 33 | private KChartRefreshListener mRefreshListener; 34 | 35 | private MACDDraw mMACDDraw; 36 | private RSIDraw mRSIDraw; 37 | private MainDraw mMainDraw; 38 | private KDJDraw mKDJDraw; 39 | private WRDraw mWRDraw; 40 | private VolumeDraw mVolumeDraw; 41 | 42 | 43 | public KLineChartView(Context context) { 44 | this(context, null); 45 | } 46 | 47 | public KLineChartView(Context context, AttributeSet attrs) { 48 | this(context, attrs, 0); 49 | } 50 | 51 | public KLineChartView(Context context, AttributeSet attrs, int defStyleAttr) { 52 | super(context, attrs, defStyleAttr); 53 | initView(); 54 | initAttrs(attrs); 55 | } 56 | 57 | private void initView() { 58 | mProgressBar = new ProgressBar(getContext()); 59 | LayoutParams layoutParams = new LayoutParams(dp2px(50), dp2px(50)); 60 | layoutParams.addRule(CENTER_IN_PARENT); 61 | addView(mProgressBar, layoutParams); 62 | mProgressBar.setVisibility(GONE); 63 | mVolumeDraw = new VolumeDraw(this); 64 | mMACDDraw = new MACDDraw(this); 65 | mWRDraw = new WRDraw(this); 66 | mKDJDraw = new KDJDraw(this); 67 | mRSIDraw = new RSIDraw(this); 68 | mMainDraw = new MainDraw(this); 69 | addChildDraw(mMACDDraw); 70 | addChildDraw(mKDJDraw); 71 | addChildDraw(mRSIDraw); 72 | // addChildDraw(mVolumeDraw); 73 | // addChildDraw(mRSIDraw); 74 | addVolDraw(mVolumeDraw); 75 | // addChildDraw(mKDJDraw); 76 | // setVolDraw(mVolumeDraw); 77 | // addChildDraw(mVolumeDraw); 78 | setMainDraw(mMainDraw); 79 | } 80 | 81 | private void initAttrs(AttributeSet attrs) { 82 | TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.KLineChartView); 83 | if (array != null) { 84 | try { 85 | //public 86 | setPointWidth(array.getDimension(R.styleable.KLineChartView_kc_point_width, getDimension(R.dimen.chart_point_width))); 87 | setTextSize(array.getDimension(R.styleable.KLineChartView_kc_text_size, getDimension(R.dimen.chart_text_size))); 88 | setTextColor(array.getColor(R.styleable.KLineChartView_kc_text_color, getColor(R.color.chart_white))); 89 | setMTextSize(array.getDimension(R.styleable.KLineChartView_kc_text_size, getDimension(R.dimen.chart_text_size))); 90 | setMTextColor(array.getColor(R.styleable.KLineChartView_kc_text_color, getColor(R.color.chart_white))); 91 | setLineWidth(array.getDimension(R.styleable.KLineChartView_kc_line_width, getDimension(R.dimen.chart_line_width))); 92 | setBackgroundColor(array.getColor(R.styleable.KLineChartView_kc_background_color, getColor(R.color.chart_bac))); 93 | setSelectPointColor(array.getColor(R.styleable.KLineChartView_kc_background_color, getColor(R.color.chart_point_bac))); 94 | 95 | setSelectedXLineColor(getColor(R.color.chart_line_color)); 96 | setSelectedXLineWidth(getDimension(R.dimen.chart_line_width)); 97 | 98 | setSelectedYLineColor(Color.parseColor("#8040424D")); 99 | setSelectedYLineWidth(getDimension(R.dimen.chart_point_width)); 100 | 101 | setGridLineWidth(array.getDimension(R.styleable.KLineChartView_kc_grid_line_width, getDimension(R.dimen.chart_grid_line_width))); 102 | setGridLineColor(array.getColor(R.styleable.KLineChartView_kc_grid_line_color, getColor(R.color.chart_grid_line))); 103 | // setGridLineColor(getColor(R.color.chart_ma5)); 104 | //macd 105 | setMACDWidth(array.getDimension(R.styleable.KLineChartView_kc_macd_width, getDimension(R.dimen.chart_candle_width))); 106 | setDIFColor(array.getColor(R.styleable.KLineChartView_kc_dif_color, getColor(R.color.chart_ma5))); 107 | setDEAColor(array.getColor(R.styleable.KLineChartView_kc_dea_color, getColor(R.color.chart_ma10))); 108 | setMACDColor(array.getColor(R.styleable.KLineChartView_kc_macd_color, getColor(R.color.chart_ma30))); 109 | //kdj 110 | setKColor(array.getColor(R.styleable.KLineChartView_kc_dif_color, getColor(R.color.chart_ma5))); 111 | setDColor(array.getColor(R.styleable.KLineChartView_kc_dea_color, getColor(R.color.chart_ma10))); 112 | setJColor(array.getColor(R.styleable.KLineChartView_kc_macd_color, getColor(R.color.chart_ma30))); 113 | //wr 114 | setRColor(array.getColor(R.styleable.KLineChartView_kc_dif_color, getColor(R.color.chart_ma5))); 115 | //rsi 116 | setRSI1Color(array.getColor(R.styleable.KLineChartView_kc_dif_color, getColor(R.color.chart_ma5))); 117 | setRSI2Color(array.getColor(R.styleable.KLineChartView_kc_dea_color, getColor(R.color.chart_ma10))); 118 | setRSI3Color(array.getColor(R.styleable.KLineChartView_kc_macd_color, getColor(R.color.chart_ma30))); 119 | //main 120 | setMa5Color(array.getColor(R.styleable.KLineChartView_kc_dif_color, getColor(R.color.chart_ma5))); 121 | setMa10Color(array.getColor(R.styleable.KLineChartView_kc_dea_color, getColor(R.color.chart_ma10))); 122 | setMa30Color(array.getColor(R.styleable.KLineChartView_kc_macd_color, getColor(R.color.chart_ma30))); 123 | setCandleWidth(array.getDimension(R.styleable.KLineChartView_kc_candle_width, getDimension(R.dimen.chart_candle_width))); 124 | setCandleLineWidth(array.getDimension(R.styleable.KLineChartView_kc_candle_line_width, getDimension(R.dimen.chart_candle_line_width))); 125 | setSelectorBackgroundColor(array.getColor(R.styleable.KLineChartView_kc_selector_background_color, getColor(R.color.chart_selector_new))); 126 | setSelectorTextSize(array.getDimension(R.styleable.KLineChartView_kc_selector_text_size, getDimension(R.dimen.chart_selector_text_size))); 127 | setCandleSolid(array.getBoolean(R.styleable.KLineChartView_kc_candle_solid, true)); 128 | } catch (Exception e) { 129 | e.printStackTrace(); 130 | } finally { 131 | array.recycle(); 132 | } 133 | } 134 | } 135 | 136 | private float getDimension(@DimenRes int resId) { 137 | return getResources().getDimension(resId); 138 | } 139 | 140 | private int getColor(@ColorRes int resId) { 141 | return ContextCompat.getColor(getContext(), resId); 142 | } 143 | 144 | @Override 145 | public void onLeftSide() { 146 | // showLoading(); 147 | } 148 | 149 | @Override 150 | public void onRightSide() { 151 | 152 | } 153 | 154 | public void showLoading() { 155 | if (!isLoadMoreEnd && !isRefreshing) { 156 | isRefreshing = true; 157 | if (mProgressBar != null) { 158 | mProgressBar.setVisibility(View.VISIBLE); 159 | } 160 | if (mRefreshListener != null) { 161 | mRefreshListener.onLoadMoreBegin(this); 162 | } 163 | mLastScaleEnable = isScaleEnable(); 164 | mLastScrollEnable = isScrollEnable(); 165 | super.setScrollEnable(false); 166 | super.setScaleEnable(false); 167 | } 168 | } 169 | 170 | public void justShowLoading() { 171 | if (!isRefreshing) { 172 | isLongPress = false; 173 | isRefreshing = true; 174 | if (mProgressBar != null) { 175 | mProgressBar.setVisibility(View.VISIBLE); 176 | } 177 | if (mRefreshListener != null) { 178 | mRefreshListener.onLoadMoreBegin(this); 179 | } 180 | mLastScaleEnable = isScaleEnable(); 181 | mLastScrollEnable = isScrollEnable(); 182 | super.setScrollEnable(false); 183 | super.setScaleEnable(false); 184 | } 185 | } 186 | 187 | private void hideLoading() { 188 | if (mProgressBar != null) { 189 | mProgressBar.setVisibility(View.GONE); 190 | } 191 | super.setScrollEnable(mLastScrollEnable); 192 | super.setScaleEnable(mLastScaleEnable); 193 | } 194 | 195 | /** 196 | * 隐藏选择器内容 197 | */ 198 | public void hideSelectData() { 199 | isLongPress = false; 200 | invalidate(); 201 | } 202 | 203 | /** 204 | * 刷新完成 205 | */ 206 | public void refreshComplete() { 207 | isRefreshing = false; 208 | hideLoading(); 209 | } 210 | 211 | /** 212 | * 刷新完成,没有数据 213 | */ 214 | public void refreshEnd() { 215 | isLoadMoreEnd = true; 216 | isRefreshing = false; 217 | hideLoading(); 218 | } 219 | 220 | /** 221 | * 重置加载更多 222 | */ 223 | public void resetLoadMoreEnd() { 224 | isLoadMoreEnd = false; 225 | } 226 | 227 | public void setLoadMoreEnd() { 228 | isLoadMoreEnd = true; 229 | } 230 | 231 | public interface KChartRefreshListener { 232 | /** 233 | * 加载更多 234 | * 235 | * @param chart 236 | */ 237 | void onLoadMoreBegin(KLineChartView chart); 238 | } 239 | 240 | @Override 241 | public void setScaleEnable(boolean scaleEnable) { 242 | if (isRefreshing) { 243 | throw new IllegalStateException("请勿在刷新状态设置属性"); 244 | } 245 | super.setScaleEnable(scaleEnable); 246 | 247 | } 248 | 249 | @Override 250 | public void setScrollEnable(boolean scrollEnable) { 251 | if (isRefreshing) { 252 | throw new IllegalStateException("请勿在刷新状态设置属性"); 253 | } 254 | super.setScrollEnable(scrollEnable); 255 | } 256 | 257 | /** 258 | * 设置DIF颜色 259 | */ 260 | public void setDIFColor(int color) { 261 | mMACDDraw.setDIFColor(color); 262 | } 263 | 264 | /** 265 | * 设置DEA颜色 266 | */ 267 | public void setDEAColor(int color) { 268 | mMACDDraw.setDEAColor(color); 269 | } 270 | 271 | /** 272 | * 设置MACD颜色 273 | */ 274 | public void setMACDColor(int color) { 275 | mMACDDraw.setMACDColor(color); 276 | } 277 | 278 | /** 279 | * 设置MACD的宽度 280 | * 281 | * @param MACDWidth 282 | */ 283 | public void setMACDWidth(float MACDWidth) { 284 | mMACDDraw.setMACDWidth(MACDWidth); 285 | } 286 | 287 | /** 288 | * 设置K颜色 289 | */ 290 | public void setKColor(int color) { 291 | mKDJDraw.setKColor(color); 292 | } 293 | 294 | /** 295 | * 设置D颜色 296 | */ 297 | public void setDColor(int color) { 298 | mKDJDraw.setDColor(color); 299 | } 300 | 301 | /** 302 | * 设置J颜色 303 | */ 304 | public void setJColor(int color) { 305 | mKDJDraw.setJColor(color); 306 | } 307 | 308 | /** 309 | * 设置R颜色 310 | */ 311 | public void setRColor(int color) { 312 | mWRDraw.setRColor(color); 313 | } 314 | 315 | /** 316 | * 设置ma5颜色 317 | * 318 | * @param color 319 | */ 320 | public void setMa5Color(int color) { 321 | mMainDraw.setMa5Color(color); 322 | mVolumeDraw.setMa5Color(color); 323 | } 324 | 325 | /** 326 | * 设置ma10颜色 327 | * 328 | * @param color 329 | */ 330 | public void setMa10Color(int color) { 331 | mMainDraw.setMa10Color(color); 332 | mVolumeDraw.setMa10Color(color); 333 | } 334 | 335 | /** 336 | * 设置ma20颜色 337 | * 338 | * @param color 339 | */ 340 | public void setMa30Color(int color) { 341 | mMainDraw.setMa30Color(color); 342 | } 343 | 344 | /** 345 | * 设置选择器文字大小 346 | * 347 | * @param textSize 348 | */ 349 | public void setSelectorTextSize(float textSize) { 350 | mMainDraw.setSelectorTextSize(textSize); 351 | } 352 | 353 | /** 354 | * 设置选择器背景 355 | * 356 | * @param color 357 | */ 358 | public void setSelectorBackgroundColor(int color) { 359 | mMainDraw.setSelectorBackgroundColor(color); 360 | } 361 | 362 | /** 363 | * 设置蜡烛宽度 364 | * 365 | * @param candleWidth 366 | */ 367 | public void setCandleWidth(float candleWidth) { 368 | mMainDraw.setCandleWidth(candleWidth); 369 | } 370 | 371 | /** 372 | * 设置蜡烛线宽度 373 | * 374 | * @param candleLineWidth 375 | */ 376 | public void setCandleLineWidth(float candleLineWidth) { 377 | mMainDraw.setCandleLineWidth(candleLineWidth); 378 | } 379 | 380 | /** 381 | * 蜡烛是否空心 382 | */ 383 | public void setCandleSolid(boolean candleSolid) { 384 | mMainDraw.setCandleSolid(candleSolid); 385 | } 386 | 387 | public void setRSI1Color(int color) { 388 | mRSIDraw.setRSI1Color(color); 389 | } 390 | 391 | public void setRSI2Color(int color) { 392 | mRSIDraw.setRSI2Color(color); 393 | } 394 | 395 | public void setRSI3Color(int color) { 396 | mRSIDraw.setRSI3Color(color); 397 | } 398 | 399 | @Override 400 | public void setTextSize(float textSize) { 401 | super.setTextSize(textSize); 402 | mMainDraw.setTextSize(textSize); 403 | mRSIDraw.setTextSize(textSize); 404 | mMACDDraw.setTextSize(textSize); 405 | mKDJDraw.setTextSize(textSize); 406 | mWRDraw.setTextSize(textSize); 407 | mVolumeDraw.setTextSize(textSize); 408 | } 409 | 410 | @Override 411 | public void setLineWidth(float lineWidth) { 412 | super.setLineWidth(lineWidth); 413 | mMainDraw.setLineWidth(lineWidth); 414 | mRSIDraw.setLineWidth(lineWidth); 415 | mMACDDraw.setLineWidth(lineWidth); 416 | mKDJDraw.setLineWidth(lineWidth); 417 | mWRDraw.setLineWidth(lineWidth); 418 | mVolumeDraw.setLineWidth(lineWidth); 419 | } 420 | 421 | @Override 422 | public void setTextColor(int color) { 423 | super.setTextColor(color); 424 | mMainDraw.setSelectorTextColor(color); 425 | } 426 | 427 | /** 428 | * 设置刷新监听 429 | */ 430 | public void setRefreshListener(KChartRefreshListener refreshListener) { 431 | mRefreshListener = refreshListener; 432 | } 433 | 434 | public void setMainDrawLine(boolean isLine) { 435 | mMainDraw.setLine(isLine); 436 | invalidate(); 437 | } 438 | 439 | public void setMainRangLine(boolean isLine) { 440 | mMainDraw.setRange(isLine); 441 | invalidate(); 442 | } 443 | 444 | public void setKlineType(String klineType) { 445 | mMainDraw.setKlineType(klineType); 446 | invalidate(); 447 | } 448 | 449 | 450 | private int startX; 451 | private int startY; 452 | 453 | @Override 454 | public boolean onInterceptTouchEvent(MotionEvent ev) { 455 | switch (ev.getAction()) { 456 | case MotionEvent.ACTION_DOWN: 457 | startX = (int) ev.getX(); 458 | startY = (int) ev.getY(); 459 | break; 460 | case MotionEvent.ACTION_MOVE: 461 | int dX = (int) (ev.getX() - startX); 462 | int dY = (int) (ev.getY() - startX); 463 | if (Math.abs(dX) > Math.abs(dY)) { 464 | //左右滑动 465 | return true; 466 | } else { 467 | //上下滑动 468 | return false; 469 | } 470 | case MotionEvent.ACTION_UP: 471 | break; 472 | default: 473 | } 474 | return super.onInterceptTouchEvent(ev); 475 | } 476 | 477 | @Override 478 | public void onLongPress(MotionEvent e) { 479 | if (!isRefreshing) { 480 | super.onLongPress(e); 481 | } 482 | } 483 | } 484 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/KLineEntity.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import com.github.fujianlian.klinechart.entity.IKLine; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * K线实体 12 | * Created by tifezh on 2016/5/16. 13 | */ 14 | public class KLineEntity implements IKLine, Parcelable { 15 | 16 | public String address; 17 | 18 | public String getAddress() { 19 | return address; 20 | } 21 | 22 | public void setAddress(String address) { 23 | this.address = address; 24 | } 25 | 26 | public String getDate() { 27 | return Date; 28 | } 29 | 30 | @Override 31 | public float getOpenPrice() { 32 | return Open; 33 | } 34 | 35 | @Override 36 | public float getHighPrice() { 37 | return High; 38 | } 39 | 40 | @Override 41 | public float getLowPrice() { 42 | return Low; 43 | } 44 | 45 | @Override 46 | public float getClosePrice() { 47 | return Close; 48 | } 49 | 50 | @Override 51 | public float getMA5Price() { 52 | return MA5Price; 53 | } 54 | 55 | @Override 56 | public float getMA10Price() { 57 | return MA10Price; 58 | } 59 | 60 | @Override 61 | public float getMA20Price() { 62 | return MA20Price; 63 | } 64 | 65 | @Override 66 | public float getMA30Price() { 67 | return MA30Price; 68 | } 69 | 70 | @Override 71 | public float getMA60Price() { 72 | return MA60Price; 73 | } 74 | 75 | @Override 76 | public float getDea() { 77 | return dea; 78 | } 79 | 80 | @Override 81 | public float getDif() { 82 | return dif; 83 | } 84 | 85 | @Override 86 | public float getMacd() { 87 | return macd; 88 | } 89 | 90 | @Override 91 | public float getK() { 92 | return k; 93 | } 94 | 95 | @Override 96 | public float getD() { 97 | return d; 98 | } 99 | 100 | @Override 101 | public float getJ() { 102 | return j; 103 | } 104 | 105 | @Override 106 | public float getR() { 107 | return r; 108 | } 109 | 110 | @Override 111 | public float getRsi() { 112 | return rsi; 113 | } 114 | 115 | @Override 116 | public float getUp() { 117 | return up; 118 | } 119 | 120 | @Override 121 | public float getMb() { 122 | return mb; 123 | } 124 | 125 | @Override 126 | public float getDn() { 127 | return dn; 128 | } 129 | 130 | @Override 131 | public float getVolume() { 132 | return Volume; 133 | } 134 | 135 | @Override 136 | public float getMA5Volume() { 137 | return MA5Volume; 138 | } 139 | 140 | @Override 141 | public float getMA10Volume() { 142 | return MA10Volume; 143 | } 144 | 145 | public int type; 146 | 147 | 148 | public int getType() { 149 | return type; 150 | } 151 | 152 | public void setType(int type) { 153 | this.type = type; 154 | } 155 | 156 | public String Date; 157 | public String timestamp; 158 | public String t; 159 | public float Open; 160 | public float High; 161 | public float Low; 162 | public float Close; 163 | public float Volume; 164 | 165 | public float MA5Price; 166 | 167 | public float MA10Price; 168 | 169 | public float MA20Price; 170 | 171 | public float MA30Price; 172 | 173 | public float MA60Price; 174 | 175 | public float dea; 176 | 177 | public float dif; 178 | 179 | public float macd; 180 | 181 | public float k; 182 | 183 | public float d; 184 | 185 | public float j; 186 | 187 | public float r; 188 | 189 | public float rsi; 190 | 191 | public float up; 192 | 193 | public float mb; 194 | 195 | public float dn; 196 | 197 | public float MA5Volume; 198 | 199 | public float MA10Volume; 200 | 201 | public void setDate(String date) { 202 | Date = date; 203 | } 204 | 205 | public void setTimestamp(String timestamp) { 206 | this.timestamp = timestamp; 207 | } 208 | 209 | public String getTimestamp() { 210 | return timestamp; 211 | } 212 | 213 | public String getT() { 214 | return t; 215 | } 216 | 217 | public void setT(String t) { 218 | this.t = t; 219 | } 220 | 221 | public void setOpen(float open) { 222 | Open = open; 223 | } 224 | 225 | public void setHigh(float high) { 226 | High = high; 227 | } 228 | 229 | public void setLow(float low) { 230 | Low = low; 231 | } 232 | 233 | public void setClose(float close) { 234 | Close = close; 235 | } 236 | 237 | public void setVolume(float volume) { 238 | Volume = volume; 239 | } 240 | 241 | public void setMA5Price(float MA5Price) { 242 | this.MA5Price = MA5Price; 243 | } 244 | 245 | public void setMA10Price(float MA10Price) { 246 | this.MA10Price = MA10Price; 247 | } 248 | 249 | public void setMA20Price(float MA20Price) { 250 | this.MA20Price = MA20Price; 251 | } 252 | 253 | public void setMA30Price(float MA30Price) { 254 | this.MA30Price = MA30Price; 255 | } 256 | 257 | public void setMA60Price(float MA60Price) { 258 | this.MA60Price = MA60Price; 259 | } 260 | 261 | public void setDea(float dea) { 262 | this.dea = dea; 263 | } 264 | 265 | public void setDif(float dif) { 266 | this.dif = dif; 267 | } 268 | 269 | public void setMacd(float macd) { 270 | this.macd = macd; 271 | } 272 | 273 | public void setK(float k) { 274 | this.k = k; 275 | } 276 | 277 | public void setD(float d) { 278 | this.d = d; 279 | } 280 | 281 | public void setJ(float j) { 282 | this.j = j; 283 | } 284 | 285 | public void setR(float r) { 286 | this.r = r; 287 | } 288 | 289 | public void setRsi(float rsi) { 290 | this.rsi = rsi; 291 | } 292 | 293 | public void setUp(float up) { 294 | this.up = up; 295 | } 296 | 297 | public void setMb(float mb) { 298 | this.mb = mb; 299 | } 300 | 301 | public void setDn(float dn) { 302 | this.dn = dn; 303 | } 304 | 305 | public void setMA5Volume(float MA5Volume) { 306 | this.MA5Volume = MA5Volume; 307 | } 308 | 309 | public void setMA10Volume(float MA10Volume) { 310 | this.MA10Volume = MA10Volume; 311 | } 312 | 313 | @Override 314 | public int describeContents() { 315 | return 0; 316 | } 317 | 318 | @Override 319 | public void writeToParcel(Parcel dest, int flags) { 320 | dest.writeString(this.address); 321 | dest.writeInt(this.type); 322 | dest.writeString(this.Date); 323 | dest.writeFloat(this.Open); 324 | dest.writeFloat(this.High); 325 | dest.writeFloat(this.Low); 326 | dest.writeFloat(this.Close); 327 | dest.writeFloat(this.Volume); 328 | dest.writeFloat(this.MA5Price); 329 | dest.writeFloat(this.MA10Price); 330 | dest.writeFloat(this.MA20Price); 331 | dest.writeFloat(this.MA30Price); 332 | dest.writeFloat(this.MA60Price); 333 | dest.writeFloat(this.dea); 334 | dest.writeFloat(this.dif); 335 | dest.writeFloat(this.macd); 336 | dest.writeFloat(this.k); 337 | dest.writeFloat(this.d); 338 | dest.writeFloat(this.j); 339 | dest.writeFloat(this.r); 340 | dest.writeFloat(this.rsi); 341 | dest.writeFloat(this.up); 342 | dest.writeFloat(this.mb); 343 | dest.writeFloat(this.dn); 344 | dest.writeFloat(this.MA5Volume); 345 | dest.writeFloat(this.MA10Volume); 346 | } 347 | 348 | public KLineEntity() { 349 | } 350 | 351 | protected KLineEntity(Parcel in) { 352 | this.address = in.readString(); 353 | this.type = in.readInt(); 354 | this.Date = in.readString(); 355 | this.Open = in.readFloat(); 356 | this.High = in.readFloat(); 357 | this.Low = in.readFloat(); 358 | this.Close = in.readFloat(); 359 | this.Volume = in.readFloat(); 360 | this.MA5Price = in.readFloat(); 361 | this.MA10Price = in.readFloat(); 362 | this.MA20Price = in.readFloat(); 363 | this.MA30Price = in.readFloat(); 364 | this.MA60Price = in.readFloat(); 365 | this.dea = in.readFloat(); 366 | this.dif = in.readFloat(); 367 | this.macd = in.readFloat(); 368 | this.k = in.readFloat(); 369 | this.d = in.readFloat(); 370 | this.j = in.readFloat(); 371 | this.r = in.readFloat(); 372 | this.rsi = in.readFloat(); 373 | this.up = in.readFloat(); 374 | this.mb = in.readFloat(); 375 | this.dn = in.readFloat(); 376 | this.MA5Volume = in.readFloat(); 377 | this.MA10Volume = in.readFloat(); 378 | } 379 | 380 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 381 | @Override 382 | public KLineEntity createFromParcel(Parcel source) { 383 | return new KLineEntity(source); 384 | } 385 | 386 | @Override 387 | public KLineEntity[] newArray(int size) { 388 | return new KLineEntity[size]; 389 | } 390 | }; 391 | } 392 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/ScrollAndScaleView.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.GestureDetectorCompat; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.GestureDetector; 8 | import android.view.MotionEvent; 9 | import android.view.ScaleGestureDetector; 10 | import android.widget.OverScroller; 11 | import android.widget.RelativeLayout; 12 | 13 | /** 14 | * 可以滑动和放大的view 15 | * Created by tian on 2016/5/3. 16 | */ 17 | public abstract class ScrollAndScaleView extends RelativeLayout implements 18 | GestureDetector.OnGestureListener, 19 | ScaleGestureDetector.OnScaleGestureListener { 20 | protected int mScrollX = 0; 21 | protected GestureDetectorCompat mDetector; 22 | protected ScaleGestureDetector mScaleDetector; 23 | 24 | protected boolean isLongPress = false; 25 | 26 | private OverScroller mScroller; 27 | 28 | protected boolean touch = false; 29 | 30 | protected float mScaleX = 1; 31 | 32 | protected float mScaleXMax = 4f; 33 | 34 | protected float mScaleXMin = 0.5f; 35 | 36 | private boolean mMultipleTouch = false; 37 | 38 | private boolean mScrollEnable = true; 39 | 40 | private boolean mScaleEnable = true; 41 | 42 | public ScrollAndScaleView(Context context) { 43 | super(context); 44 | init(); 45 | } 46 | 47 | public ScrollAndScaleView(Context context, AttributeSet attrs) { 48 | super(context, attrs); 49 | init(); 50 | } 51 | 52 | public ScrollAndScaleView(Context context, AttributeSet attrs, int defStyleAttr) { 53 | super(context, attrs, defStyleAttr); 54 | init(); 55 | } 56 | 57 | private void init() { 58 | setWillNotDraw(false); 59 | mDetector = new GestureDetectorCompat(getContext(), this); 60 | mScaleDetector = new ScaleGestureDetector(getContext(), this); 61 | mScroller = new OverScroller(getContext()); 62 | } 63 | 64 | @Override 65 | public boolean onDown(MotionEvent e) { 66 | return false; 67 | } 68 | 69 | @Override 70 | public void onShowPress(MotionEvent e) { 71 | 72 | } 73 | 74 | @Override 75 | public boolean onSingleTapUp(MotionEvent e) { 76 | return false; 77 | } 78 | 79 | @Override 80 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 81 | if (!isLongPress && !isMultipleTouch()) { 82 | scrollBy(Math.round(distanceX), 0); 83 | return true; 84 | } 85 | return false; 86 | } 87 | 88 | @Override 89 | public void onLongPress(MotionEvent e) { 90 | isLongPress = true; 91 | } 92 | 93 | @Override 94 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 95 | if (!isTouch() && isScrollEnable()) { 96 | mScroller.fling(mScrollX, 0 97 | , Math.round(velocityX / mScaleX), 0, 98 | Integer.MIN_VALUE, Integer.MAX_VALUE, 99 | 0, 0); 100 | } 101 | return true; 102 | } 103 | 104 | @Override 105 | public void computeScroll() { 106 | if (mScroller.computeScrollOffset()) { 107 | if (!isTouch()) { 108 | scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 109 | } else { 110 | mScroller.forceFinished(true); 111 | } 112 | } 113 | } 114 | 115 | @Override 116 | public void scrollBy(int x, int y) { 117 | scrollTo(mScrollX - Math.round(x / mScaleX), 0); 118 | } 119 | 120 | @Override 121 | public void scrollTo(int x, int y) { 122 | Log.i("x---", x + ""); 123 | if (!isScrollEnable()) { 124 | mScroller.forceFinished(true); 125 | return; 126 | } 127 | int oldX = mScrollX; 128 | mScrollX = x; 129 | if (mScrollX < getMinScrollX()) { 130 | mScrollX = getMinScrollX(); 131 | onRightSide(); 132 | mScroller.forceFinished(true); 133 | } else if (mScrollX > getMaxScrollX()) { 134 | mScrollX = getMaxScrollX(); 135 | onLeftSide(); 136 | mScroller.forceFinished(true); 137 | } 138 | Log.i("mScrollX---", mScrollX + ""); 139 | onScrollChanged(mScrollX, 0, oldX, 0); 140 | invalidate(); 141 | } 142 | 143 | @Override 144 | public boolean onScale(ScaleGestureDetector detector) { 145 | if (!isScaleEnable()) { 146 | return false; 147 | } 148 | float oldScale = mScaleX; 149 | mScaleX *= detector.getScaleFactor(); 150 | if (mScaleX < mScaleXMin) { 151 | mScaleX = mScaleXMin; 152 | } else if (mScaleX > mScaleXMax) { 153 | mScaleX = mScaleXMax; 154 | } else { 155 | onScaleChanged(mScaleX, oldScale); 156 | } 157 | return true; 158 | } 159 | 160 | protected void onScaleChanged(float scale, float oldScale) { 161 | invalidate(); 162 | } 163 | 164 | @Override 165 | public boolean onScaleBegin(ScaleGestureDetector detector) { 166 | return true; 167 | } 168 | 169 | @Override 170 | public void onScaleEnd(ScaleGestureDetector detector) { 171 | 172 | } 173 | 174 | float x; 175 | 176 | @Override 177 | public boolean onTouchEvent(MotionEvent event) { 178 | // 按压手指超过1个 179 | if (event.getPointerCount() > 1) { 180 | isLongPress = false; 181 | } 182 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 183 | case MotionEvent.ACTION_DOWN: 184 | touch = true; 185 | x = event.getX(); 186 | break; 187 | case MotionEvent.ACTION_MOVE: 188 | //长按之后移动 189 | if (isLongPress) { 190 | onLongPress(event); 191 | } 192 | break; 193 | case MotionEvent.ACTION_POINTER_UP: 194 | invalidate(); 195 | break; 196 | case MotionEvent.ACTION_UP: 197 | // if (x == event.getX()) { 198 | // if (isLongPress) { 199 | // isLongPress = false; 200 | // } 201 | // } 202 | if (isLongPress) { 203 | isLongPress = false; 204 | } 205 | touch = false; 206 | invalidate(); 207 | break; 208 | case MotionEvent.ACTION_CANCEL: 209 | isLongPress = false; 210 | touch = false; 211 | invalidate(); 212 | break; 213 | default: 214 | break; 215 | } 216 | mMultipleTouch = event.getPointerCount() > 1; 217 | this.mDetector.onTouchEvent(event); 218 | this.mScaleDetector.onTouchEvent(event); 219 | return true; 220 | } 221 | 222 | 223 | /** 224 | * 滑到了最左边 225 | */ 226 | abstract public void onLeftSide(); 227 | 228 | /** 229 | * 滑到了最右边 230 | */ 231 | abstract public void onRightSide(); 232 | 233 | /** 234 | * 是否在触摸中 235 | * 236 | * @return 237 | */ 238 | public boolean isTouch() { 239 | return touch; 240 | } 241 | 242 | /** 243 | * 获取位移的最小值 244 | * 245 | * @return 246 | */ 247 | public abstract int getMinScrollX(); 248 | 249 | /** 250 | * 获取位移的最大值 251 | * 252 | * @return 253 | */ 254 | public abstract int getMaxScrollX(); 255 | 256 | /** 257 | * 设置ScrollX 258 | * 259 | * @param scrollX 260 | */ 261 | public void setScrollX(int scrollX) { 262 | this.mScrollX = scrollX; 263 | scrollTo(scrollX, 0); 264 | } 265 | 266 | /** 267 | * 是否是多指触控 268 | * 269 | * @return 270 | */ 271 | public boolean isMultipleTouch() { 272 | return mMultipleTouch; 273 | } 274 | 275 | protected void checkAndFixScrollX() { 276 | if (mScrollX < getMinScrollX()) { 277 | mScrollX = getMinScrollX(); 278 | mScroller.forceFinished(true); 279 | } else if (mScrollX > getMaxScrollX()) { 280 | mScrollX = getMaxScrollX(); 281 | mScroller.forceFinished(true); 282 | } 283 | } 284 | 285 | public float getScaleXMax() { 286 | return mScaleXMax; 287 | } 288 | 289 | public float getScaleXMin() { 290 | return mScaleXMin; 291 | } 292 | 293 | public boolean isScrollEnable() { 294 | return mScrollEnable; 295 | } 296 | 297 | public boolean isScaleEnable() { 298 | return mScaleEnable; 299 | } 300 | 301 | /** 302 | * 设置缩放的最大值 303 | */ 304 | public void setScaleXMax(float scaleXMax) { 305 | mScaleXMax = scaleXMax; 306 | } 307 | 308 | /** 309 | * 设置缩放的最小值 310 | */ 311 | public void setScaleXMin(float scaleXMin) { 312 | mScaleXMin = scaleXMin; 313 | } 314 | 315 | /** 316 | * 设置是否可以滑动 317 | */ 318 | public void setScrollEnable(boolean scrollEnable) { 319 | mScrollEnable = scrollEnable; 320 | } 321 | 322 | /** 323 | * 设置是否可以缩放 324 | */ 325 | public void setScaleEnable(boolean scaleEnable) { 326 | mScaleEnable = scaleEnable; 327 | } 328 | 329 | @Override 330 | public float getScaleX() { 331 | return mScaleX; 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/base/IAdapter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.base; 2 | 3 | import android.database.DataSetObserver; 4 | 5 | import com.github.fujianlian.klinechart.KLineEntity; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 数据适配器 11 | * Created by tifezh on 2016/6/14. 12 | */ 13 | 14 | public interface IAdapter { 15 | /** 16 | * 获取点的数目 17 | * 18 | * @return 19 | */ 20 | int getCount(); 21 | 22 | /** 23 | * 通过序号获取item 24 | * 25 | * @param position 对应的序号 26 | * @return 数据实体 27 | */ 28 | Object getItem(int position); 29 | 30 | 31 | /** 32 | * 通过序号获取时间 33 | * 34 | * @param position 35 | * @return 36 | */ 37 | String getDate(int position); 38 | 39 | String getTimeStamp(int position); 40 | 41 | 42 | /** 43 | * 注册一个数据观察者 44 | * 45 | * @param observer 数据观察者 46 | */ 47 | void registerDataSetObserver(DataSetObserver observer); 48 | 49 | /** 50 | * 移除一个数据观察者 51 | * 52 | * @param observer 数据观察者 53 | */ 54 | void unregisterDataSetObserver(DataSetObserver observer); 55 | 56 | /** 57 | * 当数据发生变化时调用 58 | */ 59 | void notifyDataSetChanged(); 60 | } 61 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/base/IChartDraw.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.base; 2 | 3 | import android.graphics.Canvas; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | 7 | import com.github.fujianlian.klinechart.BaseKLineChartView; 8 | 9 | 10 | /** 11 | * 画图的基类 根据实体来画图形 12 | * Created by tifezh on 2016/6/14. 13 | */ 14 | public interface IChartDraw { 15 | 16 | /** 17 | * 需要滑动 物体draw方法 18 | * 19 | * @param canvas canvas 20 | * @param view k线图View 21 | * @param position 当前点的位置 22 | * @param lastPoint 上一个点 23 | * @param curPoint 当前点 24 | * @param lastX 上一个点的x坐标 25 | * @param curX 当前点的X坐标 26 | */ 27 | void drawTranslated(@Nullable T lastPoint, @NonNull T curPoint, float lastX, float curX, @NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position); 28 | 29 | /** 30 | * @param canvas 31 | * @param view 32 | * @param position 该点的位置 33 | * @param x x的起始坐标 34 | * @param y y的起始坐标 35 | */ 36 | void drawText(@NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position, float x, float y); 37 | 38 | /** 39 | * 获取当前实体中最大的值 40 | * 41 | * @param point 42 | * @return 43 | */ 44 | float getMaxValue(T point); 45 | 46 | /** 47 | * 获取当前实体中最小的值 48 | * 49 | * @param point 50 | * @return 51 | */ 52 | float getMinValue(T point); 53 | 54 | 55 | 56 | /** 57 | * 获取value格式化器 58 | */ 59 | IValueFormatter getValueFormatter(); 60 | } 61 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/base/IDateTimeFormatter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.base; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 时间格式化接口 7 | * Created by tifezh on 2016/6/21. 8 | */ 9 | 10 | public interface IDateTimeFormatter { 11 | String format(Date date); 12 | } 13 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/base/IValueFormatter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.base; 2 | 3 | /** 4 | * Value格式化接口 5 | * Created by tifezh on 2016/6/21. 6 | */ 7 | 8 | public interface IValueFormatter { 9 | /** 10 | * 格式化value 11 | * 12 | * @param value 传入的value值 13 | * @return 返回字符串 14 | */ 15 | String format(float value,int digit); 16 | } 17 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/draw/KDJDraw.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.draw; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | 8 | import com.github.fujianlian.klinechart.BaseKLineChartView; 9 | import com.github.fujianlian.klinechart.base.IChartDraw; 10 | import com.github.fujianlian.klinechart.base.IValueFormatter; 11 | import com.github.fujianlian.klinechart.entity.IKDJ; 12 | import com.github.fujianlian.klinechart.formatter.ValueFormatter; 13 | 14 | import static com.github.fujianlian.klinechart.utils.Constants.RANG_ITEM; 15 | 16 | /** 17 | * KDJ实现类 18 | * Created by tifezh on 2016/6/19. 19 | */ 20 | 21 | public class KDJDraw implements IChartDraw { 22 | 23 | private Paint mKPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 24 | private Paint mDPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 25 | private Paint mJPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 26 | 27 | public KDJDraw(BaseKLineChartView view) { 28 | } 29 | 30 | @Override 31 | public void drawTranslated(@Nullable IKDJ lastPoint, @NonNull IKDJ curPoint, 32 | float lastX, float curX, @NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position) { 33 | if (lastPoint.getK() != 0) { 34 | view.drawChildLine(canvas, mKPaint, lastX, lastPoint.getK(), curX, curPoint.getK()); 35 | } 36 | if (lastPoint.getD() != 0) { 37 | view.drawChildLine(canvas, mDPaint, lastX, lastPoint.getD(), curX, curPoint.getD()); 38 | } 39 | if (lastPoint.getJ() != 0) { 40 | view.drawChildLine(canvas, mJPaint, lastX, lastPoint.getJ(), curX, curPoint.getJ()); 41 | } 42 | } 43 | 44 | @Override 45 | public void drawText(@NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position, float x, float y) { 46 | IKDJ point = (IKDJ) view.getItem(position); 47 | if (point.getK() != 0) { 48 | String text = "KDJ(14,1,3) "; 49 | canvas.drawText(text, x, y, view.getTextPaint()); 50 | x += view.getTextPaint().measureText(text); 51 | text = "K:" + view.formatValue(point.getK()) + " "; 52 | canvas.drawText(text, x, y, mKPaint); 53 | x += mKPaint.measureText(text); 54 | if (point.getD() != 0) { 55 | text = "D:" + view.formatValue(point.getD()) + " "; 56 | canvas.drawText(text, x, y, mDPaint); 57 | x += mDPaint.measureText(text); 58 | text = "J:" + view.formatValue(point.getJ()) + " "; 59 | canvas.drawText(text, x, y, mJPaint); 60 | } 61 | } 62 | } 63 | 64 | @Override 65 | public float getMaxValue(IKDJ point) { 66 | return Math.max(point.getK(), Math.max(point.getD(), point.getJ())); 67 | } 68 | 69 | @Override 70 | public float getMinValue(IKDJ point) { 71 | return Math.min(point.getK(), Math.min(point.getD(), point.getJ())); 72 | } 73 | 74 | @Override 75 | public IValueFormatter getValueFormatter() { 76 | return new ValueFormatter(); 77 | } 78 | 79 | /** 80 | * 设置K颜色 81 | */ 82 | public void setKColor(int color) { 83 | mKPaint.setColor(color); 84 | } 85 | 86 | /** 87 | * 设置D颜色 88 | */ 89 | public void setDColor(int color) { 90 | mDPaint.setColor(color); 91 | } 92 | 93 | /** 94 | * 设置J颜色 95 | */ 96 | public void setJColor(int color) { 97 | mJPaint.setColor(color); 98 | } 99 | 100 | /** 101 | * 设置曲线宽度 102 | */ 103 | public void setLineWidth(float width) { 104 | mKPaint.setStrokeWidth(width); 105 | mDPaint.setStrokeWidth(width); 106 | mJPaint.setStrokeWidth(width); 107 | } 108 | 109 | /** 110 | * 设置文字大小 111 | */ 112 | public void setTextSize(float textSize) { 113 | mKPaint.setTextSize(textSize); 114 | mDPaint.setTextSize(textSize); 115 | mJPaint.setTextSize(textSize); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/draw/MACDDraw.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.draw; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.content.ContextCompat; 9 | 10 | import com.github.fujianlian.klinechart.R; 11 | import com.github.fujianlian.klinechart.BaseKLineChartView; 12 | import com.github.fujianlian.klinechart.base.IChartDraw; 13 | import com.github.fujianlian.klinechart.base.IValueFormatter; 14 | import com.github.fujianlian.klinechart.entity.IMACD; 15 | import com.github.fujianlian.klinechart.formatter.ValueFormatter; 16 | 17 | import static com.github.fujianlian.klinechart.utils.Constants.RANG_ITEM; 18 | 19 | /** 20 | * macd实现类 21 | * Created by tifezh on 2016/6/19. 22 | */ 23 | 24 | public class MACDDraw implements IChartDraw { 25 | 26 | private Paint mRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 27 | private Paint mGreenPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 28 | private Paint mDIFPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 29 | private Paint mDEAPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 30 | private Paint mMACDPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 31 | /** 32 | * macd 中柱子的宽度 33 | */ 34 | private float mMACDWidth = 0; 35 | 36 | public MACDDraw(BaseKLineChartView view) { 37 | Context context = view.getContext(); 38 | mRedPaint.setColor(ContextCompat.getColor(context, R.color.chart_red)); 39 | mGreenPaint.setColor(ContextCompat.getColor(context, R.color.chart_green)); 40 | } 41 | 42 | @Override 43 | public void drawTranslated(@Nullable IMACD lastPoint, @NonNull IMACD curPoint, 44 | float lastX, float curX, @NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position) { 45 | drawMACD(canvas, view, curX, curPoint.getMacd()); 46 | view.drawChildLine(canvas, mDIFPaint, lastX, lastPoint.getDea(), curX, curPoint.getDea()); 47 | view.drawChildLine(canvas, mDEAPaint, lastX, lastPoint.getDif(), curX, curPoint.getDif()); 48 | } 49 | 50 | @Override 51 | public void drawText(@NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position, 52 | float x, float y) { 53 | IMACD point = (IMACD) view.getItem(position); 54 | String text = "MACD "; 55 | // String text = "MACD(12,26,9) "; 56 | // canvas.drawText(text, x, y, view.getTextPaint()); 57 | // x += view.getTextPaint().measureText(text); 58 | // text = "MACD:" + view.formatValue(point.getMacd()) + " "; 59 | // canvas.drawText(text, x, y, mMACDPaint); 60 | // x += mMACDPaint.measureText(text); 61 | // text = "DIF:" + view.formatValue(point.getDif()) + " "; 62 | // canvas.drawText(text, x, y, mDEAPaint); 63 | // x += mDIFPaint.measureText(text); 64 | // text = "DEA:" + view.formatValue(point.getDea()); 65 | canvas.drawText(text, x, y, mDIFPaint); 66 | } 67 | 68 | @Override 69 | public float getMaxValue(IMACD point) { 70 | return Math.max(point.getMacd(), Math.max(point.getDea(), point.getDif())); 71 | } 72 | 73 | @Override 74 | public float getMinValue(IMACD point) { 75 | return Math.min(point.getMacd(), Math.min(point.getDea(), point.getDif())); 76 | } 77 | 78 | @Override 79 | public IValueFormatter getValueFormatter() { 80 | return new ValueFormatter(); 81 | } 82 | 83 | /** 84 | * 画macd 85 | * 86 | * @param canvas 87 | * @param x 88 | * @param macd 89 | */ 90 | private void drawMACD(Canvas canvas, BaseKLineChartView view, float x, float macd) { 91 | float macdy = view.getChildY(macd); 92 | float r = mMACDWidth / 2; 93 | float zeroy = view.getChildY(0); 94 | if (macd > 0) { 95 | // left top right bottom 96 | canvas.drawRect(x - r, macdy, x + r, zeroy, mRedPaint); 97 | } else { 98 | canvas.drawRect(x - r, zeroy, x + r, macdy, mGreenPaint); 99 | } 100 | } 101 | 102 | /** 103 | * 设置DIF颜色 104 | */ 105 | public void setDIFColor(int color) { 106 | this.mDIFPaint.setColor(color); 107 | } 108 | 109 | /** 110 | * 设置DEA颜色 111 | */ 112 | public void setDEAColor(int color) { 113 | this.mDEAPaint.setColor(color); 114 | } 115 | 116 | /** 117 | * 设置MACD颜色 118 | */ 119 | public void setMACDColor(int color) { 120 | this.mMACDPaint.setColor(color); 121 | } 122 | 123 | /** 124 | * 设置MACD的宽度 125 | * 126 | * @param MACDWidth 127 | */ 128 | public void setMACDWidth(float MACDWidth) { 129 | mMACDWidth = MACDWidth; 130 | } 131 | 132 | /** 133 | * 设置曲线宽度 134 | */ 135 | public void setLineWidth(float width) { 136 | mDEAPaint.setStrokeWidth(width); 137 | mDIFPaint.setStrokeWidth(width); 138 | mMACDPaint.setStrokeWidth(width); 139 | } 140 | 141 | /** 142 | * 设置文字大小 143 | */ 144 | public void setTextSize(float textSize) { 145 | mDEAPaint.setTextSize(textSize); 146 | mDIFPaint.setTextSize(textSize); 147 | mMACDPaint.setTextSize(textSize); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/draw/RSIDraw.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.draw; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | 8 | import com.github.fujianlian.klinechart.BaseKLineChartView; 9 | import com.github.fujianlian.klinechart.base.IChartDraw; 10 | import com.github.fujianlian.klinechart.base.IValueFormatter; 11 | import com.github.fujianlian.klinechart.entity.IRSI; 12 | import com.github.fujianlian.klinechart.formatter.ValueFormatter; 13 | 14 | /** 15 | * RSI实现类 16 | * Created by tifezh on 2016/6/19. 17 | */ 18 | public class RSIDraw implements IChartDraw { 19 | 20 | private Paint mRSI1Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 21 | private Paint mRSI2Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 22 | private Paint mRSI3Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 23 | 24 | public RSIDraw(BaseKLineChartView view) { 25 | 26 | } 27 | 28 | @Override 29 | public void drawTranslated(@Nullable IRSI lastPoint, @NonNull IRSI curPoint, 30 | float lastX, float curX, @NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position) { 31 | if (lastPoint.getRsi() != 0) { 32 | view.drawChildLine(canvas, mRSI1Paint, lastX, lastPoint.getRsi(), curX, curPoint.getRsi()); 33 | } 34 | } 35 | 36 | @Override 37 | public void drawText(@NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position, float x, float y) { 38 | IRSI point = (IRSI) view.getItem(position); 39 | if (point.getRsi() != 0) { 40 | String text = "RSI(14) "; 41 | canvas.drawText(text, x, y, view.getTextPaint()); 42 | x += view.getTextPaint().measureText(text); 43 | text = view.formatValue(point.getRsi()); 44 | canvas.drawText(text, x, y, mRSI1Paint); 45 | } 46 | } 47 | 48 | @Override 49 | public float getMaxValue(IRSI point) { 50 | return point.getRsi(); 51 | } 52 | 53 | @Override 54 | public float getMinValue(IRSI point) { 55 | return point.getRsi(); 56 | } 57 | 58 | @Override 59 | public IValueFormatter getValueFormatter() { 60 | return new ValueFormatter(); 61 | } 62 | 63 | public void setRSI1Color(int color) { 64 | mRSI1Paint.setColor(color); 65 | } 66 | 67 | public void setRSI2Color(int color) { 68 | mRSI2Paint.setColor(color); 69 | } 70 | 71 | public void setRSI3Color(int color) { 72 | mRSI3Paint.setColor(color); 73 | } 74 | 75 | /** 76 | * 设置曲线宽度 77 | */ 78 | public void setLineWidth(float width) { 79 | mRSI1Paint.setStrokeWidth(width); 80 | mRSI2Paint.setStrokeWidth(width); 81 | mRSI3Paint.setStrokeWidth(width); 82 | } 83 | 84 | /** 85 | * 设置文字大小 86 | */ 87 | public void setTextSize(float textSize) { 88 | mRSI2Paint.setTextSize(textSize); 89 | mRSI3Paint.setTextSize(textSize); 90 | mRSI1Paint.setTextSize(textSize); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/draw/Status.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.draw; 2 | 3 | /** 4 | * @author fujianlian Created on 2018/8/20 11:09 5 | * @descripe MainDraw当前子视图 6 | */ 7 | public enum Status { 8 | MA, BOLL, NONE 9 | } 10 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/draw/VolumeDraw.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.draw; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.content.ContextCompat; 9 | 10 | import com.github.fujianlian.klinechart.R; 11 | import com.github.fujianlian.klinechart.BaseKLineChartView; 12 | import com.github.fujianlian.klinechart.base.IChartDraw; 13 | import com.github.fujianlian.klinechart.base.IValueFormatter; 14 | import com.github.fujianlian.klinechart.entity.IVolume; 15 | import com.github.fujianlian.klinechart.formatter.BigValueFormatter; 16 | import com.github.fujianlian.klinechart.utils.ViewUtil; 17 | 18 | /** 19 | * Created by hjm on 2017/11/14 17:49. 20 | */ 21 | public class VolumeDraw implements IChartDraw { 22 | 23 | private Paint mRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 24 | private Paint mGreenPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 25 | private Paint ma5Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 26 | private Paint ma10Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 27 | private int pillarWidth = 0; 28 | 29 | public VolumeDraw(BaseKLineChartView view) { 30 | Context context = view.getContext(); 31 | mRedPaint.setColor(ContextCompat.getColor(context, R.color.chart_red)); 32 | mGreenPaint.setColor(ContextCompat.getColor(context, R.color.chart_green)); 33 | pillarWidth = ViewUtil.Dp2Px(context, 4); 34 | } 35 | 36 | @Override 37 | public void drawTranslated( 38 | @Nullable IVolume lastPoint, @NonNull IVolume curPoint, float lastX, float curX, 39 | @NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position) { 40 | 41 | drawHistogram(canvas, curPoint, lastPoint, curX, view, position); 42 | if (lastPoint.getMA5Volume() != 0f) { 43 | view.drawVolLine(canvas, ma5Paint, lastX, lastPoint.getMA5Volume(), curX, curPoint.getMA5Volume()); 44 | } 45 | if (lastPoint.getMA10Volume() != 0f) { 46 | view.drawVolLine(canvas, ma10Paint, lastX, lastPoint.getMA10Volume(), curX, curPoint.getMA10Volume()); 47 | } 48 | } 49 | 50 | private void drawHistogram( 51 | Canvas canvas, IVolume curPoint, IVolume lastPoint, float curX, 52 | BaseKLineChartView view, int position) { 53 | 54 | float r = pillarWidth / 2; 55 | float top = view.getVolY(curPoint.getVolume()); 56 | int bottom = view.getVolRect().bottom; 57 | if (curPoint.getClosePrice() >= curPoint.getOpenPrice()) {//涨 58 | canvas.drawRect(curX - r, top, curX + r, bottom,mGreenPaint); 59 | } else { 60 | canvas.drawRect(curX - r, top, curX + r, bottom, mRedPaint); 61 | } 62 | 63 | } 64 | 65 | @Override 66 | public void drawText( 67 | @NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position, float x, float y) { 68 | IVolume point = (IVolume) view.getItem(position); 69 | String text = "VOL"; 70 | // String text = "VOL:" + getValueFormatter().format(point.getVolume()) + " "; 71 | // canvas.drawText(text, x, y, view.getTextPaint()); 72 | // x += view.getTextPaint().measureText(text); 73 | // text = "MA5:" + getValueFormatter().format(point.getMA5Volume()) + " "; 74 | // canvas.drawText(text, x, y, ma5Paint); 75 | // x += ma5Paint.measureText(text); 76 | // text = "MA10:" + getValueFormatter().format(point.getMA10Volume()); 77 | canvas.drawText(text, x, y, ma10Paint); 78 | } 79 | 80 | @Override 81 | public float getMaxValue(IVolume point) { 82 | return Math.max(point.getVolume(), Math.max(point.getMA5Volume(), point.getMA10Volume())); 83 | } 84 | 85 | @Override 86 | public float getMinValue(IVolume point) { 87 | return Math.min(point.getVolume(), Math.min(point.getMA5Volume(), point.getMA10Volume())); 88 | } 89 | 90 | @Override 91 | public IValueFormatter getValueFormatter() { 92 | return new BigValueFormatter(); 93 | } 94 | 95 | /** 96 | * 设置 MA5 线的颜色 97 | * 98 | * @param color 99 | */ 100 | public void setMa5Color(int color) { 101 | this.ma5Paint.setColor(color); 102 | } 103 | 104 | /** 105 | * 设置 MA10 线的颜色 106 | * 107 | * @param color 108 | */ 109 | public void setMa10Color(int color) { 110 | this.ma10Paint.setColor(color); 111 | } 112 | 113 | public void setLineWidth(float width) { 114 | this.ma5Paint.setStrokeWidth(width); 115 | this.ma10Paint.setStrokeWidth(width); 116 | } 117 | 118 | /** 119 | * 设置文字大小 120 | * 121 | * @param textSize 122 | */ 123 | public void setTextSize(float textSize) { 124 | this.ma5Paint.setTextSize(textSize); 125 | this.ma10Paint.setTextSize(textSize); 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/draw/WRDraw.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.draw; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | 8 | import com.github.fujianlian.klinechart.BaseKLineChartView; 9 | import com.github.fujianlian.klinechart.base.IChartDraw; 10 | import com.github.fujianlian.klinechart.base.IValueFormatter; 11 | import com.github.fujianlian.klinechart.entity.IWR; 12 | import com.github.fujianlian.klinechart.formatter.ValueFormatter; 13 | 14 | /** 15 | * KDJ实现类 16 | * Created by tifezh on 2016/6/19. 17 | */ 18 | public class WRDraw implements IChartDraw { 19 | 20 | private Paint mRPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 21 | 22 | public WRDraw(BaseKLineChartView view) { 23 | } 24 | 25 | @Override 26 | public void drawTranslated(@Nullable IWR lastPoint, @NonNull IWR curPoint, float lastX, 27 | float curX, @NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position) { 28 | if (lastPoint.getR() != -10) { 29 | view.drawChildLine(canvas, mRPaint, lastX, lastPoint.getR(), curX, curPoint.getR()); 30 | } 31 | } 32 | 33 | @Override 34 | public void drawText(@NonNull Canvas canvas, @NonNull BaseKLineChartView view, int position, float x, float y) { 35 | IWR point = (IWR) view.getItem(position); 36 | if (point.getR() != -10) { 37 | String text = "WR(14):"; 38 | canvas.drawText(text, x, y, view.getTextPaint()); 39 | x += view.getTextPaint().measureText(text); 40 | text = view.formatValue(point.getR()) + " "; 41 | canvas.drawText(text, x, y, mRPaint); 42 | } 43 | } 44 | 45 | @Override 46 | public float getMaxValue(IWR point) { 47 | return point.getR(); 48 | } 49 | 50 | @Override 51 | public float getMinValue(IWR point) { 52 | return point.getR(); 53 | } 54 | 55 | @Override 56 | public IValueFormatter getValueFormatter() { 57 | return new ValueFormatter(); 58 | } 59 | 60 | /** 61 | * 设置%R颜色 62 | */ 63 | public void setRColor(int color) { 64 | mRPaint.setColor(color); 65 | } 66 | 67 | /** 68 | * 设置曲线宽度 69 | */ 70 | public void setLineWidth(float width) { 71 | mRPaint.setStrokeWidth(width); 72 | } 73 | 74 | /** 75 | * 设置文字大小 76 | */ 77 | public void setTextSize(float textSize) { 78 | mRPaint.setTextSize(textSize); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/ICandle.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | /** 4 | * 蜡烛图实体接口 5 | * Created by tifezh on 2016/6/9. 6 | */ 7 | public interface ICandle { 8 | 9 | /** 10 | * 开盘价 11 | */ 12 | float getOpenPrice(); 13 | 14 | /** 15 | * 最高价 16 | */ 17 | float getHighPrice(); 18 | 19 | /** 20 | * 最低价 21 | */ 22 | float getLowPrice(); 23 | 24 | /** 25 | * 收盘价 26 | */ 27 | float getClosePrice(); 28 | 29 | 30 | // 以下为MA数据 31 | /** 32 | * 五(月,日,时,分,5分等)均价 33 | */ 34 | float getMA5Price(); 35 | 36 | /** 37 | * 十(月,日,时,分,5分等)均价 38 | */ 39 | float getMA10Price(); 40 | 41 | /** 42 | * 二十(月,日,时,分,5分等)均价 43 | */ 44 | float getMA20Price(); 45 | 46 | /** 47 | * 三十(月,日,时,分,5分等)均价 48 | */ 49 | float getMA30Price(); 50 | 51 | /** 52 | * 六十(月,日,时,分,5分等)均价 53 | */ 54 | float getMA60Price(); 55 | 56 | // 以下为BOLL数据 57 | /** 58 | * 上轨线 59 | */ 60 | float getUp(); 61 | 62 | /** 63 | * 中轨线 64 | */ 65 | float getMb(); 66 | 67 | /** 68 | * 下轨线 69 | */ 70 | float getDn(); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/IKDJ.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | /** 4 | * @author fujianlian Created on 2018/8/20 16:08 5 | * @descripe KDJ指标(随机指标)接口 6 | * 相关说明:https://baike.baidu.com/item/KDJ%E6%8C%87%E6%A0%87/6328421?fr=aladdin&fromid=3423560&fromtitle=kdj 7 | */ 8 | public interface IKDJ { 9 | 10 | /** 11 | * K值 12 | */ 13 | float getK(); 14 | 15 | /** 16 | * D值 17 | */ 18 | float getD(); 19 | 20 | /** 21 | * J值 22 | */ 23 | float getJ(); 24 | 25 | } -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/IKLine.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | /** 4 | * KDJ指标(随机指标)接口 5 | * Created by tifezh on 2016/6/9. 6 | */ 7 | public interface IKLine extends ICandle, IMACD, IKDJ, IRSI, IVolume, IWR { 8 | } 9 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/IMACD.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | /** 4 | * MACD指标(指数平滑移动平均线)接口 5 | * @see 相关说明 6 | * Created by tifezh on 2016/6/10. 7 | */ 8 | 9 | public interface IMACD { 10 | 11 | 12 | /** 13 | * DEA值 14 | */ 15 | float getDea(); 16 | 17 | /** 18 | * DIF值 19 | */ 20 | float getDif(); 21 | 22 | /** 23 | * MACD值 24 | */ 25 | float getMacd(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/IRSI.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | /** 4 | * RSI指标接口 5 | * @see 相关说明 6 | * Created by tifezh on 2016/6/10. 7 | */ 8 | 9 | public interface IRSI { 10 | 11 | /** 12 | * RSI值 13 | */ 14 | float getRsi(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/IVolume.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | /** 4 | * 成交量接口 5 | * Created by hjm on 2017/11/14 17:46. 6 | */ 7 | 8 | public interface IVolume { 9 | 10 | /** 11 | * 开盘价 12 | */ 13 | float getOpenPrice(); 14 | 15 | /** 16 | * 收盘价 17 | */ 18 | float getClosePrice(); 19 | 20 | /** 21 | * 成交量 22 | */ 23 | float getVolume(); 24 | 25 | /** 26 | * 五(月,日,时,分,5分等)均量 27 | */ 28 | float getMA5Volume(); 29 | 30 | /** 31 | * 十(月,日,时,分,5分等)均量 32 | */ 33 | float getMA10Volume(); 34 | } 35 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/IWR.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | /** 4 | * @author fujianlian Created on 2018/8/20 15:16 5 | * @descripe WR指标(随机指标)接口 6 | */ 7 | public interface IWR { 8 | 9 | /** 10 | * %R值 11 | */ 12 | float getR(); 13 | 14 | } -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/entity/OrderEntity.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.entity; 2 | 3 | public class OrderEntity { 4 | private long orderTimeStamp; 5 | private long orderStopTimeStamp; 6 | private String amount; 7 | private boolean isUp; 8 | 9 | 10 | public String getAmount() { 11 | return amount; 12 | } 13 | 14 | public void setAmount(String amount) { 15 | this.amount = amount; 16 | } 17 | 18 | public long getOrderTimeStamp() { 19 | return orderTimeStamp; 20 | } 21 | 22 | public void setOrderTimeStamp(long orderTimeStamp) { 23 | this.orderTimeStamp = orderTimeStamp; 24 | } 25 | 26 | public long getOrderStopTimeStamp() { 27 | return orderStopTimeStamp; 28 | } 29 | 30 | public void setOrderStopTimeStamp(long orderStopTimeStamp) { 31 | this.orderStopTimeStamp = orderStopTimeStamp; 32 | } 33 | 34 | 35 | public boolean isUp() { 36 | return isUp; 37 | } 38 | 39 | public void setUp(boolean up) { 40 | isUp = up; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "OrderEntity{" + 46 | "orderTimeStamp=" + orderTimeStamp + 47 | ", orderStopTimeStamp=" + orderStopTimeStamp + 48 | ", amount='" + amount + '\'' + 49 | ", isUp=" + isUp + 50 | '}'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/formatter/BigValueFormatter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.formatter; 2 | 3 | import com.github.fujianlian.klinechart.base.IValueFormatter; 4 | 5 | import java.util.Locale; 6 | 7 | /** 8 | * 对较大数据进行格式化 9 | * Created by tifezh on 2017/12/13. 10 | */ 11 | 12 | public class BigValueFormatter implements IValueFormatter { 13 | 14 | //必须是排好序的 15 | private int[] values = {10000, 1000000, 100000000}; 16 | private String[] units = {"万", "百万", "亿"}; 17 | 18 | @Override 19 | public String format(float value, int digit) { 20 | String unit = ""; 21 | int i = values.length - 1; 22 | while (i >= 0) { 23 | if (value > values[i]) { 24 | value /= values[i]; 25 | unit = units[i]; 26 | break; 27 | } 28 | i--; 29 | } 30 | return String.format(Locale.getDefault(), "%.2f", value) + unit; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/formatter/DateFormatter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.formatter; 2 | 3 | import com.github.fujianlian.klinechart.base.IDateTimeFormatter; 4 | import com.github.fujianlian.klinechart.utils.DateUtil; 5 | 6 | import java.util.Date; 7 | 8 | 9 | /** 10 | * 时间格式化器 11 | * Created by tifezh on 2016/6/21. 12 | */ 13 | 14 | public class DateFormatter implements IDateTimeFormatter { 15 | @Override 16 | public String format(Date date) { 17 | if (date != null) { 18 | return DateUtil.DateFormat.format(date); 19 | } else { 20 | return ""; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/formatter/TimeFormatter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.formatter; 2 | 3 | import com.github.fujianlian.klinechart.base.IDateTimeFormatter; 4 | import com.github.fujianlian.klinechart.utils.DateUtil; 5 | 6 | import java.util.Date; 7 | 8 | 9 | /** 10 | * 时间格式化器 11 | * Created by tifezh on 2016/6/21. 12 | */ 13 | 14 | public class TimeFormatter implements IDateTimeFormatter { 15 | @Override 16 | public String format(Date date) { 17 | if (date == null) { 18 | return ""; 19 | } 20 | return DateUtil.shortTimeFormat.format(date); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/formatter/ValueFormatter.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.formatter; 2 | 3 | import com.github.fujianlian.klinechart.base.IValueFormatter; 4 | 5 | /** 6 | * Value格式化类 7 | * Created by tifezh on 2016/6/21. 8 | */ 9 | 10 | public class ValueFormatter implements IValueFormatter { 11 | 12 | 13 | @Override 14 | public String format(float value, int digit) { 15 | return String.format("%." + digit + "f", value); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/utils/Constants.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.utils; 2 | 3 | public class Constants { 4 | 5 | 6 | /** 7 | * case R.id.tv_ma: 8 | * setChildDraw(0); 9 | * break; 10 | * case R.id.tv_boll: 11 | * setChildDraw(1); 12 | * break; 13 | * case R.id.tv_macd: 14 | * setChildDraw(2); 15 | * break; 16 | * case R.id.tv_kdj: 17 | * setChildDraw(3); 18 | * break; 19 | * case R.id.tv_rsi: 20 | * setChildDraw(4); 21 | * break; 22 | * case R.id.tv_vol: 23 | * setChildDraw(5); 24 | * break; 25 | * case R.id.tv_clear: 26 | * setChildDraw(6); 27 | * break; 28 | */ 29 | public static final int MA = 0; 30 | public static final int BOLL = 1; 31 | public static final int MACD = 2; 32 | public static final int KDJ = 3; 33 | public static final int RSI = 4; 34 | public static final int VOL = 5; 35 | public static final int CLEAR = 6; 36 | 37 | public static String CURRENT_LINE_TYPE = "RANG_TYPE"; 38 | public static final String RANG_TYPE = "RANG_TYPE"; 39 | public static final String LINE_TYPE = "LINE_TYPE"; 40 | public static final String CANDLE_TYPE = "CANDLE_TYPE"; 41 | public static final int RANG_ITEM = 30; //添加假数据实现k线左移 42 | 43 | //"1min", "5min", "15min", "30min", "60min", "1day", "1week", "1mon"}; 44 | public static final String FIVE_SECOND = "5s"; 45 | public static final String ONE_MINUTE = "1min"; 46 | public static final String FIVE_MINUTE = "5min"; 47 | public static final String FIFTEEN_MINUTE = "15min"; 48 | public static final String THIRTY_MINUTE = "30min"; 49 | public static final String SIXTY_MINUTE = "60min"; 50 | public static final String ONE_DAY = "1day"; 51 | public static final String ONE_WEEK = "1week"; 52 | public static final String ONE_MON = "1mon"; 53 | } 54 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/utils/DateUtil.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.utils; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import java.util.Date; 7 | import java.util.Locale; 8 | 9 | /** 10 | * 时间工具类 11 | * Created by tifezh on 2016/4/27. 12 | */ 13 | public class DateUtil { 14 | public static SimpleDateFormat longTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 15 | public static SimpleDateFormat shortTimeFormat = new SimpleDateFormat("HH:mm"); 16 | public static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy/MM/dd"); 17 | private static String timeString; 18 | private static DatePattern pattern; 19 | 20 | 21 | /** 22 | * 枚举日期格式 23 | * 24 | * @author Administrator 25 | */ 26 | public enum DatePattern { 27 | /** 28 | * 格式:"yyyy-MM-dd HH:mm:ss" 29 | */ 30 | ALL_TIME { 31 | public String getValue() { 32 | return "yyyy-MM-dd HH:mm:ss"; 33 | } 34 | }, 35 | /** 36 | * 格式:"yyyy-MM" 37 | */ 38 | ONLY_MONTH { 39 | public String getValue() { 40 | return "yyyy-MM"; 41 | } 42 | }, 43 | /** 44 | * 格式:"yyyy-MM-dd" 45 | */ 46 | ONLY_DAY { 47 | public String getValue() { 48 | return "yyyy-MM-dd"; 49 | } 50 | }, 51 | /** 52 | * 格式:"yyyy-MM-dd HH" 53 | */ 54 | ONLY_HOUR { 55 | public String getValue() { 56 | return "yyyy-MM-dd HH"; 57 | } 58 | }, 59 | /** 60 | * 格式:"yyyy-MM-dd HH:mm" 61 | */ 62 | ONLY_MINUTE { 63 | public String getValue() { 64 | return "yyyy-MM-dd HH:mm"; 65 | } 66 | }, 67 | /** 68 | * 格式:"MM-dd" 69 | */ 70 | ONLY_MONTH_DAY { 71 | public String getValue() { 72 | return "MM-dd"; 73 | } 74 | }, 75 | /** 76 | * 格式:"MM-dd HH:mm" 77 | */ 78 | ONLY_MONTH_SEC { 79 | public String getValue() { 80 | return "MM-dd HH:mm"; 81 | } 82 | }, 83 | /** 84 | * 格式:"MM-dd HH:mm" 85 | */ 86 | ONLY_MONTH_ALL_SEC { 87 | public String getValue() { 88 | return "MM-dd HH:mm:ss"; 89 | } 90 | }, 91 | /** 92 | * 格式:"HH:mm:ss" 93 | */ 94 | ONLY_TIME { 95 | public String getValue() { 96 | return "HH:mm:ss"; 97 | } 98 | }, 99 | /** 100 | * 格式:"HH:mm" 101 | */ 102 | ONLY_HOUR_MINUTE { 103 | public String getValue() { 104 | return "HH:mm"; 105 | } 106 | }, 107 | /** 108 | * 格式:"ss" 109 | */ 110 | ONLY_SECOND { 111 | public String getValue() { 112 | return "ss"; 113 | } 114 | }; 115 | 116 | public abstract String getValue(); 117 | } 118 | 119 | //字符串转时间戳 120 | public static String getTime(String timeString, DatePattern pattern) { 121 | String timeStamp = null; 122 | SimpleDateFormat sdf = new SimpleDateFormat(pattern.getValue()); 123 | Date d; 124 | try { 125 | d = sdf.parse(timeString); 126 | long l = d.getTime(); 127 | timeStamp = String.valueOf(l); 128 | } catch (ParseException e) { 129 | e.printStackTrace(); 130 | } 131 | return timeStamp; 132 | } 133 | 134 | //时间戳转字符串 135 | public static String getStrTime(String timeStamp, DatePattern pattern) { 136 | String timeString = null; 137 | SimpleDateFormat sdf = new SimpleDateFormat(pattern.getValue()); 138 | long l = Long.valueOf(timeStamp); 139 | timeString = sdf.format(new Date(l));//单位秒 140 | return timeString; 141 | } 142 | 143 | 144 | private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); 145 | 146 | private DateUtil() { 147 | } 148 | 149 | ; 150 | 151 | 152 | /** 153 | * 往后推移时间 154 | * 155 | * @param date 156 | * @param minute 157 | * @return 158 | * @throws ParseException 159 | */ 160 | public static String dealTime(String date, int minute) throws ParseException { 161 | SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 162 | Date d = sd.parse(date); 163 | // 把当前得到的时间用date.getTime()的方法写成时间戳的形式,再加上8小时对应的毫秒数 164 | long rightTime = (d.getTime() + minute * 60 * 1000); 165 | // 把得到的新的时间戳再次格式化成时间的格式 166 | String newtime = sd.format(rightTime); 167 | return sd.parse(newtime).getTime() + ""; 168 | 169 | } 170 | 171 | 172 | /** 173 | * 将时分秒转换成时分 174 | * 175 | * @param time hh:mm:ss 176 | * @return hh:mm 177 | */ 178 | public static String getOnlyMinute(String time) { 179 | if (time.length() > 5) 180 | return time.substring(0, time.length() - 3); 181 | else return ""; 182 | } 183 | 184 | /** 185 | * 获取当前时间 186 | * 187 | * @return 返回当前时间,格式2015-12-3 10:54:21 188 | */ 189 | public static String getNowDate(DatePattern pattern) { 190 | String dateString = null; 191 | Calendar calendar = Calendar.getInstance(); 192 | Date dateNow = calendar.getTime(); 193 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.getValue(), Locale.CHINA); 194 | dateString = simpleDateFormat.format(dateNow); 195 | return dateString; 196 | } 197 | 198 | /** 199 | * 获取当前时间戳 200 | * 201 | * @return 返回当前时间,格式2015-12-3 202 | */ 203 | public static Date getNowDate(String year, String month, String day) { 204 | Date date = null; 205 | try { 206 | date = sdf.parse(year + month + day); 207 | } catch (Exception e) { 208 | e.printStackTrace(); 209 | } 210 | return date; 211 | } 212 | 213 | /** 214 | * 将一个日期字符串转换成Data对象 215 | * 216 | * @param dateString 日期字符串 217 | * @param pattern 转换格式 218 | * @return 返回转换后的日期对象 219 | */ 220 | public static Date stringToDate(String dateString, DatePattern pattern) { 221 | Date date = null; 222 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.getValue(), Locale.CHINA); 223 | try { 224 | date = simpleDateFormat.parse(dateString); 225 | } catch (ParseException e) { 226 | e.printStackTrace(); 227 | } 228 | return date; 229 | } 230 | 231 | /** 232 | * 将date转换成字符串 233 | * 234 | * @param date 日期 235 | * @param pattern 日期的目标格式 236 | * @return 237 | */ 238 | public static String dateToString(Date date, DatePattern pattern) { 239 | String string = ""; 240 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern.getValue(), Locale.CHINA); 241 | string = simpleDateFormat.format(date); 242 | return string; 243 | } 244 | 245 | /** 246 | * 获取时间差 返回单位分钟 247 | * 248 | * @param start 249 | * @return 250 | */ 251 | public static int getSpaceTime(long start) { 252 | long end = System.currentTimeMillis(); 253 | int minute = (int) ((start * 1000 - end) / 1000 / 60); 254 | return minute; 255 | } 256 | 257 | /** 258 | * 获取指定日期周几 259 | * 260 | * @param date 指定日期 261 | * @return 返回值为: "周日", "周一", "周二", "周三", "周四", "周五", "周六" 262 | */ 263 | public static String getWeekOfDate(Date date) { 264 | String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"}; 265 | Calendar calendar = Calendar.getInstance(); 266 | calendar.setTime(date); 267 | int week = calendar.get(Calendar.DAY_OF_WEEK) - 1; 268 | if (week < 0) 269 | week = 0; 270 | return weekDays[week]; 271 | } 272 | 273 | /** 274 | * 获取指定日期对应周几的序列 275 | * 276 | * @param date 指定日期 277 | * @return 周一:1 周二:2 周三:3 周四:4 周五:5 周六:6 周日:7 278 | */ 279 | public static int getIndexWeekOfDate(Date date) { 280 | // Calendar calendar = Calendar.getInstance(); 281 | // calendar.setTime(date); 282 | // int index = calendar.get(Calendar.DAY_OF_WEEK); 283 | // if(index == 1){ 284 | // return 7; 285 | // }else{ 286 | // return --index; 287 | // } 288 | Calendar now = Calendar.getInstance(); 289 | //一周第一天是否为星期天 290 | boolean isFirstSunday = (now.getFirstDayOfWeek() == Calendar.SUNDAY); 291 | //获取周几 292 | int weekDay = now.get(Calendar.DAY_OF_WEEK); 293 | //若一周第一天为星期天,则-1 294 | if (isFirstSunday) { 295 | weekDay = weekDay - 1; 296 | if (weekDay == 0) { 297 | weekDay = 7; 298 | } 299 | } 300 | return weekDay; 301 | //若当天为2014年10月13日(星期一),则打印输出:1 302 | //若当天为2014年10月17日(星期五),则打印输出:5 303 | //若当天为2014年10月19日(星期日),则打印输出:7 304 | } 305 | 306 | 307 | //获取当前月的第一天 308 | public static String getMonthStartDate(DatePattern datePattern) { 309 | // SimpleDateFormat dateFormater = new SimpleDateFormat( 310 | // "yyyy-MM-dd"); 311 | SimpleDateFormat dateFormater = new SimpleDateFormat( 312 | datePattern.getValue()); 313 | Calendar cal = Calendar.getInstance(); 314 | cal.set(Calendar.DAY_OF_MONTH, 1); 315 | cal.getTime(); 316 | return dateFormater.format(cal.getTime()) + ""; 317 | 318 | } 319 | 320 | //获取当前月的最后一天 321 | public static String getMonthEndDate(DatePattern datePattern) { 322 | SimpleDateFormat dateFormater = new SimpleDateFormat( 323 | datePattern.getValue()); 324 | Calendar cal = Calendar.getInstance(); 325 | cal.set(Calendar.DAY_OF_MONTH, 326 | cal.getActualMaximum(Calendar.DAY_OF_MONTH)); 327 | return dateFormater.format(cal.getTime()); 328 | } 329 | 330 | /** 331 | * 返回当前月份 332 | * 333 | * @return 334 | */ 335 | public static int getNowMonth() { 336 | Calendar calendar = Calendar.getInstance(); 337 | return calendar.get(Calendar.MONTH) + 1; 338 | } 339 | 340 | /** 341 | * 获取当前月号 342 | * 343 | * @return 344 | */ 345 | public static int getNowDay() { 346 | Calendar calendar = Calendar.getInstance(); 347 | return calendar.get(Calendar.DATE); 348 | } 349 | 350 | /** 351 | * 获取当前年份 352 | * 353 | * @return 354 | */ 355 | public static int getNowYear() { 356 | Calendar calendar = Calendar.getInstance(); 357 | return calendar.get(Calendar.YEAR); 358 | } 359 | 360 | /** 361 | * 获取当前小时 362 | * 363 | * @return 364 | */ 365 | public static int getNowHour() { 366 | Calendar calendar = Calendar.getInstance(); 367 | return calendar.get(Calendar.HOUR); 368 | } 369 | 370 | /** 371 | * 获取当前分钟 372 | * 373 | * @return 374 | */ 375 | public static int getNowMinute() { 376 | Calendar calendar = Calendar.getInstance(); 377 | return calendar.get(Calendar.MINUTE); 378 | } 379 | 380 | /** 381 | * 数据补0 如8月 返回08 9号返回09 382 | * 383 | * @param number 384 | * @return 385 | */ 386 | public static String getTwoDigitNumber(int number) { 387 | if (number < 10) { 388 | return "0" + number; 389 | } else { 390 | return number + ""; 391 | } 392 | } 393 | 394 | /** 395 | * 获取本月份的天数 396 | * 397 | * @param 398 | * @param 399 | * @return 400 | */ 401 | public static int getNowDaysOfMonth() { 402 | Calendar calendar = Calendar.getInstance(); 403 | return daysOfMonth(calendar.get(Calendar.YEAR), calendar.get(Calendar.DATE) + 1); 404 | } 405 | 406 | /** 407 | * 获取指定月份的天数 408 | * 409 | * @param year 年份 410 | * @param month 月份 411 | * @return 对应天数 412 | */ 413 | public static int daysOfMonth(int year, int month) { 414 | switch (month) { 415 | case 1: 416 | case 3: 417 | case 5: 418 | case 7: 419 | case 8: 420 | case 10: 421 | case 12: 422 | return 31; 423 | case 4: 424 | case 6: 425 | case 9: 426 | case 11: 427 | return 30; 428 | case 2: 429 | if ((year % 4 == 0 && year % 100 == 0) || year % 400 == 0) { 430 | return 29; 431 | } else { 432 | return 28; 433 | } 434 | default: 435 | return -1; 436 | } 437 | } 438 | 439 | 440 | /** 441 | * 推移时间 442 | * 443 | * @param stDate 被推移的当前时间 444 | * @param pattern 当前时间的时间格式 yyyy:MM:dd 445 | * @param amount 需要推移的天数 (1为 后一天 -1为前一天) 446 | * @return 447 | */ 448 | public static String dateOfMove(String stDate, int amount, DatePattern pattern) { 449 | if (stDate == null) 450 | return null; 451 | Calendar c = Calendar.getInstance(); 452 | Date date = stringToDate(stDate, pattern); 453 | c.setTime(date); 454 | c.add(Calendar.DAY_OF_MONTH, amount);// 今天+1天 455 | Date tomorrow = c.getTime(); 456 | return dateToString(tomorrow, pattern); 457 | } 458 | 459 | /** 460 | * 推移时间 461 | * 462 | * @param stDate 被推移的当前时间 463 | * @param amount 需要推移的天数 (1为 后一天 -1为前一天) 464 | * @return 465 | */ 466 | public static Date dateOfMove(Date stDate, int amount) { 467 | if (stDate == null) 468 | return null; 469 | Calendar c = Calendar.getInstance(); 470 | c.setTime(stDate); 471 | c.add(Calendar.DAY_OF_MONTH, amount);// 今天+1天 472 | Date tomorrow = c.getTime(); 473 | return tomorrow; 474 | } 475 | 476 | 477 | // a integer to xx:xx:xx 将秒转换为时分秒的字符串 478 | public static String secToTime(long time) { 479 | String timeStr = null; 480 | long hour = 0; 481 | long minute = 0; 482 | long second = 0; 483 | if (time <= 0) 484 | return "00:00"; 485 | else { 486 | minute = time / 60; 487 | if (minute < 60) { 488 | second = time % 60; 489 | timeStr = unitFormat(minute) + ":" + unitFormat(second); 490 | } else { 491 | hour = minute / 60; 492 | if (hour > 99) 493 | return "99:59:59"; 494 | minute = minute % 60; 495 | second = time - hour * 3600 - minute * 60; 496 | timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second); 497 | } 498 | } 499 | return timeStr; 500 | } 501 | 502 | public static String unitFormat(long i) { 503 | String retStr = null; 504 | if (i >= 0 && i < 10) 505 | retStr = "0" + Long.toString(i); 506 | else 507 | retStr = "" + i; 508 | return retStr; 509 | } 510 | 511 | /** 512 | * 毫秒转换为 天数 小数数 分钟数 xx 513 | * 514 | * @param nmMillSecond 515 | * @return 516 | */ 517 | public static MyTimeBean millSecondToTimeBean(long nmMillSecond) { 518 | MyTimeBean myTimeBean = new MyTimeBean(); 519 | long millSecond = nmMillSecond % 1000 / 10; 520 | myTimeBean.setMillSecond(millSecond + ""); 521 | nmMillSecond = nmMillSecond / 1000; 522 | long days = nmMillSecond / (60 * 60 * 24); 523 | 524 | //long hours = (nmMillSecond % ( 60 * 60 * 24)) / (60 * 60); 525 | long hour; 526 | if (days > 0) { 527 | hour = (nmMillSecond % (60 * 60 * 24)) / (60 * 60);//时 528 | } else { 529 | hour = nmMillSecond / 3600;//时 530 | } 531 | long minutes = (nmMillSecond % (60 * 60)) / 60; 532 | long seconds = nmMillSecond % 60; 533 | 534 | myTimeBean.setSecond(seconds + ""); 535 | myTimeBean.setMinute(minutes + ""); 536 | myTimeBean.setHour(hour + ""); 537 | myTimeBean.setDay(days + ""); 538 | return myTimeBean; 539 | } 540 | 541 | /** 542 | * 毫秒转天数+小时数+分钟数+秒数+毫秒数 543 | */ 544 | public static class MyTimeBean { 545 | String day; 546 | String hour; 547 | String minute; 548 | String second; 549 | String millSecond; 550 | 551 | public MyTimeBean() { 552 | } 553 | 554 | public String getDay() { 555 | return day; 556 | } 557 | 558 | public void setDay(String day) { 559 | this.day = day; 560 | } 561 | 562 | public String getHour() { 563 | return hour; 564 | } 565 | 566 | public void setHour(String hour) { 567 | this.hour = hour; 568 | } 569 | 570 | public String getMinute() { 571 | return minute; 572 | } 573 | 574 | public void setMinute(String minute) { 575 | this.minute = minute; 576 | } 577 | 578 | public String getSecond() { 579 | return second; 580 | } 581 | 582 | public void setSecond(String second) { 583 | this.second = second; 584 | } 585 | 586 | public String getMillSecond() { 587 | return millSecond; 588 | } 589 | 590 | public void setMillSecond(String millSecond) { 591 | this.millSecond = millSecond; 592 | } 593 | } 594 | } 595 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/java/com/github/fujianlian/klinechart/utils/ViewUtil.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart.utils; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by tian on 2016/4/11. 7 | */ 8 | public class ViewUtil { 9 | static public int Dp2Px(Context context, float dp) { 10 | final float scale = context.getResources().getDisplayMetrics().density; 11 | return (int) (dp * scale + 0.5f); 12 | } 13 | 14 | static public int Px2Dp(Context context, float px) { 15 | final float scale = context.getResources().getDisplayMetrics().density; 16 | return (int) (px / scale + 0.5f); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/ic_down_order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/KLineChartLib/src/main/res/drawable/ic_down_order.png -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/ic_point_kline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/KLineChartLib/src/main/res/drawable/ic_point_kline.png -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/ic_start_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/KLineChartLib/src/main/res/drawable/ic_start_time.png -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/ic_stop_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/KLineChartLib/src/main/res/drawable/ic_stop_time.png -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/ic_target_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/KLineChartLib/src/main/res/drawable/ic_target_normal.png -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/ic_target_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/KLineChartLib/src/main/res/drawable/ic_target_pressed.png -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/ic_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/KLineChartLib/src/main/res/drawable/ic_up.png -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/selector_button_target.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/drawable/shape_rectangle_with.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | 8 | 9 | #D04B63 10 | #FF8A7C 11 | #6384FF 12 | #E8D28E 13 | #57BEB1 14 | #53B4A9 15 | #53B4A9 16 | 17 | #5498FF 18 | #00ffffff 19 | 20 | #445498FF 21 | #6384FF 22 | 23 | #DA8AE5 24 | #39B0E8 25 | #FFC76D 26 | #ffffff 27 | #53B4A9 28 | 29 | #202326 30 | #111622 31 | #202326 32 | #662B2D52 33 | #818596 34 | #882E3546 35 | #30343C 36 | #3F51B5 37 | #FF6601 38 | #111622 39 | 40 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 10sp 3 | 12sp 4 | 1dp 5 | 6dp 6 | 1dp 7 | 0.8dp 8 | 0.5dp 9 | 7dp 10 | 15dp 11 | 15dp 12 | 10dp 13 | -------------------------------------------------------------------------------- /KLineChartLib/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | KlineChartView 4 | 5 | 6 | 注册 7 | 登录 8 | 请输入账号 9 | 请输入密码 10 | 获取验证码 11 | 验证码登录 12 | 请输入验证码 13 | 请输入邀请码 14 | 用户名     15 | 未实名认证 16 | 充值/入金 17 | 提现/出金 18 | 账户管理 19 | 交易记录 20 | 出金记录 21 | 入金记录 22 | 订单交易记录 23 | 退出账号 24 | DCF账户 25 | 银行卡 26 | 模拟账户 27 | 充值 28 | 欢迎来到DCF 29 | 注册领取5000USDT模拟金 30 | 密码不记得了,点击忘记密码 31 | 领取5000USDT模拟金 32 | 通过注册,已表示同意【条款与要求】 33 | 个人信息 34 | 启动页 35 | 请输入姓名 36 | 姓名 37 | 证件 38 | 身份证 39 | 护照 40 | 证件号码 41 | 银行卡号 42 | 请输入手机号 43 | 预留手机号 44 | 手机号 45 | 证件地址 46 | 未实名认证 47 | 用户名 48 | 姓名 49 | 国家 50 | 省份 51 | 城市 52 | 1分 53 | 时间 54 | 金额(USDT) 55 | 收益 56 | 买涨 57 | 买跌 58 | 建设银行 59 | 比特币 60 | 图表 61 | 范围图 62 | 线性图 63 | K线图 64 | 全部余额 65 | 真实账户 66 | 67 | 储蓄卡 68 | 用户名 69 | 实名认证 70 | 出金账户 71 | 目标账户 72 | 金额数量 73 | 交易时间 74 | 总收益 75 | 总百分比 76 | 总投资 77 | 总保证金 78 | 设定 79 | 止盈 80 | 添加止盈 81 | 添加止损 82 | 止损 83 | 默认 84 | 应用 85 | 保证金 86 | 百分比 87 | 订单详情 88 | 保证金以USDT计价,用于承担交易亏损。在平仓后,如盈利保证金全额退还;如亏损还有剩余保证金退还剩余部分;平仓手续费从退还保证金中扣除 89 | 密码登录 90 | 忘记密码 91 | 保存 92 | 新密码 93 | 请输入密码 94 | 请输入编号 95 | 修改成功 96 | 登录成功 97 | 重新获取 98 | 99 | %1$s 100 | %1$s USDT 101 | 订单号 %1$s 102 | 请输入用户名 103 | 请输入姓名 104 | 请输入证件号码 105 | 请输入银行卡号 106 | 立即认证 107 | 认证成功 108 | 关闭 109 | 入金 110 | 出金 111 | 充值数量(USDT) 112 | 请输入充值数量 113 | 阅读相关事项,点击充值需知 114 | 确定 115 | 充值需知 116 | 提币数量(USDT) 117 | 请输入提币数量 118 | DC账户余额 119 | 全部提币 120 | 电子钱包地址 121 | 请输入电子钱包地址 122 | 没有电子钱包,点击注册 123 | - %1$s 124 | + %1$s 125 | 总额(USDT) 126 | 立即添加 127 | 再按一次就可以退出了 128 | 本应用基本功能需要您授予权限 129 | 设定成功 130 | 注册成功 131 | 132 | 购买成功 133 | 验证码已发送至 134 | 验证码 135 | 删除 136 | 累计收益(USDT) 137 | 累计投资(USDT) 138 | 账户号码 139 | 货币类型 140 | 储蓄卡片 141 | 当前价格 142 | 当前收益(USDT): 143 | 当前P/L: 144 | 重试 145 | 投资(USDT): 146 | 确认平仓价格 147 | 您确定要退出吗 148 | 取消 149 | 杠杆 150 | 数量 151 | 止损 152 | 成交价格 153 | 平仓价 154 | 成交时间 155 | 结算时间 156 | 订单号 157 | 买入价格 158 | 平仓 159 | 购买 160 | 出售 161 | 指标 162 | 简介 163 | 期权 164 | 热门 165 | 当日 166 | 持仓订单 167 | 历史订单 168 | 暂无订单 169 | 1. 单笔提币按10的倍数执行\n2. 单笔提币金额不低于100USDT\n3. 提币承兑收取手续费为5%比率\n4. 仅支持OMNI协议的电子钱包 170 | 下一步 171 | *为了用户帐号的安全,DCF平台帐号系统将进行全面升级,已完成注册的用户需升级为助记词方式登录,对此给您造成的不便我们深感抱歉。 172 | 原手机号与密码: 173 | 手机号 174 | 新账号与密码 175 | 我知道了,下一步 176 | 使用纸笔正确地抄写助记词。\n手机遗失、损坏、可使用助记词恢复密码。 177 | 请勿将助记词在联网设备储存、传输、不要保存在\n手机相册、邮箱、网盘、社交软件中。\n不要向任何人透漏您的记词。 178 | DCF平台通过12个助记词可找回您的密码, 179 | 知道了 180 | 截屏或分享图片有恶意软件截取助记词的巨大风险。 \n为了您的密码安全,请务必正确抄写助记词。 181 | *DCF平台帐号系统全面升级, 原账号无法登入 182 | 正确抄写下面12个助记词\n助记词是恢复密码的唯一途径 183 | 我已抄好,去验证 184 | 请依次填写助记词(横向输入) 185 | 找回密码 186 | 请输入新密码 187 | 购买USDT 188 | 直充USDT 189 | 请输入电子钱包地址 190 | 账号为字母与数字组合 首位字母 6-18位字符 191 | 密码为6-18位字符 192 | 请输入原手机号 193 | 请输入账号 194 | 请再次输入密码 195 | 请再次输入密码 196 | 两次密码输入不一致 197 | 验证码有误 198 | 无可解约金额 199 | 数  字  资  产  金  融  期  权  交  易 200 | 刷新虚拟账户余额成功 201 | 图片保存成功 202 | 203 | 204 | -------------------------------------------------------------------------------- /KLineChartLib/src/test/java/com/github/fujianlian/klinechart/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.github.fujianlian.klinechart; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KLineChartView 2 | 3 | Android仿IQ Option K线图实现(包含MA,BOLL,MACD,KDJ,RSI,VOL指标) 4 | 5 | 本项目是在 https://github.com/fujianlian/KLineChart 基础上进行修改的,对UI展示进行了修改。 6 | 7 | 本项目模拟了socket实时推送数据效果,如果项目要使用StompProtocol可以参考我另外一个项目:https://github.com/VincentStory/StompForAndroid ,有具体的接入过程 8 | 9 | ## 效果预览 10 | 11 | ### 效果图中包括范围图,线性图,柱状图随意切换,以及各种指标线展示,自定义显示和隐藏VOL指标 12 | 13 | ![效果图](https://github.com/VincentStory/KLineChartView/blob/master/IMG_4115.GIF) 14 | ![截图](https://github.com/VincentStory/KLineChartView/blob/master/img1.jpg) 15 | 16 | ## 引入项目流程 17 | 18 | ### 1.xml引入KChartView 19 | ``` 20 | 24 | 25 | 26 | ``` 27 | ### 2.添加数据并刷新view 28 | ``` 29 | datas = DataRequest.getALL(MainActivity.this).subList(0, 500); 30 | adapter.addFooterData(datas); 31 | adapter.notifyDataSetChanged(); 32 | 33 | if (kLineChartView != null) { 34 | kLineChartView.startAnimation(); 35 | kLineChartView.refreshEnd(); 36 | kLineChartView.hideChildDraw(); 37 | } 38 | ``` 39 | ### 3.显示和隐藏指标线 40 | 41 | ``` 42 | setChildDraw(Constants.MA); 43 | 44 | setChildDraw(Constants.BOLL); 45 | 46 | setChildDraw(Constants.MACD); 47 | 48 | setChildDraw(Constants.KDJ); 49 | 50 | setChildDraw(Constants.RSI); 51 | 52 | setChildDraw(Constants.VOL); 53 | 54 | setChildDraw(Constants.CLEAR); 55 | ``` 56 | ### 4.如有其他特定需求,需在BaseKLineChartView改写代码完成逻辑计算,和绘制特定效果 57 | 58 | -----------------------完成-------------------- 59 | 60 | 如果对你有所帮助的话,欢迎Star或者Fork,有遇到其他问题可以加我vx进行沟通 61 | QQ:459005147 备注:android交流 62 | 63 | ``` 64 | Copyright 2018 VincentStory 65 | 66 | Licensed under the Apache License, Version 2.0 (the "License"); 67 | you may not use this file except in compliance with the License. 68 | You may obtain a copy of the License at 69 | 70 | http://www.apache.org/licenses/LICENSE-2.0 71 | 72 | Unless required by applicable law or agreed to in writing, software 73 | distributed under the License is distributed on an "AS IS" BASIS, 74 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 75 | See the License for the specific language governing permissions and 76 | limitations under the License. 77 | 78 | ``` 79 | 80 | 81 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.android.compileSdkVersion 5 | 6 | defaultConfig { 7 | applicationId rootProject.ext.android.applicationId 8 | minSdkVersion rootProject.ext.android.minSdkVersion 9 | targetSdkVersion rootProject.ext.android.targetSdkVersion 10 | versionCode rootProject.ext.android.versionCode 11 | versionName rootProject.ext.android.versionName 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | multiDexEnabled true 14 | 15 | ndk { 16 | abiFilters "armeabi", "armeabi-v7a", "x86" 17 | } 18 | 19 | 20 | } 21 | packagingOptions { 22 | doNotStrip '*/mips/*.so' 23 | doNotStrip '*/mips64/*.so' 24 | } 25 | 26 | buildTypes { 27 | release { 28 | minifyEnabled false 29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 30 | } 31 | } 32 | sourceSets { 33 | main { 34 | java { 35 | srcDir 'src/main/java' 36 | } 37 | 38 | } 39 | } 40 | 41 | 42 | 43 | compileOptions { 44 | //https://www.jianshu.com/p/f2b58ff0b152 45 | //强制使用1.8的jdk 这是让你的IDE强制使用JAVA8 46 | sourceCompatibility rootProject.ext.dependVersion.appSourceCompatibility 47 | targetCompatibility rootProject.ext.dependVersion.appTargetCompatibility 48 | } 49 | } 50 | 51 | dependencies { 52 | implementation fileTree(dir: 'libs', include: ['*.jar']) 53 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 54 | testImplementation 'junit:junit:4.12' 55 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 56 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 57 | 58 | api rootProject.ext.dependencies.design 59 | api rootProject.ext.dependencies.appcompatV7 60 | api rootProject.ext.dependencies.supportV4 61 | implementation project(':KLineChartLib') 62 | implementation 'com.google.code.gson:gson:2.2.4' 63 | implementation 'com.jakewharton:butterknife:8.5.1' 64 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1' 65 | implementation rootProject.ext.dependencies.baseAdater 66 | 67 | } 68 | -------------------------------------------------------------------------------- /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:\Users\sdt1\AppData\Local\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 | #-----------------混淆配置设定------------------------------------------------------------------------ 20 | -optimizationpasses 5 #指定代码压缩级别 21 | -dontusemixedcaseclassnames #混淆时不会产生形形色色的类名 22 | -dontskipnonpubliclibraryclasses #指定不忽略非公共类库 23 | -dontpreverify #不预校验,如果需要预校验,是-dontoptimize 24 | -ignorewarnings #屏蔽警告 25 | -verbose #混淆时记录日志 26 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #优化 27 | 28 | -dontoptimize 29 | -dontwarn cn.jpush.** 30 | -keep class cn.jpush.** { *; } 31 | 32 | -dontwarn cn.jiguang.** 33 | -keep class cn.jiguang.** { *; } 34 | -keep public class cn.jiguang.analytics.android.api.** { 35 | *; 36 | } 37 | 38 | 39 | #-----------------不需要混淆第三方类库------------------------------------------------------------------ 40 | -dontwarn android.support.v4.** #去掉警告 41 | -keep class android.support.v4.** { *; } #过滤android.support.v4 42 | -keep interface android.support.v4.app.** { *; } 43 | -keep public class * extends android.support.v4.** 44 | -keep public class * extends android.app.Fragment 45 | 46 | -keep class org.apache.**{*;} #过滤commons-httpclient-3.1.jar 47 | 48 | -keep class com.fasterxml.jackson.**{*;} #过滤jackson-core-2.1.4.jar等 49 | 50 | -dontwarn com.lidroid.xutils.** #去掉警告 51 | -keep class com.lidroid.xutils.**{*;} #过滤xUtils-2.6.14.jar 52 | -keep class * extends java.lang.annotation.Annotation{*;} #这是xUtils文档中提到的过滤掉注解 53 | -keep public class * implements com.bumptech.glide.module.GlideModule 54 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { 55 | **[] $VALUES; 56 | public *; 57 | } 58 | -keep class butterknife.** { *; } 59 | -dontwarn butterknife.internal.** 60 | -keep class **$$ViewBinder { *; } 61 | -keepclasseswithmembernames class * { 62 | @butterknife.* ; 63 | } 64 | -keepclasseswithmembernames class * { 65 | @butterknife.* ; 66 | } 67 | -dontwarn android.support.** 68 | -dontwarn com.google.android.maps.** 69 | -dontwarn com.slidingmenu.lib.app.SlidingMapActivity 70 | -keep class android.support.** { *; } 71 | -keep class com.actionbarsherlock.** { *; } 72 | -keep interface com.actionbarsherlock.** { *; } 73 | -keep class com.slidingmenu.** { *; } 74 | -keep interface com.slidingmenu.** { *; } 75 | -keepclassmembers class * implements java.io.Serializable { 76 | static final long serialVersionUID; 77 | private static final java.io.ObjectStreamField[] serialPersistentFields; 78 | private void writeObject(java.io.ObjectOutputStream); 79 | private void readObject(java.io.ObjectInputStream); 80 | java.lang.Object writeReplace(); 81 | java.lang.Object readResolve(); 82 | } 83 | -keep public class * implements java.io.Serializable {*;} 84 | -keepclassmembers class * implements android.os.Parcelable { 85 | public ; 86 | private ; 87 | } 88 | -keep class * implements android.os.Parcelable { 89 | public static final android.os.Parcelable$Creator *; 90 | } 91 | -keepclassmembers class fqcn.of.javascript.interface.for.webview { 92 | public *; 93 | } 94 | -keepclassmembers class * extends android.webkit.webViewClient { 95 | public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); 96 | public boolean *(android.webkit.WebView, java.lang.String); 97 | } 98 | -keepclassmembers class * extends android.webkit.webViewClient { 99 | public void *(android.webkit.webView, jav.lang.String); 100 | } 101 | -dontwarn javax.** 102 | -dontwarn org.junit.Test 103 | 104 | -dontwarn android.net.** 105 | -keep class android.net.SSLCertificateSocketFactory{*;} 106 | 107 | -dontwarn com.tencent.mm.** 108 | -keep class com.tencent.mm.**{*;} 109 | 110 | -dontwarn com.loopj.android.http.** 111 | -keep class com.loopj.android.http.** { *; } 112 | 113 | ##微博 114 | -keep public class com.sina.weibo.** {*;} 115 | -dontwarn com.sina.weibo.** 116 | -keep public class com.sina.sso.** {*;} 117 | -dontwarn com.sina.sso.** 118 | 119 | ##otto 120 | -keepattributes *Annotation* 121 | -keepclassmembers class ** { 122 | @com.squareup.otto.Subscribe public *; 123 | @com.squareup.otto.Produce public *; 124 | } 125 | 126 | ##拍照 127 | -keep class com.jph.takephoto.** { *; } 128 | -dontwarn com.jph.takephoto.** 129 | 130 | -keep class com.darsh.multipleimageselect.** { *; } 131 | -dontwarn com.darsh.multipleimageselect.** 132 | 133 | -keep class com.soundcloud.android.crop.** { *; } 134 | -dontwarn com.soundcloud.android.crop.** 135 | 136 | -dontwarn com.alipay.** 137 | -keep class com.alipay.** { *;} 138 | -keep class com.alipay.android.app.IAlixPay{*;} 139 | -keep class com.alipay.android.app.IAlixPay$Stub{*;} 140 | -keep class com.alipay.android.app.IRemoteServiceCallback{*;} 141 | -keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;} 142 | -keep class com.alipay.sdk.app.PayTask{ public *;} 143 | -keep class com.alipay.sdk.app.AuthTask{ public *;} 144 | -keep class com.alipay.sdk.app.H5PayCallback { 145 | ; 146 | ; 147 | } 148 | -keep class com.alipay.android.phone.mrpc.core.** { *; } 149 | -keep class com.alipay.apmobilesecuritysdk.** { *; } 150 | -keep class com.alipay.mobile.framework.service.annotation.** { *; } 151 | -keep class com.alipay.mobilesecuritysdk.face.** { *; } 152 | -keep class com.alipay.tscenter.biz.rpc.** { *; } 153 | -keep class org.json.alipay.** { *; } 154 | -keep class com.alipay.tscenter.** { *; } 155 | -keep class com.ta.utdid2.** { *;} 156 | -keep class com.ut.device.** { *;} 157 | 158 | #okhttputils 159 | -dontwarn com.zhy.http.** 160 | -keep class com.zhy.http.**{*;} 161 | #okhttp 162 | -dontwarn okhttp3.** 163 | -keep class okhttp3.**{*;} 164 | #okio 165 | -dontwarn okio.** 166 | -keep class okio.**{*;} 167 | 168 | -keepattributes Signature 169 | # For using GSON @Expose annotation 170 | -keepattributes *Annotation* 171 | # Gson specific classes 172 | -dontwarn sun.misc.** 173 | -keep class * implements com.google.gson.TypeAdapterFactory 174 | -keep class * implements com.google.gson.JsonSerializer 175 | -keep class * implements com.google.gson.JsonDeserializer 176 | 177 | -dontwarn com.mcxtzhang.nestlistview.** 178 | -keep class com.mcxtzhang.nestlistview.**{*;} 179 | 180 | -dontwarn com.bigkoo.pickerview.** 181 | -keep class com.bigkoo.pickerview.**{*;} 182 | 183 | -dontwarn lecho.lib.hellocharts.** 184 | -keep class lecho.lib.hellocharts.**{*;} 185 | 186 | -dontwarn com.bm.library.** 187 | -keep class com.bm.library.**{*;} 188 | 189 | -dontwarn org.java_websocket.** 190 | -keep class org.java_websocket.**{*;} 191 | 192 | -keep class com.chad.library.adapter.** { 193 | *; 194 | } 195 | -keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter 196 | -keep public class * extends com.chad.library.adapter.base.BaseViewHolder 197 | -keepclassmembers public class * extends com.chad.library.adapter.base.BaseViewHolder { 198 | (android.view.View); 199 | } 200 | 201 | -dontwarn q.rorbin.verticaltablayout.** 202 | -keep class q.rorbin.verticaltablayout.**{*;} 203 | 204 | -dontwarn com.readystatesoftware.systembartint.** 205 | -keep class com.readystatesoftware.systembartint.**{*;} 206 | 207 | -dontwarn com.elbbbird.android.socialsdk.** 208 | -keep class com.elbbbird.android.socialsdk.**{*;} 209 | 210 | 211 | 212 | #-----------------不需要混淆系统组件等------------------------------------------------------------------- 213 | -keep public class * extends android.app.Activity 214 | -keep public class * extends android.app.Application 215 | -keep public class * extends android.app.Service 216 | -keep public class * extends android.content.BroadcastReceiver 217 | -keep public class * extends android.content.ContentProvider 218 | -keep public class * extends android.preference.Preference 219 | -keep public class com.android.vending.licensing.ILicensingService 220 | -keep class **.R$* { 221 | *;-ru 222 | } 223 | -keepclassmembers class * { 224 | void *(**On*Event); 225 | } 226 | -keepattributes EnclosingMethod 227 | 228 | -keep class com.android.aishangauction.model.**{*;} #过滤掉自己编写的实体类 229 | 230 | 231 | #----------------保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在------------------------------------ 232 | -keepclasseswithmembernames class * { 233 | public (android.content.Context, android.util.AttributeSet); 234 | } 235 | 236 | -keepclasseswithmembernames class * { 237 | public (android.content.Context, android.util.AttributeSet, int); 238 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/vincent/story/DataBean.java: -------------------------------------------------------------------------------- 1 | package com.vincent.story; 2 | 3 | public class DataBean { 4 | private String data; 5 | private boolean isSelected; 6 | private int type; 7 | private int position; 8 | 9 | public int getPosition() { 10 | return position; 11 | } 12 | 13 | public void setPosition(int position) { 14 | this.position = position; 15 | } 16 | 17 | public int getType() { 18 | return type; 19 | } 20 | 21 | public void setType(int type) { 22 | this.type = type; 23 | } 24 | 25 | public boolean isSelected() { 26 | return isSelected; 27 | } 28 | 29 | public void setSelected(boolean selected) { 30 | isSelected = selected; 31 | } 32 | 33 | public String getData() { 34 | return data; 35 | } 36 | 37 | public void setData(String data) { 38 | this.data = data; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "DataBean{" + 44 | "data='" + data + '\'' + 45 | ", isSelected=" + isSelected + 46 | ", type=" + type + 47 | ", position=" + position + 48 | '}'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/vincent/story/DataRequest.java: -------------------------------------------------------------------------------- 1 | package com.vincent.story; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.github.fujianlian.klinechart.DataHelper; 7 | import com.github.fujianlian.klinechart.KLineEntity; 8 | import com.google.gson.Gson; 9 | import com.google.gson.reflect.TypeToken; 10 | 11 | 12 | import java.io.InputStream; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * 模拟网络请求 18 | * Created by tifezh on 2017/7/3. 19 | */ 20 | 21 | public class DataRequest { 22 | private static List datas = null; 23 | 24 | public static String getStringFromAssert(Context context, String fileName) { 25 | try { 26 | InputStream in = context.getResources().getAssets().open(fileName); 27 | int length = in.available(); 28 | byte[] buffer = new byte[length]; 29 | in.read(buffer); 30 | return new String(buffer, 0, buffer.length, "UTF-8"); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | Log.i("exception==",e.getMessage()); 34 | } 35 | return ""; 36 | } 37 | 38 | public static List getALL(Context context) { 39 | if (datas == null) { 40 | // String string = getStringFromAssert(context, "ibm.json"); 41 | // Log.i("string==", string); 42 | final List data = new Gson().fromJson(getStringFromAssert(context, "ibm.json"), new TypeToken>() { 43 | }.getType()); 44 | 45 | DataHelper.calculate(data); 46 | datas = data; 47 | } 48 | return datas; 49 | } 50 | 51 | public static List addData(Context context) { 52 | if (datas != null) { 53 | KLineEntity entity = new KLineEntity(); 54 | entity.setClose((float) 86.875); 55 | entity.setDate("2016/10/28"); 56 | entity.setHigh((float) 154.059998); 57 | entity.setLow((float) 152.020004); 58 | entity.setOpen((float) 152.820007); 59 | entity.setVolume((float) 4126800); 60 | datas.add(new KLineEntity()); 61 | DataHelper.calculate(datas); 62 | } 63 | return datas; 64 | } 65 | 66 | 67 | /** 68 | * 分页查询 69 | * 70 | * @param context 71 | * @param offset 开始的索引 72 | * @param size 每次查询的条数 73 | */ 74 | public static List getData(Context context, int offset, int size) { 75 | List all = getALL(context); 76 | List data = new ArrayList<>(); 77 | int start = Math.max(0, all.size() - 1 - offset - size); 78 | int stop = Math.min(all.size(), all.size() - offset); 79 | for (int i = start; i < stop; i++) { 80 | data.add(all.get(i)); 81 | } 82 | return data; 83 | } 84 | 85 | } 86 | 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/vincent/story/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.vincent.story; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.support.annotation.LayoutRes; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.GridLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.util.Log; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.view.WindowManager; 14 | import android.widget.TextView; 15 | 16 | import com.github.fujianlian.klinechart.KLineChartAdapter; 17 | import com.github.fujianlian.klinechart.KLineChartView; 18 | import com.github.fujianlian.klinechart.KLineEntity; 19 | import com.github.fujianlian.klinechart.draw.Status; 20 | import com.github.fujianlian.klinechart.utils.Constants; 21 | import com.vincent.story.adapter.DateCycleAdapter; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | import java.util.Timer; 26 | import java.util.TimerTask; 27 | 28 | import butterknife.ButterKnife; 29 | import butterknife.OnClick; 30 | import butterknife.Unbinder; 31 | 32 | import static com.github.fujianlian.klinechart.utils.Constants.BOLL; 33 | import static com.github.fujianlian.klinechart.utils.Constants.CANDLE_TYPE; 34 | import static com.github.fujianlian.klinechart.utils.Constants.LINE_TYPE; 35 | import static com.github.fujianlian.klinechart.utils.Constants.RANG_ITEM; 36 | import static com.github.fujianlian.klinechart.utils.Constants.RANG_TYPE; 37 | 38 | 39 | public class MainActivity extends AppCompatActivity { 40 | 41 | private KLineChartView kLineChartView; 42 | 43 | private List datas;//模拟历史数据 44 | 45 | private List newDatas = new ArrayList<>();//模拟最新数据 46 | 47 | protected KLineChartAdapter adapter = new KLineChartAdapter(); 48 | 49 | private int position = 6;//默认关闭子view 50 | 51 | private Unbinder mBinder; 52 | 53 | private Timer timer = new Timer();//当前时间刷新 54 | 55 | private int mSecond = 0;//秒数 56 | 57 | @Override 58 | protected void onCreate(@Nullable Bundle savedInstanceState) { 59 | super.onCreate(savedInstanceState); 60 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 61 | setContentView(R.layout.activity_main); 62 | mBinder = ButterKnife.bind(this); 63 | kLineChartView = findViewById(R.id.kLineChartView); 64 | 65 | kLineChartView.setAdapter(adapter); 66 | kLineChartView.justShowLoading(); 67 | 68 | 69 | datas = DataRequest.getALL(MainActivity.this).subList(0, 500); 70 | newDatas.addAll(datas); 71 | Log.i("data==", datas.toString()); 72 | 73 | adapter.addFooterData(datas); 74 | adapter.notifyDataSetChanged(); 75 | 76 | if (kLineChartView != null) { 77 | kLineChartView.startAnimation(); 78 | kLineChartView.refreshEnd(); 79 | kLineChartView.hideChildDraw(); 80 | } 81 | 82 | setChildDraw(Constants.CLEAR); 83 | 84 | refreshData(); 85 | 86 | 87 | } 88 | 89 | 90 | @Override 91 | protected void onDestroy() { 92 | super.onDestroy(); 93 | mBinder.unbind(); 94 | } 95 | 96 | /** 97 | * 每秒刷新一次数据 ,每5秒新增一条数据 98 | */ 99 | private void refreshData() { 100 | timer.schedule(new TimerTask() { 101 | @Override 102 | public void run() { 103 | if (mSecond + RANG_ITEM + 1 >= newDatas.size()) { 104 | mSecond = 0; 105 | } 106 | KLineEntity kLineEntity = newDatas.get(newDatas.size() - mSecond - RANG_ITEM - 1); 107 | mSecond++; 108 | if (mSecond % 5 == 0) { 109 | datas.add(datas.size() - RANG_ITEM, kLineEntity); 110 | adapter.addData(kLineEntity, 0, "2"); 111 | } else { 112 | adapter.replaceData(kLineEntity, 0, "2"); 113 | datas.set(datas.size() - RANG_ITEM - 1, kLineEntity); 114 | } 115 | // adapter.addFooterData(datas); 116 | adapter.notifyDataSetChanged(); 117 | 118 | } 119 | }, 1000, 1000); 120 | } 121 | 122 | 123 | /** 124 | * 显示底部k线view和MA BOLL SAR 125 | * 126 | * @param position 127 | */ 128 | public void setChildDraw(int position) { 129 | this.position = position; 130 | if (kLineChartView != null) { 131 | if (position == Constants.MA) { 132 | kLineChartView.changeMainDrawType(Status.MA); 133 | } else if (position == Constants.BOLL) { 134 | kLineChartView.changeMainDrawType(Status.BOLL); 135 | } else if (position != Constants.CLEAR) { 136 | position -= 2; 137 | kLineChartView.setChildDraw(position); 138 | } else { 139 | hideChildView(); 140 | } 141 | 142 | } 143 | adapter.notifyDataSetChanged(); 144 | } 145 | 146 | public void hideChildView() { 147 | if (kLineChartView != null) { 148 | kLineChartView.hideChildDraw(); 149 | kLineChartView.changeMainDrawType(Status.NONE); 150 | } 151 | } 152 | 153 | public void setKlineType(String klineType) { 154 | if (kLineChartView != null) { 155 | kLineChartView.setKlineType(klineType); 156 | } 157 | adapter.notifyDataSetChanged(); 158 | 159 | } 160 | 161 | 162 | @OnClick({R.id.tv_rang, R.id.tv_line, R.id.tv_candle, R.id.tv_ma, R.id.tv_boll, R.id.tv_macd 163 | , R.id.tv_kdj, R.id.tv_rsi, R.id.tv_vol, R.id.tv_clear}) 164 | public void onClick(View v) { 165 | switch (v.getId()) { 166 | case R.id.tv_rang: 167 | setKlineType(RANG_TYPE); 168 | break; 169 | case R.id.tv_line: 170 | setKlineType(LINE_TYPE); 171 | break; 172 | case R.id.tv_candle: 173 | setKlineType(CANDLE_TYPE); 174 | break; 175 | case R.id.tv_ma: 176 | setChildDraw(Constants.MA); 177 | break; 178 | case R.id.tv_boll: 179 | setChildDraw(Constants.BOLL); 180 | break; 181 | case R.id.tv_macd: 182 | setChildDraw(Constants.MACD); 183 | break; 184 | case R.id.tv_kdj: 185 | setChildDraw(Constants.KDJ); 186 | break; 187 | case R.id.tv_rsi: 188 | setChildDraw(Constants.RSI); 189 | break; 190 | case R.id.tv_vol: 191 | setChildDraw(Constants.VOL); 192 | break; 193 | case R.id.tv_clear: 194 | setChildDraw(Constants.CLEAR); 195 | break; 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /app/src/main/java/com/vincent/story/adapter/DateCycleAdapter.java: -------------------------------------------------------------------------------- 1 | package com.vincent.story.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.content.ContextCompat; 6 | import android.widget.TextView; 7 | 8 | 9 | import com.chad.library.adapter.base.BaseQuickAdapter; 10 | import com.chad.library.adapter.base.BaseViewHolder; 11 | import com.vincent.story.DataBean; 12 | import com.vincent.story.R; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * 时间周期适配器 18 | */ 19 | public class DateCycleAdapter extends BaseQuickAdapter { 20 | 21 | private DateListener listener; 22 | 23 | 24 | public void setListener(DateListener listener) { 25 | this.listener = listener; 26 | } 27 | 28 | public DateCycleAdapter(Context context, int layoutResId, @Nullable List data) { 29 | super(layoutResId, data); 30 | this.mContext = context; 31 | } 32 | 33 | @Override 34 | protected void convert(BaseViewHolder helper, DataBean item) { 35 | helper.setText(R.id.tv_data, item.getData()); 36 | if (item.isSelected()) 37 | ((TextView) helper.getView(R.id.tv_data)).setTextColor(ContextCompat.getColor(mContext, R.color.color_6384FF)); 38 | else 39 | ((TextView) helper.getView(R.id.tv_data)).setTextColor(ContextCompat.getColor(mContext, R.color.white)); 40 | 41 | helper.getView(R.id.tv_data).setOnClickListener(l -> { 42 | // initData(); 43 | listener.chooseDate(item.getData(), item.getPosition()); 44 | }); 45 | 46 | } 47 | 48 | // 49 | // public void initData() { 50 | //// List list = getData(); 51 | // for (DataBean bean : getData()) { 52 | // bean.setSelected(false); 53 | // } 54 | // } 55 | 56 | public interface DateListener { 57 | void chooseDate(String period, int position); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/vincent/story/app/ActivityStack.java: -------------------------------------------------------------------------------- 1 | package com.vincent.story.app; 2 | 3 | import android.app.Activity; 4 | 5 | import java.util.LinkedList; 6 | 7 | public class ActivityStack { 8 | /** 9 | * 存activity的list,方便管理activity 10 | */ 11 | public LinkedList activityList = null; 12 | 13 | public ActivityStack() { 14 | activityList = new LinkedList(); 15 | } 16 | 17 | /** 18 | * 将Activity添加到activityList中 19 | * 20 | * @param activity 21 | */ 22 | public void addActivity(Activity activity) { 23 | activityList.add(activity); 24 | } 25 | 26 | /** 27 | * 获取栈顶Activity 28 | * 29 | * @return 30 | */ 31 | public Activity getLastActivity() { 32 | return activityList.getLast(); 33 | } 34 | 35 | /** 36 | * 将Activity移除 37 | * 38 | * @param activity 39 | */ 40 | public void removeActivity(Activity activity) { 41 | if (null != activity && activityList.contains(activity)) { 42 | activityList.remove(activity); 43 | } 44 | } 45 | 46 | /** 47 | * 判断某一Activity是否在运行 48 | * 49 | * @param className 50 | * @return 51 | */ 52 | public boolean isActivityRunning(String className) { 53 | if (className != null) { 54 | for (Activity activity : activityList) { 55 | if (activity.getClass().getName().equals(className)) { 56 | return true; 57 | } 58 | } 59 | } 60 | return false; 61 | } 62 | 63 | 64 | /** 65 | * 退出所有的Activity 66 | */ 67 | public void finishAllActivity() { 68 | for (Activity activity : activityList) { 69 | if (null != activity) { 70 | activity.finish(); 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * 退出应用程序 77 | */ 78 | public void AppExit() { 79 | try { 80 | finishAllActivity(); 81 | // 杀死该应用进程 82 | android.os.Process.killProcess(android.os.Process.myPid()); 83 | System.exit(0); 84 | } catch (Exception e) { 85 | 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/vincent/story/app/MyApp.java: -------------------------------------------------------------------------------- 1 | package com.vincent.story.app; 2 | 3 | 4 | import android.app.Application; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.util.DisplayMetrics; 8 | 9 | 10 | public class MyApp extends Application { 11 | 12 | public static MyApp instance; 13 | //临时保存 需要登录才能访问的页面 在登录成功后跳转 14 | private Intent intent; 15 | //屏幕宽高 16 | int screenWidth; 17 | int screenHeight; 18 | /** 19 | * Activity 栈 20 | */ 21 | public ActivityStack mActivityStack = null; 22 | 23 | @Override 24 | public void onCreate() { 25 | super.onCreate(); 26 | instance = this; 27 | //1、通过WindowManager获取 28 | DisplayMetrics dm = new DisplayMetrics(); 29 | screenWidth = dm.heightPixels; // 屏幕宽(像素,如:480px) 30 | screenHeight = dm.widthPixels; // 屏幕高(像素) 31 | //初始化友盟推送 不用友盟换极光 32 | //UmengHelper.getInstance().initUmeng(); 33 | // JPushInterface.setDebugMode(true); 34 | 35 | mActivityStack = new ActivityStack(); 36 | 37 | 38 | // String registrationId = JPushInterface.getRegistrationID(this); 39 | // SharedPreferencesUtil.put(getApplicationContext(), "RegistrationId", registrationId); 40 | // L.i("RegistrationId", registrationId); 41 | } 42 | 43 | 44 | public int getScreenWidth() { 45 | return screenWidth; 46 | } 47 | 48 | public int getScreenHeight() { 49 | return screenHeight; 50 | } 51 | 52 | public static MyApp getInstance() { 53 | return instance; 54 | } 55 | 56 | public Intent getIntent() { 57 | return intent; 58 | } 59 | 60 | public void putIntent(Intent intent) { 61 | this.intent = intent; 62 | } 63 | 64 | public void jumpToTargetActivity(Context context) { 65 | context.startActivity(intent); 66 | this.intent = null; 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 34 | 35 | 36 | 43 | 44 | 51 | 52 | 53 | 60 | 61 | 68 | 69 | 76 | 77 | 84 | 85 | 92 | 93 | 100 | 101 | 108 | 109 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_tv_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/app/src/main/res/mipmap-xhdpi/ic_no_image.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/icon_temp_load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/app/src/main/res/mipmap-xhdpi/icon_temp_load.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values-sw384dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17.0667dp 4 | 17.0667dp 5 | 53.3333dp 6 | @dimen/dp_15 7 | -64.0000dp 8 | -32.0000dp 9 | -21.3333dp 10 | -12.8000dp 11 | -10.6667dp 12 | -8.5333dp 13 | -5.3333dp 14 | -2.1333dp 15 | -1.0667dp 16 | 0.0000dp 17 | 0.1067dp 18 | 0.5333dp 19 | 1.0667dp 20 | 1.6000dp 21 | 2.1333dp 22 | 2.6667dp 23 | 3.2000dp 24 | 3.7333dp 25 | 4.2667dp 26 | 4.8000dp 27 | 5.3333dp 28 | 6.4000dp 29 | 7.4667dp 30 | 8.0000dp 31 | 8.5333dp 32 | 9.6000dp 33 | 10.6667dp 34 | 11.7333dp 35 | 12.8000dp 36 | 13.8667dp 37 | 14.9333dp 38 | 16.0000dp 39 | 17.0667dp 40 | 18.1333dp 41 | 19.2000dp 42 | 20.2667dp 43 | 21.3333dp 44 | 22.4000dp 45 | 23.4667dp 46 | 24.5333dp 47 | 25.6000dp 48 | 26.6667dp 49 | 27.7333dp 50 | 28.8000dp 51 | 29.8667dp 52 | 30.9333dp 53 | 32.0000dp 54 | 33.0667dp 55 | 34.1333dp 56 | 35.2000dp 57 | 36.2667dp 58 | 37.3333dp 59 | 38.4000dp 60 | 39.4667dp 61 | 40.5333dp 62 | 41.6000dp 63 | 42.6667dp 64 | 43.7333dp 65 | 44.8000dp 66 | 45.8667dp 67 | 46.9333dp 68 | 48.0000dp 69 | 49.0667dp 70 | 50.1333dp 71 | 51.2000dp 72 | 52.2667dp 73 | 53.3333dp 74 | 54.4000dp 75 | 55.4667dp 76 | 56.5333dp 77 | 57.6000dp 78 | 58.6667dp 79 | 59.7333dp 80 | 60.8000dp 81 | 61.8667dp 82 | 62.9333dp 83 | 64.0000dp 84 | 65.0667dp 85 | 66.1333dp 86 | 67.2000dp 87 | 68.2667dp 88 | 69.3333dp 89 | 70.4000dp 90 | 71.4667dp 91 | 72.5333dp 92 | 73.6000dp 93 | 74.6667dp 94 | 75.7333dp 95 | 76.8000dp 96 | 77.8667dp 97 | 78.9333dp 98 | 80.0000dp 99 | 81.0667dp 100 | 82.1333dp 101 | 83.2000dp 102 | 84.2667dp 103 | 85.3333dp 104 | 86.4000dp 105 | 87.4667dp 106 | 88.5333dp 107 | 89.6000dp 108 | 90.6667dp 109 | 91.7333dp 110 | 92.8000dp 111 | 93.8667dp 112 | 94.9333dp 113 | 96.0000dp 114 | 97.0667dp 115 | 98.1333dp 116 | 99.2000dp 117 | 100.2667dp 118 | 101.3333dp 119 | 102.4000dp 120 | 103.4667dp 121 | 104.5333dp 122 | 105.6000dp 123 | 106.6667dp 124 | 107.7333dp 125 | 108.8000dp 126 | 109.8667dp 127 | 110.9333dp 128 | 111.4667dp 129 | 112.0000dp 130 | 113.0667dp 131 | 114.1333dp 132 | 115.2000dp 133 | 116.2667dp 134 | 117.3333dp 135 | 118.4000dp 136 | 119.4667dp 137 | 120.5333dp 138 | 121.6000dp 139 | 122.6667dp 140 | 123.7333dp 141 | 124.8000dp 142 | 125.8667dp 143 | 126.9333dp 144 | 128.0000dp 145 | 129.0667dp 146 | 130.1333dp 147 | 131.2000dp 148 | 132.2667dp 149 | 133.3333dp 150 | 134.4000dp 151 | 135.4667dp 152 | 136.5333dp 153 | 137.6000dp 154 | 138.6667dp 155 | 139.7333dp 156 | 140.8000dp 157 | 141.8667dp 158 | 142.9333dp 159 | 143.4667dp 160 | 144.0000dp 161 | 145.0667dp 162 | 146.1333dp 163 | 147.2000dp 164 | 148.2667dp 165 | 149.3333dp 166 | 150.4000dp 167 | 151.4667dp 168 | 152.5333dp 169 | 153.6000dp 170 | 154.6667dp 171 | 155.7333dp 172 | 156.8000dp 173 | 157.8667dp 174 | 158.9333dp 175 | 160.0000dp 176 | 161.0667dp 177 | 162.1333dp 178 | 163.2000dp 179 | 164.2667dp 180 | 165.3333dp 181 | 166.4000dp 182 | 167.4667dp 183 | 168.5333dp 184 | 169.6000dp 185 | 170.6667dp 186 | 171.7333dp 187 | 172.8000dp 188 | 173.8667dp 189 | 174.9333dp 190 | 176.0000dp 191 | 177.0667dp 192 | 178.1333dp 193 | 179.2000dp 194 | 180.2667dp 195 | 181.3333dp 196 | 182.4000dp 197 | 183.4667dp 198 | 184.5333dp 199 | 185.6000dp 200 | 186.6667dp 201 | 187.7333dp 202 | 188.8000dp 203 | 189.8667dp 204 | 190.9333dp 205 | 192.0000dp 206 | 193.0667dp 207 | 194.1333dp 208 | 195.2000dp 209 | 196.2667dp 210 | 197.3333dp 211 | 198.4000dp 212 | 199.4667dp 213 | 200.5333dp 214 | 201.6000dp 215 | 202.6667dp 216 | 203.7333dp 217 | 204.0000dp 218 | 204.8000dp 219 | 205.8667dp 220 | 206.9333dp 221 | 208.0000dp 222 | 209.0667dp 223 | 210.1333dp 224 | 211.2000dp 225 | 212.2667dp 226 | 213.3333dp 227 | 214.4000dp 228 | 215.4667dp 229 | 216.5333dp 230 | 217.6000dp 231 | 218.6667dp 232 | 219.7333dp 233 | 220.8000dp 234 | 221.8667dp 235 | 222.9333dp 236 | 224.0000dp 237 | 225.0667dp 238 | 226.1333dp 239 | 227.2000dp 240 | 228.2667dp 241 | 229.3333dp 242 | 230.4000dp 243 | 231.4667dp 244 | 232.5333dp 245 | 233.6000dp 246 | 234.6667dp 247 | 235.7333dp 248 | 236.8000dp 249 | 237.8667dp 250 | 238.9333dp 251 | 240.0000dp 252 | 241.0667dp 253 | 242.1333dp 254 | 243.2000dp 255 | 244.2667dp 256 | 245.3333dp 257 | 246.4000dp 258 | 247.4667dp 259 | 248.5333dp 260 | 249.6000dp 261 | 250.6667dp 262 | 251.7333dp 263 | 252.8000dp 264 | 253.8667dp 265 | 254.9333dp 266 | 256.0000dp 267 | 257.0667dp 268 | 258.1333dp 269 | 259.2000dp 270 | 260.2667dp 271 | 261.3333dp 272 | 262.4000dp 273 | 263.4667dp 274 | 264.5333dp 275 | 265.6000dp 276 | 266.6667dp 277 | 267.7333dp 278 | 268.8000dp 279 | 269.8667dp 280 | 270.9333dp 281 | 272.0000dp 282 | 273.0667dp 283 | 274.1333dp 284 | 275.2000dp 285 | 276.2667dp 286 | 277.3333dp 287 | 278.4000dp 288 | 279.4667dp 289 | 280.5333dp 290 | 281.6000dp 291 | 282.6667dp 292 | 283.7333dp 293 | 284.8000dp 294 | 285.8667dp 295 | 286.9333dp 296 | 288.0000dp 297 | 289.0667dp 298 | 290.1333dp 299 | 291.2000dp 300 | 292.2667dp 301 | 293.3333dp 302 | 294.4000dp 303 | 295.4667dp 304 | 296.5333dp 305 | 297.6000dp 306 | 298.6667dp 307 | 299.7333dp 308 | 300.8000dp 309 | 301.8667dp 310 | 302.9333dp 311 | 304.0000dp 312 | 305.0667dp 313 | 306.1333dp 314 | 307.2000dp 315 | 308.2667dp 316 | 309.3333dp 317 | 310.4000dp 318 | 311.4667dp 319 | 312.5333dp 320 | 313.6000dp 321 | 314.6667dp 322 | 315.7333dp 323 | 316.8000dp 324 | 317.8667dp 325 | 318.9333dp 326 | 320.0000dp 327 | 321.0667dp 328 | 322.1333dp 329 | 323.2000dp 330 | 324.2667dp 331 | 325.3333dp 332 | 326.4000dp 333 | 327.4667dp 334 | 328.5333dp 335 | 329.6000dp 336 | 330.6667dp 337 | 331.7333dp 338 | 332.8000dp 339 | 333.8667dp 340 | 334.9333dp 341 | 336.0000dp 342 | 337.0667dp 343 | 338.1333dp 344 | 339.2000dp 345 | 340.2667dp 346 | 341.3333dp 347 | 342.4000dp 348 | 343.4667dp 349 | 344.5333dp 350 | 345.6000dp 351 | 346.6667dp 352 | 347.7333dp 353 | 348.8000dp 354 | 349.8667dp 355 | 350.9333dp 356 | 352.0000dp 357 | 353.0667dp 358 | 354.1333dp 359 | 355.2000dp 360 | 356.2667dp 361 | 357.3333dp 362 | 358.4000dp 363 | 359.4667dp 364 | 360.5333dp 365 | 361.6000dp 366 | 362.6667dp 367 | 363.7333dp 368 | 364.8000dp 369 | 365.8667dp 370 | 366.9333dp 371 | 368.0000dp 372 | 369.0667dp 373 | 370.1333dp 374 | 371.2000dp 375 | 372.2667dp 376 | 373.3333dp 377 | 374.4000dp 378 | 375.4667dp 379 | 376.5333dp 380 | 377.6000dp 381 | 378.6667dp 382 | 379.7333dp 383 | 380.8000dp 384 | 381.8667dp 385 | 382.9333dp 386 | 384.0000dp 387 | 389.3333dp 388 | 394.6667dp 389 | 426.6667dp 390 | 437.3333dp 391 | 450.1333dp 392 | 503.4667dp 393 | 533.3333dp 394 | 640.0000dp 395 | 682.6667dp 396 | 768.0000dp 397 | 6.4000sp 398 | 7.4667sp 399 | 8.5333sp 400 | 9.6000sp 401 | 10.6667sp 402 | 11.7333sp 403 | 12.8000sp 404 | 13.8667sp 405 | 14.9333sp 406 | 16.0000sp 407 | 17.0667sp 408 | 18.1333sp 409 | 19.2000sp 410 | 20.2667sp 411 | 21.3333sp 412 | 22.4000sp 413 | 23.4667sp 414 | 24.5333sp 415 | 25.6000sp 416 | 26.6667sp 417 | 29.8667sp 418 | 32.0000sp 419 | 34.1333sp 420 | 36.2667sp 421 | 38.4000sp 422 | 40.5333sp 423 | 42.6667sp 424 | 44.8000sp 425 | 51.2000sp 426 | 427 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #1F1F27 5 | #FFFAE0 6 | #707070 7 | #E87439 8 | #F2B89B 9 | #DCB476 10 | #696969 11 | 12 | #FF2741 13 | #FF2741 14 | #FF2741 15 | #FF4081 16 | 17 | #00000000 18 | #55000000 19 | #333333 20 | #292836 21 | #ffffff 22 | #2d2e3d 23 | #292836 24 | #9A9A9A 25 | #D6D6D6 26 | #FFFFFF 27 | #33355C 28 | #3D3E63 29 | #C3C4EA 30 | #67688E 31 | #99FFFFFF 32 | #44FFFFFF 33 | #2E3546 34 | #D04B63 35 | #77E53737 36 | 37 | #4EC2E3 38 | 39 | #2982D1 40 | #232544 41 | #252647 42 | #26284A 43 | #77E0F7 44 | #5577E0F7 45 | #999999 46 | #e5e5e5 47 | #7577AD 48 | #76EE00 49 | 50 | #F5F5F5 51 | #1A202E 52 | #1C1D3A 53 | #5a5a5a 54 | #eeeeee 55 | #333333 56 | #e9ecf0 57 | #cc3A3949 58 | #393a49 59 | #cccccc 60 | #aaaaaa 61 | #808080 62 | #ababab 63 | #ffc000 64 | #FFF000 65 | #FEFEC2 66 | #55797AAF 67 | 68 | #29A8D1 69 | #5529A8D1 70 | #767CA1 71 | #20223F 72 | #34365B 73 | #E6C57D 74 | #ff86b9b5 75 | #80000000 76 | #50000000 77 | #00ffffff 78 | #292836 79 | 80 | 81 | #9e9e9e 82 | #1b66c7 83 | 84 | 85 | 86 | #808080 87 | #ff0000 88 | #d7160f 89 | #FF2741 90 | #FFC024 91 | #CED9E7 92 | #53B4A9 93 | #26284A 94 | #aa1A202E 95 | #7723C224 96 | #346fc3 97 | #ABAABF 98 | #EDEDF3 99 | #2B2D52 100 | #2E3052 101 | 102 | 103 | 104 | #DA8AE5 105 | #39B0E8 106 | #FFC76D 107 | #E7A520 108 | #ffffff 109 | 110 | #202326 111 | #B1B2B6 112 | #c830343C 113 | #30343C 114 | #FF6601 115 | 116 | 117 | #4262DC 118 | #7390FF 119 | #6384FF 120 | #53B4A9 121 | #D04B63 122 | #1F202E 123 | #2E3546 124 | #1A202E 125 | #101625 126 | #656F82 127 | #9D9EC3 128 | #72739C 129 | #393A6B 130 | #797AAF 131 | #0E121C 132 | #5A83FF 133 | #13141E 134 | #1EE39D 135 | #661EE39D 136 | #12A2CA 137 | #6612A2CA 138 | #FF8A7C 139 | #66FF8A7C 140 | #66DE3957 141 | #DE3957 142 | #111622 143 | #2D3445 144 | #30384C 145 | #E64D60 146 | #14ADC2 147 | #6D778B 148 | #E4475D 149 | #CBCFF1 150 | #14B014 151 | #6B778D 152 | #47526D 153 | 154 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | KlineChartView 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 17 | 18 | 22 | 23 | 24 | 29 | 30 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/xml/filepaths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | apply from: "config.gradle" 3 | buildscript { 4 | 5 | repositories { 6 | jcenter() 7 | mavenCentral() 8 | google() 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.2.0' 12 | // classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 13 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' 14 | // classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 15 | // classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1' 16 | //GreenDao3依赖 17 | classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1' 18 | classpath 'com.android.tools.build:gradle:3.0.1' 19 | // NOTE: Do not place your application dependencies here; they belong 20 | // in the individual module build.gradle files 21 | } 22 | } 23 | 24 | allprojects { 25 | repositories { 26 | google() 27 | jcenter() 28 | maven { url "https://jitpack.io" } 29 | } 30 | } 31 | 32 | 33 | task clean(type: Delete) { 34 | delete rootProject.buildDir 35 | } 36 | -------------------------------------------------------------------------------- /config.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | plugins = [ 3 | library : 'com.android.library', 4 | application: 'com.android.application', 5 | maven : 'com.github.dcendents.android-maven', 6 | bintray : 'com.jfrog.bintray' 7 | ] 8 | 9 | android = [ 10 | applicationId : "com.android.project", 11 | compileSdkVersion : 28, 12 | buildToolsVersion : "27.0.3", 13 | 14 | minSdkVersion : 17, 15 | targetSdkVersion : 28, 16 | 17 | versionCode : 1, 18 | versionName : "1.0", 19 | androidSupportVersion: '27.1.1', 20 | junitVersion : "4.12" 21 | ] 22 | 23 | dependVersion = [ 24 | support : "28.0.0", 25 | sdkSourceCompatibility: 1.8, 26 | sdkTargetCompatibility: 1.8, 27 | appSourceCompatibility: 1.8, 28 | appTargetCompatibility: 1.8 29 | ] 30 | dependencies = [ 31 | // support 32 | supportV4 : "com.android.support:support-v4:${dependVersion.support}", 33 | appcompatV7 : "com.android.support:appcompat-v7:${dependVersion.support}", 34 | recyclerview : "com.android.support:recyclerview-v7:${dependVersion.support}", 35 | design : "com.android.support:design:${dependVersion.support}", 36 | cardView : "com.android.support:cardview-v7:${dependVersion.support}", 37 | 38 | constraintLayout : 'com.android.support.constraint:constraint-layout:1.0.2', 39 | 40 | loading : 'com.yanzhenjie:loading:1.0.2', 41 | swipeRecyclerView : 'com.yanzhenjie:recyclerview-swipe:1.1.3', 42 | //权限管理 43 | easypermissions : 'pub.devrel:easypermissions:0.2.0', 44 | //沉浸式状态栏 45 | statusbaruitl : 'com.jaeger.statusbaruitl:library:1.3.5', 46 | //图片放大缩小框架 47 | photoview : 'com.github.chrisbanes.photoview:library:1.2.3', 48 | //类似微信的图片选择PhotoPicker 49 | //compile 'me.iwf.photopicker:PhotoPicker:0.9.5@aar' 50 | photoPicker : 'me.iwf.photopicker:PhotoPicker:0.1.8', 51 | //PhotoPicker需要用到 52 | nineoldandroids : 'com.nineoldandroids:library:2.4.0', 53 | //PhotoPicker需要用到 glide图片加载框架 54 | glide : 'com.github.bumptech.glide:glide:4.2.0', 55 | //图片压缩 56 | compressHelper : 'com.github.nanchen2251:CompressHelper:1.0.5', 57 | //greendao数据库依赖 58 | greendao : 'org.greenrobot:greendao:3.2.0', 59 | //retrofit 60 | retrofit : 'com.squareup.retrofit2:retrofit:2.2.0', 61 | converterGson : 'com.squareup.retrofit2:converter-gson:2.2.0', 62 | //rx+retrofit 63 | adapterRxjava : 'com.squareup.retrofit2:adapter-rxjava2:2.2.0', 64 | //rxjava 65 | rxjava : 'io.reactivex.rxjava2:rxjava:2.0.8', 66 | rxandroid : 'io.reactivex.rxjava2:rxandroid:2.0.1', 67 | //效果好看的刷新加载库 68 | SmartRefreshLayout : 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.4', 69 | //没有使用特殊Header,可以不加这行 70 | SmartRefreshHeader : 'com.scwang.smartrefresh:SmartRefreshHeader:1.0.4', 71 | //一个开源gif控件 72 | gifDrawable : 'pl.droidsonroids.gif:android-gif-drawable:1.2.3', 73 | //头部广告轮播https://github.com/youth5201314/banner 74 | youthBanner : 'com.youth.banner:banner:1.4.10', 75 | //星星评分控件https://www.cnblogs.com/everhad/p/6828627.html?utm_source=tuicool&utm_medium=referral 76 | ratingStar : 'com.github.everhad:AndroidRatingStar:v1.0.1', 77 | //tag 78 | tagView : 'co.lujun:androidtagview:1.1.4', 79 | //baseAdater 80 | baseAdater : 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30', 81 | //okhttop 日志拦截打印 82 | okhttpInterceptor : 'com.squareup.okhttp3:logging-interceptor:3.4.1', 83 | //弹框 84 | easyPopup : 'com.github.zyyoona7:EasyPopup:1.1.2', 85 | //文本多级联动 地址选择器 86 | TextPickerView : 'com.contrarywind:Android-PickerView:4.1.5', 87 | //EvenBus 88 | EvenBus : 'org.greenrobot:eventbus:3.1.1', 89 | //butterknife 90 | butterknife : 'com.jakewharton:butterknife:8.5.1', 91 | butterknifeCompiler: 'com.jakewharton:butterknife-compiler:8.5.1', 92 | 93 | ] 94 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /img1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/img1.jpg -------------------------------------------------------------------------------- /img2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VincentStory/KLineChartView/3c6ddc7d735d0cac90eaeb1b692212c9214d284a/img2.jpg -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':KLineChartLib' 2 | --------------------------------------------------------------------------------