├── .gradle
└── 3.2
│ ├── taskArtifacts
│ ├── fileHashes.bin
│ ├── fileSnapshots.bin
│ ├── taskArtifacts.bin
│ └── taskArtifacts.lock
│ └── tasks
│ ├── _app_compileDebugJavaWithJavac
│ ├── localClassSetAnalysis
│ │ ├── localClassSetAnalysis.bin
│ │ └── localClassSetAnalysis.lock
│ └── localJarClasspathSnapshot
│ │ ├── localJarClasspathSnapshot.bin
│ │ └── localJarClasspathSnapshot.lock
│ └── _ikvStockChart_compileReleaseJavaWithJavac
│ ├── localClassSetAnalysis
│ ├── localClassSetAnalysis.bin
│ └── localClassSetAnalysis.lock
│ └── localJarClasspathSnapshot
│ ├── localJarClasspathSnapshot.bin
│ └── localJarClasspathSnapshot.lock
├── .idea
├── gradle.xml
├── libraries
│ ├── __local_jars___D__github_ikvStockChart_master_app_libs_gson_2_2_1_jar_unspecified_jar.xml
│ ├── com_alibaba_fastjson_1_1_46_android_jar.xml
│ ├── com_android_support_animated_vector_drawable_25_1_0.xml
│ ├── com_android_support_appcompat_v7_25_1_0.xml
│ ├── com_android_support_design_25_1_0.xml
│ ├── com_android_support_multidex_1_0_1.xml
│ ├── com_android_support_multidex_instrumentation_1_0_1.xml
│ ├── com_android_support_recyclerview_v7_25_1_0.xml
│ ├── com_android_support_support_annotations_25_1_0_jar.xml
│ ├── com_android_support_support_compat_25_1_0.xml
│ ├── com_android_support_support_core_ui_25_1_0.xml
│ ├── com_android_support_support_core_utils_25_1_0.xml
│ ├── com_android_support_support_fragment_25_1_0.xml
│ ├── com_android_support_support_media_compat_25_1_0.xml
│ ├── com_android_support_support_v4_25_1_0.xml
│ ├── com_android_support_support_vector_drawable_25_1_0.xml
│ ├── com_android_support_transition_25_1_0.xml
│ ├── com_chanven_lib_cptr_1_1_0.xml
│ ├── com_readystatesoftware_systembartint_systembartint_1_0_3_jar.xml
│ ├── com_tbruyelle_rxpermissions_rxpermissions_0_9_3.xml
│ ├── com_wordplat_RecyclerViewEasyDivider_1_0_4.xml
│ ├── io_reactivex_rxandroid_1_2_1.xml
│ ├── io_reactivex_rxjava_1_1_9_jar.xml
│ ├── junit_junit_4_12_jar.xml
│ ├── org_hamcrest_hamcrest_core_1_3_jar.xml
│ └── org_xutils_xutils_3_3_36.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── workspace.xml
├── 20180620144949.jpg
├── 20180620144955.jpg
├── CHANGE_LOG.md
├── PROPERTY.md
├── README.md
├── Screenshots
├── S70413-224859.jpg
├── S70413-224945.jpg
├── S70413-225013.jpg
├── S70413-225055.jpg
├── S70413-225125.jpg
├── S70413-225235.jpg
├── S70417-010650.jpg
└── S70628-230542.jpg
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── libs
│ ├── gson-2.2.1.jar
│ └── picasso-release-2.5.2.4b.aar
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ └── kline1.txt
│ ├── java
│ │ └── com
│ │ │ └── wordplat
│ │ │ └── quickstart
│ │ │ ├── activity
│ │ │ ├── BaseActivity.java
│ │ │ ├── Disable_Left_And_Right_Refresh_Activity.java
│ │ │ ├── Enable_Left_And_Right_Refresh_Activity.java
│ │ │ ├── MACD_RSI_KDJ_Show_Together_Activity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── Multi_Color_Dynamic_Change_Configuration_Activity.java
│ │ │ ├── Simple_TimeLine_Example_Activity.java
│ │ │ ├── TestKLineActivty.java
│ │ │ ├── With_Fragment_And_TabLayout_Switcher_Example_Activity.java
│ │ │ ├── With_Pull_To_Refresh_Example_Activity.java
│ │ │ └── With_RecyclerView_Example_Activity.java
│ │ │ ├── adapter
│ │ │ ├── BaseViewHolder.java
│ │ │ ├── TextAdapter.java
│ │ │ └── TextViewHolder.java
│ │ │ ├── app
│ │ │ ├── App.java
│ │ │ ├── AppRuntime.java
│ │ │ ├── AppRuntimeInitializer.java
│ │ │ └── DeviceRuntime.java
│ │ │ ├── bean
│ │ │ ├── BtcBean.java
│ │ │ ├── KLineBean.java
│ │ │ ├── ResultBean.java
│ │ │ ├── request
│ │ │ │ └── ServerRequestParams.java
│ │ │ └── response
│ │ │ │ ├── IResultResponse.java
│ │ │ │ ├── ServerResponse.java
│ │ │ │ └── ServerResponseParser.java
│ │ │ ├── fragment
│ │ │ ├── BaseFragment.java
│ │ │ └── KLineFragment.java
│ │ │ ├── mvp
│ │ │ ├── BasePresenter.java
│ │ │ ├── BaseRequest.java
│ │ │ ├── BaseView.java
│ │ │ ├── BaseViewListener.java
│ │ │ ├── BtcChinaApiRequest.java
│ │ │ ├── BtcChinaPresenter.java
│ │ │ ├── LoadingView.java
│ │ │ ├── LoadingViewListener.java
│ │ │ ├── StockApiRequest.java
│ │ │ ├── StockPresenter.java
│ │ │ └── exception
│ │ │ │ ├── NetworkTimeOutException.java
│ │ │ │ ├── NoNetworkException.java
│ │ │ │ ├── ResultEmptyException.java
│ │ │ │ ├── ResultFailedException.java
│ │ │ │ └── ResultParseException.java
│ │ │ ├── utils
│ │ │ ├── AppUtils.java
│ │ │ └── SSLHelper.java
│ │ │ └── widget
│ │ │ ├── TabButton.java
│ │ │ └── pulllistview
│ │ │ ├── ListRefreshView.java
│ │ │ ├── LoadMoreViewFooter.java
│ │ │ └── PullListLayout.java
│ └── res
│ │ ├── anim
│ │ ├── dialog_enter.xml
│ │ └── dialog_exit.xml
│ │ ├── animator
│ │ └── loading_rotation.xml
│ │ ├── drawable-v21
│ │ └── btn_tab.xml
│ │ ├── drawable
│ │ ├── bg_ad_image_mark.xml
│ │ ├── bg_tab.xml
│ │ ├── btn_tab.xml
│ │ ├── ic_default.xml
│ │ ├── text_tab.xml
│ │ ├── vector_drawable_loading.xml
│ │ ├── vector_drawable_loading2.xml
│ │ ├── vector_drawable_loading2_anim.xml
│ │ └── vector_drawable_loading_anim.xml
│ │ ├── layout
│ │ ├── activity_left_and_right_refresh.xml
│ │ ├── activity_macd_rsi_kdj_show_together.xml
│ │ ├── activity_main.xml
│ │ ├── activity_simple_timeline.xml
│ │ ├── activity_with_fragment_and_tablayout_switcher.xml
│ │ ├── activity_with_pull_to_refresh.xml
│ │ ├── activtiy_test_kline.xml
│ │ ├── fragment_kline.xml
│ │ ├── item_text.xml
│ │ └── view_list_refresh.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── image.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── raw
│ │ ├── client.p12
│ │ └── mytruststore.bks
│ │ ├── values-v19
│ │ └── styles.xml
│ │ ├── values-v21
│ │ └── styles.xml
│ │ └── values
│ │ ├── attri.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ ├── styles.xml
│ │ └── warning.xml
│ └── test
│ └── java
│ └── com
│ └── wordplat
│ └── quickstart
│ └── ExampleUnitTest.java
├── build.gradle
├── build
└── generated
│ └── mockable-android-25.jar
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── ikvStockChart-master.iml
├── ikvStockChart
├── .gitignore
├── build.gradle
├── ikvStockChart.iml
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wordplat
│ │ │ └── ikvstockchart
│ │ │ ├── InteractiveKLineLayout.java
│ │ │ ├── InteractiveKLineView.java
│ │ │ ├── KLineHandler.java
│ │ │ ├── SimpleKLineHandler.java
│ │ │ ├── align
│ │ │ ├── XMarkerAlign.java
│ │ │ ├── YLabelAlign.java
│ │ │ └── YMarkerAlign.java
│ │ │ ├── compat
│ │ │ ├── GestureMoveActionCompat.java
│ │ │ ├── PerformenceAnalyser.java
│ │ │ └── ViewUtils.java
│ │ │ ├── drawing
│ │ │ ├── BOLLDrawing.java
│ │ │ ├── CandleDrawing.java
│ │ │ ├── EmptyDataDrawing.java
│ │ │ ├── HighlightDrawing.java
│ │ │ ├── IDrawing.java
│ │ │ ├── KDJDrawing.java
│ │ │ ├── KLineGridAxisDrawing.java
│ │ │ ├── KLineVolumeDrawing.java
│ │ │ ├── KLineVolumeHighlightDrawing.java
│ │ │ ├── MACDDrawing.java
│ │ │ ├── MADrawing.java
│ │ │ ├── RSIDrawing.java
│ │ │ ├── StockIndexYLabelDrawing.java
│ │ │ ├── TimeLineDrawing.java
│ │ │ └── TimeLineGridAxisDrawing.java
│ │ │ ├── entry
│ │ │ ├── Entry.java
│ │ │ ├── EntryAdapter.java
│ │ │ ├── EntrySet.java
│ │ │ ├── SizeColor.java
│ │ │ ├── StockBOLLIndex.java
│ │ │ ├── StockDataTest.java
│ │ │ ├── StockIndex.java
│ │ │ ├── StockKDJIndex.java
│ │ │ ├── StockKLineVolumeIndex.java
│ │ │ ├── StockMACDIndex.java
│ │ │ ├── StockPlaceIndex.java
│ │ │ └── StockRSIIndex.java
│ │ │ ├── marker
│ │ │ ├── IMarkerView.java
│ │ │ ├── XAxisTextMarkerView.java
│ │ │ └── YAxisTextMarkerView.java
│ │ │ └── render
│ │ │ ├── AbstractRender.java
│ │ │ ├── KLineRender.java
│ │ │ └── TimeLineRender.java
│ └── res
│ │ ├── drawable
│ │ └── text_tab.xml
│ │ ├── layout
│ │ └── tab_stockindex.xml
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── wordplat
│ └── ikvstockchart
│ └── ExampleUnitTest.java
├── local.properties
└── settings.gradle
/.gradle/3.2/taskArtifacts/fileHashes.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/taskArtifacts/fileHashes.bin
--------------------------------------------------------------------------------
/.gradle/3.2/taskArtifacts/fileSnapshots.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/taskArtifacts/fileSnapshots.bin
--------------------------------------------------------------------------------
/.gradle/3.2/taskArtifacts/taskArtifacts.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/taskArtifacts/taskArtifacts.bin
--------------------------------------------------------------------------------
/.gradle/3.2/taskArtifacts/taskArtifacts.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/taskArtifacts/taskArtifacts.lock
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_app_compileDebugJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.bin
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localClassSetAnalysis/localClassSetAnalysis.lock
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.bin
--------------------------------------------------------------------------------
/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NativeMonkey/kline/cf6e3c1b9dcbdf81be8257d2829144a79828b603/.gradle/3.2/tasks/_ikvStockChart_compileReleaseJavaWithJavac/localJarClasspathSnapshot/localJarClasspathSnapshot.lock
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
14 |
19 |
24 |
Disable_Left_And_Right_Refresh_Activity
9 | *Date: 2017/3/31
10 | * 11 | * @author afon 12 | */ 13 | 14 | public class Disable_Left_And_Right_Refresh_Activity extends Enable_Left_And_Right_Refresh_Activity { 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | 20 | kLineLayout.getKLineView().setEnableLeftRefresh(false); 21 | kLineLayout.getKLineView().setEnableRightRefresh(false); 22 | } 23 | 24 | public static Intent createIntent(Context context) { 25 | Intent intent = new Intent(context, Disable_Left_And_Right_Refresh_Activity.class); 26 | return intent; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.widget.LinearLayoutManager; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.Log; 7 | import android.view.KeyEvent; 8 | import android.widget.Toast; 9 | 10 | import com.wordplat.easydivider.RecyclerViewCornerRadius; 11 | import com.wordplat.easydivider.RecyclerViewLinearDivider; 12 | import com.wordplat.quickstart.R; 13 | import com.wordplat.quickstart.adapter.TextAdapter; 14 | import com.wordplat.quickstart.utils.AppUtils; 15 | 16 | import org.xutils.view.annotation.ContentView; 17 | import org.xutils.view.annotation.ViewInject; 18 | 19 | @ContentView(R.layout.activity_main) 20 | public class MainActivity extends BaseActivity { 21 | private static final String TAG = "MainActivity"; 22 | 23 | @ViewInject(R.id.textList) private RecyclerView textList = null; 24 | 25 | private TextAdapter textAdapter; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | textAdapter = new TextAdapter(mActivity); 32 | textList.setLayoutManager(new LinearLayoutManager(mActivity)); 33 | textList.setAdapter(textAdapter); 34 | 35 | RecyclerViewCornerRadius cornerRadius = new RecyclerViewCornerRadius(textList); 36 | cornerRadius.setCornerRadius(AppUtils.dpTopx(mActivity, 10)); 37 | 38 | RecyclerViewLinearDivider linearDivider = new RecyclerViewLinearDivider(mActivity, LinearLayoutManager.VERTICAL); 39 | linearDivider.setDividerSize(1); 40 | linearDivider.setDividerColor(0xff888888); 41 | linearDivider.setDividerMargin(AppUtils.dpTopx(mActivity, 10), AppUtils.dpTopx(mActivity, 10)); 42 | linearDivider.setDividerBackgroundColor(0xffffffff); 43 | linearDivider.setShowHeaderDivider(false); 44 | linearDivider.setShowFooterDivider(false); 45 | 46 | // 圆角背景必须第一个添加 47 | textList.addItemDecoration(cornerRadius); 48 | textList.addItemDecoration(linearDivider); 49 | 50 | for (int i = 0 ; i < 16 ; i++) { 51 | String result = Integer.toHexString(255 - i * 12); 52 | Log.i(TAG, "##d onCreate: " + result); 53 | } 54 | } 55 | 56 | /** 57 | * 点击两次退出 58 | */ 59 | private long exitTime = 0; 60 | 61 | @Override 62 | public boolean onKeyDown(int keyCode, KeyEvent event) { 63 | if (keyCode == KeyEvent.KEYCODE_BACK) { 64 | exit(); 65 | return false; 66 | } 67 | return super.onKeyDown(keyCode, event); 68 | } 69 | 70 | private void exit() { 71 | if ((System.currentTimeMillis() - exitTime) > 2000) { 72 | Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show(); 73 | exitTime = System.currentTimeMillis(); 74 | } else { 75 | finish(); 76 | System.exit(0); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/activity/Multi_Color_Dynamic_Change_Configuration_Activity.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | /** 8 | *Multi_Color_Dynamic_Change_Configuration_Activity
9 | *Date: 2017/3/31
10 | * 11 | * @author afon 12 | */ 13 | 14 | public class Multi_Color_Dynamic_Change_Configuration_Activity extends BaseActivity { 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | 20 | // TODO: 2017/4/11 21 | } 22 | 23 | public static Intent createIntent(Context context) { 24 | Intent intent = new Intent(context, Multi_Color_Dynamic_Change_Configuration_Activity.class); 25 | return intent; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/activity/Simple_TimeLine_Example_Activity.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import com.wordplat.ikvstockchart.InteractiveKLineView; 8 | import com.wordplat.ikvstockchart.entry.Entry; 9 | import com.wordplat.ikvstockchart.entry.EntrySet; 10 | import com.wordplat.ikvstockchart.render.TimeLineRender; 11 | import com.wordplat.quickstart.R; 12 | import com.wordplat.quickstart.bean.BtcBean; 13 | import com.wordplat.quickstart.mvp.BtcChinaPresenter; 14 | import com.wordplat.quickstart.mvp.LoadingViewListener; 15 | 16 | import org.xutils.view.annotation.ContentView; 17 | import org.xutils.view.annotation.ViewInject; 18 | 19 | /** 20 | *Simple_TimeLine_Example_Activity
21 | *Date: 2017/4/16
22 | * 23 | * @author afon 24 | */ 25 | 26 | @ContentView(R.layout.activity_simple_timeline) 27 | public class Simple_TimeLine_Example_Activity extends BaseActivity { 28 | 29 | @ViewInject(R.id.timeLineView) private InteractiveKLineView timeLineView = null; 30 | 31 | private static final int REQUEST_BTC_DATA = 1; 32 | 33 | private final EntrySet entrySet = new EntrySet(); 34 | 35 | private final BtcChinaPresenter presenter = new BtcChinaPresenter(); 36 | 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | 41 | 42 | } 43 | 44 | @Override 45 | protected void onResume() { 46 | super.onResume(); 47 | 48 | presenter.attachView(btcChinaListener); 49 | presenter.getSimple(REQUEST_BTC_DATA); 50 | } 51 | 52 | @Override 53 | protected void onPause() { 54 | super.onPause(); 55 | 56 | presenter.detachView(); 57 | } 58 | 59 | 60 | private LoadingViewListener btcChinaListener = new LoadingViewListener() { 61 | @Override 62 | public void onStartRequest(int requestCode) { 63 | 64 | } 65 | 66 | @Override 67 | public void onFinishRequest(int requestCode) { 68 | 69 | } 70 | 71 | @Override 72 | public void onSuccess(int requestCode) { 73 | for (BtcBean btcBean : presenter.getBtcList()) { 74 | Entry entry = new Entry(btcBean.getPrice(), (int) btcBean.getAmount(), ""); 75 | entrySet.addEntry(entry); 76 | } 77 | entrySet.getEntryList().get(0).setXLabel("09:30"); 78 | entrySet.getEntryList().get(2).setXLabel("11:30/13:00"); 79 | entrySet.getEntryList().get(4).setXLabel("15:00"); 80 | 81 | timeLineView.notifyDataSetChanged(); 82 | } 83 | 84 | @Override 85 | public void onResultEmpty(int requestCode) { 86 | entrySet.setLoadingStatus(false); 87 | timeLineView.notifyDataSetChanged(); 88 | } 89 | 90 | @Override 91 | public void onNoNetworkError(int requestCode) { 92 | super.onNoNetworkError(requestCode); 93 | onResultEmpty(requestCode); 94 | } 95 | 96 | @Override 97 | public void onNetworkTimeOutError(int requestCode) { 98 | super.onNetworkTimeOutError(requestCode); 99 | onResultEmpty(requestCode); 100 | } 101 | }; 102 | 103 | public static Intent createIntent(Context context) { 104 | Intent intent = new Intent(context, Simple_TimeLine_Example_Activity.class); 105 | return intent; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/activity/TestKLineActivty.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import com.wordplat.ikvstockchart.InteractiveKLineView; 8 | import com.wordplat.ikvstockchart.entry.Entry; 9 | import com.wordplat.ikvstockchart.entry.EntrySet; 10 | import com.wordplat.ikvstockchart.entry.StockDataTest; 11 | import com.wordplat.ikvstockchart.render.TimeLineRender; 12 | import com.wordplat.quickstart.R; 13 | import com.wordplat.quickstart.bean.BtcBean; 14 | import com.wordplat.quickstart.mvp.BtcChinaPresenter; 15 | import com.wordplat.quickstart.mvp.LoadingViewListener; 16 | 17 | import org.xutils.view.annotation.ContentView; 18 | import org.xutils.view.annotation.ViewInject; 19 | 20 | import java.io.InputStream; 21 | 22 | /** 23 | * Created by adminstartor on 2018/4/27. 24 | */ 25 | @ContentView(R.layout.activtiy_test_kline) 26 | public class TestKLineActivty extends BaseActivity { 27 | @ViewInject(R.id.timeLineView) private InteractiveKLineView timeLineView = null; 28 | 29 | private static final int REQUEST_BTC_DATA = 1; 30 | 31 | private EntrySet entrySet = new EntrySet(); 32 | 33 | private final BtcChinaPresenter presenter = new BtcChinaPresenter(); 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | 39 | 40 | loadData(); 41 | } 42 | 43 | @Override 44 | protected void onResume() { 45 | super.onResume(); 46 | 47 | presenter.attachView(btcChinaListener); 48 | presenter.getSimple(REQUEST_BTC_DATA); 49 | } 50 | 51 | private void loadData() 52 | { 53 | String kLineData = ""; 54 | try { 55 | InputStream in = getResources().getAssets().open("kline1.txt"); 56 | int length = in.available(); 57 | byte[] buffer = new byte[length]; 58 | in.read(buffer); 59 | kLineData = new String(buffer, "UTF-8"); 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | entrySet = StockDataTest.parseKLineData(kLineData); 64 | timeLineView.notifyDataSetChanged(); 65 | } 66 | 67 | @Override 68 | protected void onPause() { 69 | super.onPause(); 70 | 71 | presenter.detachView(); 72 | } 73 | 74 | 75 | private LoadingViewListener btcChinaListener = new LoadingViewListener() { 76 | @Override 77 | public void onStartRequest(int requestCode) { 78 | 79 | } 80 | 81 | @Override 82 | public void onFinishRequest(int requestCode) { 83 | 84 | } 85 | 86 | @Override 87 | public void onSuccess(int requestCode) { 88 | for (BtcBean btcBean : presenter.getBtcList()) { 89 | Entry entry = new Entry(btcBean.getPrice(), (int) btcBean.getAmount(), ""); 90 | entrySet.addEntry(entry); 91 | } 92 | entrySet.getEntryList().get(0).setXLabel("09:30"); 93 | entrySet.getEntryList().get(2).setXLabel("11:30/13:00"); 94 | entrySet.getEntryList().get(4).setXLabel("15:00"); 95 | 96 | timeLineView.notifyDataSetChanged(); 97 | } 98 | 99 | @Override 100 | public void onResultEmpty(int requestCode) { 101 | entrySet.setLoadingStatus(false); 102 | timeLineView.notifyDataSetChanged(); 103 | } 104 | 105 | @Override 106 | public void onNoNetworkError(int requestCode) { 107 | super.onNoNetworkError(requestCode); 108 | onResultEmpty(requestCode); 109 | } 110 | 111 | @Override 112 | public void onNetworkTimeOutError(int requestCode) { 113 | super.onNetworkTimeOutError(requestCode); 114 | onResultEmpty(requestCode); 115 | } 116 | }; 117 | 118 | public static Intent createIntent(Context context) { 119 | Intent intent = new Intent(context, Simple_TimeLine_Example_Activity.class); 120 | return intent; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/activity/With_Pull_To_Refresh_Example_Activity.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import com.chanven.lib.cptr.PtrDefaultHandler; 8 | import com.chanven.lib.cptr.PtrFrameLayout; 9 | import com.wordplat.quickstart.R; 10 | import com.wordplat.quickstart.widget.pulllistview.PullListLayout; 11 | 12 | import org.xutils.view.annotation.ContentView; 13 | import org.xutils.view.annotation.ViewInject; 14 | 15 | /** 16 | *With_Pull_To_Refresh_Example_Activity
17 | *Date: 2017/3/31
18 | * 19 | * @author afon 20 | */ 21 | 22 | @ContentView(R.layout.activity_with_pull_to_refresh) 23 | public class With_Pull_To_Refresh_Example_Activity extends Enable_Left_And_Right_Refresh_Activity { 24 | 25 | @ViewInject(R.id.pullListLayout) private PullListLayout pullListLayout = null; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | initUI(); 32 | } 33 | 34 | private void initUI() { 35 | pullListLayout.setPtrHandler(ptrHandler); 36 | } 37 | 38 | private PtrDefaultHandler ptrHandler = new PtrDefaultHandler() { 39 | @Override 40 | public void onRefreshBegin(PtrFrameLayout frame) { 41 | pullListLayout.postDelayed(new Runnable() { 42 | @Override 43 | public void run() { 44 | pullListLayout.refreshComplete(); 45 | } 46 | }, 2000); 47 | } 48 | }; 49 | 50 | public static Intent createIntent(Context context) { 51 | Intent intent = new Intent(context, With_Pull_To_Refresh_Example_Activity.class); 52 | return intent; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/activity/With_RecyclerView_Example_Activity.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | /** 8 | *With_RecyclerView_Example_Activity
9 | *Date: 2017/3/31
10 | * 11 | * @author afon 12 | */ 13 | 14 | public class With_RecyclerView_Example_Activity extends BaseActivity { 15 | 16 | private static final String TAG = "Activity"; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | 22 | // TODO: 2017/4/11 23 | } 24 | 25 | public static Intent createIntent(Context context) { 26 | Intent intent = new Intent(context, With_RecyclerView_Example_Activity.class); 27 | return intent; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/adapter/BaseViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | import org.xutils.x; 8 | 9 | /** 10 | * Created by afon on 2017/2/5. 11 | */ 12 | 13 | public abstract class BaseViewHolder extends RecyclerView.ViewHolder { 14 | 15 | protected Context mContext; 16 | 17 | public BaseViewHolder(View itemView) { 18 | super(itemView); 19 | 20 | mContext = itemView.getContext(); 21 | 22 | x.view().inject(this, itemView); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/adapter/TextAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.adapter; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.wordplat.quickstart.R; 11 | import com.wordplat.quickstart.activity.Disable_Left_And_Right_Refresh_Activity; 12 | import com.wordplat.quickstart.activity.Enable_Left_And_Right_Refresh_Activity; 13 | import com.wordplat.quickstart.activity.MACD_RSI_KDJ_Show_Together_Activity; 14 | import com.wordplat.quickstart.activity.Multi_Color_Dynamic_Change_Configuration_Activity; 15 | import com.wordplat.quickstart.activity.Simple_TimeLine_Example_Activity; 16 | import com.wordplat.quickstart.activity.TestKLineActivty; 17 | import com.wordplat.quickstart.activity.With_Fragment_And_TabLayout_Switcher_Example_Activity; 18 | import com.wordplat.quickstart.activity.With_Pull_To_Refresh_Example_Activity; 19 | import com.wordplat.quickstart.activity.With_RecyclerView_Example_Activity; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | /** 25 | * Created by afon on 2017/2/10. 26 | */ 27 | 28 | public class TextAdapter extends RecyclerView.AdapterBtcBean
5 | *Date: 2017/4/16
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class BtcBean { 11 | 12 | private long date; 13 | 14 | private float price; 15 | 16 | private float amount; 17 | 18 | private long tid; 19 | 20 | private String type; 21 | 22 | public long getDate() { 23 | return date; 24 | } 25 | 26 | public void setDate(long date) { 27 | this.date = date; 28 | } 29 | 30 | public float getPrice() { 31 | return price; 32 | } 33 | 34 | public void setPrice(float price) { 35 | this.price = price; 36 | } 37 | 38 | public float getAmount() { 39 | return amount; 40 | } 41 | 42 | public void setAmount(float amount) { 43 | this.amount = amount; 44 | } 45 | 46 | public long getTid() { 47 | return tid; 48 | } 49 | 50 | public void setTid(long tid) { 51 | this.tid = tid; 52 | } 53 | 54 | public String getType() { 55 | return type; 56 | } 57 | 58 | public void setType(String type) { 59 | this.type = type; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/bean/KLineBean.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.bean; 2 | 3 | /** 4 | *KLineBean
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class KLineBean { 11 | 12 | private float open; 13 | 14 | private float high; 15 | 16 | private float low; 17 | 18 | private float close; 19 | 20 | private int volume; 21 | 22 | private String date; 23 | 24 | public float getOpen() { 25 | return open; 26 | } 27 | 28 | public void setOpen(float open) { 29 | this.open = open; 30 | } 31 | 32 | public float getHigh() { 33 | return high; 34 | } 35 | 36 | public void setHigh(float high) { 37 | this.high = high; 38 | } 39 | 40 | public float getLow() { 41 | return low; 42 | } 43 | 44 | public void setLow(float low) { 45 | this.low = low; 46 | } 47 | 48 | public float getClose() { 49 | return close; 50 | } 51 | 52 | public void setClose(float close) { 53 | this.close = close; 54 | } 55 | 56 | public int getVolume() { 57 | return volume; 58 | } 59 | 60 | public void setVolume(int volume) { 61 | this.volume = volume; 62 | } 63 | 64 | public String getDate() { 65 | return date; 66 | } 67 | 68 | public void setDate(String date) { 69 | this.date = date; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/bean/ResultBean.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.bean; 2 | 3 | /** 4 | *ResultBean
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class ResultBean { 11 | 12 | private int resultCode; 13 | 14 | private String resultMessage; 15 | 16 | public int getResultCode() { 17 | return resultCode; 18 | } 19 | 20 | public void setResultCode(int resultCode) { 21 | this.resultCode = resultCode; 22 | } 23 | 24 | public String getResultMessage() { 25 | return resultMessage; 26 | } 27 | 28 | public void setResultMessage(String resultMessage) { 29 | this.resultMessage = resultMessage; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/bean/request/ServerRequestParams.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.bean.request; 2 | 3 | import android.text.TextUtils; 4 | import android.util.Log; 5 | 6 | import com.alibaba.fastjson.JSONObject; 7 | import com.wordplat.quickstart.BuildConfig; 8 | import com.wordplat.quickstart.app.AppRuntime; 9 | import com.wordplat.quickstart.utils.SSLHelper; 10 | 11 | import org.xutils.http.RequestParams; 12 | 13 | import java.io.File; 14 | 15 | import javax.net.ssl.SSLSocketFactory; 16 | 17 | /** 18 | *ServerRequestParams
19 | *Date: 2017/4/5
20 | * 21 | * @author afon 22 | */ 23 | 24 | public class ServerRequestParams extends RequestParams { 25 | private static final String TAG = "ServerRequestParams"; 26 | 27 | private JSONObject params = null; 28 | 29 | private JSONObject requestJson= null; 30 | 31 | private String uploadKey = null; 32 | private Object uploadValue = null; 33 | 34 | public ServerRequestParams(String URL) { 35 | super(URL); 36 | params = new JSONObject(); 37 | 38 | requestJson = new JSONObject(); 39 | 40 | setMaxRetryCount(2); 41 | setConnectTimeout(20000); 42 | 43 | SSLSocketFactory sslSocketFactory = SSLHelper.getSSLSocketFactory(AppRuntime.sContext); 44 | if (sslSocketFactory != null) { 45 | setSslSocketFactory(sslSocketFactory); 46 | } 47 | } 48 | 49 | public void addRequestParams(String key, Object value) { 50 | if (TextUtils.isEmpty(key) || value == null) { 51 | return; 52 | } 53 | 54 | requestJson.put(key, value); 55 | } 56 | 57 | public void addCustomParams(String key, JSONObject jsonObject) { 58 | if (TextUtils.isEmpty(key) || jsonObject == null) { 59 | return; 60 | } 61 | 62 | params.put(key, jsonObject); 63 | } 64 | 65 | /** 66 | * 上传文件 67 | * 68 | * @param value 可以是File, InputStream 或 byte[] 69 | */ 70 | public void upload(Object value) { 71 | uploadKey = "uploadFile"; 72 | uploadValue = value; 73 | } 74 | 75 | /** 76 | * 添加完参数或设置参数后调用此方法 77 | */ 78 | public void commit() { 79 | params.put("RequestParams", requestJson); 80 | 81 | if (BuildConfig.DEBUG) { 82 | Log.i(TAG, "##d 请求数据: " + requestJson.toJSONString()); 83 | } 84 | 85 | addBodyParameter("", requestJson.toJSONString()); 86 | 87 | if (!TextUtils.isEmpty(uploadKey) && uploadValue != null) { 88 | if (uploadValue instanceof org.json.JSONArray) { 89 | addParameter(uploadKey, uploadValue); 90 | 91 | } else if(uploadValue instanceof String) { 92 | addBodyParameter(uploadKey, new File((String) uploadValue)); 93 | 94 | } else if(uploadValue instanceof File) { 95 | addBodyParameter(uploadKey, (File)uploadValue); 96 | 97 | } else { 98 | addBodyParameter(uploadKey, uploadValue, "image/jpeg", System.currentTimeMillis()+".jpg"); 99 | } 100 | } 101 | } 102 | 103 | @Override 104 | public String toString() { 105 | return params.toJSONString(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/bean/response/IResultResponse.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.bean.response; 2 | 3 | /** 4 | *IResultResponse
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public interface IResultResponse { 11 | 12 | /** 13 | * 服务器返回的逻辑结果响应码 14 | */ 15 | int getResultCode(); 16 | 17 | /** 18 | * 服务器返回的逻辑结果错误信息 19 | */ 20 | String getResultDescr(); 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/bean/response/ServerResponse.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.bean.response; 2 | 3 | import org.xutils.http.annotation.HttpResponse; 4 | 5 | /** 6 | *ServerResponse
7 | *Date: 2017/4/11
8 | * 9 | * @author afon 10 | */ 11 | 12 | @HttpResponse(parser = ServerResponseParser.class) 13 | public class ServerResponse implements IResultResponse { 14 | 15 | @Override 16 | public int getResultCode() { 17 | return 0; 18 | } 19 | 20 | @Override 21 | public String getResultDescr() { 22 | return null; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/bean/response/ServerResponseParser.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.bean.response; 2 | 3 | import android.util.Log; 4 | 5 | import com.alibaba.fastjson.JSON; 6 | import com.wordplat.quickstart.BuildConfig; 7 | 8 | import org.xutils.http.app.ResponseParser; 9 | import org.xutils.http.request.UriRequest; 10 | 11 | import java.lang.reflect.Type; 12 | 13 | /** 14 | *ServerResponseParser
15 | *Date: 2017/4/11
16 | * 17 | * @author afon 18 | */ 19 | 20 | public class ServerResponseParser implements ResponseParser { 21 | private static final String TAG = "ServerResponseParser"; 22 | 23 | @Override 24 | public void checkResponse(UriRequest request) throws Throwable { 25 | 26 | } 27 | 28 | @Override 29 | public Object parse(Type resultType, Class> resultClass, String result) throws Throwable { 30 | if (BuildConfig.DEBUG) { 31 | Log.i(TAG, "##d 服务器返回数据:" + result); 32 | } 33 | 34 | return JSON.parseObject(result, resultClass); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.fragment; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import org.xutils.x; 12 | 13 | public class BaseFragment extends Fragment { 14 | protected Activity mActivity; // 给子类用的 15 | 16 | @Override 17 | public void onCreate(@Nullable Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | mActivity = getActivity(); 20 | } 21 | 22 | @Override 23 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 24 | return x.view().inject(this, inflater, container); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp; 2 | 3 | import android.text.TextUtils; 4 | import android.util.Log; 5 | import android.widget.EditText; 6 | 7 | import com.wordplat.quickstart.BuildConfig; 8 | import com.wordplat.quickstart.R; 9 | import com.wordplat.quickstart.app.AppRuntime; 10 | import com.wordplat.quickstart.mvp.exception.NetworkTimeOutException; 11 | import com.wordplat.quickstart.mvp.exception.NoNetworkException; 12 | import com.wordplat.quickstart.mvp.exception.ResultEmptyException; 13 | import com.wordplat.quickstart.mvp.exception.ResultFailedException; 14 | import com.wordplat.quickstart.mvp.exception.ResultParseException; 15 | 16 | import rx.Subscription; 17 | import rx.subscriptions.CompositeSubscription; 18 | 19 | /** 20 | *BasePresenter
21 | *Date: 2017/4/11
22 | * 23 | * @author afon 24 | */ 25 | 26 | public abstract class BasePresenter5 | * requestCode 请求编码 的意思是: 6 | * 对每一次 presenter 的调用指定一个唯一编码。 7 | * 比如,一个 Activity 中使用了两个以上的 presenter 方法,在 Activity 中 implement 了本接口, 8 | * 那么此时如果返回结果,就需根据请求编码来作对应的UI呈现。 9 | *
10 | *Date: 2017/4/11
11 | * 12 | * @author afon 13 | */ 14 | 15 | public interface BaseView { 16 | 17 | /** 18 | * 没有网络 19 | * 20 | * @param requestCode 请求编码 21 | */ 22 | void onNoNetworkError(int requestCode); 23 | 24 | /** 25 | * 网络超时 26 | * 27 | * @param requestCode 请求编码 28 | */ 29 | void onNetworkTimeOutError(int requestCode); 30 | 31 | /** 32 | * 操作成功 33 | * 34 | * @param requestCode 请求编码 35 | */ 36 | void onSuccess(int requestCode); 37 | 38 | /** 39 | * 网络请求结果解析错误 40 | * 41 | * @param requestCode 请求编码 42 | */ 43 | void onResultParseError(int requestCode); 44 | 45 | /** 46 | * 服务器返回失败、返回错误 47 | * 48 | * @param requestCode 请求编码 49 | * @param errCode 服务器返回的错误编码 50 | * @param errMessage 服务器返回的错误信息 51 | */ 52 | void onResultFailed(int requestCode, int errCode, String errMessage); 53 | 54 | /** 55 | * 服务器返回结果为空,或者是解析数据出错,也视为空 56 | * 57 | * @param requestCode 请求编码 58 | */ 59 | void onResultEmpty(int requestCode); 60 | 61 | /** 62 | * 显示一个警告信息 63 | * 64 | * @param requestCode 请求编码 65 | * @param errMessageResId 要显示的错误 String 的资源ID 66 | */ 67 | void onShowWarning(int requestCode, int errMessageResId); 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/BaseViewListener.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp; 2 | 3 | import android.text.TextUtils; 4 | import android.widget.Toast; 5 | 6 | import com.wordplat.quickstart.R; 7 | import com.wordplat.quickstart.app.AppRuntime; 8 | 9 | /** 10 | *BaseViewListener
11 | *Date: 2017/5/15
12 | * 13 | * @author afon 14 | */ 15 | 16 | public class BaseViewListener implements BaseView { 17 | @Override 18 | public void onNoNetworkError(int requestCode) { 19 | Toast.makeText(AppRuntime.sContext, 20 | AppRuntime.sContext.getResources().getString(R.string.Warning_No_Network), 21 | Toast.LENGTH_SHORT).show(); 22 | } 23 | 24 | @Override 25 | public void onNetworkTimeOutError(int requestCode) { 26 | Toast.makeText(AppRuntime.sContext, 27 | AppRuntime.sContext.getResources().getString(R.string.Warning_Network_Timeout), 28 | Toast.LENGTH_SHORT).show(); 29 | } 30 | 31 | @Override 32 | public void onSuccess(int requestCode) { 33 | 34 | } 35 | 36 | @Override 37 | public void onResultParseError(int requestCode) { 38 | 39 | } 40 | 41 | @Override 42 | public void onResultFailed(int requestCode, int errCode, String errMessage) { 43 | if (!TextUtils.isEmpty(errMessage)) { 44 | Toast.makeText(AppRuntime.sContext, errMessage, Toast.LENGTH_SHORT).show(); 45 | } 46 | } 47 | 48 | @Override 49 | public void onResultEmpty(int requestCode) { 50 | 51 | } 52 | 53 | @Override 54 | public void onShowWarning(int requestCode, int errMessageResId) { 55 | Toast.makeText(AppRuntime.sContext, 56 | AppRuntime.sContext.getResources().getString(errMessageResId), 57 | Toast.LENGTH_SHORT).show(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/BtcChinaApiRequest.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp; 2 | 3 | import android.util.Log; 4 | 5 | import com.wordplat.quickstart.BuildConfig; 6 | import com.wordplat.quickstart.bean.BtcBean; 7 | 8 | import org.xutils.http.RequestParams; 9 | 10 | import java.util.List; 11 | import java.util.Locale; 12 | 13 | import rx.Observable; 14 | import rx.Subscriber; 15 | import rx.schedulers.Schedulers; 16 | 17 | /** 18 | *BtcChinaApiRequest
19 | *Date: 2017/4/16
20 | * 21 | * @author afon 22 | */ 23 | 24 | public class BtcChinaApiRequest extends BaseRequest { 25 | private static final String TAG = "BtcChinaApiRequest"; 26 | 27 | private static final String URL = "https://data.btcchina.com/data/historydata?since=%d&limit=%d"; 28 | 29 | public static ObservableBtcChinaPresenter
13 | *Date: 2017/4/16
14 | * 15 | * @author afon 16 | */ 17 | 18 | public class BtcChinaPresenter extends BasePresenterLoadingView
5 | *Date: 2017/5/15
6 | * 7 | * @author afon 8 | */ 9 | 10 | public interface LoadingView extends BaseView { 11 | 12 | void onStartRequest(int requestCode); 13 | 14 | void onFinishRequest(int requestCode); 15 | 16 | void onSuccess(int requestCode); 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/LoadingViewListener.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp; 2 | 3 | /** 4 | *LoadingViewListener
5 | *Date: 2017/5/22
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class LoadingViewListener extends BaseViewListener implements LoadingView { 11 | 12 | @Override 13 | public void onStartRequest(int requestCode) { 14 | 15 | } 16 | 17 | @Override 18 | public void onFinishRequest(int requestCode) { 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/StockApiRequest.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp; 2 | 3 | import com.wordplat.quickstart.bean.KLineBean; 4 | import com.wordplat.quickstart.bean.request.ServerRequestParams; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | import java.util.List; 9 | import java.util.Locale; 10 | 11 | import rx.Observable; 12 | import rx.Subscriber; 13 | import rx.schedulers.Schedulers; 14 | 15 | /** 16 | *自己搭建的股票 API 服务器接口
17 | *Date: 2017/4/11
18 | * 19 | * @author afon 20 | */ 21 | 22 | public class StockApiRequest extends BaseRequest { 23 | private static final String TAG = "StockApiRequest"; 24 | 25 | private static final String URL = "https://api.wordplat.com/ts/v1/get_k_data/%s"; 26 | 27 | private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 28 | 29 | 30 | public static Observable网络超时错误
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class NetworkTimeOutException extends Exception { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/exception/NoNetworkException.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp.exception; 2 | 3 | /** 4 | *没有网络
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class NoNetworkException extends Exception { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/exception/ResultEmptyException.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp.exception; 2 | 3 | /** 4 | *服务器返回结果为空
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class ResultEmptyException extends Exception { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/exception/ResultFailedException.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp.exception; 2 | 3 | /** 4 | *服务器返回错误码
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class ResultFailedException extends Exception { 11 | 12 | private int errCode; 13 | 14 | private String errMessage; 15 | 16 | public ResultFailedException(int errCode, String errMessage) { 17 | this.errCode = errCode; 18 | this.errMessage = errMessage; 19 | } 20 | 21 | public int getErrCode() { 22 | return errCode; 23 | } 24 | 25 | public String getErrMessage() { 26 | return errMessage; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/mvp/exception/ResultParseException.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.mvp.exception; 2 | 3 | /** 4 | *解析服务器返回的数据失败
5 | *Date: 2017/4/11
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class ResultParseException extends Exception { 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.utils; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | /** 8 | * APP工具 9 | * 10 | * @author liutao 11 | */ 12 | 13 | public class AppUtils { 14 | 15 | /** 16 | * 网络是否连接 17 | * 18 | * @param context 19 | */ 20 | public static boolean isConnected(Context context) { 21 | ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 22 | NetworkInfo netInfo = connManager.getActiveNetworkInfo(); 23 | 24 | return netInfo == null || !netInfo.isConnected() ? false : true; 25 | } 26 | 27 | /** 28 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 29 | */ 30 | public static int dpTopx(Context context, float dpValue) { 31 | final float scale = context.getResources().getDisplayMetrics().density; 32 | return (int) (dpValue * scale + 0.5f); 33 | } 34 | 35 | /** 36 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp 37 | */ 38 | public static int pxTodp(Context context, float pxValue) { 39 | final float scale = context.getResources().getDisplayMetrics().density; 40 | return (int) (pxValue / scale + 0.5f); 41 | } 42 | 43 | /** 44 | * 获取App版本号 45 | */ 46 | public static String getAppVersionName(Context context) { 47 | String packageName = null; 48 | String versionName = null; 49 | int versionCode = 0; 50 | try { 51 | packageName = context.getPackageName(); 52 | 53 | versionName = context.getPackageManager().getPackageInfo(packageName, 0).versionName; 54 | 55 | versionCode = context.getPackageManager().getPackageInfo(packageName, 0).versionCode; 56 | 57 | } catch (Exception e) { 58 | e.printStackTrace(); 59 | } 60 | return versionName; 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/utils/SSLHelper.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.utils; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.wordplat.quickstart.R; 7 | 8 | import java.io.InputStream; 9 | import java.security.KeyStore; 10 | 11 | import javax.net.ssl.KeyManagerFactory; 12 | import javax.net.ssl.SSLContext; 13 | import javax.net.ssl.SSLSocketFactory; 14 | import javax.net.ssl.TrustManagerFactory; 15 | 16 | /** 17 | *SSLHelper
18 | *Date: 2017/5/29
19 | * 20 | * @author afon 21 | */ 22 | 23 | public class SSLHelper { 24 | private static final String KEY_STORE_TYPE_BKS = "bks"; // 证书类型 固定值 25 | private static final String KEY_STORE_TYPE_P12 = "PKCS12"; // 证书类型 固定值 26 | 27 | private static final int KEY_STORE_CLIENT_PATH = R.raw.client; // 客户端要给服务器端认证的证书 28 | private static final String KEY_STORE_PASSWORD = "123456"; // 证书密码 29 | 30 | private static final int KEY_STORE_TRUST_PATH = R.raw.mytruststore; // 客户端验证服务器端的证书库 31 | private static final String KEY_STORE_TRUST_PASSWORD = "123456"; // 证书库密码 32 | 33 | /** 34 | * 获取SSLContext 35 | * 36 | * @param context 上下文 37 | * @return SSLContext 38 | */ 39 | public static SSLSocketFactory getSSLSocketFactory(Context context) { 40 | try { 41 | // 服务器端需要验证的客户端证书 42 | KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12); 43 | // 客户端信任的服务器端证书 44 | KeyStore trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS); 45 | 46 | InputStream ksIn = context.getResources().openRawResource(KEY_STORE_CLIENT_PATH); 47 | InputStream tsIn = context.getResources().openRawResource(KEY_STORE_TRUST_PATH); 48 | try { 49 | keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray()); 50 | trustStore.load(tsIn, KEY_STORE_TRUST_PASSWORD.toCharArray()); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } finally { 54 | try { 55 | ksIn.close(); 56 | } catch (Exception ignore) { 57 | } 58 | try { 59 | tsIn.close(); 60 | } catch (Exception ignore) { 61 | } 62 | } 63 | 64 | SSLContext sslContext = SSLContext.getInstance("TLS"); 65 | TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 66 | trustManagerFactory.init(trustStore); 67 | 68 | KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509"); 69 | keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray()); 70 | 71 | sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); 72 | return sslContext.getSocketFactory(); 73 | 74 | } catch (Exception e) { 75 | Log.e("SSLHelper", e.getMessage(), e); 76 | } 77 | return null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/widget/TabButton.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.widget; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.drawable.Drawable; 9 | import android.util.AttributeSet; 10 | import android.widget.RadioButton; 11 | 12 | import com.wordplat.quickstart.R; 13 | import com.wordplat.quickstart.utils.AppUtils; 14 | 15 | /** 16 | * 带提示红点的Tab按键 17 | * 18 | * @author liutao 19 | */ 20 | public class TabButton extends RadioButton { 21 | private int radius = 0; 22 | private int offset = 0; 23 | private Paint paint = null; 24 | private boolean isShow = false; 25 | 26 | private int topDrawableWidth = 0; 27 | 28 | public TabButton(Context context) { 29 | this(context, null); 30 | } 31 | 32 | public TabButton(Context context, AttributeSet attrs) { 33 | this(context, attrs, android.R.attr.radioButtonStyle); 34 | } 35 | 36 | public TabButton(Context context, AttributeSet attrs, int defStyle) { 37 | super(context, attrs, defStyle); 38 | setButtonDrawable(null); 39 | 40 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabButton); 41 | radius = (int) a.getDimension(R.styleable.TabButton_dotSize, AppUtils.dpTopx(context, 4)); 42 | a.recycle(); 43 | 44 | paint = new Paint(); 45 | paint.setColor(Color.RED); 46 | paint.setAntiAlias(true); 47 | offset = radius * 2; 48 | 49 | Drawable[] drawables = null; 50 | try { 51 | drawables = getCompoundDrawables(); 52 | 53 | if(drawables == null || drawables[1] == null){ 54 | return; 55 | } 56 | 57 | topDrawableWidth = drawables[1].getIntrinsicWidth(); 58 | }catch (Exception e) { 59 | e.printStackTrace(); 60 | }finally { 61 | drawables = null; 62 | } 63 | } 64 | 65 | @Override 66 | protected void onDraw(Canvas canvas) { 67 | super.onDraw(canvas); 68 | if(isShow) { 69 | canvas.drawCircle((getWidth()/2+topDrawableWidth/2), offset, radius, paint); 70 | } 71 | } 72 | 73 | public void setShowTag(boolean isShow) { 74 | this.isShow = isShow; 75 | invalidate(); 76 | } 77 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/widget/pulllistview/LoadMoreViewFooter.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.widget.pulllistview; 2 | 3 | import android.view.View; 4 | import android.widget.ProgressBar; 5 | import android.widget.TextView; 6 | 7 | import com.chanven.lib.cptr.loadmore.ILoadMoreViewFactory; 8 | 9 | /** 10 | * Created by afon on 2016/12/9. 11 | */ 12 | 13 | public class LoadMoreViewFooter implements ILoadMoreViewFactory { 14 | 15 | private LoadMoreHelper loadMoreHelper; 16 | 17 | public LoadMoreHelper getLoadMoreView() { 18 | return loadMoreHelper; 19 | } 20 | 21 | @Override 22 | public ILoadMoreView madeLoadMoreView() { 23 | loadMoreHelper = new LoadMoreHelper(); 24 | return loadMoreHelper; 25 | } 26 | 27 | public static class LoadMoreHelper implements ILoadMoreView { 28 | 29 | protected View footerView; 30 | protected TextView footerTv; 31 | protected ProgressBar footerBar; 32 | 33 | protected View.OnClickListener onClickRefreshListener; 34 | 35 | @Override 36 | public void init(FootViewAdder footViewHolder, View.OnClickListener onClickRefreshListener) { 37 | footerView = footViewHolder.addFootView(com.chanven.lib.cptr.R.layout.loadmore_default_footer); 38 | footerTv = (TextView) footerView.findViewById(com.chanven.lib.cptr.R.id.loadmore_default_footer_tv); 39 | footerBar = (ProgressBar) footerView.findViewById(com.chanven.lib.cptr.R.id.loadmore_default_footer_progressbar); 40 | footerView.setClickable(true); 41 | footerView.setFocusable(true); 42 | footerView.setFocusableInTouchMode(true); 43 | this.onClickRefreshListener = onClickRefreshListener; 44 | showNormal(); 45 | } 46 | 47 | @Override 48 | public void showNormal() { 49 | footerTv.setText("点击加载更多"); 50 | footerBar.setVisibility(View.GONE); 51 | footerView.setOnClickListener(onClickRefreshListener); 52 | } 53 | 54 | @Override 55 | public void showLoading() { 56 | footerTv.setText("正在加载中..."); 57 | footerBar.setVisibility(View.VISIBLE); 58 | footerView.setOnClickListener(null); 59 | } 60 | 61 | @Override 62 | public void showFail(Exception exception) { 63 | footerTv.setText("加载失败,点击重新加载"); 64 | footerBar.setVisibility(View.GONE); 65 | footerView.setOnClickListener(onClickRefreshListener); 66 | } 67 | 68 | @Override 69 | public void showNomore() { 70 | footerTv.setText("已经加载完毕"); 71 | footerBar.setVisibility(View.GONE); 72 | footerView.setOnClickListener(null); 73 | } 74 | 75 | @Override 76 | public void setFooterVisibility(boolean isVisible) { 77 | footerView.setVisibility(isVisible ? View.VISIBLE : View.GONE); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/wordplat/quickstart/widget/pulllistview/PullListLayout.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.quickstart.widget.pulllistview; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.MotionEventCompat; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | import com.chanven.lib.cptr.PtrFrameLayout; 9 | import com.chanven.lib.cptr.loadmore.DefaultLoadMoreViewFooter; 10 | import com.chanven.lib.cptr.loadmore.ILoadMoreViewFactory; 11 | import com.wordplat.ikvstockchart.compat.GestureMoveActionCompat; 12 | 13 | /** 14 | * Created by liutao on 16/9/6. 15 | */ 16 | 17 | public class PullListLayout extends PtrFrameLayout { 18 | private ListRefreshView listRefreshView = null; 19 | 20 | private boolean isRefresh = true; 21 | 22 | private GestureMoveActionCompat gestureCompat; 23 | 24 | public PullListLayout(Context context) { 25 | this(context, null); 26 | } 27 | 28 | public PullListLayout(Context context, AttributeSet attrs) { 29 | this(context, attrs, 0); 30 | } 31 | 32 | public PullListLayout(Context context, AttributeSet attrs, int defStyle) { 33 | super(context, attrs, defStyle); 34 | initUI(); 35 | } 36 | 37 | private void initUI() { 38 | gestureCompat = new GestureMoveActionCompat(null); 39 | 40 | setRatioOfHeaderHeightToRefresh(1f); 41 | setResistance(3f); 42 | setDurationToCloseHeader(500); 43 | 44 | listRefreshView = new ListRefreshView(getContext()); 45 | setHeaderView(listRefreshView); 46 | addPtrUIHandler(listRefreshView); 47 | 48 | ILoadMoreViewFactory loadMoreViewFactory = new DefaultLoadMoreViewFooter(); 49 | setFooterView(loadMoreViewFactory); 50 | } 51 | 52 | public void setStatusHintColor(int colorResId) { 53 | listRefreshView.setStatusHintColor(colorResId); 54 | } 55 | 56 | public void setUpdateTimeColor(int colorResId) { 57 | listRefreshView.setUpdateTimeColor(colorResId); 58 | } 59 | 60 | public void setPullRefresh(boolean isRefresh) { 61 | this.isRefresh = isRefresh; 62 | } 63 | 64 | @Override 65 | public boolean dispatchTouchEvent(MotionEvent e) { 66 | // 解决 PullListLayout 垂直滑动(下拉刷新)与横向滑动冲突 67 | if (gestureCompat.onTouchEvent(e, e.getRawX(), e.getRawY())) { 68 | return dispatchTouchEventSupper(e); 69 | } 70 | // 解决双指缩放的冲突 71 | if (MotionEventCompat.getActionMasked(e) == MotionEvent.ACTION_POINTER_DOWN) { 72 | isRefresh = false; 73 | } 74 | 75 | if (isRefresh) { 76 | return super.dispatchTouchEvent(e); 77 | } 78 | 79 | switch (e.getAction()) { 80 | case MotionEvent.ACTION_UP: 81 | case MotionEvent.ACTION_CANCEL: 82 | isRefresh = true; 83 | return super.dispatchTouchEvent(e); 84 | } 85 | 86 | return dispatchTouchEventSupper(e); 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/dialog_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |KLineHandler
27 | *Date: 2017/3/22
28 | * 29 | * @author afon 30 | */ 31 | 32 | public interface KLineHandler { 33 | 34 | void onLeftRefresh(); 35 | 36 | void onRightRefresh(); 37 | 38 | void onSingleTap(MotionEvent e, float x, float y); 39 | 40 | void onDoubleTap(MotionEvent e, float x, float y); 41 | 42 | void onHighlight(Entry entry, int entryIndex, float x, float y); 43 | 44 | void onCancelHighlight(); 45 | } 46 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/SimpleKLineHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart; 20 | 21 | import android.view.MotionEvent; 22 | 23 | import com.wordplat.ikvstockchart.entry.Entry; 24 | 25 | /** 26 | *SimpleKLineHandler
27 | *Date: 2017/3/22
28 | * 29 | * @author afon 30 | */ 31 | 32 | public class SimpleKLineHandler implements KLineHandler { 33 | 34 | public void onLeftRefresh() { 35 | 36 | } 37 | 38 | public void onRightRefresh() { 39 | 40 | } 41 | 42 | public void onSingleTap(MotionEvent e, float x, float y) { 43 | 44 | } 45 | 46 | public void onDoubleTap(MotionEvent e, float x, float y) { 47 | 48 | } 49 | 50 | @Override 51 | public void onHighlight(Entry entry, int entryIndex, float x, float y) { 52 | 53 | } 54 | 55 | @Override 56 | public void onCancelHighlight() { 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/align/XMarkerAlign.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.ikvstockchart.align; 2 | 3 | /** 4 | *XMarkerAlign
5 | *Date: 2017/4/25
6 | * 7 | * @author afon 8 | */ 9 | 10 | public enum XMarkerAlign { 11 | 12 | TOP, 13 | 14 | BOTTOM, 15 | 16 | AUTO, 17 | } 18 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/align/YLabelAlign.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.ikvstockchart.align; 2 | 3 | /** 4 | *YLabelAlign
5 | *Date: 2017/4/25
6 | * 7 | * @author afon 8 | */ 9 | 10 | public enum YLabelAlign { 11 | 12 | LEFT, 13 | 14 | RIGHT, 15 | } 16 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/align/YMarkerAlign.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.ikvstockchart.align; 2 | 3 | /** 4 | *YMarkerAlign
5 | *Date: 2017/4/25
6 | * 7 | * @author afon 8 | */ 9 | 10 | public enum YMarkerAlign { 11 | 12 | LEFT, 13 | 14 | RIGHT, 15 | 16 | AUTO, 17 | } 18 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/compat/GestureMoveActionCompat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.compat; 20 | 21 | import android.view.MotionEvent; 22 | 23 | /** 24 | *横向移动、垂直移动 识别,解决滑动冲突用的
25 | *Date: 2017/1/22
26 | * 27 | * @author afon 28 | */ 29 | 30 | public class GestureMoveActionCompat { 31 | private OnGestureMoveListener gestureMoveListener; 32 | 33 | /** 34 | * 本次 ACTION_DOWN 事件的坐标 x 35 | */ 36 | private float lastMotionX; 37 | 38 | /** 39 | * 本次 ACTION_DOWN 事件的坐标 y 40 | */ 41 | private float lastMotionY; 42 | 43 | /** 44 | * 当前滑动的方向。0 无滑动(视为点击);1 垂直滑动;2 横向滑动 45 | */ 46 | private int interceptStatus = 0; 47 | 48 | /** 49 | * 是否响应点击事件 50 | * 51 | * 因为有手指抖动的影响,有时候会产生少量的 ACTION_MOVE 事件,造成程序识别错误。 52 | * 如果需要减少识别错误的几率,使用 {@link GestureMoveDetectorCompat} 这个类。 53 | */ 54 | private boolean mEnableClick = true; 55 | 56 | /** 57 | * 避免程序识别错误的一个阀值。只有触摸移动的距离大于这个阀值时,才认为是一个有效的移动。 58 | */ 59 | private int touchSlop = 20; 60 | 61 | private boolean dragging = false; 62 | 63 | public GestureMoveActionCompat(OnGestureMoveListener onGestureMoveListener) { 64 | gestureMoveListener = onGestureMoveListener; 65 | } 66 | 67 | public void enableClick(boolean enableClick) { 68 | mEnableClick = enableClick; 69 | } 70 | 71 | public void setTouchSlop(int touchSlop) { 72 | this.touchSlop = touchSlop; 73 | } 74 | 75 | public boolean isDragging() { 76 | return dragging; 77 | } 78 | 79 | /** 80 | * @param e 事件 e 81 | * @param x 本次事件的坐标 x。可以是 e.getRawX() 或是 e.getX(),具体看情况 82 | * @param y 本次事件的坐标 y。可以是 e.getRawY() 或是 e.getY(),具体看情况 83 | * 84 | * @return 事件是否是横向滑动 85 | */ 86 | public boolean onTouchEvent(MotionEvent e, float x, float y) { 87 | switch (e.getAction()) { 88 | case MotionEvent.ACTION_DOWN: 89 | lastMotionY = y; 90 | lastMotionX = x; 91 | interceptStatus = 0; 92 | dragging = false; 93 | break; 94 | 95 | case MotionEvent.ACTION_MOVE: 96 | float deltaY = Math.abs(y - lastMotionY); 97 | float deltaX = Math.abs(x - lastMotionX); 98 | 99 | /** 100 | * 如果之前是垂直滑动,即使现在是横向滑动,仍然认为它是垂直滑动的 101 | * 如果之前是横向滑动,即使现在是垂直滑动,仍然认为它是横向滑动的 102 | * 防止在一个方向上来回滑动时,发生垂直滑动和横向滑动的频繁切换,造成识别错误 103 | */ 104 | if (interceptStatus != 1 && 105 | (dragging || deltaX > deltaY && deltaX > touchSlop)) { 106 | interceptStatus = 2; 107 | dragging = true; 108 | 109 | if (gestureMoveListener != null) { 110 | gestureMoveListener.onHorizontalMove(e, x, y); 111 | } 112 | } else if (interceptStatus != 2 && 113 | (dragging || deltaX < deltaY && deltaY > touchSlop)) { 114 | interceptStatus = 1; 115 | dragging = true; 116 | 117 | if (gestureMoveListener != null) { 118 | gestureMoveListener.onVerticalMove(e, x, y); 119 | } 120 | } 121 | break; 122 | 123 | case MotionEvent.ACTION_UP: 124 | if (interceptStatus == 0) { 125 | if (mEnableClick && gestureMoveListener != null) { 126 | gestureMoveListener.onClick(e, x, y); 127 | } 128 | } 129 | interceptStatus = 0; 130 | dragging = false; 131 | break; 132 | } 133 | return interceptStatus == 2; 134 | } 135 | 136 | public interface OnGestureMoveListener { 137 | 138 | /** 139 | * 横向移动 140 | */ 141 | void onHorizontalMove(MotionEvent e, float x, float y); 142 | 143 | /** 144 | * 垂直移动 145 | */ 146 | void onVerticalMove(MotionEvent e, float x, float y); 147 | 148 | /** 149 | * 点击事件 150 | */ 151 | void onClick(MotionEvent e, float x, float y); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/compat/PerformenceAnalyser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.compat; 20 | 21 | import android.util.Log; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | /** 27 | *统计方法执行时间的分析器
28 | *Date: 2016/12/29
29 | * 30 | * @author afon 31 | */ 32 | 33 | public class PerformenceAnalyser { 34 | private static final String TAG = "PerformenceAnalyser"; 35 | 36 | private static volatile PerformenceAnalyser instance; 37 | 38 | private long methodStartTime = 0; 39 | 40 | private MapEmptyDataDrawing
30 | *Date: 2017/3/21
31 | * 32 | * @author afon 33 | */ 34 | 35 | public class EmptyDataDrawing implements IDrawing { 36 | 37 | private Paint textPaint; 38 | private final Paint.FontMetrics fontMetrics = new Paint.FontMetrics(); 39 | 40 | private AbstractRender render; 41 | private SizeColor sizeColor; 42 | private final RectF contentRect = new RectF(); 43 | 44 | @Override 45 | public void onInit(RectF contentRect, AbstractRender render) { 46 | this.render = render; 47 | this.contentRect.set(contentRect); 48 | this.sizeColor = render.getSizeColor(); 49 | 50 | if (textPaint == null) { 51 | textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 52 | } 53 | textPaint.setTextAlign(Paint.Align.CENTER); 54 | } 55 | 56 | @Override 57 | public void computePoint(int minIndex, int maxIndex, int currentIndex) { 58 | 59 | } 60 | 61 | @Override 62 | public void onComputeOver(Canvas canvas, int minIndex, int maxIndex, float minY, float maxY) { 63 | 64 | } 65 | 66 | @Override 67 | public void onDrawOver(Canvas canvas) { 68 | if (render.getEntrySet().getEntryList().size() == 0) { 69 | final String drawText; 70 | if (render.getEntrySet().isLoadingStatus()) { 71 | textPaint.setTextSize(sizeColor.getLoadingTextSize()); 72 | textPaint.setColor(sizeColor.getLoadingTextColor()); 73 | drawText = sizeColor.getLoadingText(); 74 | } else { 75 | textPaint.setTextSize(sizeColor.getErrorTextSize()); 76 | textPaint.setColor(sizeColor.getErrorTextColor()); 77 | drawText = sizeColor.getErrorText(); 78 | } 79 | 80 | textPaint.getFontMetrics(fontMetrics); 81 | 82 | canvas.drawText(drawText, 83 | contentRect.width() / 2, 84 | (contentRect.top + contentRect.bottom - fontMetrics.top - fontMetrics.bottom) / 2, 85 | textPaint); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/drawing/HighlightDrawing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.drawing; 20 | 21 | import android.graphics.Canvas; 22 | import android.graphics.Color; 23 | import android.graphics.Paint; 24 | import android.graphics.RectF; 25 | import android.util.Log; 26 | 27 | import com.wordplat.ikvstockchart.entry.SizeColor; 28 | import com.wordplat.ikvstockchart.marker.IMarkerView; 29 | import com.wordplat.ikvstockchart.marker.XAxisTextMarkerView; 30 | import com.wordplat.ikvstockchart.marker.YAxisTextMarkerView; 31 | import com.wordplat.ikvstockchart.render.AbstractRender; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | /** 37 | *HighlightDrawing
38 | *Date: 2017/3/23
39 | * 40 | * @author afon 41 | */ 42 | 43 | public class HighlightDrawing implements IDrawing { 44 | 45 | protected Paint highlightPaint; // 高亮线条画笔 46 | 47 | protected final RectF contentRect = new RectF(); // 绘图区域 48 | protected AbstractRender render; 49 | 50 | private ListIDrawing
28 | *Date: 2017/3/9
29 | * 30 | * @author afon 31 | */ 32 | 33 | public interface IDrawing { 34 | 35 | /** 36 | * 初始化 37 | * 38 | * @param contentRect 视图区域 39 | * @param render render 40 | */ 41 | void onInit(RectF contentRect, AbstractRender render); 42 | 43 | /** 44 | * 计算预绘制的坐标 45 | * 46 | * @param minIndex 当前视图区域的可见 entry 最小索引 47 | * @param maxIndex 当前视图区域的可见 entry 最大索引 48 | * @param currentIndex 当前循环中的 entry 索引 49 | */ 50 | void computePoint(int minIndex, int maxIndex, int currentIndex); 51 | 52 | /** 53 | * 计算结束,开始绘制 54 | * 55 | * @param canvas canvas 56 | * @param minIndex 当前视图区域的可见 entry 最小索引 57 | * @param maxIndex 当前视图区域的可见 entry 最大索引 58 | * @param minY 当前视图区域的 Y 轴最小值 59 | * @param maxY 当前视图区域的 Y 轴最大值 60 | */ 61 | void onComputeOver(Canvas canvas, int minIndex, int maxIndex, float minY, float maxY); 62 | 63 | /** 64 | * 绘制结束 65 | * 66 | * @param canvas canvas 67 | */ 68 | void onDrawOver(Canvas canvas); 69 | } 70 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/drawing/KLineVolumeHighlightDrawing.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.ikvstockchart.drawing; 2 | 3 | import android.graphics.Canvas; 4 | 5 | /** 6 | *KLineVolumeHighlightDrawing K线成交量的高亮绘制
7 | *Date: 2017/6/28
8 | * 9 | * @author afon 10 | */ 11 | 12 | public class KLineVolumeHighlightDrawing extends HighlightDrawing { 13 | 14 | @Override 15 | public void onDrawOver(Canvas canvas) { 16 | // 绘制高亮 成交量的高亮线条不需要垂直移动 17 | if (render.isHighlight()) { 18 | final float[] highlightPoint = render.getHighlightPoint(); 19 | 20 | canvas.save(); 21 | canvas.clipRect(contentRect); 22 | 23 | canvas.drawLine(highlightPoint[0], contentRect.top, highlightPoint[0], contentRect.bottom, highlightPaint); 24 | 25 | canvas.restore(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/drawing/MADrawing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.drawing; 20 | 21 | import android.graphics.Canvas; 22 | import android.graphics.Paint; 23 | import android.graphics.RectF; 24 | 25 | import com.wordplat.ikvstockchart.entry.Entry; 26 | import com.wordplat.ikvstockchart.entry.EntrySet; 27 | import com.wordplat.ikvstockchart.entry.SizeColor; 28 | import com.wordplat.ikvstockchart.render.AbstractRender; 29 | 30 | /** 31 | *MADrawing
32 | *Date: 2017/3/9
33 | * 34 | * @author afon 35 | */ 36 | 37 | public class MADrawing implements IDrawing { 38 | 39 | private Paint ma5Paint; 40 | private Paint ma10Paint; 41 | private Paint ma20Paint; 42 | 43 | private final RectF candleRect = new RectF(); // K 线图显示区域 44 | private AbstractRender render; 45 | 46 | // 计算 MA(5, 10, 20) 线条坐标用的 47 | private float[] ma5Buffer = new float[4]; 48 | private float[] ma10Buffer = new float[4]; 49 | private float[] ma20Buffer = new float[4]; 50 | 51 | @Override 52 | public void onInit(RectF contentRect, AbstractRender render) { 53 | this.render = render; 54 | final SizeColor sizeColor = render.getSizeColor(); 55 | 56 | if (ma5Paint == null) { 57 | ma5Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 58 | ma5Paint.setStyle(Paint.Style.STROKE); 59 | } 60 | 61 | if (ma10Paint == null) { 62 | ma10Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 63 | ma10Paint.setStyle(Paint.Style.STROKE); 64 | } 65 | 66 | if (ma20Paint == null) { 67 | ma20Paint = new Paint(Paint.ANTI_ALIAS_FLAG); 68 | ma20Paint.setStyle(Paint.Style.STROKE); 69 | } 70 | 71 | ma5Paint.setStrokeWidth(sizeColor.getMaLineSize()); 72 | ma10Paint.setStrokeWidth(sizeColor.getMaLineSize()); 73 | ma20Paint.setStrokeWidth(sizeColor.getMaLineSize()); 74 | 75 | ma5Paint.setColor(sizeColor.getMa5Color()); 76 | ma10Paint.setColor(sizeColor.getMa10Color()); 77 | ma20Paint.setColor(sizeColor.getMa20Color()); 78 | 79 | candleRect.set(contentRect); 80 | } 81 | 82 | @Override 83 | public void computePoint(int minIndex, int maxIndex, int currentIndex) { 84 | final int count = (maxIndex - minIndex) * 4; 85 | if (ma5Buffer.length < count) { 86 | ma5Buffer = new float[count]; 87 | ma10Buffer = new float[count]; 88 | ma20Buffer = new float[count]; 89 | } 90 | 91 | final EntrySet entrySet = render.getEntrySet(); 92 | final Entry entry = entrySet.getEntryList().get(currentIndex); 93 | final int i = currentIndex - minIndex; 94 | 95 | if (currentIndex < maxIndex - 1) { 96 | ma5Buffer[i * 4 + 0] = currentIndex + 0.5f; 97 | ma5Buffer[i * 4 + 1] = entry.getMa5(); 98 | ma5Buffer[i * 4 + 2] = currentIndex + 1 + 0.5f; 99 | ma5Buffer[i * 4 + 3] = entrySet.getEntryList().get(currentIndex + 1).getMa5(); 100 | 101 | ma10Buffer[i * 4 + 0] = ma5Buffer[i * 4 + 0]; 102 | ma10Buffer[i * 4 + 1] = entry.getMa10(); 103 | ma10Buffer[i * 4 + 2] = ma5Buffer[i * 4 + 2]; 104 | ma10Buffer[i * 4 + 3] = entrySet.getEntryList().get(currentIndex + 1).getMa10(); 105 | 106 | ma20Buffer[i * 4 + 0] = ma5Buffer[i * 4 + 0]; 107 | ma20Buffer[i * 4 + 1] = entry.getMa20(); 108 | ma20Buffer[i * 4 + 2] = ma5Buffer[i * 4 + 2]; 109 | ma20Buffer[i * 4 + 3] = entrySet.getEntryList().get(currentIndex + 1).getMa20(); 110 | } 111 | } 112 | 113 | @Override 114 | public void onComputeOver(Canvas canvas, int minIndex, int maxIndex, float minY, float maxY) { 115 | canvas.save(); 116 | canvas.clipRect(candleRect); 117 | 118 | render.mapPoints(ma5Buffer); 119 | render.mapPoints(ma10Buffer); 120 | render.mapPoints(ma20Buffer); 121 | 122 | final int count = (maxIndex - minIndex) * 4; 123 | 124 | // 使用 drawLines 方法比依次调用 drawLine 方法要快 125 | canvas.drawLines(ma5Buffer, 0, count, ma5Paint); 126 | canvas.drawLines(ma10Buffer, 0, count, ma10Paint); 127 | canvas.drawLines(ma20Buffer, 0, count, ma20Paint); 128 | 129 | canvas.restore(); 130 | } 131 | 132 | @Override 133 | public void onDrawOver(Canvas canvas) { 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/drawing/StockIndexYLabelDrawing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.drawing; 20 | 21 | import android.graphics.Canvas; 22 | import android.graphics.Paint; 23 | import android.graphics.RectF; 24 | 25 | import com.wordplat.ikvstockchart.align.YLabelAlign; 26 | import com.wordplat.ikvstockchart.entry.SizeColor; 27 | import com.wordplat.ikvstockchart.render.AbstractRender; 28 | 29 | import java.text.DecimalFormat; 30 | 31 | /** 32 | *StockIndexYLabelDrawing
33 | *Date: 2017/3/28
34 | * 35 | * @author afon 36 | */ 37 | 38 | public class StockIndexYLabelDrawing implements IDrawing { 39 | 40 | private Paint yLabelPaint; // Y 轴标签的画笔 41 | private final Paint.FontMetrics fontMetrics = new Paint.FontMetrics(); // 用于 labelPaint 计算文字位置 42 | private final DecimalFormat decimalFormatter = new DecimalFormat("0.00"); 43 | 44 | private final RectF indexRect = new RectF(); 45 | 46 | private YLabelAlign yLabelAlign; // Y 轴标签对齐方向 47 | 48 | @Override 49 | public void onInit(RectF contentRect, AbstractRender render) { 50 | final SizeColor sizeColor = render.getSizeColor(); 51 | 52 | if (yLabelPaint == null) { 53 | yLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 54 | yLabelPaint.setTextSize(sizeColor.getYLabelSize()); 55 | } 56 | yLabelPaint.setColor(sizeColor.getYLabelColor()); 57 | yLabelPaint.getFontMetrics(fontMetrics); 58 | yLabelAlign = sizeColor.getYLabelAlign(); 59 | if (yLabelAlign == YLabelAlign.RIGHT) { 60 | yLabelPaint.setTextAlign(Paint.Align.RIGHT); 61 | } 62 | 63 | indexRect.set(contentRect); 64 | } 65 | 66 | @Override 67 | public void computePoint(int minIndex, int maxIndex, int currentIndex) { 68 | 69 | } 70 | 71 | @Override 72 | public void onComputeOver(Canvas canvas, int minIndex, int maxIndex, float minY, float maxY) { 73 | float labelX = yLabelAlign == YLabelAlign.LEFT ? indexRect.left + 5 : indexRect.right - 5; 74 | 75 | canvas.drawText( 76 | decimalFormatter.format(maxY), 77 | labelX, 78 | indexRect.top - fontMetrics.top, 79 | yLabelPaint); 80 | 81 | canvas.drawText( 82 | decimalFormatter.format(minY), 83 | labelX, 84 | indexRect.bottom - fontMetrics.bottom, 85 | yLabelPaint); 86 | } 87 | 88 | @Override 89 | public void onDrawOver(Canvas canvas) { 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/drawing/TimeLineDrawing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.drawing; 20 | 21 | import android.graphics.Canvas; 22 | import android.graphics.Paint; 23 | import android.graphics.RectF; 24 | import android.util.Log; 25 | 26 | import com.wordplat.ikvstockchart.entry.Entry; 27 | import com.wordplat.ikvstockchart.entry.EntrySet; 28 | import com.wordplat.ikvstockchart.entry.SizeColor; 29 | import com.wordplat.ikvstockchart.render.AbstractRender; 30 | 31 | /** 32 | *TimeLineDrawing
33 | *Date: 2017/3/9
34 | * 35 | * @author afon 36 | */ 37 | 38 | public class TimeLineDrawing implements IDrawing { 39 | 40 | private Paint linePaint; 41 | 42 | private final RectF chartRect = new RectF(); // 分时图显示区域 43 | private AbstractRender render; 44 | 45 | private float[] lineBuffer = new float[4]; 46 | private float[] pointBuffer = new float[2]; 47 | 48 | @Override 49 | public void onInit(RectF contentRect, AbstractRender render) { 50 | this.render = render; 51 | final SizeColor sizeColor = render.getSizeColor(); 52 | 53 | if (linePaint == null) { 54 | linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 55 | linePaint.setStyle(Paint.Style.FILL); 56 | } 57 | linePaint.setStrokeWidth(sizeColor.getTimeLineSize()); 58 | linePaint.setColor(sizeColor.getTimeLineColor()); 59 | 60 | chartRect.set(contentRect); 61 | } 62 | 63 | @Override 64 | public void computePoint(int minIndex, int maxIndex, int currentIndex) { 65 | final int count = (maxIndex - minIndex) * 4; 66 | 67 | if (lineBuffer.length < count) { 68 | lineBuffer = new float[count]; 69 | } 70 | 71 | final EntrySet entrySet = render.getEntrySet(); 72 | final Entry entry = entrySet.getEntryList().get(currentIndex); 73 | final int i = currentIndex - minIndex; 74 | 75 | if (currentIndex < maxIndex - 1) { 76 | lineBuffer[i * 4] = currentIndex; 77 | lineBuffer[i * 4 + 1] = entry.getClose(); 78 | lineBuffer[i * 4 + 2] = currentIndex + 1; 79 | lineBuffer[i * 4 + 3] = entrySet.getEntryList().get(currentIndex + 1).getClose(); 80 | } 81 | } 82 | 83 | @Override 84 | public void onComputeOver(Canvas canvas, int minIndex, int maxIndex, float minY, float maxY) { 85 | canvas.save(); 86 | canvas.clipRect(chartRect); 87 | 88 | render.mapPoints(lineBuffer); 89 | 90 | final int count = (maxIndex - minIndex) * 4; 91 | 92 | if (count > 0) { 93 | canvas.drawLines(lineBuffer, 0, count, linePaint); 94 | } 95 | 96 | // 计算高亮坐标 97 | if (render.isHighlight()) { 98 | final EntrySet entrySet = render.getEntrySet(); 99 | final int lastEntryIndex = entrySet.getEntryList().size() - 2; 100 | final float[] highlightPoint = render.getHighlightPoint(); 101 | pointBuffer[0] = highlightPoint[0]; 102 | render.invertMapPoints(pointBuffer); 103 | final int highlightIndex = pointBuffer[0] < 0 ? 0 : (int) pointBuffer[0]; 104 | final int i = highlightIndex - minIndex; 105 | entrySet.setHighlightIndex(highlightIndex); 106 | Log.e("indexOut",i+"==="+ highlightIndex + "==="+lastEntryIndex); 107 | if(i >= 0 && highlightIndex < lastEntryIndex ) { 108 | highlightPoint[0] = highlightIndex < lastEntryIndex ? 109 | lineBuffer[i * 4]: lineBuffer[lastEntryIndex * 4 + 2]; 110 | highlightPoint[1] = highlightIndex < lastEntryIndex ? 111 | lineBuffer[i * 4 + 1] : lineBuffer[lastEntryIndex * 4 + 3]; 112 | } 113 | } 114 | canvas.restore(); 115 | } 116 | 117 | @Override 118 | public void onDrawOver(Canvas canvas) { 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/entry/StockBOLLIndex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.entry; 20 | 21 | /** 22 | *BOLL 指标
23 | *Date: 2017/3/16
24 | * 25 | * @author afon 26 | */ 27 | 28 | public class StockBOLLIndex extends StockIndex { 29 | 30 | public StockBOLLIndex() { 31 | super(STANDARD_HEIGHT); 32 | } 33 | 34 | public StockBOLLIndex(int height) { 35 | super(height); 36 | } 37 | 38 | @Override 39 | public void computeMinMax(int currentIndex, Entry entry) { 40 | if (entry.getMb() < getMinY()) { 41 | setMinY(entry.getMb()); 42 | } 43 | 44 | if (entry.getMb() > getMaxY()) { 45 | setMaxY(entry.getMb()); 46 | } 47 | 48 | if (currentIndex > 0) { 49 | if (entry.getUp() < getMinY()) { 50 | setMinY(entry.getUp()); 51 | } 52 | if (entry.getDn() < getMinY()) { 53 | setMinY(entry.getDn()); 54 | } 55 | 56 | if (entry.getUp() > getMaxY()) { 57 | setMaxY(entry.getUp()); 58 | } 59 | if (entry.getDn() > getMaxY()) { 60 | setMaxY(entry.getDn()); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/entry/StockKDJIndex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.entry; 20 | 21 | /** 22 | *KDJ 指标
23 | *Date: 2017/3/16
24 | * 25 | * @author afon 26 | */ 27 | 28 | public class StockKDJIndex extends StockIndex { 29 | 30 | public StockKDJIndex() { 31 | super(STANDARD_HEIGHT); 32 | } 33 | 34 | public StockKDJIndex(int height) { 35 | super(height); 36 | } 37 | 38 | @Override 39 | public void computeMinMax(int currentIndex, Entry entry) { 40 | if (entry.getK() < getMinY()) { 41 | setMinY(entry.getK()); 42 | } 43 | if (entry.getD() < getMinY()) { 44 | setMinY(entry.getD()); 45 | } 46 | if (entry.getJ() < getMinY()) { 47 | setMinY(entry.getJ()); 48 | } 49 | 50 | if (entry.getK() > getMaxY()) { 51 | setMaxY(entry.getK()); 52 | } 53 | if (entry.getD() > getMaxY()) { 54 | setMaxY(entry.getD()); 55 | } 56 | if (entry.getJ() > getMaxY()) { 57 | setMaxY(entry.getJ()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/entry/StockKLineVolumeIndex.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.ikvstockchart.entry; 2 | 3 | /** 4 | *StockKLineVolumeIndex
5 | *Date: 2017/6/28
6 | * 7 | * @author afon 8 | */ 9 | 10 | public class StockKLineVolumeIndex extends StockIndex { 11 | 12 | public StockKLineVolumeIndex() { 13 | super(STANDARD_HEIGHT); 14 | setExtremumYScale(1f); 15 | } 16 | 17 | public StockKLineVolumeIndex(int height) { 18 | super(height); 19 | 20 | setExtremumYScale(1f); 21 | } 22 | 23 | @Override 24 | public void computeMinMax(int currentIndex, Entry entry) { 25 | if (entry.getVolume() < getMinY()) { 26 | setMinY(entry.getVolume()); 27 | } 28 | if (entry.getVolumeMa5() < getMinY()) { 29 | setMinY((float) entry.getVolumeMa5()); 30 | } 31 | if (entry.getVolumeMa10() < getMinY()) { 32 | setMinY((float) entry.getVolumeMa10()); 33 | } 34 | 35 | if (entry.getVolume() > getMaxY()) { 36 | setMaxY(entry.getVolume()); 37 | } 38 | if (entry.getVolumeMa5() > getMaxY()) { 39 | setMaxY((float) entry.getVolumeMa5()); 40 | } 41 | if (entry.getVolumeMa10() > getMaxY()) { 42 | setMaxY((float) entry.getVolumeMa10()); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/entry/StockMACDIndex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.entry; 20 | 21 | /** 22 | *MACD 指标
23 | *Date: 2017/3/16
24 | * 25 | * @author afon 26 | */ 27 | 28 | public class StockMACDIndex extends StockIndex { 29 | 30 | public StockMACDIndex() { 31 | super(STANDARD_HEIGHT); 32 | } 33 | 34 | public StockMACDIndex(int height) { 35 | super(height); 36 | } 37 | 38 | @Override 39 | public void computeMinMax(int currentIndex, Entry entry) { 40 | if (entry.getMacd() < getMinY()) { 41 | setMinY(entry.getMacd()); 42 | } 43 | if (entry.getDea() < getMinY()) { 44 | setMinY(entry.getDea()); 45 | } 46 | if (entry.getDiff() < getMinY()) { 47 | setMinY(entry.getDiff()); 48 | } 49 | 50 | if (entry.getMacd() > getMaxY()) { 51 | setMaxY(entry.getMacd()); 52 | } 53 | if (entry.getDea() > getMaxY()) { 54 | setMaxY(entry.getDea()); 55 | } 56 | if (entry.getDiff() > getMaxY()) { 57 | setMaxY(entry.getDiff()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/entry/StockPlaceIndex.java: -------------------------------------------------------------------------------- 1 | package com.wordplat.ikvstockchart.entry; 2 | 3 | /** 4 | * Created by adminstartor on 2018/5/8. 5 | */ 6 | 7 | public class StockPlaceIndex extends StockIndex { 8 | 9 | public StockPlaceIndex(int height) { 10 | super(height); 11 | } 12 | 13 | @Override 14 | public void computeMinMax(int currentIndex, Entry entry) { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/entry/StockRSIIndex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.entry; 20 | 21 | /** 22 | *RSI 指标
23 | *Date: 2017/3/16
24 | * 25 | * @author afon 26 | */ 27 | 28 | public class StockRSIIndex extends StockIndex { 29 | 30 | public StockRSIIndex() { 31 | super(STANDARD_HEIGHT); 32 | } 33 | 34 | public StockRSIIndex(int height) { 35 | super(height); 36 | } 37 | 38 | @Override 39 | public void computeMinMax(int currentIndex, Entry entry) { 40 | if (entry.getRsi1() < getMinY()) { 41 | setMinY(entry.getRsi1()); 42 | } 43 | if (entry.getRsi2() < getMinY()) { 44 | setMinY(entry.getRsi2()); 45 | } 46 | if (entry.getRsi3() < getMinY()) { 47 | setMinY(entry.getRsi3()); 48 | } 49 | 50 | if (entry.getRsi1() > getMaxY()) { 51 | setMaxY(entry.getRsi1()); 52 | } 53 | if (entry.getRsi2() > getMaxY()) { 54 | setMaxY(entry.getRsi2()); 55 | } 56 | if (entry.getRsi3() > getMaxY()) { 57 | setMaxY(entry.getRsi3()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ikvStockChart/src/main/java/com/wordplat/ikvstockchart/marker/IMarkerView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 WordPlat Open Source Project 3 | * 4 | * https://wordplat.com/InteractiveKLineView/ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.wordplat.ikvstockchart.marker; 20 | 21 | import android.graphics.Canvas; 22 | import android.graphics.RectF; 23 | 24 | import com.wordplat.ikvstockchart.render.AbstractRender; 25 | 26 | /** 27 | *IMarkerView
28 | *Date: 2017/3/23
29 | * 30 | * @author afon 31 | */ 32 | 33 | public interface IMarkerView { 34 | 35 | /** 36 | * 初始化 MarkerView 37 | * 38 | * @param contentRect 视图区域 39 | * @param render render 40 | */ 41 | void onInitMarkerView(RectF contentRect, AbstractRender render); 42 | 43 | /** 44 | * onDrawMarkerView 45 | * 46 | * @param canvas canvas 47 | * @param highlightPointX 高亮中心坐标 x 48 | * @param highlightPointY 高亮中心坐标 y 49 | */ 50 | void onDrawMarkerView(Canvas canvas, float highlightPointX, float highlightPointY); 51 | } -------------------------------------------------------------------------------- /ikvStockChart/src/main/res/drawable/text_tab.xml: -------------------------------------------------------------------------------- 1 | 2 |